PERFORCE change 165588 for review

Alexander Motin mav at FreeBSD.org
Sat Jul 4 11:12:51 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=165588

Change 165588 by mav at mav_mavbook on 2009/07/04 11:12:37

	Set device to use it's maximal supported transfer mode.
	It should not have much reason to do it for SATA, but
	some (at least ATAPI) devices aren't working without it.
	
	Change moments, when SIM reported PMP presence.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#11 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#11 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#25 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#11 (text+ko) ====

@@ -221,3 +221,80 @@
 		dst[j++] = 0x00;
 }
 
+int
+ata_max_pmode(struct ata_params *ap)
+{
+    if (ap->atavalid & ATA_FLAG_64_70) {
+	if (ap->apiomodes & 0x02)
+	    return ATA_PIO4;
+	if (ap->apiomodes & 0x01)
+	    return ATA_PIO3;
+    }
+    if (ap->mwdmamodes & 0x04)
+	return ATA_PIO4;
+    if (ap->mwdmamodes & 0x02)
+	return ATA_PIO3;
+    if (ap->mwdmamodes & 0x01)
+	return ATA_PIO2;
+    if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x200)
+	return ATA_PIO2;
+    if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x100)
+	return ATA_PIO1;
+    if ((ap->retired_piomode & ATA_RETIRED_PIO_MASK) == 0x000)
+	return ATA_PIO0;
+    return ATA_PIO0;
+}
+
+int
+ata_max_wmode(struct ata_params *ap)
+{
+    if (ap->mwdmamodes & 0x04)
+	return ATA_WDMA2;
+    if (ap->mwdmamodes & 0x02)
+	return ATA_WDMA1;
+    if (ap->mwdmamodes & 0x01)
+	return ATA_WDMA0;
+    return -1;
+}
+
+int
+ata_max_umode(struct ata_params *ap)
+{
+    if (ap->atavalid & ATA_FLAG_88) {
+	if (ap->udmamodes & 0x40)
+	    return ATA_UDMA6;
+	if (ap->udmamodes & 0x20)
+	    return ATA_UDMA5;
+	if (ap->udmamodes & 0x10)
+	    return ATA_UDMA4;
+	if (ap->udmamodes & 0x08)
+	    return ATA_UDMA3;
+	if (ap->udmamodes & 0x04)
+	    return ATA_UDMA2;
+	if (ap->udmamodes & 0x02)
+	    return ATA_UDMA1;
+	if (ap->udmamodes & 0x01)
+	    return ATA_UDMA0;
+    }
+    return -1;
+}
+
+int
+ata_max_mode(struct ata_params *ap, int mode, int maxmode)
+{
+
+    if (maxmode && mode > maxmode)
+	mode = maxmode;
+
+    if (mode >= ATA_UDMA0 && ata_max_umode(ap) > 0)
+	return (min(mode, ata_max_umode(ap)));
+
+    if (mode >= ATA_WDMA0 && ata_max_wmode(ap) > 0)
+	return (min(mode, ata_max_wmode(ap)));
+
+    if (mode > ata_max_pmode(ap))
+	return (min(mode, ata_max_pmode(ap)));
+
+    return (mode);
+}
+

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#11 (text+ko) ====

@@ -95,4 +95,9 @@
 void	ata_btrim(int8_t *buf, int len);
 void	ata_bpack(int8_t *src, int8_t *dst, int len);
 
+int	ata_max_pmode(struct ata_params *ap);
+int	ata_max_wmode(struct ata_params *ap);
+int	ata_max_umode(struct ata_params *ap);
+int	ata_max_mode(struct ata_params *ap, int mode, int maxmode);
+
 #endif

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#25 (text+ko) ====

