dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
  Fix bug - Implement bfin ata interrupt handler to avoid "irq 68 nobody cared" (v2)
  sata_mv: Improve naming of main_irq cause/mask identifiers
  libata-scsi: improve rbuf handling for simulated commands
  libata-scsi: clean up inquiry / mode sense related functions
  [MIPS] ATA: Rename routerboard 500 to 532
This commit is contained in:
Linus Torvalds 2008-04-29 08:52:05 -07:00
commit c135b6592b
7 changed files with 365 additions and 459 deletions

View File

@ -566,11 +566,11 @@ config PATA_RADISYS
If unsure, say N. If unsure, say N.
config PATA_RB500 config PATA_RB532
tristate "RouterBoard 500 PATA CompactFlash support" tristate "RouterBoard 532 PATA CompactFlash support"
depends on MIKROTIK_RB500 depends on MIKROTIK_RB532
help help
This option enables support for the RouterBoard 500 This option enables support for the RouterBoard 532
PATA CompactFlash controller. PATA CompactFlash controller.
If unsure, say N. If unsure, say N.

View File

@ -55,7 +55,7 @@ obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o
obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o
obj-$(CONFIG_PATA_QDI) += pata_qdi.o obj-$(CONFIG_PATA_QDI) += pata_qdi.o
obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RB500) += pata_rb500_cf.o obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o
obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o

View File

