Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2009 14:56:01 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r199386 - stable/8/sys/cam/ata
Message-ID:  <200911171456.nAHEu1UG014474@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Tue Nov 17 14:56:00 2009
New Revision: 199386
URL: http://svn.freebsd.org/changeset/base/199386

Log:
  MFC r198328:
  Add support for PIO-only devices.
  Fix maxio values and 256 sectors transactions for 28bits commands.
  Implement periodic ordered commands insertion, sames as da driver does.
  Remove some SCSIsms.

Modified:
  stable/8/sys/cam/ata/ata_da.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/cam/ata/ata_da.c
==============================================================================
--- stable/8/sys/cam/ata/ata_da.c	Tue Nov 17 14:49:35 2009	(r199385)
+++ stable/8/sys/cam/ata/ata_da.c	Tue Nov 17 14:56:00 2009	(r199386)
@@ -63,37 +63,32 @@ __FBSDID("$FreeBSD$");
 #define ATA_MAX_28BIT_LBA               268435455UL
 
 typedef enum {
-	ADA_STATE_NORMAL
+	ADA_STATE_NORMAL,
+	ADA_STATE_SET_MULTI
 } ada_state;
 
 typedef enum {
 	ADA_FLAG_PACK_INVALID	= 0x001,
 	ADA_FLAG_CAN_48BIT	= 0x002,
 	ADA_FLAG_CAN_FLUSHCACHE	= 0x004,
-	ADA_FLAG_CAN_NCQ		= 0x008,
-	ADA_FLAG_TAGGED_QUEUING	= 0x010,
+	ADA_FLAG_CAN_NCQ	= 0x008,
+	ADA_FLAG_CAN_DMA	= 0x010,
 	ADA_FLAG_NEED_OTAG	= 0x020,
 	ADA_FLAG_WENT_IDLE	= 0x040,
-	ADA_FLAG_RETRY_UA	= 0x080,
 	ADA_FLAG_OPEN		= 0x100,
 	ADA_FLAG_SCTX_INIT	= 0x200
 } ada_flags;
 
 typedef enum {
-	ADA_Q_NONE		= 0x00,
-	ADA_Q_NO_SYNC_CACHE	= 0x01,
-	ADA_Q_NO_6_BYTE		= 0x02,
-	ADA_Q_NO_PREVENT		= 0x04
+	ADA_Q_NONE		= 0x00
 } ada_quirks;
 
 typedef enum {
-	ADA_CCB_PROBE		= 0x01,
-	ADA_CCB_PROBE2		= 0x02,
+	ADA_CCB_SET_MULTI	= 0x01,
 	ADA_CCB_BUFFER_IO	= 0x03,
 	ADA_CCB_WAITING		= 0x04,
 	ADA_CCB_DUMP		= 0x05,
 	ADA_CCB_TYPE_MASK	= 0x0F,
-	ADA_CCB_RETRY_UA		= 0x10
 } ada_ccb_state;
 
 /* Offsets into our private area for storing information */
@@ -117,6 +112,7 @@ struct ada_softc {
 	ada_quirks quirks;
 	int	 ordered_tag_count;
 	int	 outstanding_cmds;
+	int	 secsperint;
 	struct	 disk_params params;
 	struct	 disk *disk;
 	union	 ccb saved_ccb;
@@ -289,8 +285,7 @@ adaclose(struct disk *dp)
 		else
 			ata_28bit_cmd(&ccb->ataio, ATA_FLUSHCACHE, 0, 0, 0);
 		cam_periph_runccb(ccb, /*error_routine*/NULL, /*cam_flags*/0,
-		    /*sense_flags*/SF_RETRY_UA,
-		    softc->disk->d_devstat);
+		    /*sense_flags*/0, softc->disk->d_devstat);
 
 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
 			xpt_print(periph->path, "Synchronize cache failed\n");
@@ -331,19 +326,6 @@ adastrategy(struct bio *bp)
 
 	cam_periph_lock(periph);
 
-#if 0
-	/*
-	 * check it's not too big a transfer for our adapter
-	 */
-	scsi_minphys(bp,&sd_switch);
-#endif
-
-	/*
-	 * Mask interrupts so that the pack cannot be invalidated until
-	 * after we are in the queue.  Otherwise, we might not properly
-	 * clean up one of the buffers.
-	 */
-	
 	/*
 	 * If the device has been made invalid, error out
 	 */
