diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 21:32:01 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-28 21:32:01 -0400 |
commit | 5615ca7906aefbdc3318604c89db5931d0a25910 (patch) | |
tree | c34bcc7e314f49005ad88ac84c908128729c0329 /drivers/scsi | |
parent | 7a9f8f93d2dad38f30fbc79d8a1e6517373aa4b6 (diff) | |
parent | 9dfb7808fb05643b0d06df7411b94d9546696bf1 (diff) |
Merge branch 'upstream'
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/ch.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lasi700.c | 6 | ||||
-rw-r--r-- | drivers/scsi/libata-scsi.c | 786 | ||||
-rw-r--r-- | drivers/scsi/libata.h | 3 | ||||
-rw-r--r-- | drivers/scsi/osst.c | 2 | ||||
-rw-r--r-- | drivers/scsi/pdc_adma.c | 26 | ||||
-rw-r--r-- | drivers/scsi/sata_promise.c | 4 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 10 | ||||
-rw-r--r-- | drivers/scsi/st.c | 2 | ||||
-rw-r--r-- | drivers/scsi/zalon.c | 4 |
10 files changed, 687 insertions, 158 deletions
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index da6e51c7fe6..540147cb51c 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -936,7 +936,7 @@ static int ch_probe(struct device *dev) if (init) ch_init_elem(ch); - class_device_create(ch_sysfs_class, + class_device_create(ch_sysfs_class, NULL, MKDEV(SCSI_CHANGER_MAJOR,ch->minor), dev, "s%s", ch->name); diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4cbb6187cc4..459a4daebec 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(parisc, lasi700_ids); static int __init lasi700_probe(struct parisc_device *dev) { - unsigned long base = dev->hpa + LASI_SCSI_CORE_OFFSET; + unsigned long base = dev->hpa.start + LASI_SCSI_CORE_OFFSET; struct NCR_700_Host_Parameters *hostdata; struct Scsi_Host *host; @@ -125,8 +125,6 @@ lasi700_probe(struct parisc_device *dev) hostdata->dmode_extra = DMODE_FC2; } - NCR_700_set_mem_mapped(hostdata); - host = NCR_700_detect(&lasi700_template, hostdata, &dev->dev); if (!host) goto out_kfree; @@ -168,7 +166,7 @@ lasi700_driver_remove(struct parisc_device *dev) } static struct parisc_driver lasi700_driver = { - .name = "Lasi SCSI", + .name = "lasi_scsi", .id_table = lasi700_ids, .probe = lasi700_probe, .remove = __devexit_p(lasi700_driver_remove), diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index a68c0341dc8..69058510f43 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -40,14 +40,56 @@ #include "scsi.h" #include <scsi/scsi_host.h> #include <linux/libata.h> +#include <linux/hdreg.h> #include <asm/uaccess.h> #include "libata.h" +#define SECTOR_SIZE 512 + typedef unsigned int (*ata_xlat_func_t)(struct ata_queued_cmd *qc, const u8 *scsicmd); static struct ata_device * ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev); +#define RW_RECOVERY_MPAGE 0x1 +#define RW_RECOVERY_MPAGE_LEN 12 +#define CACHE_MPAGE 0x8 +#define CACHE_MPAGE_LEN 20 +#define CONTROL_MPAGE 0xa +#define CONTROL_MPAGE_LEN 12 +#define ALL_MPAGES 0x3f +#define ALL_SUB_MPAGES 0xff + + +static const u8 def_rw_recovery_mpage[] = { + RW_RECOVERY_MPAGE, + RW_RECOVERY_MPAGE_LEN - 2, + (1 << 7) | /* AWRE, sat-r06 say it shall be 0 */ + (1 << 6), /* ARRE (auto read reallocation) */ + 0, /* read retry count */ + 0, 0, 0, 0, + 0, /* write retry count */ + 0, 0, 0 +}; + +static const u8 def_cache_mpage[CACHE_MPAGE_LEN] = { + CACHE_MPAGE, + CACHE_MPAGE_LEN - 2, + 0, /* contains WCE, needs to be 0 for logic */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, /* contains DRA, needs to be 0 for logic */ + 0, 0, 0, 0, 0, 0, 0 +}; + +static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { + CONTROL_MPAGE, + CONTROL_MPAGE_LEN - 2, + 2, /* DSENSE=0, GLTSD=1 */ + 0, /* [QAM+QERR may be 1, see 05-359r1] */ + 0, 0, 0, 0, 0xff, 0xff, + 0, 30 /* extended self test time, see 05-359r1 */ +}; + static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) @@ -86,6 +128,150 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev, return 0; } +/** + * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl + * @dev: Device to whom we are issuing command + * @arg: User provided data for issuing command + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ + +int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) +{ + int rc = 0; + u8 scsi_cmd[MAX_COMMAND_SIZE]; + u8 args[4], *argbuf = NULL; + int argsize = 0; + struct scsi_request *sreq; + + if (NULL == (void *)arg) + return -EINVAL; + + if (copy_from_user(args, arg, sizeof(args))) + return -EFAULT; + + sreq = scsi_allocate_request(scsidev, GFP_KERNEL); + if (!sreq) + return -EINTR; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + + if (args[3]) { + argsize = SECTOR_SIZE * args[3]; + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) { + rc = -ENOMEM; + goto error; + } + + scsi_cmd[1] = (4 << 1); /* PIO Data-in */ + scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev, + block count in sector count field */ + sreq->sr_data_direction = DMA_FROM_DEVICE; + } else { + scsi_cmd[1] = (3 << 1); /* Non-data */ + /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + sreq->sr_data_direction = DMA_NONE; + } + + scsi_cmd[0] = ATA_16; + + scsi_cmd[4] = args[2]; + if (args[0] == WIN_SMART) { /* hack -- ide driver does this too... */ + scsi_cmd[6] = args[3]; + scsi_cmd[8] = args[1]; + scsi_cmd[10] = 0x4f; + scsi_cmd[12] = 0xc2; + } else { + scsi_cmd[6] = args[1]; + } + scsi_cmd[14] = args[0]; + + /* Good values for timeout and retries? Values below + from scsi_ioctl_send_command() for default case... */ + scsi_wait_req(sreq, scsi_cmd, argbuf, argsize, (10*HZ), 5); + + if (sreq->sr_result) { + rc = -EIO; + goto error; + } + + /* Need code to retrieve data from check condition? */ + + if ((argbuf) + && copy_to_user((void *)(arg + sizeof(args)), argbuf, argsize)) + rc = -EFAULT; +error: + scsi_release_request(sreq); + + if (argbuf) + kfree(argbuf); + + return rc; +} + +/** + * ata_task_ioctl - Handler for HDIO_DRIVE_TASK ioctl + * @dev: Device to whom we are issuing command + * @arg: User provided data for issuing command + * + * LOCKING: + * Defined by the SCSI layer. We don't really care. + * + * RETURNS: + * Zero on success, negative errno on error. + */ +int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg) +{ + int rc = 0; + u8 scsi_cmd[MAX_COMMAND_SIZE]; + u8 args[7]; + struct scsi_request *sreq; + + if (NULL == (void *)arg) + return -EINVAL; + + if (copy_from_user(args, arg, sizeof(args))) + return -EFAULT; + + memset(scsi_cmd, 0, sizeof(scsi_cmd)); + scsi_cmd[0] = ATA_16; + scsi_cmd[1] = (3 << 1); /* Non-data */ + /* scsi_cmd[2] is already 0 -- no off.line, cc, or data xfer */ + scsi_cmd[4] = args[1]; + scsi_cmd[6] = args[2]; + scsi_cmd[8] = args[3]; + scsi_cmd[10] = args[4]; + scsi_cmd[12] = args[5]; + scsi_cmd[14] = args[0]; + + sreq = scsi_allocate_request(scsidev, GFP_KERNEL); + if (!sreq) { + rc = -EINTR; + goto error; + } + + sreq->sr_data_direction = DMA_NONE; + /* Good values for timeout and retries? Values below + from scsi_ioctl_send_command() for default case... */ + scsi_wait_req(sreq, scsi_cmd, NULL, 0, (10*HZ), 5); + + if (sreq->sr_result) { + rc = -EIO; + goto error; + } + + /* Need code to retrieve data from check condition? */ + +error: + scsi_release_request(sreq); + return rc; +} + int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) { struct ata_port *ap; @@ -115,6 +301,16 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg) return -EINVAL; return 0; + case HDIO_DRIVE_CMD: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ata_cmd_ioctl(scsidev, arg); + + case HDIO_DRIVE_TASK: + if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) + return -EACCES; + return ata_task_ioctl(scsidev, arg); + default: rc = -ENOTTY; break; @@ -173,23 +369,70 @@ struct ata_queued_cmd *ata_scsi_qc_new(struct ata_port *ap, } /** + * ata_dump_status - user friendly display of error info + * @id: id of the port in question + * @tf: ptr to filled out taskfile + * + * Decode and dump the ATA error/status registers for the user so + * that they have some idea what really happened at the non + * make-believe layer. + * + * LOCKING: + * inherited from caller + */ +void ata_dump_status(unsigned id, struct ata_taskfile *tf) +{ + u8 stat = tf->command, err = tf->feature; + + printk(KERN_WARNING "ata%u: status=0x%02x { ", id, stat); + if (stat & ATA_BUSY) { + printk("Busy }\n"); /* Data is not valid in this case */ + } else { + if (stat & 0x40) printk("DriveReady "); + if (stat & 0x20) printk("DeviceFault "); + if (stat & 0x10) printk("SeekComplete "); + if (stat & 0x08) printk("DataRequest "); + if (stat & 0x04) printk("CorrectedError "); + if (stat & 0x02) printk("Index "); + if (stat & 0x01) printk("Error "); + printk("}\n"); + + if (err) { + printk(KERN_WARNING "ata%u: error=0x%02x { ", id, err); + if (err & 0x04) printk("DriveStatusError "); + if (err & 0x80) { + if (err & 0x04) printk("BadCRC "); + else printk("Sector "); + } + if (err & 0x40) printk("UncorrectableError "); + if (err & 0x10) printk("SectorIdNotFound "); + if (err & 0x02) printk("TrackZeroNotFound "); + if (err & 0x01) printk("AddrMarkNotFound "); + printk("}\n"); + } + } +} + +/** * ata_to_sense_error - convert ATA error to SCSI error - * @qc: Command that we are erroring out * @drv_stat: value contained in ATA status register + * @drv_err: value contained in ATA error register + * @sk: the sense key we'll fill out + * @asc: the additional sense code we'll fill out + * @ascq: the additional sense code qualifier we'll fill out * - * Converts an ATA error into a SCSI error. While we are at it - * we decode and dump the ATA error for the user so that they - * have some idea what really happened at the non make-believe - * layer. + * Converts an ATA error into a SCSI error. Fill out pointers to + * SK, ASC, and ASCQ bytes for later use in fixed or descriptor + * format sense blocks. * * LOCKING: * spin_lock_irqsave(host_set lock) */ - -void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) +void ata_to_sense_error(unsigned id, u8 drv_stat, u8 drv_err, u8 *sk, u8 *asc, + u8 *ascq) { - struct scsi_cmnd *cmd = qc->scsicmd; - u8 err = 0; + int i; + /* Based on the 3ware driver translation table */ static unsigned char sense_table[][4] = { /* BBD|ECC|ID|MAR */ @@ -230,96 +473,184 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat) {0x04, RECOVERED_ERROR, 0x11, 0x00}, // Recovered ECC error Medium error, recovered {0xFF, 0xFF, 0xFF, 0xFF}, // END mark }; - int i = 0; /* * Is this an error we can process/parse */ - - if(drv_stat & ATA_ERR) - /* Read the err bits */ - err = ata_chk_err(qc->ap); - - /* Display the ATA level error info */ - - printk(KERN_WARNING "ata%u: status=0x%02x { ", qc->ap->id, drv_stat); - if(drv_stat & 0x80) - { - printk("Busy "); - err = 0; /* Data is not valid in this case */ + if (drv_stat & ATA_BUSY) { + drv_err = 0; /* Ignore the err bits, they're invalid */ } - else { - if(drv_stat & 0x40) printk("DriveReady "); - if(drv_stat & 0x20) printk("DeviceFault "); - if(drv_stat & 0x10) printk("SeekComplete "); - if(drv_stat & 0x08) printk("DataRequest "); - if(drv_stat & 0x04) printk("CorrectedError "); - if(drv_stat & 0x02) printk("Index "); - if(drv_stat & 0x01) printk("Error "); + + if (drv_err) { + /* Look for drv_err */ + for (i = 0; sense_table[i][0] != 0xFF; i++) { + /* Look for best matches first */ + if ((sense_table[i][0] & drv_err) == + sense_table[i][0]) { + *sk = sense_table[i][1]; + *asc = sense_table[i][2]; + *ascq = sense_table[i][3]; + goto translate_done; + } + } + /* No immediate match */ + printk(KERN_WARNING "ata%u: no sense translation for " + "error 0x%02x\n", id, drv_err); } - printk("}\n"); - - if(err) - { - printk(KERN_WARNING "ata%u: error=0x%02x { ", qc->ap->id, err); - if(err & 0x04) printk("DriveStatusError "); - if(err & 0x80) - { - if(err & 0x04) - printk("BadCRC "); - else - printk("Sector "); + + /* Fall back to interpreting status bits */ + for (i = 0; stat_table[i][0] != 0xFF; i++) { + if (stat_table[i][0] & drv_stat) { + *sk = stat_table[i][1]; + *asc = stat_table[i][2]; + *ascq = stat_table[i][3]; + goto translate_done; } - if(err & 0x40) printk("UncorrectableError "); - if(err & 0x10) printk("SectorIdNotFound "); - if(err & 0x02) printk("TrackZeroNotFound "); - if(err & 0x01) printk("AddrMarkNotFound "); - printk("}\n"); + } + /* No error? Undecoded? */ + printk(KERN_WARNING "ata%u: no sense translation for status: 0x%02x\n", + id, drv_stat); - /* Should we dump sector info here too ?? */ + /* For our last chance pick, use medium read error because + * it's much more common than an ATA drive telling you a write + * has failed. + */ + *sk = MEDIUM_ERROR; + *asc = 0x11; /* "unrecovered read error" */ + *ascq = 0x04; /* "auto-reallocation failed" */ + + translate_done: + printk(KERN_ERR "ata%u: translated ATA stat/err 0x%02x/%02x to " + "SCSI SK/ASC/ASCQ 0x%x/%02x/%02x\n", id, drv_stat, drv_err, + *sk, *asc, *ascq); + return; +} + +/* + * ata_gen_ata_desc_sense - Generate check condition sense block. + * @qc: Command that completed. + * + * This function is specific to the ATA descriptor format sense + * block specified for the ATA pass through commands. Regardless + * of whether the command errored or not, return a sense + * block. Copy all controller registers into the sense + * block. Clear sense key, ASC & ASCQ if there is no error. + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + */ +void ata_gen_ata_desc_sense(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_taskfile *tf = &qc->tf; + unsigned char *sb = cmd->sense_buffer; + unsigned char *desc = sb + 8; + + memset(sb, 0, SCSI_SENSE_BUFFERSIZE); + + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; + + /* + * Read the controller registers. + */ + assert(NULL != qc->ap->ops->tf_read); + qc->ap->ops->tf_read(qc->ap, tf); + + /* + * Use ata_to_sense_error() to map status register bits + * onto sense key, asc & ascq. + */ + if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + &sb[1], &sb[2], &sb[3]); + sb[1] &= 0x0f; } + /* + * Sense data is current and format is descriptor. + */ + sb[0] = 0x72; - /* Look for err */ - while(sense_table[i][0] != 0xFF) - { - /* Look for best matches first */ - if((sense_table[i][0] & err) == sense_table[i][0]) - { - ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */, - sense_table[i][2] /* asc */, - sense_table[i][3] /* ascq */ ); - return; - } - i++; + desc[0] = 0x09; + + /* + * Set length of additional sense data. + * Since we only populate descriptor 0, the total + * length is the same (fixed) length as descriptor 0. + */ + desc[1] = sb[7] = 14; + + /* + * Copy registers into sense buffer. + */ + desc[2] = 0x00; + desc[3] = tf->feature; /* == error reg */ + desc[5] = tf->nsect; + desc[7] = tf->lbal; + desc[9] = tf->lbam; + desc[11] = tf->lbah; + desc[12] = tf->device; + desc[13] = tf->command; /* == status reg */ + + /* + * Fill in Extend bit, and the high order bytes + * if applicable. + */ + if (tf->flags & ATA_TFLAG_LBA48) { + desc[2] |= 0x01; + desc[4] = tf->hob_nsect; + desc[6] = tf->hob_lbal; + desc[8] = tf->hob_lbam; + desc[10] = tf->hob_lbah; } - /* No immediate match */ - if(err) - printk(KERN_DEBUG "ata%u: no sense translation for 0x%02x\n", qc->ap->id, err); +} - i = 0; - /* Fall back to interpreting status bits */ - while(stat_table[i][0] != 0xFF) - { - if(stat_table[i][0] & drv_stat) - { - ata_scsi_set_sense(cmd, sense_table[i][1] /* sk */, - sense_table[i][2] /* asc */, - sense_table[i][3] /* ascq */ ); - return; - } - i++; +/** + * ata_gen_fixed_sense - generate a SCSI fixed sense block + * @qc: Command that we are erroring out + * + * Leverage ata_to_sense_error() to give us the codes. Fit our + * LBA in here if there's room. + * + * LOCKING: + * inherited from caller + */ +void ata_gen_fixed_sense(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *cmd = qc->scsicmd; + struct ata_taskfile *tf = &qc->tf; + unsigned char *sb = cmd->sense_buffer; + + memset(sb, 0, SCSI_SENSE_BUFFERSIZE); + + cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION; + + /* + * Read the controller registers. + */ + assert(NULL != qc->ap->ops->tf_read); + qc->ap->ops->tf_read(qc->ap, tf); + + /* + * Use ata_to_sense_error() to map status register bits + * onto sense key, asc & ascq. + */ + if (unlikely(tf->command & (ATA_BUSY | ATA_DF | ATA_ERR | ATA_DRQ))) { + ata_to_sense_error(qc->ap->id, tf->command, tf->feature, + &sb[2], &sb[12], &sb[13]); + sb[2] &= 0x0f; } - /* No error ?? */ - printk(KERN_ERR "ata%u: called with no error (%02X)!\n", qc->ap->id, drv_stat); - /* additional-sense-code[-qualifier] */ - if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0x11, 0x4); - /* "unrecovered read error" */ - } else { - ata_scsi_set_sense(cmd, MEDIUM_ERROR, 0xc, 0x2); - /* "write error - auto-reallocation failed" */ + sb[0] = 0x70; + sb[7] = 0x0a; + + if (tf->flags & ATA_TFLAG_LBA && !(tf->flags & ATA_TFLAG_LBA48)) { + /* A small (28b) LBA will fit in the 32b info field */ + sb[0] |= 0x80; /* set valid bit */ + sb[3] = tf->device & 0x0f; + sb[4] = tf->lbah; + sb[5] = tf->lbam; + sb[6] = tf->lbal; } } @@ -881,11 +1212,36 @@ nothing_to_do: static int ata_scsi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) { struct scsi_cmnd *cmd = qc->scsicmd; + int need_sense = drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ); + + /* For ATA pass thru (SAT) commands, generate a sense block if + * user mandated it or if there's an error. Note that if we + * generate because the user forced us to, a check condition + * is generated and the ATA register values are returned + * whether the command completed successfully or not. If there + * was no error, SK, ASC and ASCQ will all be zero. + */ + if (((cmd->cmnd[0] == ATA_16) || (cmd->cmnd[0] == ATA_12)) && + ((cmd->cmnd[2] & 0x20) || need_sense)) { + ata_gen_ata_desc_sense(qc); + } else { + if (!need_sense) { + cmd->result = SAM_STAT_GOOD; + } else { + /* TODO: decide which descriptor format to use + * for 48b LBA devices and call that here + * instead of the fixed desc, which is only + * good for smaller LBA (and maybe CHS?) + * devices. + */ + ata_gen_fixed_sense(qc); + } + } - if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) - ata_to_sense_error(qc, drv_stat); - else - cmd->result = SAM_STAT_GOOD; + if (need_sense) { + /* The ata_gen_..._sense routines fill in tf */ + ata_dump_status(qc->ap->id, &qc->tf); + } qc->scsidone(cmd); @@ -1276,13 +1632,9 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last, static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, const u8 *last) { - u8 page[] = { - 0x8, /* page code */ - 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 */ - }; + u8 page[CACHE_MPAGE_LEN]; + memcpy(page, def_cache_mpage, sizeof(page)); if (ata_id_wcache_enabled(id)) page[2] |= (1 << 2); /* write cache enable */ if (!ata_id_rahead_enabled(id)) @@ -1306,15 +1658,9 @@ static unsigned int ata_msense_caching(u16 *id, u8 **ptr_io, static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) { - const u8 page[] = {0xa, 0xa, 6, 0, 0, 0, 0, 0, 0xff, 0xff, 0, 30}; - - /* byte 2: set the descriptor format sense data bit (bit 2) - * since we need to support returning this format for SAT - * commands and any SCSI commands against a 48b LBA device. - */ - - ata_msense_push(ptr_io, last, page, sizeof(page)); - return sizeof(page); + ata_msense_push(ptr_io, last, def_control_mpage, + sizeof(def_control_mpage)); + return sizeof(def_control_mpage); } /** @@ -1331,15 +1677,10 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last) 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_msense_push(ptr_io, last, def_rw_recovery_mpage, + sizeof(def_rw_recovery_mpage)); + return sizeof(def_rw_recovery_mpage); } /** @@ -1348,7 +1689,9 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. * @buflen: Response buffer length. * - * Simulate MODE SENSE commands. + * Simulate MODE SENSE commands. Assume this is invoked for direct + * access devices (e.g. disks) only. There should be no block + * descriptor for other device types. * * LOCKING: * spin_lock_irqsave(host_set lock) @@ -1358,15 +1701,22 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen) { u8 *scsicmd = args->cmd->cmnd, *p, *last; - unsigned int page_control, six_byte, output_len; + const u8 sat_blk_desc[] = { + 0, 0, 0, 0, /* number of blocks: sat unspecified */ + 0, + 0, 0x2, 0x0 /* block length: 512 bytes */ + }; + u8 pg, spg; + unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; VPRINTK("ENTER\n"); six_byte = (scsicmd[0] == MODE_SENSE); - - /* we only support saved and current values (which we treat - * in the same manner) + ebd = !(scsicmd[1] & 0x8); /* dbd bit inverted == edb */ + /* + * LLBA bit in msense(10) ignored (compliant) */ + page_control = scsicmd[2] >> 6; switch (page_control) { case 0: /* current */ @@ -1379,29 +1729,42 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, goto invalid_fld; } - if (six_byte) - output_len = 4; - else - output_len = 8; + if (six_byte) { + output_len = 4 + (ebd ? 8 : 0); + alloc_len = scsicmd[4]; + } else { + 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 + buflen - 1; + last = rbuf + minlen - 1; + + pg = scsicmd[2] & 0x3f; + spg = scsicmd[3]; + /* + * No mode subpages supported (yet) but asking for _all_ + * subpages may be valid + */ + if (spg && (spg != ALL_SUB_MPAGES)) + goto invalid_fld; - switch(scsicmd[2] & 0x3f) { - case 0x01: /* r/w error recovery */ + switch(pg) { + case RW_RECOVERY_MPAGE: output_len += ata_msense_rw_recovery(&p, last); break; - case 0x08: /* caching */ + case CACHE_MPAGE: output_len += ata_msense_caching(args->id, &p, last); break; - case 0x0a: { /* control mode */ + case CONTROL_MPAGE: { output_len += ata_msense_ctl_mode(&p, last); break; } - case 0x3f: /* all pages */ + case ALL_MPAGES: output_len += ata_msense_rw_recovery(&p, last); output_len += ata_msense_caching(args->id, &p, last); output_len += ata_msense_ctl_mode(&p, last); @@ -1411,15 +1774,31 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, goto invalid_fld; } + if (minlen < 1) + return 0; if (six_byte) { output_len--; rbuf[0] = output_len; + if (ebd) { + if (minlen > 3) + rbuf[3] = sizeof(sat_blk_desc); + if (minlen > 11) + memcpy(rbuf + 4, sat_blk_desc, + sizeof(sat_blk_desc)); + } } else { output_len -= 2; rbuf[0] = output_len >> 8; - rbuf[1] = output_len; + if (minlen > 1) + rbuf[1] = output_len; + if (ebd) { + if (minlen > 7) + rbuf[7] = sizeof(sat_blk_desc); + if (minlen > 15) + memcpy(rbuf + 8, sat_blk_desc, + sizeof(sat_blk_desc)); + } } - return 0; invalid_fld: @@ -1633,7 +2012,12 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat) VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat); if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ))) - ata_to_sense_error(qc, drv_stat); + /* FIXME: not quite right; we don't want the + * translation of taskfile registers into + * a sense descriptors, since that's only + * correct for ATA, not ATAPI + */ + ata_gen_ata_desc_sense(qc); else if (unlikely(drv_stat & ATA_ERR)) { DPRINTK("request check condition\n"); @@ -1792,6 +2176,143 @@ ata_scsi_find_dev(struct ata_port *ap, const struct scsi_device *scsidev) return dev; } +/* + * ata_scsi_map_proto - Map pass-thru protocol value to taskfile value. + * @byte1: Byte 1 from pass-thru CDB. + * + * RETURNS: + * ATA_PROT_UNKNOWN if mapping failed/unimplemented, protocol otherwise. + */ +static u8 +ata_scsi_map_proto(u8 byte1) +{ + switch((byte1 & 0x1e) >> 1) { + case 3: /* Non-data */ + return ATA_PROT_NODATA; + + case 6: /* DMA */ + return ATA_PROT_DMA; + + case 4: /* PIO Data-in */ + case 5: /* PIO Data-out */ + if (byte1 & 0xe0) { + return ATA_PROT_PIO_MULT; + } + return ATA_PROT_PIO; + + case 10: /* Device Reset */ + case 0: /* Hard Reset */ + case 1: /* SRST */ + case 2: /* Bus Idle */ + case 7: /* Packet */ + case 8: /* DMA Queued */ + case 9: /* Device Diagnostic */ + case 11: /* UDMA Data-in */ + case 12: /* UDMA Data-Out */ + case 13: /* FPDMA */ + default: /* Reserved */ + break; + } + + return ATA_PROT_UNKNOWN; +} + +/** + * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile + * @qc: command structure to be initialized + * @cmd: SCSI command to convert + * + * Handles either 12 or 16-byte versions of the CDB. + * + * RETURNS: + * Zero on success, non-zero on failure. + */ +static unsigned int +ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) +{ + struct ata_taskfile *tf = &(qc->tf); + struct scsi_cmnd *cmd = qc->scsicmd; + + if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) + return 1; + + /* + * 12 and 16 byte CDBs use different offsets to + * provide the various register values. + */ + if (scsicmd[0] == ATA_16) { + /* + * 16-byte CDB - may contain extended commands. + * + * If that is the case, copy the upper byte register values. + */ + if (scsicmd[1] & 0x01) { + tf->hob_feature = scsicmd[3]; + tf->hob_nsect = scsicmd[5]; + tf->hob_lbal = scsicmd[7]; + tf->hob_lbam = scsicmd[9]; + tf->hob_lbah = scsicmd[11]; + tf->flags |= ATA_TFLAG_LBA48; + } else + tf->flags &= ~ATA_TFLAG_LBA48; + + /* + * Always copy low byte, device and command registers. + */ + tf->feature = scsicmd[4]; + tf->nsect = scsicmd[6]; + tf->lbal = scsicmd[8]; + tf->lbam = scsicmd[10]; + tf->lbah = scsicmd[12]; + tf->device = scsicmd[13]; + tf->command = scsicmd[14]; + } else { + /* + * 12-byte CDB - incapable of extended commands. + */ + tf->flags &= ~ATA_TFLAG_LBA48; + + tf->feature = scsicmd[3]; + tf->nsect = scsicmd[4]; + tf->lbal = scsicmd[5]; + tf->lbam = scsicmd[6]; + tf->lbah = scsicmd[7]; + tf->device = scsicmd[8]; + tf->command = scsicmd[9]; + } + + /* + * Filter SET_FEATURES - XFER MODE command -- otherwise, + * SET_FEATURES - XFER MODE must be preceded/succeeded + * by an update to hardware-specific registers for each + * controller (i.e. the reason for ->set_piomode(), + * ->set_dmamode(), and ->post_set_mode() hooks). + */ + if ((tf->command == ATA_CMD_SET_FEATURES) + && (tf->feature == SETFEATURES_XFER)) + return 1; + + /* + * Set flags so that all registers will be written, + * and pass on write indication (used for PIO/DMA + * setup.) + */ + tf->flags |= (ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE); + + if (cmd->sc_data_direction == DMA_TO_DEVICE) + tf->flags |= ATA_TFLAG_WRITE; + + /* + * Set transfer length. + * + * TODO: find out if we need to do more here to + * cover scatter/gather case. + */ + qc->nsect = cmd->bufflen / ATA_SECT_SIZE; + + return 0; +} + /** * ata_get_xlat_func - check if SCSI to ATA translation is possible * @dev: ATA device @@ -1824,6 +2345,11 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) case VERIFY: case VERIFY_16: return ata_scsi_verify_xlat; + + case ATA_12: + case ATA_16: + return ata_scsi_pass_thru; + case START_STOP: return ata_scsi_start_stop_xlat; } @@ -1982,7 +2508,7 @@ void ata_scsi_simulate(u16 *id, ata_scsi_rbuf_fill(&args, ata_scsiop_report_luns); break; - /* mandantory commands we haven't implemented yet */ + /* mandatory commands we haven't implemented yet */ case REQUEST_SENSE: /* all other commands */ diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h index 3d60190584b..65c264b9113 100644 --- a/drivers/scsi/libata.h +++ b/drivers/scsi/libata.h @@ -50,13 +50,14 @@ extern void ata_dev_select(struct ata_port *ap, unsigned int device, unsigned int wait, unsigned int can_sleep); extern void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf); extern void swap_buf_le16(u16 *buf, unsigned int buf_words); +extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); +extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); /* libata-scsi.c */ extern void atapi_request_sense(struct ata_port *ap, struct ata_device *dev, struct scsi_cmnd *cmd); extern void ata_scsi_scan_host(struct ata_port *ap); -extern void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat); extern int ata_scsi_error(struct Scsi_Host *host); extern unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index af1133104b3..172839fce0e 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5629,7 +5629,7 @@ static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape * if (!osst_sysfs_valid) return; - osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name); + osst_class_member = class_device_create(osst_sysfs_class, NULL, dev, device, "%s", name); if (IS_ERR(osst_class_member)) { printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name); return; diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 85ec5b1d7aa..eebb3eb2025 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -46,7 +46,7 @@ #include <linux/libata.h> #define DRV_NAME "pdc_adma" -#define DRV_VERSION "0.01" +#define DRV_VERSION "0.03" /* macro to calculate base address for ATA regs */ #define ADMA_ATA_REGS(base,port_no) ((base) + ((port_no) * 0x40)) @@ -79,7 +79,6 @@ enum { aNIEN = (1 << 8), /* irq mask: 1==masked */ aGO = (1 << 7), /* packet trigger ("Go!") */ aRSTADM = (1 << 5), /* ADMA logic reset */ - aRSTA = (1 << 2), /* ATA hard reset */ aPIOMD4 = 0x0003, /* PIO mode 4 */ /* ADMA_STATUS register bits */ @@ -452,24 +451,25 @@ static inline unsigned int adma_intr_pkt(struct ata_host_set *host_set) struct adma_port_priv *pp; struct ata_queued_cmd *qc; void __iomem *chan = ADMA_REGS(mmio_base, port_no); - u8 drv_stat, status = readb(chan + ADMA_STATUS); + u8 drv_stat = 0, status = readb(chan + ADMA_STATUS); if (status == 0) continue; handled = 1; adma_enter_reg_mode(ap); - if ((ap->flags & ATA_FLAG_PORT_DISABLED)) + if (ap->flags & (ATA_FLAG_PORT_DISABLED | ATA_FLAG_NOINTR)) continue; pp = ap->private_data; if (!pp || pp->state != adma_state_pkt) continue; qc = ata_qc_from_tag(ap, ap->active_tag); - drv_stat = 0; - if ((status & (aPERR | aPSD | aUIRQ))) - drv_stat = ATA_ERR; - else if (pp->pkt[0] != cDONE) - drv_stat = ATA_ERR; - ata_qc_complete(qc, drv_stat); + if (qc && (!(qc->tf.ctl & ATA_NIEN))) { + if ((status & (aPERR | aPSD | aUIRQ))) + drv_stat = ATA_ERR; + else if (pp->pkt[0] != cDONE) + drv_stat = ATA_ERR; + ata_qc_complete(qc, drv_stat); + } } return handled; } @@ -561,15 +561,15 @@ static int adma_port_start(struct ata_port *ap) if ((pp->pkt_dma & 7) != 0) { printk("bad alignment for pp->pkt_dma: %08x\n", (u32)pp->pkt_dma); - goto err_out_kfree2; + dma_free_coherent(dev, ADMA_PKT_BYTES, + pp->pkt, pp->pkt_dma); + goto err_out_kfree; } memset(pp->pkt, 0, ADMA_PKT_BYTES); ap->private_data = pp; adma_reinit_engine(ap); return 0; -err_out_kfree2: - kfree(pp); err_out_kfree: kfree(pp); err_out: diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index eee93b0016d..63911f16b6e 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -195,6 +195,8 @@ static struct ata_port_info pdc_port_info[] = { static struct pci_device_id pdc_ata_pci_tbl[] = { { PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3570, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -207,6 +209,8 @@ static struct pci_device_id pdc_ata_pci_tbl[] = { board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3d75, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_2037x }, + { PCI_VENDOR_ID_PROMISE, 0x3d73, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_2037x }, { PCI_VENDOR_ID_PROMISE, 0x3318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_20319 }, diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index fd56b7ec88b..861e51375d7 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -104,8 +104,8 @@ static int sg_allow_dio = SG_ALLOW_DIO_DEF; #define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ -static int sg_add(struct class_device *); -static void sg_remove(struct class_device *); +static int sg_add(struct class_device *, struct class_interface *); +static void sg_remove(struct class_device *, struct class_interface *); static Scsi_Request *dummy_cmdp; /* only used for sizeof */ @@ -1506,7 +1506,7 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) } static int -sg_add(struct class_device *cl_dev) +sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); struct gendisk *disk; @@ -1550,7 +1550,7 @@ sg_add(struct class_device *cl_dev) if (sg_sysfs_valid) { struct class_device * sg_class_member; - sg_class_member = class_device_create(sg_sysfs_class, + sg_class_member = class_device_create(sg_sysfs_class, NULL, MKDEV(SCSI_GENERIC_MAJOR, k), cl_dev->dev, "%s", disk->disk_name); @@ -1582,7 +1582,7 @@ out: } static void -sg_remove(struct class_device *cl_dev) +sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); Sg_device *sdp = NULL; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 927d700f007..5eb54d8019b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4377,7 +4377,7 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) snprintf(name, 10, "%s%s%s", rew ? "n" : "", STp->disk->disk_name, st_formats[i]); st_class_member = - class_device_create(st_sysfs_class, + class_device_create(st_sysfs_class, NULL, MKDEV(SCSI_TAPE_MAJOR, TAPE_MINOR(dev_num, mode, rew)), &STp->device->sdev_gendev, "%s", name); diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index 5a51051e31f..b131432c677 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -88,7 +88,7 @@ zalon_probe(struct parisc_device *dev) struct gsc_irq gsc_irq; u32 zalon_vers; int error = -ENODEV; - void __iomem *zalon = ioremap(dev->hpa, 4096); + void __iomem *zalon = ioremap(dev->hpa.start, 4096); void __iomem *io_port = zalon + GSC_SCSI_ZALON_OFFSET; static int unit = 0; struct Scsi_Host *host; @@ -127,7 +127,7 @@ zalon_probe(struct parisc_device *dev) device.chip = zalon720_chip; device.host_id = 7; device.dev = &dev->dev; - device.slot.base = dev->hpa + GSC_SCSI_ZALON_OFFSET; + device.slot.base = dev->hpa.start + GSC_SCSI_ZALON_OFFSET; device.slot.base_v = io_port; device.slot.irq = dev->irq; device.differential = 2; |