@ -49,7 +49,11 @@
#include "libata.h" #include "libata.h"
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
#define ATA_SCSI_RBUF_SIZE 4096
static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc); typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc);
@ -179,6 +183,13 @@ DEVICE_ATTR(link_power_management_policy, S_IRUGO | S_IWUSR,
ata_scsi_lpm_show, ata_scsi_lpm_put); ata_scsi_lpm_show, ata_scsi_lpm_put);
EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy); EXPORT_SYMBOL_GPL(dev_attr_link_power_management_policy);
static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *)) void (*done)(struct scsi_cmnd *))
{ {
@ -1632,53 +1643,48 @@ defer:
/** /**
* ata_scsi_rbuf_get - Map response buffer. * ata_scsi_rbuf_get - Map response buffer.
* @cmd: SCSI command containing buffer to be mapped. * @flags: unsigned long variable to store irq enable status
* @buf_out: Pointer to mapped area. * @copy_in: copy in from user buffer
* *
* Maps buffer contained within SCSI command @cmd. * Prepare buffer for simulated SCSI commands.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(ata_scsi_rbuf_lock) on success
* *
* RETURNS: * RETURNS:
* Length of response buffer. * Pointer to response buffer.
*/ */
static void *ata_scsi_rbuf_get(struct scsi_cmnd *cmd, bool copy_in,
static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) unsigned long *flags)
{ {
u8 *buf; spin_lock_irqsave(&ata_scsi_rbuf_lock, *flags);
unsigned int buflen;
struct scatterlist *sg = scsi_sglist(cmd); memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE);
if (copy_in)
if (sg) { sg_copy_to_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset; ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
buflen = sg->length; return ata_scsi_rbuf;
} else {
buf = NULL;
buflen = 0;
}
*buf_out = buf;
return buflen;
} }
/** /**
* ata_scsi_rbuf_put - Unmap response buffer. * ata_scsi_rbuf_put - Unmap response buffer.
* @cmd: SCSI command containing buffer to be unmapped. * @cmd: SCSI command containing buffer to be unmapped.
* @buf: buffer to unmap * @copy_out: copy out result
* @flags: @flags passed to ata_scsi_rbuf_get()
* *
* Unmaps response buffer contained within @cmd. * Returns rbuf buffer. The result is copied to @cmd's buffer if
* @copy_back is true.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * Unlocks ata_scsi_rbuf_lock.
*/ */
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, bool copy_out,
static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf) unsigned long *flags)
{ {
struct scatterlist *sg = scsi_sglist(cmd); if (copy_out)
if (sg) sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd),
kunmap_atomic(buf - sg->offset, KM_IRQ0); ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE);
spin_unlock_irqrestore(&ata_scsi_rbuf_lock, *flags);
} }
/** /**
@ -1696,51 +1702,27 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf)
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor)(struct ata_scsi_args *args, u8 *rbuf))
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen))
{ {
u8 *rbuf; u8 *rbuf;
unsigned int buflen, rc; unsigned int rc;
struct scsi_cmnd *cmd = args->cmd; struct scsi_cmnd *cmd = args->cmd;
unsigned long flags; unsigned long flags;
local_irq_save(flags); rbuf = ata_scsi_rbuf_get(cmd, false, &flags);
rc = actor(args, rbuf);
buflen = ata_scsi_rbuf_get(cmd, &rbuf); ata_scsi_rbuf_put(cmd, rc == 0, &flags);
memset(rbuf, 0, buflen);
rc = actor(args, rbuf, buflen);
ata_scsi_rbuf_put(cmd, rbuf);
local_irq_restore(flags);
if (rc == 0) if (rc == 0)
cmd->result = SAM_STAT_GOOD; cmd->result = SAM_STAT_GOOD;
args->done(cmd); args->done(cmd);
} }
/**
* ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer
* @idx: byte index into SCSI response buffer
* @val: value to set
*
* To be used by SCSI command simulator functions. This macros
* expects two local variables, u8 *rbuf and unsigned int buflen,
* are in scope.
*
* LOCKING:
* None.
*/
#define ATA_SCSI_RBUF_SET(idx, val) do { \
if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \
} while (0)
/** /**
* ata_scsiop_inq_std - Simulate INQUIRY command * ata_scsiop_inq_std - Simulate INQUIRY command
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Returns standard device identification data associated * Returns standard device identification data associated
* with non-VPD INQUIRY command output. * with non-VPD INQUIRY command output.
@ -1748,10 +1730,17 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
const u8 versions[] = {
0x60, /* SAM-3 (no version claimed) */
0x03,
0x20, /* SBC-2 (no version claimed) */
0x02,
0x60 /* SPC-3 (no version claimed) */
};
u8 hdr[] = { u8 hdr[] = {
TYPE_DISK, TYPE_DISK,
0, 0,
@ -1760,35 +1749,21 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
95 - 4 95 - 4
}; };
VPRINTK("ENTER\n");
/* set scsi removeable (RMB) bit per ata bit */ /* set scsi removeable (RMB) bit per ata bit */
if (ata_id_removeable(args->id)) if (ata_id_removeable(args->id))
hdr[1] |= (1 << 7); hdr[1] |= (1 << 7);
VPRINTK("ENTER\n");
memcpy(rbuf, hdr, sizeof(hdr)); memcpy(rbuf, hdr, sizeof(hdr));
memcpy(&rbuf[8], "ATA ", 8);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
if (buflen > 35) { if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[8], "ATA ", 8); memcpy(&rbuf[32], "n/a ", 4);
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
}
if (buflen > 63) { memcpy(rbuf + 59, versions, sizeof(versions));
const u8 versions[] = {
0x60, /* SAM-3 (no version claimed) */
0x03,
0x20, /* SBC-2 (no version claimed) */
0x02,
0x60 /* SPC-3 (no version claimed) */
};
memcpy(rbuf + 59, versions, sizeof(versions));
}
return 0; return 0;
} }
@ -1797,27 +1772,22 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages * ata_scsiop_inq_00 - Simulate INQUIRY VPD page 0, list of pages
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Returns list of inquiry VPD pages available. * Returns list of inquiry VPD pages available.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
const u8 pages[] = { const u8 pages[] = {
0x00, /* page 0x00, this page */ 0x00, /* page 0x00, this page */
0x80, /* page 0x80, unit serial no page */ 0x80, /* page 0x80, unit serial no page */
0x83 /* page 0x83, device ident page */ 0x83 /* page 0x83, device ident page */
}; };
rbuf[3] = sizeof(pages); /* number of supported VPD pages */ rbuf[3] = sizeof(pages); /* number of supported VPD pages */
memcpy(rbuf + 4, pages, sizeof(pages));
if (buflen > 6)
memcpy(rbuf + 4, pages, sizeof(pages));
return 0; return 0;
} }
@ -1825,16 +1795,13 @@ unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number * ata_scsiop_inq_80 - Simulate INQUIRY VPD page 80, device serial number
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Returns ATA device serial number. * Returns ATA device serial number.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
const u8 hdr[] = { const u8 hdr[] = {
0, 0,
@ -1842,12 +1809,10 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
0, 0,
ATA_ID_SERNO_LEN, /* page len */ ATA_ID_SERNO_LEN, /* page len */
}; };
memcpy(rbuf, hdr, sizeof(hdr)); memcpy(rbuf, hdr, sizeof(hdr));
ata_id_string(args->id, (unsigned char *) &rbuf[4],
if (buflen > (ATA_ID_SERNO_LEN + 4 - 1)) ATA_ID_SERNO, ATA_ID_SERNO_LEN);
ata_id_string(args->id, (unsigned char *) &rbuf[4],
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
return 0; return 0;
} }
@ -1855,7 +1820,6 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity * ata_scsiop_inq_83 - Simulate INQUIRY VPD page 83, device identity
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Yields two logical unit device identification designators: * Yields two logical unit device identification designators:
* - vendor specific ASCII containing the ATA serial number * - vendor specific ASCII containing the ATA serial number
@ -1865,41 +1829,37 @@ unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
int num;
const int sat_model_serial_desc_len = 68; const int sat_model_serial_desc_len = 68;
int num;
rbuf[1] = 0x83; /* this page code */ rbuf[1] = 0x83; /* this page code */
num = 4; num = 4;
if (buflen > (ATA_ID_SERNO_LEN + num + 3)) { /* piv=0, assoc=lu, code_set=ACSII, designator=vendor */
/* piv=0, assoc=lu, code_set=ACSII, designator=vendor */ rbuf[num + 0] = 2;
rbuf[num + 0] = 2; rbuf[num + 3] = ATA_ID_SERNO_LEN;
rbuf[num + 3] = ATA_ID_SERNO_LEN; num += 4;
num += 4; ata_id_string(args->id, (unsigned char *) rbuf + num,
ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO, ATA_ID_SERNO_LEN);
ATA_ID_SERNO, ATA_ID_SERNO_LEN); num += ATA_ID_SERNO_LEN;
num += ATA_ID_SERNO_LEN;
} /* SAT defined lu model and serial numbers descriptor */
if (buflen > (sat_model_serial_desc_len + num + 3)) { /* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */
/* SAT defined lu model and serial numbers descriptor */ rbuf[num + 0] = 2;
/* piv=0, assoc=lu, code_set=ACSII, designator=t10 vendor id */ rbuf[num + 1] = 1;
rbuf[num + 0] = 2; rbuf[num + 3] = sat_model_serial_desc_len;
rbuf[num + 1] = 1; num += 4;
rbuf[num + 3] = sat_model_serial_desc_len; memcpy(rbuf + num, "ATA ", 8);
num += 4; num += 8;
memcpy(rbuf + num, "ATA ", 8); ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_PROD,
num += 8; ATA_ID_PROD_LEN);
ata_id_string(args->id, (unsigned char *) rbuf + num, num += ATA_ID_PROD_LEN;
ATA_ID_PROD, ATA_ID_PROD_LEN); ata_id_string(args->id, (unsigned char *) rbuf + num, ATA_ID_SERNO,
num += ATA_ID_PROD_LEN; ATA_ID_SERNO_LEN);
ata_id_string(args->id, (unsigned char *) rbuf + num, num += ATA_ID_SERNO_LEN;
ATA_ID_SERNO, ATA_ID_SERNO_LEN);
num += ATA_ID_SERNO_LEN;
}
rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */
return 0; return 0;
} }
@ -1908,35 +1868,26 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info * ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Yields SAT-specified ATA VPD page. * Yields SAT-specified ATA VPD page.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
u8 pbuf[60];
struct ata_taskfile tf; struct ata_taskfile tf;
unsigned int i;
if (!buflen)
return 0;
memset(&pbuf, 0, sizeof(pbuf));
memset(&tf, 0, sizeof(tf)); memset(&tf, 0, sizeof(tf));
pbuf[1] = 0x89; /* our page code */ rbuf[1] = 0x89; /* our page code */
pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */ rbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
pbuf[3] = (0x238 & 0xff); rbuf[3] = (0x238 & 0xff);
memcpy(&pbuf[8], "linux ", 8); memcpy(&rbuf[8], "linux ", 8);
memcpy(&pbuf[16], "libata ", 16); memcpy(&rbuf[16], "libata ", 16);
memcpy(&pbuf[32], DRV_VERSION, 4); memcpy(&rbuf[32], DRV_VERSION, 4);
ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4); ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
/* we don't store the ATA device signature, so we fake it */ /* we don't store the ATA device signature, so we fake it */
@ -1944,19 +1895,12 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
tf.lbal = 0x1; tf.lbal = 0x1;
tf.nsect = 0x1; tf.nsect = 0x1;
ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */ ata_tf_to_fis(&tf, 0, 1, &rbuf[36]); /* TODO: PMP? */
pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */ rbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
pbuf[56] = ATA_CMD_ID_ATA; rbuf[56] = ATA_CMD_ID_ATA;
i = min(buflen, 60U); memcpy(&rbuf[60], &args->id[0], 512);
memcpy(rbuf, &pbuf[0], i);
buflen -= i;
if (!buflen)
return 0;
memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
return 0; return 0;
} }
@ -1964,7 +1908,6 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_noop - Command handler that simply returns success. * ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* No operation. Simply returns success to caller, to indicate * No operation. Simply returns success to caller, to indicate
* that the caller should successfully complete this SCSI command. * that the caller should successfully complete this SCSI command.
@ -1972,47 +1915,16 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
return 0; return 0;
} }
/**
* ata_msense_push - Push data onto MODE SENSE data output buffer
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* @buf: Pointer to BLOB being added to output buffer
* @buflen: Length of BLOB
*
* Store MODE SENSE data on an output buffer.
*
* LOCKING:
* None.
*/
static void ata_msense_push(u8 **ptr_io, const u8 *last,
const u8 *buf, unsigned int buflen)
{
u8 *ptr = *ptr_io;
if ((ptr + buflen - 1) > last)
return;
memcpy(ptr, buf, buflen);
ptr += buflen;
*ptr_io = ptr;
}
/** /**
* ata_msense_caching - Simulate MODE SENSE caching info page * ata_msense_caching - Simulate MODE SENSE caching info page
* @id: device IDENTIFY data * @id: device IDENTIFY data
* @ptr_io: (input/output) Location to store more output data * @buf: output buffer
* @last: End of output data buffer
* *
* Generate a caching info page, which conditionally indicates * Generate a caching info page, which conditionally indicates
* write caching to the SCSI layer, depending on device * write caching to the SCSI layer, depending on device
@ -2021,58 +1933,43 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_caching(u16 *id, u8 *buf)
static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io,
const u8 *last)
{ {
u8 page[CACHE_MPAGE_LEN]; memcpy(buf, def_cache_mpage, sizeof(def_cache_mpage));
memcpy(page, def_cache_mpage, sizeof(page));
if (ata_id_wcache_enabled(id)) if (ata_id_wcache_enabled(id))
page[2] |= (1 << 2); /* write cache enable */ buf[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(id)) if (!ata_id_rahead_enabled(id))
page[12] |= (1 << 5); /* disable read ahead */ buf[12] |= (1 << 5); /* disable read ahead */
return sizeof(def_cache_mpage);
ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page);
} }
/** /**
* ata_msense_ctl_mode - Simulate MODE SENSE control mode page * ata_msense_ctl_mode - Simulate MODE SENSE control mode page
* @dev: Device associated with this MODE SENSE command * @buf: output buffer
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* *
* Generate a generic MODE SENSE control mode page. * Generate a generic MODE SENSE control mode page.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_ctl_mode(u8 *buf)
static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
{ {
ata_msense_push(ptr_io, last, def_control_mpage, memcpy(buf, def_control_mpage, sizeof(def_control_mpage));
sizeof(def_control_mpage));
return sizeof(def_control_mpage); return sizeof(def_control_mpage);
} }
/** /**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page * ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @dev: Device associated with this MODE SENSE command * @bufp: output buffer
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
* *
* Generate a generic MODE SENSE r/w error recovery page. * Generate a generic MODE SENSE r/w error recovery page.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
static unsigned int ata_msense_rw_recovery(u8 *buf)
static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
{ {
memcpy(buf, def_rw_recovery_mpage, sizeof(def_rw_recovery_mpage));
ata_msense_push(ptr_io, last, def_rw_recovery_mpage,
sizeof(def_rw_recovery_mpage));
return sizeof(def_rw_recovery_mpage); return sizeof(def_rw_recovery_mpage);
} }
@ -2104,7 +2001,6 @@ static int ata_dev_supports_fua(u16 *id)
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Simulate MODE SENSE commands. Assume this is invoked for direct * Simulate MODE SENSE commands. Assume this is invoked for direct
* access devices (e.g. disks) only. There should be no block * access devices (e.g. disks) only. There should be no block
@ -2113,19 +2009,17 @@ static int ata_dev_supports_fua(u16 *id)
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
struct ata_device *dev = args->dev; struct ata_device *dev = args->dev;
u8 *scsicmd = args->cmd->cmnd, *p, *last; u8 *scsicmd = args->cmd->cmnd, *p = rbuf;
const u8 sat_blk_desc[] = { const u8 sat_blk_desc[] = {
0, 0, 0, 0, /* number of blocks: sat unspecified */ 0, 0, 0, 0, /* number of blocks: sat unspecified */
0, 0,
0, 0x2, 0x0 /* block length: 512 bytes */ 0, 0x2, 0x0 /* block length: 512 bytes */
}; };
u8 pg, spg; u8 pg, spg;
unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; unsigned int ebd, page_control, six_byte;
u8 dpofua; u8 dpofua;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
@ -2148,17 +2042,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
goto invalid_fld; goto invalid_fld;
} }
if (six_byte) { if (six_byte)
output_len = 4 + (ebd ? 8 : 0); p += 4 + (ebd ? 8 : 0);
alloc_len = scsicmd[4]; else
} else { p += 8 + (ebd ? 8 : 0);
output_len = 8 + (ebd ? 8 : 0);
alloc_len = (scsicmd[7] << 8) + scsicmd[8];
}
minlen = (alloc_len < buflen) ? alloc_len : buflen;
p = rbuf + output_len;
last = rbuf + minlen - 1;
pg = scsicmd[2] & 0x3f; pg = scsicmd[2] & 0x3f;
spg = scsicmd[3]; spg = scsicmd[3];
@ -2171,61 +2058,48 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
switch(pg) { switch(pg) {
case RW_RECOVERY_MPAGE: case RW_RECOVERY_MPAGE:
output_len += ata_msense_rw_recovery(&p, last); p += ata_msense_rw_recovery(p);
break; break;
case CACHE_MPAGE: case CACHE_MPAGE:
output_len += ata_msense_caching(args->id, &p, last); p += ata_msense_caching(args->id, p);
break; break;
case CONTROL_MPAGE: { case CONTROL_MPAGE:
output_len += ata_msense_ctl_mode(&p, last); p += ata_msense_ctl_mode(p);
break; break;
}
case ALL_MPAGES: case ALL_MPAGES:
output_len += ata_msense_rw_recovery(&p, last); p += ata_msense_rw_recovery(p);
output_len += ata_msense_caching(args->id, &p, last); p += ata_msense_caching(args->id, p);
output_len += ata_msense_ctl_mode(&p, last); p += ata_msense_ctl_mode(p);
break; break;
default: /* invalid page code */ default: /* invalid page code */
goto invalid_fld; goto invalid_fld;
} }
if (minlen < 1)
return 0;
dpofua = 0; dpofua = 0;
if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) && if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) &&
(!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count))
dpofua = 1 << 4; dpofua = 1 << 4;
if (six_byte) { if (six_byte) {
output_len--; rbuf[0] = p - rbuf - 1;
rbuf[0] = output_len; rbuf[2] |= dpofua;
if (minlen > 2)
rbuf[2] |= dpofua;
if (ebd) { if (ebd) {
if (minlen > 3) rbuf[3] = sizeof(sat_blk_desc);
rbuf[3] = sizeof(sat_blk_desc); memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc));
if (minlen > 11)
memcpy(rbuf + 4, sat_blk_desc,
sizeof(sat_blk_desc));
} }
} else { } else {
output_len -= 2; unsigned int output_len = p - rbuf - 2;
rbuf[0] = output_len >> 8; rbuf[0] = output_len >> 8;
if (minlen > 1) rbuf[1] = output_len;
rbuf[1] = output_len; rbuf[3] |= dpofua;
if (minlen > 3)
rbuf[3] |= dpofua;
if (ebd) { if (ebd) {
if (minlen > 7) rbuf[7] = sizeof(sat_blk_desc);
rbuf[7] = sizeof(sat_blk_desc); memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc));
if (minlen > 15)
memcpy(rbuf + 8, sat_blk_desc,
sizeof(sat_blk_desc));
} }
} }
return 0; return 0;
@ -2245,15 +2119,13 @@ saving_not_supp:
* ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands * ata_scsiop_read_cap - Simulate READ CAPACITY[ 16] commands
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Simulate READ CAPACITY commands. * Simulate READ CAPACITY commands.
* *
* LOCKING: * LOCKING:
* None. * None.
*/ */
unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
unsigned int buflen)
{ {
u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */ u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */
@ -2264,28 +2136,28 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
last_lba = 0xffffffff; last_lba = 0xffffffff;
/* sector count, 32-bit */ /* sector count, 32-bit */
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3)); rbuf[0] = last_lba >> (8 * 3);
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2)); rbuf[1] = last_lba >> (8 * 2);
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1)); rbuf[2] = last_lba >> (8 * 1);
ATA_SCSI_RBUF_SET(3, last_lba); rbuf[3] = last_lba;
/* sector size */ /* sector size */
ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8); rbuf[6] = ATA_SECT_SIZE >> 8;
ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff); rbuf[7] = ATA_SECT_SIZE & 0xff;
} else { } else {
/* sector count, 64-bit */ /* sector count, 64-bit */
ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7)); rbuf[0] = last_lba >> (8 * 7);
ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6)); rbuf[1] = last_lba >> (8 * 6);
ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5)); rbuf[2] = last_lba >> (8 * 5);
ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4)); rbuf[3] = last_lba >> (8 * 4);
ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3)); rbuf[4] = last_lba >> (8 * 3);
ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2)); rbuf[5] = last_lba >> (8 * 2);
ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1)); rbuf[6] = last_lba >> (8 * 1);
ATA_SCSI_RBUF_SET(7, last_lba); rbuf[7] = last_lba;
/* sector size */ /* sector size */
ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8); rbuf[10] = ATA_SECT_SIZE >> 8;
ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff); rbuf[11] = ATA_SECT_SIZE & 0xff;
} }
return 0; return 0;
@ -2295,16 +2167,13 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
* ata_scsiop_report_luns - Simulate REPORT LUNS command * ata_scsiop_report_luns - Simulate REPORT LUNS command
* @args: device IDENTIFY data / SCSI command of interest. * @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
* *
* Simulate REPORT LUNS command. * Simulate REPORT LUNS command.
* *
* LOCKING: * LOCKING:
* spin_lock_irqsave(host lock) * spin_lock_irqsave(host lock)
*/ */
static unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf)
unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{ {
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */ rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */
@ -2312,53 +2181,6 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
return 0; return 0;
} }
/**
* ata_scsi_set_sense - Set SCSI sense data and status
* @cmd: SCSI request to be handled
* @sk: SCSI-defined sense key
* @asc: SCSI-defined additional sense code
* @ascq: SCSI-defined additional sense code qualifier
*
* Helper function that builds a valid fixed format, current
* response code and the given sense key (sk), additional sense
* code (asc) and additional sense code qualifier (ascq) with
* a SCSI command status of %SAM_STAT_CHECK_CONDITION and
* DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
*
* LOCKING:
* Not required
*/
void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
/**
* ata_scsi_badcmd - End a SCSI request with an error
* @cmd: SCSI request to be handled
* @done: SCSI command completion function
* @asc: SCSI-defined additional sense code
* @ascq: SCSI-defined additional sense code qualifier
*
* Helper function that completes a SCSI command with
* %SAM_STAT_CHECK_CONDITION, with a sense key %ILLEGAL_REQUEST
* and the specified additional sense codes.
*
* LOCKING:
* spin_lock_irqsave(host lock)
*/
void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
{
DPRINTK("ENTER\n");
ata_scsi_set_sense(cmd, ILLEGAL_REQUEST, asc, ascq);
done(cmd);
}
static void atapi_sense_complete(struct ata_queued_cmd *qc) static void atapi_sense_complete(struct ata_queued_cmd *qc)
{ {
if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) { if (qc->err_mask && ((qc->err_mask & AC_ERR_DEV) == 0)) {
@ -2485,13 +2307,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
u8 *scsicmd = cmd->cmnd; u8 *scsicmd = cmd->cmnd;
if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) { if ((scsicmd[0] == INQUIRY) && ((scsicmd[1] & 0x03) == 0)) {
u8 *buf = NULL;
unsigned int buflen;
unsigned long flags; unsigned long flags;
u8 *buf;
local_irq_save(flags); buf = ata_scsi_rbuf_get(cmd, true, &flags);
buflen = ata_scsi_rbuf_get(cmd, &buf);
/* ATAPI devices typically report zero for their SCSI version, /* ATAPI devices typically report zero for their SCSI version,
* and sometimes deviate from the spec WRT response data * and sometimes deviate from the spec WRT response data
@ -2506,9 +2325,7 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
buf[3] = 0x32; buf[3] = 0x32;
} }
ata_scsi_rbuf_put(cmd, buf); ata_scsi_rbuf_put(cmd, true, &flags);
local_irq_restore(flags);
} }
cmd->result = SAM_STAT_GOOD; cmd->result = SAM_STAT_GOOD;

View File

@ -146,34 +146,6 @@ extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
extern int ata_scsi_offline_dev(struct ata_device *dev); extern int ata_scsi_offline_dev(struct ata_device *dev);
extern void ata_scsi_media_change_notify(struct ata_device *dev); extern void ata_scsi_media_change_notify(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work); extern void ata_scsi_hotplug(struct work_struct *work);
extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_80(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_noop(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_sync_cache(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen);
extern void ata_scsi_badcmd(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *),
u8 asc, u8 ascq);
extern void ata_scsi_set_sense(struct scsi_cmnd *cmd,
u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int (*actor) (struct ata_scsi_args *args,
u8 *rbuf, unsigned int buflen));
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work); extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap); extern int ata_bus_probe(struct ata_port *ap);

View File

@ -1272,8 +1272,8 @@ static void bfin_freeze(struct ata_port *ap)
void bfin_thaw(struct ata_port *ap) void bfin_thaw(struct ata_port *ap)
{ {
dev_dbg(ap->dev, "in atapi dma thaw\n");
bfin_check_status(ap); bfin_check_status(ap);
bfin_irq_clear(ap);
bfin_irq_on(ap); bfin_irq_on(ap);
} }
@ -1339,13 +1339,130 @@ static int bfin_port_start(struct ata_port *ap)
return 0; return 0;
} }
static unsigned int bfin_ata_host_intr(struct ata_port *ap,
struct ata_queued_cmd *qc)
{
struct ata_eh_info *ehi = &ap->link.eh_info;
u8 status, host_stat = 0;
VPRINTK("ata%u: protocol %d task_state %d\n",
ap->print_id, qc->tf.protocol, ap->hsm_task_state);
/* Check whether we are expecting interrupt in this state */
switch (ap->hsm_task_state) {
case HSM_ST_FIRST:
/* Some pre-ATAPI-4 devices assert INTRQ
* at this state when ready to receive CDB.
*/
/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
* The flag was turned on only for atapi devices.
* No need to check is_atapi_taskfile(&qc->tf) again.
*/
if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
goto idle_irq;
break;
case HSM_ST_LAST:
if (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATAPI_PROT_DMA) {
/* check status of DMA engine */
host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n",
ap->print_id, host_stat);
/* if it's not our irq... */
if (!(host_stat & ATA_DMA_INTR))
goto idle_irq;
/* before we do anything else, clear DMA-Start bit */
ap->ops->bmdma_stop(qc);
if (unlikely(host_stat & ATA_DMA_ERR)) {
/* error when transfering data to/from memory */
qc->err_mask |= AC_ERR_HOST_BUS;
ap->hsm_task_state = HSM_ST_ERR;
}
}
break;
case HSM_ST:
break;
default:
goto idle_irq;
}
/* check altstatus */
status = ap->ops->sff_check_altstatus(ap);
if (status & ATA_BUSY)
goto busy_ata;
/* check main status, clearing INTRQ */
status = ap->ops->sff_check_status(ap);
if (unlikely(status & ATA_BUSY))
goto busy_ata;
/* ack bmdma irq events */
ap->ops->sff_irq_clear(ap);
ata_sff_hsm_move(ap, qc, status, 0);
if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
qc->tf.protocol == ATAPI_PROT_DMA))
ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
busy_ata:
return 1; /* irq handled */
idle_irq:
ap->stats.idle_irq++;
#ifdef ATA_IRQ_TRAP
if ((ap->stats.idle_irq % 1000) == 0) {
ap->ops->irq_ack(ap, 0); /* debug trap */
ata_port_printk(ap, KERN_WARNING, "irq trap\n");
return 1;
}
#endif
return 0; /* irq not handled */
}
static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
{
struct ata_host *host = dev_instance;
unsigned int i;
unsigned int handled = 0;
unsigned long flags;
/* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
spin_lock_irqsave(&host->lock, flags);
for (i = 0; i < host->n_ports; i++) {
struct ata_port *ap;
ap = host->ports[i];
if (ap &&
!(ap->flags & ATA_FLAG_DISABLED)) {
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->link.active_tag);
if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) &&
(qc->flags & ATA_QCFLAG_ACTIVE))
handled |= bfin_ata_host_intr(ap, qc);
}
}
spin_unlock_irqrestore(&host->lock, flags);
return IRQ_RETVAL(handled);
}
static struct scsi_host_template bfin_sht = { static struct scsi_host_template bfin_sht = {
ATA_BASE_SHT(DRV_NAME), ATA_BASE_SHT(DRV_NAME),
.sg_tablesize = SG_NONE, .sg_tablesize = SG_NONE,
.dma_boundary = ATA_DMA_BOUNDARY, .dma_boundary = ATA_DMA_BOUNDARY,
}; };
static const struct ata_port_operations bfin_pata_ops = { static struct ata_port_operations bfin_pata_ops = {
.inherits = &ata_sff_port_ops, .inherits = &ata_sff_port_ops,
.set_piomode = bfin_set_piomode, .set_piomode = bfin_set_piomode,
@ -1370,7 +1487,6 @@ static const struct ata_port_operations bfin_pata_ops = {
.thaw = bfin_thaw, .thaw = bfin_thaw,
.softreset = bfin_softreset, .softreset = bfin_softreset,
.postreset = bfin_postreset, .postreset = bfin_postreset,
.post_internal_cmd = bfin_bmdma_stop,
.sff_irq_clear = bfin_irq_clear, .sff_irq_clear = bfin_irq_clear,
.sff_irq_on = bfin_irq_on, .sff_irq_on = bfin_irq_on,
@ -1507,7 +1623,7 @@ static int __devinit bfin_atapi_probe(struct platform_device *pdev)
} }
if (ata_host_activate(host, platform_get_irq(pdev, 0), if (ata_host_activate(host, platform_get_irq(pdev, 0),
ata_sff_interrupt, IRQF_SHARED, &bfin_sht) != 0) { bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
peripheral_free_list(atapi_io_port); peripheral_free_list(atapi_io_port);
dev_err(&pdev->dev, "Fail to attach ATAPI device\n"); dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
return -ENODEV; return -ENODEV;

View File

@ -32,7 +32,7 @@
#include <asm/gpio.h> #include <asm/gpio.h>
#define DRV_NAME "pata-rb500-cf" #define DRV_NAME "pata-rb532-cf"
#define DRV_VERSION "0.1.0" #define DRV_VERSION "0.1.0"
#define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash" #define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash"
@ -43,7 +43,7 @@
#define RB500_CF_REG_CTRL 0x080E #define RB500_CF_REG_CTRL 0x080E
#define RB500_CF_REG_DATA 0x0C00 #define RB500_CF_REG_DATA 0x0C00
struct rb500_cf_info { struct rb532_cf_info {
void __iomem *iobase; void __iomem *iobase;
unsigned int gpio_line; unsigned int gpio_line;
int frozen; int frozen;
@ -52,10 +52,10 @@ struct rb500_cf_info {
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static inline void rb500_pata_finish_io(struct ata_port *ap) static inline void rb532_pata_finish_io(struct ata_port *ap)
{ {
struct ata_host *ah = ap->host; struct ata_host *ah = ap->host;
struct rb500_cf_info *info = ah->private_data; struct rb532_cf_info *info = ah->private_data;
ata_sff_altstatus(ap); ata_sff_altstatus(ap);
ndelay(RB500_CF_IO_DELAY); ndelay(RB500_CF_IO_DELAY);
@ -63,14 +63,14 @@ static inline void rb500_pata_finish_io(struct ata_port *ap)
set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
} }
static void rb500_pata_exec_command(struct ata_port *ap, static void rb532_pata_exec_command(struct ata_port *ap,
const struct ata_taskfile *tf) const struct ata_taskfile *tf)
{ {
writeb(tf->command, ap->ioaddr.command_addr); writeb(tf->command, ap->ioaddr.command_addr);
rb500_pata_finish_io(ap); rb532_pata_finish_io(ap);
} }
static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf, static void rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data) unsigned int buflen, int write_data)
{ {
struct ata_port *ap = adev->link->ap; struct ata_port *ap = adev->link->ap;
@ -84,27 +84,27 @@ static void rb500_pata_data_xfer(struct ata_device *adev, unsigned char *buf,
*buf = readb(ioaddr); *buf = readb(ioaddr);
} }
rb500_pata_finish_io(adev->link->ap); rb532_pata_finish_io(adev->link->ap);
} }
static void rb500_pata_freeze(struct ata_port *ap) static void rb532_pata_freeze(struct ata_port *ap)
{ {
struct rb500_cf_info *info = ap->host->private_data; struct rb532_cf_info *info = ap->host->private_data;
info->frozen = 1; info->frozen = 1;
} }
static void rb500_pata_thaw(struct ata_port *ap) static void rb532_pata_thaw(struct ata_port *ap)
{ {
struct rb500_cf_info *info = ap->host->private_data; struct rb532_cf_info *info = ap->host->private_data;
info->frozen = 0; info->frozen = 0;
} }
static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance) static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance)
{ {
struct ata_host *ah = dev_instance; struct ata_host *ah = dev_instance;
struct rb500_cf_info *info = ah->private_data; struct rb532_cf_info *info = ah->private_data;
if (gpio_get_value(info->gpio_line)) { if (gpio_get_value(info->gpio_line)) {
set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
@ -117,30 +117,30 @@ static irqreturn_t rb500_pata_irq_handler(int irq, void *dev_instance)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static struct ata_port_operations rb500_pata_port_ops = { static struct ata_port_operations rb532_pata_port_ops = {
.inherits = &ata_sff_port_ops, .inherits = &ata_sff_port_ops,
.sff_exec_command = rb500_pata_exec_command, .sff_exec_command = rb532_pata_exec_command,
.sff_data_xfer = rb500_pata_data_xfer, .sff_data_xfer = rb532_pata_data_xfer,
.freeze = rb500_pata_freeze, .freeze = rb532_pata_freeze,
.thaw = rb500_pata_thaw, .thaw = rb532_pata_thaw,
}; };
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static struct scsi_host_template rb500_pata_sht = { static struct scsi_host_template rb532_pata_sht = {
ATA_PIO_SHT(DRV_NAME), ATA_PIO_SHT(DRV_NAME),
}; };
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
static void rb500_pata_setup_ports(struct ata_host *ah) static void rb532_pata_setup_ports(struct ata_host *ah)
{ {
struct rb500_cf_info *info = ah->private_data; struct rb532_cf_info *info = ah->private_data;
struct ata_port *ap; struct ata_port *ap;
ap = ah->ports[0]; ap = ah->ports[0];
ap->ops = &rb500_pata_port_ops; ap->ops = &rb532_pata_port_ops;
ap->pio_mask = 0x1f; /* PIO4 */ ap->pio_mask = 0x1f; /* PIO4 */
ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
@ -153,13 +153,13 @@ static void rb500_pata_setup_ports(struct ata_host *ah)
ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA; ap->ioaddr.data_addr = info->iobase + RB500_CF_REG_DATA;
} }
static __devinit int rb500_pata_driver_probe(struct platform_device *pdev) static __devinit int rb532_pata_driver_probe(struct platform_device *pdev)
{ {
unsigned int irq; unsigned int irq;
int gpio; int gpio;
struct resource *res; struct resource *res;
struct ata_host *ah; struct ata_host *ah;
struct rb500_cf_info *info; struct rb532_cf_info *info;
int ret; int ret;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -213,10 +213,10 @@ static __devinit int rb500_pata_driver_probe(struct platform_device *pdev)
goto err_free_gpio; goto err_free_gpio;
} }
rb500_pata_setup_ports(ah); rb532_pata_setup_ports(ah);
ret = ata_host_activate(ah, irq, rb500_pata_irq_handler, ret = ata_host_activate(ah, irq, rb532_pata_irq_handler,
IRQF_TRIGGER_LOW, &rb500_pata_sht); IRQF_TRIGGER_LOW, &rb532_pata_sht);
if (ret) if (ret)
goto err_free_gpio; goto err_free_gpio;
@ -228,10 +228,10 @@ err_free_gpio:
return ret; return ret;
} }
static __devexit int rb500_pata_driver_remove(struct platform_device *pdev) static __devexit int rb532_pata_driver_remove(struct platform_device *pdev)
{ {
struct ata_host *ah = platform_get_drvdata(pdev); struct ata_host *ah = platform_get_drvdata(pdev);
struct rb500_cf_info *info = ah->private_data; struct rb532_cf_info *info = ah->private_data;
ata_host_detach(ah); ata_host_detach(ah);
gpio_free(info->gpio_line); gpio_free(info->gpio_line);
@ -242,9 +242,9 @@ static __devexit int rb500_pata_driver_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:" DRV_NAME); MODULE_ALIAS("platform:" DRV_NAME);
static struct platform_driver rb500_pata_platform_driver = { static struct platform_driver rb532_pata_platform_driver = {
.probe = rb500_pata_driver_probe, .probe = rb532_pata_driver_probe,
.remove = __devexit_p(rb500_pata_driver_remove), .remove = __devexit_p(rb532_pata_driver_remove),
.driver = { .driver = {
.name = DRV_NAME, .name = DRV_NAME,
.owner = THIS_MODULE, .owner = THIS_MODULE,
@ -255,16 +255,16 @@ static struct platform_driver rb500_pata_platform_driver = {
#define DRV_INFO DRV_DESC " version " DRV_VERSION #define DRV_INFO DRV_DESC " version " DRV_VERSION
static int __init rb500_pata_module_init(void) static int __init rb532_pata_module_init(void)
{ {
printk(KERN_INFO DRV_INFO "\n"); printk(KERN_INFO DRV_INFO "\n");
return platform_driver_register(&rb500_pata_platform_driver); return platform_driver_register(&rb532_pata_platform_driver);
} }
static void __exit rb500_pata_module_exit(void) static void __exit rb532_pata_module_exit(void)
{ {
platform_driver_unregister(&rb500_pata_platform_driver); platform_driver_unregister(&rb532_pata_platform_driver);
} }
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
@ -273,5 +273,5 @@ MODULE_DESCRIPTION(DRV_DESC);
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(rb500_pata_module_init); module_init(rb532_pata_module_init);
module_exit(rb500_pata_module_exit); module_exit(rb532_pata_module_exit);

View File

@ -172,10 +172,11 @@ enum {
PCIE_IRQ_MASK_OFS = 0x1910, PCIE_IRQ_MASK_OFS = 0x1910,
PCIE_UNMASK_ALL_IRQS = 0x40a, /* assorted bits */ PCIE_UNMASK_ALL_IRQS = 0x40a, /* assorted bits */
HC_MAIN_IRQ_CAUSE_OFS = 0x1d60, /* Host Controller Main Interrupt Cause/Mask registers (1 per-chip) */
HC_MAIN_IRQ_MASK_OFS = 0x1d64, PCI_HC_MAIN_IRQ_CAUSE_OFS = 0x1d60,
HC_SOC_MAIN_IRQ_CAUSE_OFS = 0x20020, PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64,
HC_SOC_MAIN_IRQ_MASK_OFS = 0x20024, SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020,
SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024,
ERR_IRQ = (1 << 0), /* shift by port # */ ERR_IRQ = (1 << 0), /* shift by port # */
DONE_IRQ = (1 << 1), /* shift by port # */ DONE_IRQ = (1 << 1), /* shift by port # */
HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */
@ -445,8 +446,8 @@ struct mv_host_priv {
const struct mv_hw_ops *ops; const struct mv_hw_ops *ops;
int n_ports; int n_ports;
void __iomem *base; void __iomem *base;
void __iomem *main_cause_reg_addr; void __iomem *main_irq_cause_addr;
void __iomem *main_mask_reg_addr; void __iomem *main_irq_mask_addr;
u32 irq_cause_ofs; u32 irq_cause_ofs;
u32 irq_mask_ofs; u32 irq_mask_ofs;
u32 unmask_all_irqs; u32 unmask_all_irqs;
@ -727,8 +728,8 @@ static inline unsigned int mv_hardport_from_port(unsigned int port)
* Simple code, with two return values, so macro rather than inline. * Simple code, with two return values, so macro rather than inline.
* *
* port is the sole input, in range 0..7. * port is the sole input, in range 0..7.
* shift is one output, for use with the main_cause and main_mask registers. * shift is one output, for use with main_irq_cause / main_irq_mask registers.
* hardport is the other output, in range 0..3 * hardport is the other output, in range 0..3.
* *
* Note that port and hardport may be the same variable in some cases. * Note that port and hardport may be the same variable in some cases.
*/ */
@ -1679,12 +1680,12 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
/** /**
* mv_host_intr - Handle all interrupts on the given host controller * mv_host_intr - Handle all interrupts on the given host controller
* @host: host specific structure * @host: host specific structure
* @main_cause: Main interrupt cause register for the chip. * @main_irq_cause: Main interrupt cause register for the chip.
* *
* LOCKING: * LOCKING:
* Inherited from caller. * Inherited from caller.
*/ */
static int mv_host_intr(struct ata_host *host, u32 main_cause) static int mv_host_intr(struct ata_host *host, u32 main_irq_cause)
{ {
struct mv_host_priv *hpriv = host->private_data; struct mv_host_priv *hpriv = host->private_data;
void __iomem *mmio = hpriv->base, *hc_mmio = NULL; void __iomem *mmio = hpriv->base, *hc_mmio = NULL;
@ -1705,7 +1706,7 @@ static int mv_host_intr(struct ata_host *host, u32 main_cause)
* Do nothing if port is not interrupting or is disabled: * Do nothing if port is not interrupting or is disabled:
*/ */
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
port_cause = (main_cause >> shift) & (DONE_IRQ | ERR_IRQ); port_cause = (main_irq_cause >> shift) & (DONE_IRQ | ERR_IRQ);
if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED)) if (!port_cause || !ap || (ap->flags & ATA_FLAG_DISABLED))
continue; continue;
/* /*
@ -1811,20 +1812,20 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
struct ata_host *host = dev_instance; struct ata_host *host = dev_instance;
struct mv_host_priv *hpriv = host->private_data; struct mv_host_priv *hpriv = host->private_data;
unsigned int handled = 0; unsigned int handled = 0;
u32 main_cause, main_mask; u32 main_irq_cause, main_irq_mask;
spin_lock(&host->lock); spin_lock(&host->lock);
main_cause = readl(hpriv->main_cause_reg_addr); main_irq_cause = readl(hpriv->main_irq_cause_addr);
main_mask = readl(hpriv->main_mask_reg_addr); main_irq_mask = readl(hpriv->main_irq_mask_addr);
/* /*
* Deal with cases where we either have nothing pending, or have read * Deal with cases where we either have nothing pending, or have read
* a bogus register value which can indicate HW removal or PCI fault. * a bogus register value which can indicate HW removal or PCI fault.
*/ */
if ((main_cause & main_mask) && (main_cause != 0xffffffffU)) { if ((main_irq_cause & main_irq_mask) && (main_irq_cause != 0xffffffffU)) {
if (unlikely((main_cause & PCI_ERR) && HAS_PCI(host))) if (unlikely((main_irq_cause & PCI_ERR) && HAS_PCI(host)))
handled = mv_pci_error(host, hpriv->base); handled = mv_pci_error(host, hpriv->base);
else else
handled = mv_host_intr(host, main_cause); handled = mv_host_intr(host, main_irq_cause);
} }
spin_unlock(&host->lock); spin_unlock(&host->lock);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
@ -2027,7 +2028,7 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
ZERO(MV_PCI_DISC_TIMER); ZERO(MV_PCI_DISC_TIMER);
ZERO(MV_PCI_MSI_TRIGGER); ZERO(MV_PCI_MSI_TRIGGER);
writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT); writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT);
ZERO(HC_MAIN_IRQ_MASK_OFS); ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
ZERO(MV_PCI_SERR_MASK); ZERO(MV_PCI_SERR_MASK);
ZERO(hpriv->irq_cause_ofs); ZERO(hpriv->irq_cause_ofs);
ZERO(hpriv->irq_mask_ofs); ZERO(hpriv->irq_mask_ofs);
@ -2404,7 +2405,7 @@ static void mv_eh_freeze(struct ata_port *ap)
{ {
struct mv_host_priv *hpriv = ap->host->private_data; struct mv_host_priv *hpriv = ap->host->private_data;
unsigned int shift, hardport, port = ap->port_no; unsigned int shift, hardport, port = ap->port_no;
u32 main_mask; u32 main_irq_mask;
/* FIXME: handle coalescing completion events properly */ /* FIXME: handle coalescing completion events properly */
@ -2412,9 +2413,9 @@ static void mv_eh_freeze(struct ata_port *ap)
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport); MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
/* disable assertion of portN err, done events */ /* disable assertion of portN err, done events */
main_mask = readl(hpriv->main_mask_reg_addr); main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_mask &= ~((DONE_IRQ | ERR_IRQ) << shift); main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_mask, hpriv->main_mask_reg_addr); writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
} }
static void mv_eh_thaw(struct ata_port *ap) static void mv_eh_thaw(struct ata_port *ap)
@ -2423,7 +2424,7 @@ static void mv_eh_thaw(struct ata_port *ap)
unsigned int shift, hardport, port = ap->port_no; unsigned int shift, hardport, port = ap->port_no;
void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port); void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
void __iomem *port_mmio = mv_ap_base(ap); void __iomem *port_mmio = mv_ap_base(ap);
u32 main_mask, hc_irq_cause; u32 main_irq_mask, hc_irq_cause;
/* FIXME: handle coalescing completion events properly */ /* FIXME: handle coalescing completion events properly */
@ -2438,9 +2439,9 @@ static void mv_eh_thaw(struct ata_port *ap)
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
/* enable assertion of portN err, done events */ /* enable assertion of portN err, done events */
main_mask = readl(hpriv->main_mask_reg_addr); main_irq_mask = readl(hpriv->main_irq_mask_addr);
main_mask |= ((DONE_IRQ | ERR_IRQ) << shift); main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
writelfl(main_mask, hpriv->main_mask_reg_addr); writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
} }
/** /**
@ -2654,15 +2655,15 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
goto done; goto done;
if (HAS_PCI(host)) { if (HAS_PCI(host)) {
hpriv->main_cause_reg_addr = mmio + HC_MAIN_IRQ_CAUSE_OFS; hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_mask_reg_addr = mmio + HC_MAIN_IRQ_MASK_OFS; hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
} else { } else {
hpriv->main_cause_reg_addr = mmio + HC_SOC_MAIN_IRQ_CAUSE_OFS; hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
hpriv->main_mask_reg_addr = mmio + HC_SOC_MAIN_IRQ_MASK_OFS; hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
} }
/* global interrupt mask: 0 == mask everything */ /* global interrupt mask: 0 == mask everything */
writel(0, hpriv->main_mask_reg_addr); writel(0, hpriv->main_irq_mask_addr);
n_hc = mv_get_hc_count(host->ports[0]->flags); n_hc = mv_get_hc_count(host->ports[0]->flags);
@ -2712,23 +2713,23 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs); writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
if (IS_GEN_I(hpriv)) if (IS_GEN_I(hpriv))
writelfl(~HC_MAIN_MASKED_IRQS_5, writelfl(~HC_MAIN_MASKED_IRQS_5,
hpriv->main_mask_reg_addr); hpriv->main_irq_mask_addr);
else else
writelfl(~HC_MAIN_MASKED_IRQS, writelfl(~HC_MAIN_MASKED_IRQS,
hpriv->main_mask_reg_addr); hpriv->main_irq_mask_addr);
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x " VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
"PCI int cause/mask=0x%08x/0x%08x\n", "PCI int cause/mask=0x%08x/0x%08x\n",
readl(hpriv->main_cause_reg_addr), readl(hpriv->main_irq_cause_addr),
readl(hpriv->main_mask_reg_addr), readl(hpriv->main_irq_mask_addr),
readl(mmio + hpriv->irq_cause_ofs), readl(mmio + hpriv->irq_cause_ofs),
readl(mmio + hpriv->irq_mask_ofs)); readl(mmio + hpriv->irq_mask_ofs));
} else { } else {
writelfl(~HC_MAIN_MASKED_IRQS_SOC, writelfl(~HC_MAIN_MASKED_IRQS_SOC,
hpriv->main_mask_reg_addr); hpriv->main_irq_mask_addr);
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n", VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
readl(hpriv->main_cause_reg_addr), readl(hpriv->main_irq_cause_addr),
readl(hpriv->main_mask_reg_addr)); readl(hpriv->main_irq_mask_addr));
} }
done: done:
return rc; return rc;