// SPDX-License-Identifier: GPL-2.0-or-later
/*
* sata_sx4.c - Promise SATA
*
* Maintained by: Tejun Heo <tj@kernel.org>
* Please ALWAYS copy linux-ide@vger.kernel.org
* on emails.
*
* Copyright 2003-2004 Red Hat, Inc.
*
* libata documentation is available via 'make {ps|pdf}docs',
* as Documentation/driver-api/libata.rst
*
* Hardware documentation available under NDA.
*/
/*
Theory of operation
-------------------
The SX4 (PDC20621) chip features a single Host DMA (HDMA) copy
engine, DIMM memory, and four ATA engines (one per SATA port).
Data is copied to/from DIMM memory by the HDMA engine, before
handing off to one (or more) of the ATA engines. The ATA
engines operate solely on DIMM memory.
The SX4 behaves like a PATA chip, with no SATA controls or
knowledge whatsoever, leading to the presumption that
PATA<->SATA bridges exist on SX4 boards, external to the
PDC20621 chip itself.
The chip is quite capable, supporting an XOR engine and linked
hardware commands (permits a string to transactions to be
submitted and waited-on as a single unit), and an optional
microprocessor.
The limiting factor is largely software. This Linux driver was
written to multiplex the single HDMA engine to copy disk
transactions into a fixed DIMM memory space, from where an ATA
engine takes over. As a result, each WRITE looks like this:
submit HDMA packet to hardware
hardware copies data from system memory to DIMM
hardware raises interrupt
submit ATA packet to hardware
hardware executes ATA WRITE command, w/ data in DIMM
hardware raises interrupt
and each READ looks like this:
submit ATA packet to hardware
hardware executes ATA READ command, w/ data in DIMM
hardware raises interrupt
submit HDMA packet to hardware
hardware copies data from DIMM to system memory
hardware raises interrupt
This is a very slow, lock-step way of doing things that can
certainly be improved by motivated kernel hackers.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include "sata_promise.h"
#define DRV_NAME "sata_sx4"
#define DRV_VERSION "0.12"
enum {
PDC_MMIO_BAR