Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Feb 2010 10:06:03 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r203421 - in head/sys: cam/ata sys
Message-ID:  <201002031006.o13A63Ov057997@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Feb  3 10:06:03 2010
New Revision: 203421
URL: http://svn.freebsd.org/changeset/base/203421

Log:
  MFp4:
  Add Power Up In Stand-by feature support. Device with PUIS enabled
  require explicit command to do initial spin-up. Mark that command
  with CAM_HIGH_POWER flag, to allow CAM manage staggered spin-up.

Modified:
  head/sys/cam/ata/ata_all.c
  head/sys/cam/ata/ata_xpt.c
  head/sys/sys/ata.h

Modified: head/sys/cam/ata/ata_all.c
==============================================================================
--- head/sys/cam/ata/ata_all.c	Wed Feb  3 08:42:08 2010	(r203420)
+++ head/sys/cam/ata/ata_all.c	Wed Feb  3 10:06:03 2010	(r203421)
@@ -146,6 +146,9 @@ ata_op_string(struct ata_cmd *cmd)
 	        case 0x03: return ("SETFEATURES SET TRANSFER MODE");
 	        case 0x02: return ("SETFEATURES ENABLE WCACHE");
 	        case 0x82: return ("SETFEATURES DISABLE WCACHE");
+	        case 0x06: return ("SETFEATURES ENABLE PUIS");
+	        case 0x86: return ("SETFEATURES DISABLE PUIS");
+	        case 0x07: return ("SETFEATURES SPIN-UP");
 	        case 0xaa: return ("SETFEATURES ENABLE RCACHE");
 	        case 0x55: return ("SETFEATURES DISABLE RCACHE");
 	        }

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c	Wed Feb  3 08:42:08 2010	(r203420)
+++ head/sys/cam/ata/ata_xpt.c	Wed Feb  3 10:06:03 2010	(r203421)
@@ -86,6 +86,7 @@ PERIPHDRIVER_DECLARE(aprobe, probe_drive
 typedef enum {
 	PROBE_RESET,
 	PROBE_IDENTIFY,
+	PROBE_SPINUP,
 	PROBE_SETMODE,
 	PROBE_SET_MULTI,
 	PROBE_INQUIRY,
@@ -98,6 +99,7 @@ typedef enum {
 static char *probe_action_text[] = {
 	"PROBE_RESET",
 	"PROBE_IDENTIFY",
+	"PROBE_SPINUP",
 	"PROBE_SETMODE",
 	"PROBE_SET_MULTI",
 	"PROBE_INQUIRY",
@@ -129,6 +131,7 @@ typedef struct {
 	uint32_t	pm_pid;
 	uint32_t	pm_prv;
 	int		restart;
+	int		spinup;
 	struct cam_periph *periph;
 } probe_softc;
 
@@ -212,7 +215,7 @@ proberegister(struct cam_periph *periph,
 		return(CAM_REQ_CMP_ERR);
 	}
 
-	softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_NOWAIT);
+	softc = (probe_softc *)malloc(sizeof(*softc), M_CAMXPT, M_ZERO | M_NOWAIT);
 
 	if (softc == NULL) {
 		printf("proberegister: Unable to probe new device. "
@@ -314,6 +317,19 @@ probestart(struct cam_periph *periph, un
 		else
 			ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
 		break;
+	case PROBE_SPINUP:
+		if (bootverbose)
+			xpt_print(path, "Spinning up device\n");
+		cam_fill_ataio(ataio,
+		      1,
+		      probedone,
+		      /*flags*/CAM_DIR_NONE | CAM_HIGH_POWER,
+		      0,
+		      /*data_ptr*/NULL,
+		      /*dxfer_len*/0,
+		      30 * 1000);
+		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_PUIS_SPINUP, 0, 0);
+		break;
 	case PROBE_SETMODE:
 	{
 		int mode, wantmode;
@@ -768,8 +784,18 @@ noerror:
 		ata_bpack(ident_buf->revision, ident_buf->revision, sizeof(ident_buf->revision));
 		ata_btrim(ident_buf->serial, sizeof(ident_buf->serial));
 		ata_bpack(ident_buf->serial, ident_buf->serial, sizeof(ident_buf->serial));
+		/* Device may need spin-up before IDENTIFY become valid. */
+		if ((ident_buf->config & ATA_RESP_INCOMPLETE) ||
+		    ((ident_buf->support.command2 & ATA_SUPPORT_STANDBY) &&
+		     (ident_buf->enabled.command2 & ATA_SUPPORT_STANDBY) &&
+		     (ident_buf->support.command2 & ATA_SUPPORT_SPINUP) &&
+		      softc->spinup == 0)) {
+			PROBE_SET_ACTION(softc, PROBE_SPINUP);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		}
 		ident_buf = &path->device->ident_data;
-
 		if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) == 0) {
 			/* Check that it is the same device. */
 			if (bcmp(softc->ident_data.model, ident_buf->model,
@@ -829,6 +855,14 @@ noerror:
 		xpt_schedule(periph, priority);
 		return;
 	}
+	case PROBE_SPINUP:
+		if (bootverbose)
+			xpt_print(path, "Spin-up done\n");
+		softc->spinup = 1;
+		PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
+		xpt_release_ccb(done_ccb);
+		xpt_schedule(periph, priority);
+		return;
 	case PROBE_SETMODE:
 		if (path->device->protocol == PROTO_ATA) {
 			PROBE_SET_ACTION(softc, PROBE_SET_MULTI);

Modified: head/sys/sys/ata.h
==============================================================================
--- head/sys/sys/ata.h	Wed Feb  3 08:42:08 2010	(r203420)
+++ head/sys/sys/ata.h	Wed Feb  3 10:06:03 2010	(r203421)
@@ -48,6 +48,7 @@ struct ata_params {
 #define ATA_DRQ_SLOW                    0x0000  /* cpu 3 ms delay */
 #define ATA_DRQ_INTR                    0x0020  /* interrupt 10 ms delay */
 #define ATA_DRQ_FAST                    0x0040  /* accel 50 us delay */
+#define ATA_RESP_INCOMPLETE             0x0004
 
 /*001*/ u_int16_t       cylinders;              /* # of cylinders */
 	u_int16_t       reserved2;
@@ -345,6 +346,9 @@ struct ata_params {
 #define         ATA_SF_SETXFER          0x03    /* set transfer mode */
 #define         ATA_SF_ENAB_WCACHE      0x02    /* enable write cache */
 #define         ATA_SF_DIS_WCACHE       0x82    /* disable write cache */
+#define         ATA_SF_ENAB_PUIS        0x06    /* enable PUIS */
+#define         ATA_SF_DIS_PUIS         0x86    /* disable PUIS */
+#define         ATA_SF_PUIS_SPINUP      0x07    /* PUIS spin-up */
 #define         ATA_SF_ENAB_RCACHE      0xaa    /* enable readahead cache */
 #define         ATA_SF_DIS_RCACHE       0x55    /* disable readahead cache */
 #define         ATA_SF_ENAB_RELIRQ      0x5d    /* enable release interrupt */



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