@@ -551,11 +533,6 @@ adaasync(void *callback_arg, u_int32_t c
 		if (cgd->protocol != PROTO_ATA)
 			break;
 
-//		if (SID_TYPE(&cgd->inq_data) != T_DIRECT
-//		    && SID_TYPE(&cgd->inq_data) != T_RBC
-//		    && SID_TYPE(&cgd->inq_data) != T_OPTICAL)
-//			break;
-
 		/*
 		 * Allocate a peripheral instance for
 		 * this device and start the probe
@@ -576,18 +553,18 @@ adaasync(void *callback_arg, u_int32_t c
 	case AC_SENT_BDR:
 	case AC_BUS_RESET:
 	{
-		struct ada_softc *softc;
-		struct ccb_hdr *ccbh;
+		struct ada_softc *softc = (struct ada_softc *)periph->softc;
 
-		softc = (struct ada_softc *)periph->softc;
+		cam_periph_async(periph, code, path, arg);
+		if (softc->state != ADA_STATE_NORMAL)
+			break;
 		/*
-		 * Don't fail on the expected unit attention
-		 * that will occur.
+		 * Restore device configuration.
 		 */
-		softc->flags |= ADA_FLAG_RETRY_UA;
-		LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
-			ccbh->ccb_state |= ADA_CCB_RETRY_UA;
-		/* FALLTHROUGH*/
+		softc->state = ADA_STATE_SET_MULTI;
+		cam_periph_acquire(periph);
+		xpt_schedule(periph, 0);
+		break;
 	}
 	default:
 		cam_periph_async(periph, code, path, arg);
@@ -651,14 +628,15 @@ adaregister(struct cam_periph *periph, v
 
 	if (softc == NULL) {
 		printf("adaregister: Unable to probe new device. "
-		       "Unable to allocate softc\n");				
+		    "Unable to allocate softc\n");
 		return(CAM_REQ_CMP_ERR);
 	}
 
 	LIST_INIT(&softc->pending_ccbs);
-	softc->state = ADA_STATE_NORMAL;
 	bioq_init(&softc->bio_queue);
 
+	if (cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA)
+		softc->flags |= ADA_FLAG_CAN_DMA;
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
 		softc->flags |= ADA_FLAG_CAN_48BIT;
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
@@ -666,8 +644,8 @@ adaregister(struct cam_periph *periph, v
 	if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
 	    cgd->ident_data.queue >= 31)
 		softc->flags |= ADA_FLAG_CAN_NCQ;
-//	if ((cgd->inq_data.flags & SID_CmdQue) != 0)
-//		softc->flags |= ADA_FLAG_TAGGED_QUEUING;
+	softc->secsperint = max(1, min(cgd->ident_data.sectors_intr, 16));
+	softc->state = ADA_STATE_SET_MULTI;
 
 	periph->softc = softc;
 
