svn commit: r203421 - in head/sys: cam/ata sys
Alexander Motin
mav at FreeBSD.org
Wed Feb 3 10:06:04 UTC 2010
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 */
More information about the svn-src-head
mailing list