From mboxrd@z Thu Jan 1 00:00:00 1970 From: Pat LaVarre Subject: Re: [PATCH] atapi request sense work Date: 02 Jun 2004 17:53:10 -0600 Sender: linux-ide-owner@vger.kernel.org Message-ID: <1086220390.3285.2.camel@patibmrh9> References: <068F5E91-B237-11D8-819C-000393A22C62@ieee.org><1085930101.3135. 4.camel@patibmrh9> <1086019779.3144.6.camel@patibmrh9><1086134487.12245.0. camel@patibmrh9> <1086209532.8016.2.camel@patibmrh9><1086215808.16228.6.ca mel@patibmrh9> Mime-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit Return-path: Received: from email-out2.iomega.com ([147.178.1.83]:21216 "EHLO email.iomega.com") by vger.kernel.org with ESMTP id S264108AbUFBXxP (ORCPT ); Wed, 2 Jun 2004 19:53:15 -0400 In-Reply-To: <1086215808.16228.6.camel@patibmrh9> List-Id: linux-ide@vger.kernel.org To: Jeff Garzik Cc: linux-ide@vger.kernel.org I'm delighted to report also atapi_sense_pio worked when I tried it here, provided I tried it immediately after op xA1 ATA_CMD_ID_ATAPI, and provided I omitted all reference to struct ata_queued_cmd * qc. My successful dmesg were: ata_dev_identify: atapi_sense_pio ata_tf_load_pio: feat 0x0 nsect 0x0 lba 0x0 0x60 0x0 ata_tf_load_pio: device 0xA0 ata_exec: ata2: cmd 0xA0 ata_exec_command_pio: ata2: cmd 0xA0 atapi_sense_pio: send 0xC bytes of cdb atapi_sense_pio: 0x0020 = len atapi_sense_pio: sense x 6 29 00 00000000 atapi_sense_pio: sense injected without error atapi_sense_pio: EXIT Pat LaVarre P.S. The specific default choice of x60 = 96 = SCSI_SENSE_BUFFERSIZE does matter. The device I have rounds that down to x20 (32), and the code Jeff wrote accepts the rounding down and survives. But for the sake of compatibility, I also tried the elsewhere popular default of x12 (18): - u8 max = min(0xFF, SCSI_SENSE_BUFFERSIZE); + u8 max = min(0x12, SCSI_SENSE_BUFFERSIZE); Given that not-cleanly-divisible-by-four suggestion of x12 (18), my device agrees to copy in precisely that many bytes, which then leads to such trouble as: kernel: ATA: abnormal status 0x58 on port 0xE007 Rumour tells me many devices round down to x12 (18) bytes of sense data, rather than x20 (32). Either that rumour is wrong, or I've broken the source myself, or else we'll have to fix this someday. diff -urp o/include/linux/ata.h linux-2.6.7-rc2-pel/include/linux/ata.h diff -urp o/include/linux/libata.h linux-2.6.7-rc2-pel/include/linux/libata.h diff -urp o/drivers/scsi/libata-core.c linux-2.6.7-rc2-pel/drivers/scsi/libata-core.c --- o/drivers/scsi/libata-core.c 2004-05-30 08:53:41.000000000 -0600 +++ linux-2.6.7-rc2-pel/drivers/scsi/libata-core.c 2004-06-02 17:32:18.000000000 -0600 @@ -938,6 +938,77 @@ static inline void ata_dump_id(struct at } /** + * atapi_sense_pio - FIXME + */ + +static void atapi_sense_pio(struct ata_port *ap) +{ + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; + struct ata_taskfile tf; + u8 status; + u8 max = min(0xFF, SCSI_SENSE_BUFFERSIZE); + u16 len; + const u8 request_sense_cdb[16] = { + REQUEST_SENSE, 0, 0, 0, max, 0, + }; + u8 err = ata_chk_err(ap); /* fetch before ata_tf_to_host */ + + ata_tf_init(ap, &tf, 0); /* FIXME: qc->dev->devno */ + tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; + tf.protocol = ATA_PROT_ATAPI; + tf.ctl |= ATA_NIEN; + tf.lbam = max; + tf.command = ATA_CMD_PACKET; + ata_tf_to_host(ap, &tf); + + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + goto sense_not; + + status = ata_chk_status(ap); + if ((status & ATA_DRQ) == 0) + goto sense_not; + + /* FIXME: mmio-ize */ + DPRINTK("send 0x%X bytes of cdb\n", ap->host->max_cmd_len); + outsl(ap->ioaddr.data_addr, request_sense_cdb, + ap->host->max_cmd_len / 4); + + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + goto sense_not; + + status = ata_chk_status(ap); + if ((status & ATA_DRQ) == 0) + goto sense_not; + + ap->ops->tf_read(ap, &tf); + len = tf.lbam; + len |= ((u16)tf.lbah) << 8; + DPRINTK("0x%04X = len\n", len); + + if (!len || (len % 4) || (max < len)) + printk(KERN_WARNING "ata%u: surprise ATAPI length %u\n", + ap->id, len); + memset(sense, 0, sizeof(sense)); + insl(ap->ioaddr.data_addr, sense, (len + 4 - 1) / 4); + + if ((sense[0] & 0x7e) != 0x70) { + DPRINTK("sense unintelligible"); + sense[0] = 0x70; + sense[2] = err >> 4; + } else { + DPRINTK("sense x %X %02X %02X %02X%02X%02X%02X\n", + (sense[2] & 0x0F), sense[0xC], sense[0xD], + sense[3], sense[4], sense[5], sense[6]); + } + + if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) + goto sense_not; + DPRINTK("sense injected without error\n"); +sense_not: + DPRINTK("EXIT\n"); +} + +/** * ata_dev_identify - obtain IDENTIFY x DEVICE page * @ap: port on which device we wish to probe resides * @device: device bus address, starting at zero @@ -1057,6 +1128,8 @@ retry: status); goto err_out; } + DPRINTK("atapi_sense_pio\n"); + atapi_sense_pio(ap); ata_irq_on(ap); /* re-enable interrupts */ diff -urp o/drivers/scsi/libata-scsi.c linux-2.6.7-rc2-pel/drivers/scsi/libata-scsi.c