@@ -93,6 +93,7 @@
 typedef enum {
 	PROBE_RESET,
 	PROBE_IDENTIFY,
+	PROBE_SETMODE,
 	PROBE_INQUIRY,
 	PROBE_FULL_INQUIRY,
 	PROBE_PM_PID,
@@ -108,6 +109,7 @@
 static char *probe_action_text[] = {
 	"PROBE_RESET",
 	"PROBE_IDENTIFY",
+	"PROBE_SETMODE",
 	"PROBE_INQUIRY",
 	"PROBE_FULL_INQUIRY",
 	"PROBE_PM_PID",
@@ -277,7 +279,7 @@
 	if (periph->path->device->flags & CAM_DEV_UNCONFIGURED)
 		PROBE_SET_ACTION(softc, PROBE_RESET);
 	else if (periph->path->device->protocol == PROTO_SATAPM)
-		PROBE_SET_ACTION(softc, PROBE_RESET);
+		PROBE_SET_ACTION(softc, PROBE_PM_PID);
 	else
 		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
 
@@ -295,6 +297,7 @@
 	/* Probe the device that our peripheral driver points to */
 	struct ccb_ataio *ataio;
 	struct ccb_scsiio *csio;
+	struct ccb_trans_settings cts;
 	probe_softc *softc;
 
 	CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probestart\n"));
@@ -305,6 +308,16 @@
 
 	switch (softc->action) {
 	case PROBE_RESET:
+		if (start_ccb->ccb_h.target_id == 15) {
+			/* Report SIM that we have no knowledge about PM presence. */
+			bzero(&cts, sizeof(cts));
+			xpt_setup_ccb(&cts.ccb_h, start_ccb->ccb_h.path, 1);
+			cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+			cts.type = CTS_TYPE_CURRENT_SETTINGS;
+			cts.xport_specific.sata.pm_present = 0;
+			cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
+			xpt_action((union ccb *)&cts);
+		}
 		cam_fill_ataio(ataio,
 		      0,
 		      probedone,
@@ -350,6 +363,23 @@
 			ata_36bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
 		break;
 	}
+	case PROBE_SETMODE:
+	{
+		struct ata_params *ident_buf =
+		    &periph->path->device->ident_data;
+
+		cam_fill_ataio(ataio,
+		      1,
+		      probedone,
+		      /*flags*/CAM_DIR_IN,
+		      MSG_SIMPLE_Q_TAG,
+		      /*data_ptr*/(u_int8_t *)ident_buf,
+		      /*dxfer_len*/sizeof(struct ata_params),
+		      30 * 1000);
+		ata_36bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
+		    ata_max_mode(ident_buf, ATA_UDMA6, ATA_UDMA6));
+		break;
+	}
 	case PROBE_INQUIRY:
 	case PROBE_FULL_INQUIRY:
 	{
@@ -369,7 +399,7 @@
 		 */
 		inquiry_len = roundup2(inquiry_len, 2);
 		scsi_inquiry(csio,
-			     /*retries*/4,
+			     /*retries*/1,
 			     probedone,
 			     MSG_SIMPLE_Q_TAG,
 			     (u_int8_t *)inq_buf,
@@ -623,6 +653,16 @@
 				PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
 			} else if (sign == 0x9669 &&
 			    done_ccb->ccb_h.target_id == 15) {
+				struct ccb_trans_settings cts;
+
+				/* Report SIM that PM is present. */
+				bzero(&cts, sizeof(cts));
+				xpt_setup_ccb(&cts.ccb_h, path, 1);
+				cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+				cts.type = CTS_TYPE_CURRENT_SETTINGS;
+				cts.xport_specific.sata.pm_present = 1;
+				cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
+				xpt_action((union ccb *)&cts);
 				path->device->protocol = PROTO_SATAPM;
 				PROBE_SET_ACTION(softc, PROBE_PM_PID);
 			} else if (sign == 0xeb14 &&
@@ -721,21 +761,10 @@
 			scsi_find_quirk(path->device);
 			ata_device_transport(path);
 
-//			if ((softc->flags & PROBE_NO_ANNOUNCE) == 0) {
-			if (path->device->protocol == PROTO_ATA) {
-				path->device->flags &= ~CAM_DEV_UNCONFIGURED;
-				done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
-				xpt_action(done_ccb);
-				xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
-				    done_ccb);
-				xpt_release_ccb(done_ccb);
-				break;
-			} else {
-				PROBE_SET_ACTION(softc, PROBE_INQUIRY);
-				xpt_release_ccb(done_ccb);
-				xpt_schedule(periph, priority);
-				return;
-			}
+			PROBE_SET_ACTION(softc, PROBE_SETMODE);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
 		} else if (cam_periph_error(done_ccb, 0, 0,
 					    &softc->saved_ccb) == ERESTART) {
 			return;
@@ -762,6 +791,33 @@
 		xpt_release_ccb(done_ccb);
 		break;
 	}
+	case PROBE_SETMODE:
+	{
+		if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+			if (path->device->protocol == PROTO_ATA) {
+				path->device->flags &= ~CAM_DEV_UNCONFIGURED;
+				done_ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+				xpt_action(done_ccb);
+				xpt_async(AC_FOUND_DEVICE, done_ccb->ccb_h.path,
+				    done_ccb);
+				xpt_release_ccb(done_ccb);
+				break;
+			} else {
+				PROBE_SET_ACTION(softc, PROBE_INQUIRY);
+				xpt_release_ccb(done_ccb);
+				xpt_schedule(periph, priority);
+				return;
+			}
+		} else if (cam_periph_error(done_ccb, 0, 0,
+					    &softc->saved_ccb) == ERESTART) {
+			return;
+		} else if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
+			/* Don't wedge the queue */
+			xpt_release_devq(done_ccb->ccb_h.path, /*count*/1,
+					 /*run_queue*/TRUE);
+		}
+		goto device_fail;
+	}
 	case PROBE_INQUIRY:
 	case PROBE_FULL_INQUIRY:
 	{
@@ -1081,7 +1137,6 @@
 	struct	cam_path *path;
 	ata_scan_bus_info *scan_info;
 	union	ccb *work_ccb;
-	struct	ccb_trans_settings cts;
 	cam_status status;
 
 	CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
@@ -1118,14 +1173,6 @@
 		scan_info->cpi = &work_ccb->cpi;
 		scan_info->found = 0x8001;
 		scan_info->counter = 0;
-		/* Report SIM that we have no knowledge about PM presence. */
-		bzero(&cts, sizeof(cts));
-		xpt_setup_ccb(&cts.ccb_h, scan_info->request_ccb->ccb_h.path, 1);
-		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
-		cts.type = CTS_TYPE_CURRENT_SETTINGS;
-		cts.xport_specific.sata.pm_present = 0;
-		cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
-		xpt_action((union ccb *)&cts);
 		/* If PM supported, probe it first. */
 		if (scan_info->cpi->hba_inquiry & PI_SATAPM)
 			scan_info->counter = 15;
@@ -1145,18 +1192,23 @@
 		/* Free the current request path- we're done with it. */
 		xpt_free_path(work_ccb->ccb_h.path);
 		/* If there is PM... */
-		if (scan_info->counter == 15 &&
-		    work_ccb->ccb_h.ppriv_field1 != 0) {
-			/* Save PM probe result. */
-			scan_info->found = work_ccb->ccb_h.ppriv_field1;
-			/* Report SIM that PM is present. */
-			bzero(&cts, sizeof(cts));
-			xpt_setup_ccb(&cts.ccb_h, scan_info->request_ccb->ccb_h.path, 1);
-			cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
-			cts.type = CTS_TYPE_CURRENT_SETTINGS;
-			cts.xport_specific.sata.pm_present = 1;
-			cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
-			xpt_action((union ccb *)&cts);
+		if (scan_info->counter == 15) {
+			if (work_ccb->ccb_h.ppriv_field1 != 0) {
+				/* Save PM probe result. */
+				scan_info->found = work_ccb->ccb_h.ppriv_field1;
+			} else {
+				struct ccb_trans_settings cts;
+
+				/* Report SIM that PM is absent. */
+				bzero(&cts, sizeof(cts));
+				xpt_setup_ccb(&cts.ccb_h,
+				    scan_info->request_ccb->ccb_h.path, 1);
+				cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+				cts.type = CTS_TYPE_CURRENT_SETTINGS;
+				cts.xport_specific.sata.pm_present = 1;
+				cts.xport_specific.sata.valid = CTS_SATA_VALID_PM;
+				xpt_action((union ccb *)&cts);
+			}
 		}
 take_next:
 		/* Take next device. Wrap from 15 (PM) to 0. */


More information about the p4-projects mailing list