Commit 277c7105 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://gkernel.bkbits.net/libata-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents fadf035a 043ea303
...@@ -818,7 +818,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device) ...@@ -818,7 +818,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
* @dev: Device whose IDENTIFY DEVICE results we will examine * @dev: Device whose IDENTIFY DEVICE results we will examine
* @s: string into which data is output * @s: string into which data is output
* @ofs: offset into identify device page * @ofs: offset into identify device page
* @len: length of string to return * @len: length of string to return. must be an even number.
* *
* The strings in the IDENTIFY DEVICE page are broken up into * The strings in the IDENTIFY DEVICE page are broken up into
* 16-bit chunks. Run through the string, and output each * 16-bit chunks. Run through the string, and output each
...@@ -847,29 +847,6 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s, ...@@ -847,29 +847,6 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
} }
} }
/**
* ata_dev_parse_strings - Store useful IDENTIFY DEVICE page strings
* @dev: Device whose IDENTIFY DEVICE page info we use
*
* We store 'vendor' and 'product' strings read from the device,
* for later use in the SCSI simulator's INQUIRY data.
*
* Set these strings here, in the case of 'product', using
* data read from the ATA IDENTIFY DEVICE page.
*
* LOCKING:
* caller.
*/
static void ata_dev_parse_strings(struct ata_device *dev)
{
assert (dev->class == ATA_DEV_ATA);
memcpy(dev->vendor, "ATA ", 8);
ata_dev_id_string(dev, dev->product, ATA_ID_PROD_OFS,
sizeof(dev->product));
}
/** /**
* __ata_dev_select - Select device 0/1 on ATA bus * __ata_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate * @ap: ATA channel to manipulate
...@@ -1127,8 +1104,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ...@@ -1127,8 +1104,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
ata_dump_id(dev); ata_dump_id(dev);
ata_dev_parse_strings(dev);
/* ATA-specific feature tests */ /* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) { if (dev->class == ATA_DEV_ATA) {
if (!ata_id_is_ata(dev)) /* sanity check */ if (!ata_id_is_ata(dev)) /* sanity check */
...@@ -2346,7 +2321,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) ...@@ -2346,7 +2321,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if (cmd) { if (cmd) {
if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) { if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
if (qc->flags & ATA_QCFLAG_ATAPI) if (is_atapi_taskfile(&qc->tf))
cmd->result = SAM_STAT_CHECK_CONDITION; cmd->result = SAM_STAT_CHECK_CONDITION;
else else
ata_to_sense_error(qc); ata_to_sense_error(qc);
...@@ -2659,6 +2634,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -2659,6 +2634,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
unsigned int handled = 0; unsigned int handled = 0;
switch (qc->tf.protocol) { switch (qc->tf.protocol) {
/* BMDMA completion */
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
if (ap->flags & ATA_FLAG_MMIO) { if (ap->flags & ATA_FLAG_MMIO) {
...@@ -2677,8 +2654,16 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -2677,8 +2654,16 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
handled = 1; handled = 1;
break; break;
/* command completion, but no data xfer */
/* FIXME: a shared interrupt _will_ cause a non-data command
* to be completed prematurely, with an error.
*
* This doesn't matter right now, since we aren't sending
* non-data commands down this pipe except in development
* situations.
*/
case ATA_PROT_ATAPI: case ATA_PROT_ATAPI:
case ATA_PROT_NODATA: /* command completion, but no data xfer */ case ATA_PROT_NODATA:
status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status); DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
ata_qc_complete(qc, status); ata_qc_complete(qc, status);
...@@ -3525,3 +3510,4 @@ EXPORT_SYMBOL_GPL(ata_scsi_error); ...@@ -3525,3 +3510,4 @@ EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release); EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr); EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(ata_dev_id_string);
...@@ -498,7 +498,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, ...@@ -498,7 +498,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
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) unsigned int buflen)
{ {
const u8 hdr[] = { struct ata_device *dev = args->dev;
u8 hdr[] = {
TYPE_DISK, TYPE_DISK,
0, 0,
0x5, /* claim SPC-3 version compatibility */ 0x5, /* claim SPC-3 version compatibility */
...@@ -506,14 +508,20 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, ...@@ -506,14 +508,20 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
96 - 4 96 - 4
}; };
/* set scsi removeable (RMB) bit per ata bit */
if (ata_id_removeable(dev))
hdr[1] |= (1 << 7);
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
memcpy(rbuf, hdr, sizeof(hdr)); memcpy(rbuf, hdr, sizeof(hdr));
if (buflen > 36) { if (buflen > 36) {
memcpy(&rbuf[8], args->dev->vendor, 8); memcpy(&rbuf[8], "ATA ", 8);
memcpy(&rbuf[16], args->dev->product, 16); ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
memcpy(&rbuf[32], DRV_VERSION, 4); ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
if (rbuf[32] == 0 || rbuf[32] == ' ')
memcpy(&rbuf[32], "n/a ", 4);
} }
if (buflen > 63) { if (buflen > 63) {
...@@ -687,9 +695,17 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last, ...@@ -687,9 +695,17 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io, static unsigned int ata_msense_caching(struct ata_device *dev, u8 **ptr_io,
const u8 *last) const u8 *last)
{ {
u8 page[7] = { 0xf, 0, 0x10, 0, 0x8, 0xa, 0 }; u8 page[] = {
if (dev->flags & ATA_DFLAG_WCACHE) 0x8, /* page code */
page[6] = 0x4; 0x12, /* page length */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 zeroes */
0, 0, 0, 0, 0, 0, 0, 0 /* 8 zeroes */
};
if (ata_id_wcache_enabled(dev))
page[2] |= (1 << 2); /* write cache enable */
if (!ata_id_rahead_enabled(dev))
page[12] |= (1 << 5); /* disable read ahead */
ata_msense_push(ptr_io, last, page, sizeof(page)); ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page); return sizeof(page);
...@@ -715,6 +731,31 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) ...@@ -715,6 +731,31 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
return sizeof(page); return sizeof(page);
} }
/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @dev: Device associated with this MODE SENSE command
* @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.
*
* LOCKING:
* None.
*/
static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last)
{
const u8 page[] = {
0x1, /* page code */
0xa, /* page length */
(1 << 7) | (1 << 6), /* note auto r/w reallocation */
0, 0, 0, 0, 0, 0, 0, 0, 0 /* 9 zeroes */
};
ata_msense_push(ptr_io, last, page, sizeof(page));
return sizeof(page);
}
/** /**
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: Port / device / SCSI command of interest. * @args: Port / device / SCSI command of interest.
...@@ -754,6 +795,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, ...@@ -754,6 +795,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
last = rbuf + buflen - 1; last = rbuf + buflen - 1;
switch(scsicmd[2] & 0x3f) { switch(scsicmd[2] & 0x3f) {
case 0x01: /* r/w error recovery */
output_len += ata_msense_rw_recovery(&p, last);
break;
case 0x08: /* caching */ case 0x08: /* caching */
output_len += ata_msense_caching(dev, &p, last); output_len += ata_msense_caching(dev, &p, last);
break; break;
...@@ -764,6 +809,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, ...@@ -764,6 +809,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
} }
case 0x3f: /* all pages */ case 0x3f: /* all pages */
output_len += ata_msense_rw_recovery(&p, last);
output_len += ata_msense_caching(dev, &p, last); output_len += ata_msense_caching(dev, &p, last);
output_len += ata_msense_ctl_mode(&p, last); output_len += ata_msense_ctl_mode(&p, last);
break; break;
...@@ -804,20 +850,23 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, ...@@ -804,20 +850,23 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
n_sectors--; /* one off */ n_sectors--; /* ATA TotalUserSectors - 1 */
tmp = n_sectors; /* note: truncates, if lba48 */ tmp = n_sectors; /* note: truncates, if lba48 */
if (args->cmd->cmnd[0] == READ_CAPACITY) { if (args->cmd->cmnd[0] == READ_CAPACITY) {
/* sector count, 32-bit */
rbuf[0] = tmp >> (8 * 3); rbuf[0] = tmp >> (8 * 3);
rbuf[1] = tmp >> (8 * 2); rbuf[1] = tmp >> (8 * 2);
rbuf[2] = tmp >> (8 * 1); rbuf[2] = tmp >> (8 * 1);
rbuf[3] = tmp; rbuf[3] = tmp;
/* sector size */
tmp = ATA_SECT_SIZE; tmp = ATA_SECT_SIZE;
rbuf[6] = tmp >> 8; rbuf[6] = tmp >> 8;
rbuf[7] = tmp; rbuf[7] = tmp;
} else { } else {
/* sector count, 64-bit */
rbuf[2] = n_sectors >> (8 * 7); rbuf[2] = n_sectors >> (8 * 7);
rbuf[3] = n_sectors >> (8 * 6); rbuf[3] = n_sectors >> (8 * 6);
rbuf[4] = n_sectors >> (8 * 5); rbuf[4] = n_sectors >> (8 * 5);
...@@ -827,6 +876,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, ...@@ -827,6 +876,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
rbuf[8] = tmp >> (8 * 1); rbuf[8] = tmp >> (8 * 1);
rbuf[9] = tmp; rbuf[9] = tmp;
/* sector size */
tmp = ATA_SECT_SIZE; tmp = ATA_SECT_SIZE;
rbuf[12] = tmp >> 8; rbuf[12] = tmp >> 8;
rbuf[13] = tmp; rbuf[13] = tmp;
...@@ -901,8 +951,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) ...@@ -901,8 +951,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
{ {
struct scsi_cmnd *cmd = qc->scsicmd; struct scsi_cmnd *cmd = qc->scsicmd;
qc->flags |= ATA_QCFLAG_ATAPI;
qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
if (cmd->sc_data_direction == SCSI_DATA_WRITE) { if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
qc->tf.flags |= ATA_TFLAG_WRITE; qc->tf.flags |= ATA_TFLAG_WRITE;
...@@ -1106,7 +1154,11 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, ...@@ -1106,7 +1154,11 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
args.done = done; args.done = done;
switch(scsicmd[0]) { switch(scsicmd[0]) {
case TEST_UNIT_READY: /* FIXME: correct? */ /* no-op's, complete with success */
case REZERO_UNIT:
case SEEK_6:
case SEEK_10:
case TEST_UNIT_READY:
case FORMAT_UNIT: /* FIXME: correct? */ case FORMAT_UNIT: /* FIXME: correct? */
case SEND_DIAGNOSTIC: /* FIXME: correct? */ case SEND_DIAGNOSTIC: /* FIXME: correct? */
ata_scsi_rbuf_fill(&args, ata_scsiop_noop); ata_scsi_rbuf_fill(&args, ata_scsiop_noop);
......
...@@ -36,8 +36,6 @@ struct ata_scsi_args { ...@@ -36,8 +36,6 @@ struct ata_scsi_args {
}; };
/* libata-core.c */ /* libata-core.c */
extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
unsigned int ofs, unsigned int len);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev); struct ata_device *dev);
extern int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_qc_issue(struct ata_queued_cmd *qc);
......
...@@ -276,8 +276,14 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) ...@@ -276,8 +276,14 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
{ {
unsigned int n, quirks = 0; unsigned int n, quirks = 0;
const char *s = &dev->product[0]; unsigned char model_num[40];
unsigned int len = strnlen(s, sizeof(dev->product)); const char *s;
unsigned int len;
ata_dev_id_string(dev, model_num, ATA_ID_PROD_OFS,
sizeof(model_num));
s = &model_num[0];
len = strnlen(s, sizeof(model_num));
/* ATAPI specifies that empty space is blank-filled; remove blanks */ /* ATAPI specifies that empty space is blank-filled; remove blanks */
while ((len > 0) && (s[len - 1] == ' ')) while ((len > 0) && (s[len - 1] == ' '))
......
...@@ -38,6 +38,7 @@ enum { ...@@ -38,6 +38,7 @@ enum {
ATA_ID_WORDS = 256, ATA_ID_WORDS = 256,
ATA_ID_PROD_OFS = 27, ATA_ID_PROD_OFS = 27,
ATA_ID_FW_REV_OFS = 23,
ATA_ID_SERNO_OFS = 10, ATA_ID_SERNO_OFS = 10,
ATA_ID_MAJOR_VER = 80, ATA_ID_MAJOR_VER = 80,
ATA_ID_PIO_MODES = 64, ATA_ID_PIO_MODES = 64,
...@@ -103,6 +104,7 @@ enum { ...@@ -103,6 +104,7 @@ enum {
ATA_REG_IRQ = ATA_REG_NSECT, ATA_REG_IRQ = ATA_REG_NSECT,
/* ATA device commands */ /* ATA device commands */
ATA_CMD_CHK_POWER = 0xE5, /* check power mode */
ATA_CMD_EDD = 0x90, /* execute device diagnostic */ ATA_CMD_EDD = 0x90, /* execute device diagnostic */
ATA_CMD_FLUSH = 0xE7, ATA_CMD_FLUSH = 0xE7,
ATA_CMD_FLUSH_EXT = 0xEA, ATA_CMD_FLUSH_EXT = 0xEA,
...@@ -200,11 +202,14 @@ struct ata_taskfile { ...@@ -200,11 +202,14 @@ struct ata_taskfile {
}; };
#define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0) #define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0)
#define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
#define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5)) #define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
#define ata_id_has_lba48(dev) ((dev)->id[83] & (1 << 10)) #define ata_id_has_lba48(dev) ((dev)->id[83] & (1 << 10))
#define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5)) #define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5))
#define ata_id_has_pm(dev) ((dev)->id[82] & (1 << 3))
#define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 8)) #define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 8))
#define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 9)) #define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 9))
#define ata_id_removeable(dev) ((dev)->id[0] & (1 << 7))
#define ata_id_u32(dev,n) \ #define ata_id_u32(dev,n) \
(((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)])) (((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
#define ata_id_u64(dev,n) \ #define ata_id_u64(dev,n) \
...@@ -213,4 +218,10 @@ struct ata_taskfile { ...@@ -213,4 +218,10 @@ struct ata_taskfile {
((u64) dev->id[(n) + 1] << 16) | \ ((u64) dev->id[(n) + 1] << 16) | \
((u64) dev->id[(n) + 0]) ) ((u64) dev->id[(n) + 0]) )
static inline int is_atapi_taskfile(struct ata_taskfile *tf)
{
return (tf->protocol == ATA_PROT_ATAPI) ||
(tf->protocol == ATA_PROT_ATAPI_DMA);
}
#endif /* __LINUX_ATA_H__ */ #endif /* __LINUX_ATA_H__ */
...@@ -111,7 +111,6 @@ enum { ...@@ -111,7 +111,6 @@ enum {
ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */ ATA_QCFLAG_ACTIVE = (1 << 1), /* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */ ATA_QCFLAG_DMA = (1 << 2), /* data delivered via DMA */
ATA_QCFLAG_ATAPI = (1 << 3), /* is ATAPI packet command? */
ATA_QCFLAG_SG = (1 << 4), /* have s/g table? */ ATA_QCFLAG_SG = (1 << 4), /* have s/g table? */
/* various lengths of time */ /* various lengths of time */
...@@ -260,12 +259,6 @@ struct ata_device { ...@@ -260,12 +259,6 @@ struct ata_device {
unsigned int pio_mode; unsigned int pio_mode;
unsigned int udma_mode; unsigned int udma_mode;
unsigned char vendor[8]; /* space-padded, not ASCIIZ */
unsigned char product[32]; /* WARNING: shorter than
* ATAPI7 spec size, 40 ASCII
* characters
*/
/* cache info about current transfer mode */ /* cache info about current transfer mode */
u8 xfer_protocol; /* taskfile xfer protocol */ u8 xfer_protocol; /* taskfile xfer protocol */
u8 read_cmd; /* opcode to use on read */ u8 read_cmd; /* opcode to use on read */
...@@ -398,6 +391,8 @@ extern int ata_port_start (struct ata_port *ap); ...@@ -398,6 +391,8 @@ extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_fill_sg(struct ata_queued_cmd *qc); extern void ata_fill_sg(struct ata_queued_cmd *qc);
extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc); extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc); extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment