kern/103602: drive gets wedged on READ CD CAPACITY if no disc is in

Thomas Quinot thomas at FreeBSD.ORG
Tue Apr 24 16:58:45 UTC 2007


* Josh Carroll, 2007-04-24 :

> Here is my output (first with no disk, second with). I see sk=02 here as 
> well:
> 
> % ./readcap /dev/acd0
> ioctl returned error 5 Input/output error
> Sense data: error=70 sk=02 asc=3a ascq=00
> 
> % ./readcap /dev/acd0
> ioctl returned error 0 Unknown error: 0
> Sense data: error=00 sk=00 asc=00 ascq=00
> LBA of last sector in last session: 185805
> Sector size: 2048

It just occurred to me that there is one point that is different when
using readcap, compared to sg_readcap+ATAPI/CAM: only in the latter case
is DMA used.

*And* you mentioned, very early in this PR, that disabling DMA
altogether made the problem disappear. So, let's try something: enable
DMA only for READ and WRITE commands (where it's most useful).

Apparently it's not a completely unhead-of situation that some drives
have problems with DMA for commands other than READ and WRITE, see:
http://www.mail-archive.com/linux-ide@vger.kernel.org/msg05425.html

Patch attached.

Thomas.

-------------- next part --------------
Index: sys/dev/ata/atapi-cam.c
===================================================================
RCS file: /space/mirror/ncvs/src/sys/dev/ata/atapi-cam.c,v
retrieving revision 1.50
diff -u -r1.50 atapi-cam.c
--- sys/dev/ata/atapi-cam.c	14 Mar 2007 01:59:00 -0000	1.50
+++ sys/dev/ata/atapi-cam.c	24 Apr 2007 16:57:11 -0000
@@ -516,10 +516,10 @@
 
 	switch (ccb_h->flags & CAM_DIR_MASK) {
 	case CAM_DIR_IN:
-	     request_flags |= ATA_R_READ|ATA_R_DMA;
+	     request_flags |= ATA_R_READ;
 	     break;
 	case CAM_DIR_OUT:
-	     request_flags |= ATA_R_WRITE|ATA_R_DMA;
+	     request_flags |= ATA_R_WRITE;
 	     break;
 	case CAM_DIR_NONE:
 	     /* No flags need to be set */
@@ -528,8 +528,6 @@
 	     device_printf(softc->dev, "unknown IO operation\n");
 	     goto action_invalid;
 	}
-	if (softc->atadev[tid]->mode < ATA_DMA)
-	    request_flags &= ~ATA_R_DMA;
 
 	if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) {
 	    printf("cannot allocate ATAPI/CAM hcb\n");
@@ -594,7 +592,23 @@
 	    request->u.atapi.ccb[3] = request->u.atapi.ccb[1] & 0x1f;
 	    request->u.atapi.ccb[2] = 0;
 	    request->u.atapi.ccb[1] = 0;
+
+	case READ_10:
+	    /* FALLTHROUGH */
+	case WRITE_10:
+	    /* FALLTHROUGH */
+	case READ_12:
+	    /* FALLTHROUGH */
+	case WRITE_12:
+	    /*
+	     * Enable DMA (if target supports it) for READ and WRITE commands
+	     * only, as some combinations of drive, controller and chipset do
+	     * not behave correctly when DMA is enabled for other commands.
+	     */
+	    if (softc->atadev[tid]->mode >= ATA_DMA)
+		request_flags |= ATA_R_DMA;
 	    break;
+
 	}
 
 	if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) {
@@ -616,7 +630,7 @@
 
 	/*
 	 * no retries are to be performed at the ATA level; any retries
-	 * will be done by CAM .
+	 * will be done by CAM.
 	 */
 	request->retries = 0;
 


More information about the freebsd-scsi mailing list