Linux ATA/IDE development
 help / color / mirror / Atom feed
From: Pat LaVarre <p.lavarre@ieee.org>
To: jgarzik@pobox.com
Cc: linux-ide@vger.kernel.org
Subject: Re: SATA ATAPI work in progress
Date: 12 May 2004 17:14:14 -0600	[thread overview]
Message-ID: <1084403654.3196.31.camel@patibmrh9> (raw)
In-Reply-To: <40A28BB6.7090204@pobox.com>

Jeff G:

> decent first step ...
> Good guess ...
> ..
> [1] not sure you should bother ...
> [2] don't use ifdef, test ATA_QCFLAG_DMA ...
> [3] for DMA, ... zero
> [4] for PIO, ... 8K (one SATA FIS) ...
> [5] eliminate the dev->class test ...
> [6] modify ata_get_xlat_func
> to return atapi_xlat when dev->class == ATAPI

Changes complete as requested, I hope, in the new patch inline.

> > -	VPRINTK("ENTER, drv_stat = 0x%x\n", ata_chk_status(ap));
> > ...
> > -	atapi_start(qc);
>
> Note that by deleting this, there is no
> longer anything to start the ATAPI transfer
> really.

Aye, the dmesg tell me I'm timing out with command incomplete.

> You must the latter half of the above code
> [the part you are deleting] either to
> ata_qc_issue_prot() or your new atapi_xlat().

The dmesg tell me my guess below of how to do this actually ended up
writing the x1F7 Command = xA0 Packet twice, whoops.

Please choose for me from:

1) Keep only the atapi_start/ ata_tf_to_host_nolock/
ata_exec_command_pio.

2) Keep only the worker_thread/ atapi_packet_task/ ata_bmdma_start_pio/
ata_exec_command_pio.

3) Try something else entirely.