@@ -713,9 +691,9 @@ adaregister(struct cam_periph *periph, v
 	else if (maxio > MAXPHYS)
 		maxio = MAXPHYS;	/* for safety */
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
-		maxio = min(maxio, 65535 * 512);
+		maxio = min(maxio, 65536 * 512);
 	else					/* 28bit ATA command limit */
-		maxio = min(maxio, 255 * 512);
+		maxio = min(maxio, 256 * 512);
 	softc->disk->d_maxsize = maxio;
 	softc->disk->d_unit = periph->unit_number;
 	softc->disk->d_flags = 0;
@@ -730,8 +708,6 @@ adaregister(struct cam_periph *periph, v
 	/* XXX: these are not actually "firmware" values, so they may be wrong */
 	softc->disk->d_fwsectors = softc->params.secs_per_track;
 	softc->disk->d_fwheads = softc->params.heads;
-//	softc->disk->d_devstat->block_size = softc->params.secsize;
-//	softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE;
 
 	disk_create(softc->disk, DISK_VERSION);
 	mtx_lock(periph->sim->mtx);
@@ -766,8 +742,8 @@ adaregister(struct cam_periph *periph, v
 	 * to finish the probe.  The reference will be dropped in adadone at
 	 * the end of probe.
 	 */
-//	(void)cam_periph_hold(periph, PRIBIO);
-//	xpt_schedule(periph, /*priority*/5);
+	cam_periph_acquire(periph);
+	xpt_schedule(periph, /*priority*/5);
 
 	/*
 	 * Schedule a periodic event to occasionally send an
@@ -784,9 +760,8 @@ adaregister(struct cam_periph *periph, v
 static void
 adastart(struct cam_periph *periph, union ccb *start_ccb)
 {
-	struct ada_softc *softc;
-
-	softc = (struct ada_softc *)periph->softc;
+	struct ada_softc *softc = (struct ada_softc *)periph->softc;
+	struct ccb_ataio *ataio = &start_ccb->ataio;
 
 	switch (softc->state) {
 	case ADA_STATE_NORMAL:
@@ -809,7 +784,6 @@ adastart(struct cam_periph *periph, unio
 		} else if (bp == NULL) {
 			xpt_release_ccb(start_ccb);
 		} else {
-			struct ccb_ataio *ataio = &start_ccb->ataio;
 			u_int8_t tag_code;
 
 			bioq_remove(&softc->bio_queue, bp);
@@ -817,9 +791,9 @@ adastart(struct cam_periph *periph, unio
 			if ((softc->flags & ADA_FLAG_NEED_OTAG) != 0) {
 				softc->flags &= ~ADA_FLAG_NEED_OTAG;
 				softc->ordered_tag_count++;
-				tag_code = 0;//MSG_ORDERED_Q_TAG;
+				tag_code = 0;
 			} else {
-				tag_code = 0;//MSG_SIMPLE_Q_TAG;
+				tag_code = 1;
 			}
 			switch (bp->bio_cmd) {
 			case BIO_READ:
@@ -838,7 +812,7 @@ adastart(struct cam_periph *periph, unio
 				    bp->bio_bcount,
 				    ada_default_timeout*1000);
 
-				if (softc->flags & ADA_FLAG_CAN_NCQ) {
+				if ((softc->flags & ADA_FLAG_CAN_NCQ) && tag_code) {
 					if (bp->bio_cmd == BIO_READ) {
 						ata_ncq_cmd(ataio, ATA_READ_FPDMA_QUEUED,
 						    lba, count);
@@ -848,21 +822,43 @@ adastart(struct cam_periph *periph, unio
 					}
 				} else if ((softc->flags & ADA_FLAG_CAN_48BIT) &&
 				    (lba + count >= ATA_MAX_28BIT_LBA ||
-				    count >= 256)) {
-					if (bp->bio_cmd == BIO_READ) {
-						ata_48bit_cmd(ataio, ATA_READ_DMA48,
-						    0, lba, count);
+				    count > 256)) {
+					if (softc->flags & ADA_FLAG_CAN_DMA) {
+						if (bp->bio_cmd == BIO_READ) {
+							ata_48bit_cmd(ataio, ATA_READ_DMA48,
+							    0, lba, count);
+						} else {
+							ata_48bit_cmd(ataio, ATA_WRITE_DMA48,
+							    0, lba, count);
+						}
 					} else {
-						ata_48bit_cmd(ataio, ATA_WRITE_DMA48,
-						    0, lba, count);
+						if (bp->bio_cmd == BIO_READ) {
+							ata_48bit_cmd(ataio, ATA_READ_MUL48,
+							    0, lba, count);
+						} else {
+							ata_48bit_cmd(ataio, ATA_WRITE_MUL48,
+							    0, lba, count);
+						}
 					}
 				} else {
-					if (bp->bio_cmd == BIO_READ) {
-						ata_28bit_cmd(ataio, ATA_READ_DMA,
-						    0, lba, count);
+					if (count == 256)
+						count = 0;
+					if (softc->flags & ADA_FLAG_CAN_DMA) {
+						if (bp->bio_cmd == BIO_READ) {
+							ata_28bit_cmd(ataio, ATA_READ_DMA,
+							    0, lba, count);
+						} else {
+							ata_28bit_cmd(ataio, ATA_WRITE_DMA,
+							    0, lba, count);
+						}
 					} else {
-						ata_28bit_cmd(ataio, ATA_WRITE_DMA,
-						    0, lba, count);
+						if (bp->bio_cmd == BIO_READ) {
+							ata_28bit_cmd(ataio, ATA_READ_MUL,
+							    0, lba, count);
+						} else {
+							ata_28bit_cmd(ataio, ATA_WRITE_MUL,
+							    0, lba, count);
+						}
 					}
 				}
 			}
@@ -872,7 +868,7 @@ adastart(struct cam_periph *periph, unio
 				    1,
 				    adadone,
 				    CAM_DIR_NONE,
-				    tag_code,
+				    0,
 				    NULL,
 				    0,
 				    ada_default_timeout*1000);
@@ -893,12 +889,6 @@ adastart(struct cam_periph *periph, unio
 					 &start_ccb->ccb_h, periph_links.le);
 			softc->outstanding_cmds++;
 
-			/* We expect a unit attention from this device */
-			if ((softc->flags & ADA_FLAG_RETRY_UA) != 0) {
-				start_ccb->ccb_h.ccb_state |= ADA_CCB_RETRY_UA;
-				softc->flags &= ~ADA_FLAG_RETRY_UA;
-			}
-
 			start_ccb->ccb_h.ccb_bp = bp;
 			bp = bioq_first(&softc->bio_queue);
 
@@ -911,6 +901,21 @@ adastart(struct cam_periph *periph, unio
 		}
 		break;
 	}
+	case ADA_STATE_SET_MULTI:
+	{
+		cam_fill_ataio(ataio,
+		    ada_retry_count,
+		    adadone,
+		    CAM_DIR_NONE,
+		    0,
+		    NULL,
+		    0,
+		    ada_default_timeout*1000);
+
+		ata_28bit_cmd(ataio, ATA_SET_MULTI, 0, 0, softc->secsperint);
+		start_ccb->ccb_h.ccb_state = ADA_CCB_SET_MULTI;
+		xpt_action(start_ccb);
+	}
 	}
 }
 
@@ -931,16 +936,12 @@ adadone(struct cam_periph *periph, union
 		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 			int error;
 			
-			error = adaerror(done_ccb, CAM_RETRY_SELTO, 0);
+			error = adaerror(done_ccb, 0, 0);
 			if (error == ERESTART) {
-				/*
-				 * A retry was scheuled, so
-				 * just return.
-				 */
+				/* A retry was scheduled, so just return. */
 				return;
 			}
 			if (error != 0) {
-
 				if (error == ENXIO) {
 					/*
 					 * Catastrophic error.  Mark our pack as
@@ -1002,6 +1003,35 @@ adadone(struct cam_periph *periph, union
 		wakeup(&done_ccb->ccb_h.cbfcnp);
 		return;
 	}
+	case ADA_CCB_SET_MULTI:
+	{
+		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+		} else {
+			int	error;
+
+			error = adaerror(done_ccb, 0, 0);
+			if (error == ERESTART) {
+				/* A retry was scheduled, so just return. */
+				return;
+			}
+		}
+		softc->state = ADA_STATE_NORMAL;
+		/*
+		 * Since our peripheral may be invalidated by an error
+		 * above or an external event, we must release our CCB
+		 * before releasing the probe lock on the peripheral.
+		 * The peripheral will only go away once the last lock
+		 * is removed, and we need it around for the CCB release
+		 * operation.
+		 */
+		xpt_release_ccb(done_ccb);
+		if (bioq_first(&softc->bio_queue) != NULL) {
+			/* Have more work to do, so ensure we stay scheduled */
+			xpt_schedule(periph, 1);
+		}
+		cam_periph_release_locked(periph);
+		return;
+	}
 	case ADA_CCB_DUMP:
 		/* No-op.  We're polling */
 		return;
@@ -1049,10 +1079,6 @@ adasetgeom(struct cam_periph *periph, st
 	lbasize = (u_int32_t)cgd->ident_data.lba_size_1 |
 		  ((u_int32_t)cgd->ident_data.lba_size_2 << 16);
 
-    /* does this device need oldstyle CHS addressing */
-//    if (!ad_version(cgd->ident_data.version_major) || !lbasize)
-//	atadev->flags |= ATA_D_USE_CHS;
-
 	/* use the 28bit LBA size if valid or bigger than the CHS mapping */
 	if (cgd->ident_data.cylinders == 16383 || dp->sectors < lbasize)
 		dp->sectors = lbasize;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200911171456.nAHEu1UG014474>