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.
This commit is contained in:
mav 2010-02-03 10:06:03 +00:00
parent fab0a47626
commit 45cc6dda97
3 changed files with 43 additions and 2 deletions

View File

@ -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");
}

View File

@ -86,6 +86,7 @@ PERIPHDRIVER_DECLARE(aprobe, probe_driver);
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, void *arg)
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, union ccb *start_ccb)
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 @@ device_fail: if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) {
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 @@ device_fail: if (cam_periph_error(done_ccb, 0, 0, NULL) == ERESTART) {
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);

View File

@ -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 */