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.
This commit is contained in:
parent
fab0a47626
commit
45cc6dda97
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user