> drivers/ide and Hale Landis's ATADRVR
> (http://www.ata-atapi.com/) for comparing IO
> write-for-write, to make sure I have the steps
> and the state machine correct.  And of course
> the state machine docs itself, in ATA/ATAPI7.

Yes.  Myself, I have experience making Dos talk UDMA, a PATA bus
analyser on my desk, and intermittent access to a SATA bus analyser.

> you need to make sure your ATAPI device
> supports ultra DMA,

Please tell me if you want more evidence.

The paper that accompanied my (Silicon Image 3611CT80 1.5) SATA/ PATA
bridge tells me it talks UDMA "66, 100, 133 and 150" Mb/s though not
UDMA 33/ MWDMA/ SWMA.

I remember the paper that accompanied my PATA device tells me it talks
at least UDMA 4, maybe actually UDMA 5.  I know I have myself seen this
device sustain about 1.5 GB/min = 25 MB/s.  I could reboot to quote its
op xEC Identify "word"s any time we like.

> as you don't want
> to bother with PIO or [SM]WDMA right now.

I'm happy starting with SATA PIO, if you like that better.

I do eventually want to talk SATA UDMA because I hope to end by
achieving burst rates more like the 133 MB/s of UDMA, well above the
16.7 MB/s limit of PATA PIO 4.

For ATAPI myself I recommend DMA only for well-known block ops, in order
to get the exact byte counting of PIO otherwise.

> > modprobe -r ata-piix
> > modprobe ata-piix

modprobe's still mostly work, but depending on my patch, I see that
`modprobe ata-piix` may appear to halt my kernel with the HDD activity
light lit after the dmesg:

ata_bus_reset: ENTER, host 2, port 1
ata_bus_softreset: ata2: bus reset via SRST

Pat LaVarre

diff -Nurp linux-2.6.6-bk1/drivers/scsi/libata-core.c linux-2.6.6-bk1-pel/drivers/scsi/libata-core.c
--- linux-2.6.6-bk1/drivers/scsi/libata-core.c	2004-05-12 09:57:09.000000000 -0600
+++ linux-2.6.6-bk1-pel/drivers/scsi/libata-core.c	2004-05-12 16:32:20.000000000 -0600
@@ -245,6 +245,9 @@ void ata_tf_load_mmio(struct ata_port *a
 void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
+if (tf->command == 0xA0) {
+	dump_stack();
+}
 
        	outb(tf->command, ap->ioaddr.command_addr);
 	ata_pause(ap);
@@ -2438,6 +2441,7 @@ static int ata_qc_issue_prot(struct ata_
 
 	ata_dev_select(ap, qc->dev->devno, 1, 0);
 
+	DPRINTK("qc->tf.protocol = %d\n", qc->tf.protocol);
 	switch (qc->tf.protocol) {
 	case ATA_PROT_NODATA:
 		ata_tf_to_host_nolock(ap, &qc->tf);
@@ -2456,6 +2460,12 @@ static int ata_qc_issue_prot(struct ata_
 		queue_work(ata_wq, &ap->pio_task);
 		break;
 
+	case ATA_PROT_ATAPI_DMA:
+		atapi_start(qc);
+		break;
+
+	case ATA_PROT_ATAPI:
+		DPRINTK("Assertion fail: qc->tf.protocol != ATA_PROT_ATAPI\n");
 	default:
 		WARN_ON(1);
 		return -1;
@@ -2812,6 +2822,9 @@ static void atapi_packet_task(void *_dat
 	/* if we are DMA'ing, irq handler takes over from here */
 	if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
 		/* FIXME: start DMA here */
+		DPRINTK("before bmdma_start\n");
+		ap->ops->bmdma_start(qc);
+		DPRINTK("after bmdma_start\n");
 	} else {
 		ap->pio_task_state = PIO_ST;
 		queue_work(ata_wq, &ap->pio_task);
diff -Nurp linux-2.6.6-bk1/drivers/scsi/libata-scsi.c linux-2.6.6-bk1-pel/drivers/scsi/libata-scsi.c
--- linux-2.6.6-bk1/drivers/scsi/libata-scsi.c	2004-05-12 09:57:09.000000000 -0600
+++ linux-2.6.6-bk1-pel/drivers/scsi/libata-scsi.c	2004-05-12 15:51:10.000000000 -0600
@@ -215,6 +215,45 @@ int ata_scsi_error(struct Scsi_Host *hos
 
 	DPRINTK("EXIT\n");
 	return 0;
+} 
+
+/**
+ *	atapi_xlat - Pass SCSI r/w command thru to ATAPI
+ *	@qc: Storage for translated ATA taskfile
+ *	@scsicmd: SCSI command to translate
+ *
+ *	Trust caller already cleared *qc->tf (often via ata_tf_init),
+ *	deciding tf->device & (0x10 ATA_DEV1 | 0x07 SFF 8070i LUN), etc.
+ *
+ *	Choose ATAPI PIO BCL from:
+ *
+ *		0x2000 = 8 Ki = one SATA FIS
+ *		0xFFFE = largest specified in oldest public docs
+ *		0xFFFF = first massively distributed (Win 95B)
+ *
+ *	RETURNS:
+ *	Zero on success, non-zero on error.
+ */
+
+static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
+{
+	int bcl = (8 * 0x400); /* PIO "byte count limit" */
+	struct ata_taskfile *tf = &qc->tf;
+	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+	tf->protocol = qc->dev->xfer_protocol;
+	tf->command = ATA_CMD_PACKET; /* often 0xA0 */
+	if (qc->flags & ATA_QCFLAG_DMA) {
+		DPRINTK("DMA ATAPI 0x%lX %d\n", qc->flags, qc->tf.protocol);
+		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
+		tf->feature = ATAPI_PKT_DMA; /* often x01 */
+	} else {
+		DPRINTK("PIO ATAPI 0x%lX %d\n", qc->flags, qc->tf.protocol);
+		qc->tf.protocol = ATA_PROT_ATAPI;
+		tf->lbam = bcl >> 8;
+		tf->lbah = bcl;
+	}
+	qc->flags |= ATA_QCFLAG_ATAPI;
+	return 0;
 }
 
 /**
@@ -885,78 +924,6 @@ void ata_scsi_badcmd(struct scsi_cmnd *c
 }
 
 /**
- *	atapi_scsi_queuecmd - Send CDB to ATAPI device
- *	@ap: Port to which ATAPI device is attached.
- *	@dev: Target device for CDB.
- *	@cmd: SCSI command being sent to device.
- *	@done: SCSI command completion function.
- *
- *	Sends CDB to ATAPI device.  If the Linux SCSI layer sends a
- *	non-data command, then this function handles the command
- *	directly, via polling.  Otherwise, the bmdma engine is started.
- *
- *	LOCKING:
- *	spin_lock_irqsave(host_set lock)
- */
-
-static void atapi_scsi_queuecmd(struct ata_port *ap, struct ata_device *dev,
-			       struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
-	struct ata_queued_cmd *qc;
-	u8 *scsicmd = cmd->cmnd;
-
-	VPRINTK("ENTER, drv_stat = 0x%x\n", ata_chk_status(ap));
-
-	if (cmd->sc_data_direction == SCSI_DATA_UNKNOWN) {
-		DPRINTK("unknown data, scsicmd 0x%x\n", scsicmd[0]);
-		ata_bad_cdb(cmd, done);
-		return;
-	}
-
-	switch(scsicmd[0]) {
-	case READ_6:
-	case WRITE_6:
-	case MODE_SELECT:
-	case MODE_SENSE:
-		DPRINTK("read6/write6/modesel/modesense trap\n");
-		ata_bad_scsiop(cmd, done);
-		return;
-
-	default:
-		/* do nothing */
-		break;
-	}
-
-	qc = ata_scsi_qc_new(ap, dev, cmd, done);
-	if (!qc) {
-		printk(KERN_ERR "ata%u: command queue empty\n", ap->id);
-		return;
-	}
-
-	qc->flags |= ATA_QCFLAG_ATAPI;
-
-	qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-	if (cmd->sc_data_direction == SCSI_DATA_WRITE) {
-		qc->tf.flags |= ATA_TFLAG_WRITE;
-		DPRINTK("direction: write\n");
-	}
-
-	qc->tf.command = ATA_CMD_PACKET;
-
-	if (cmd->sc_data_direction == SCSI_DATA_NONE) {
-		qc->tf.protocol = ATA_PROT_ATAPI;
-		qc->flags |= ATA_QCFLAG_POLL;
-		qc->tf.ctl |= ATA_NIEN;	/* disable interrupts */
-	} else {
-		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
-		qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
-		qc->tf.feature |= ATAPI_PKT_DMA;
-	}
-
-	atapi_start(qc);
-}
-
-/**
  *	ata_scsi_find_dev - lookup ata_device from scsi_cmnd
  *	@ap: ATA port to which the device is attached
  *	@cmd: SCSI command to be sent to the device
@@ -1010,8 +977,12 @@ ata_scsi_find_dev(struct ata_port *ap, s
  *	Pointer to translation function if possible, %NULL if not.
  */
 
-static inline ata_xlat_func_t ata_get_xlat_func(u8 cmd)
+static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
 {
+	if (dev->class == ATA_DEV_ATAPI) { /* (thus != ATA_DEV_ATAPI_UNSUP) */
+		return atapi_xlat;
+	}
+
 	switch (cmd) {
 	case READ_6:
 	case READ_10:
@@ -1072,6 +1043,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
 {
 	struct ata_port *ap;
 	struct ata_device *dev;
+	ata_xlat_func_t xlat_func;
 
 	ap = (struct ata_port *) &cmd->device->host->hostdata[0];
 
@@ -1084,15 +1056,11 @@ int ata_scsi_queuecmd(struct scsi_cmnd *
 		goto out_unlock;
 	}
 
-	if (dev->class == ATA_DEV_ATA) {
-		ata_xlat_func_t xlat_func = ata_get_xlat_func(cmd->cmnd[0]);
-
-		if (xlat_func)
-			ata_scsi_translate(ap, dev, cmd, done, xlat_func);
-		else
-			ata_scsi_simulate(ap, dev, cmd, done);
-	} else
-		atapi_scsi_queuecmd(ap, dev, cmd, done);
+	xlat_func = ata_get_xlat_func(dev, cmd->cmnd[0]);
+	if (xlat_func)
+		ata_scsi_translate(ap, dev, cmd, done, xlat_func);
+	else
+		ata_scsi_simulate(ap, dev, cmd, done);
 
 out_unlock:
 	return 0;



  reply	other threads:[~2004-05-12 23:14 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-05-12 20:20 SATA ATAPI work in progress Pat LaVarre
2004-05-12 20:40 ` Jeff Garzik
2004-05-12 23:14   ` Pat LaVarre [this message]
2004-05-13 15:07     ` Pat LaVarre
2004-05-13 20:56       ` Jeff Garzik
2004-05-13 21:16     ` Jeff Garzik
2004-05-13 21:25       ` Jeff Garzik
2004-05-13 21:36         ` Pat LaVarre
2004-05-13 21:44           ` Jeff Garzik
2004-05-13 21:49             ` Jeff Garzik
2004-05-14 18:23       ` Pat LaVarre
2004-05-14 18:55         ` Jeff Garzik
2004-05-14 19:37           ` when limited to a single DRQ block per disk transaction Pat LaVarre
2004-05-14 19:50             ` Jeff Garzik
2004-05-14 20:12               ` Pat LaVarre
2004-05-14 23:47           ` SATA ATAPI work in progress Pat LaVarre
2004-05-15  0:02             ` Pat LaVarre
2004-05-15  0:38               ` Jeff Garzik
2004-05-15 13:06                 ` Pat LaVarre
2004-05-15 13:49                   ` Pat LaVarre
2004-05-15 15:27                     ` Jeff Garzik
2004-05-15 15:49                       ` Pat LaVarre
2004-05-15 15:56                         ` Pat LaVarre
2004-05-15 16:04                           ` Pat LaVarre
2004-05-15 16:32                             ` Jeff Garzik
2004-05-15 16:43                               ` Pat LaVarre
2004-05-15 16:50                                 ` Pat LaVarre
2004-05-15 16:30                         ` Jeff Garzik
2004-05-15  0:46               ` [PATCH] " Jeff Garzik
2004-05-15 13:08                 ` Pat LaVarre
2004-05-15 13:10                   ` Pat LaVarre
2004-05-15 14:13                     ` Pat LaVarre
2004-05-14 18:28       ` Pat LaVarre
2004-05-14 18:38         ` Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1084403654.3196.31.camel@patibmrh9 \
    --to=p.lavarre@ieee.org \
    --cc=jgarzik@pobox.com \
    --cc=linux-ide@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox