Improve SATA Asynchronous Notification feature support in CAM:
- make SATA SIMs announce capabilities to handle SDB with Notification bit; - make PMP driver honor this SIMs capability; - make SATA XPT to negotiate and enable this feature for ATAPI devices. This feature allows supporting SATA ATAPI devices to inform system about some events happened, that may require attention. In my case this allows LG GH22LS50 SATA DVR-RW drive to report tray open/close events. Events reported to CAM in form of AC_SCSI_AEN async. Further they could be used as a hints for checking device status and reporting media change to upper layers, for example, via spoiling mechanism of GEOM.
This commit is contained in:
parent
235ab70e0a
commit
8d169381e4
@ -533,7 +533,8 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
pmp_default_timeout * 1000);
|
||||
ata_pm_write_cmd(ataio, 0x60, 15, 0xf);
|
||||
ata_pm_write_cmd(ataio, 0x60, 15, 0x07 |
|
||||
((softc->caps & CTS_SATA_CAPS_H_AN) ? 0x08 : 0));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -672,7 +673,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
|
||||
cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION;
|
||||
cts.xport_specific.sata.caps = softc->caps &
|
||||
(CTS_SATA_CAPS_H_PMREQ | CTS_SATA_CAPS_H_DMAAA);
|
||||
(CTS_SATA_CAPS_H_PMREQ |
|
||||
CTS_SATA_CAPS_H_DMAAA |
|
||||
CTS_SATA_CAPS_H_AN);
|
||||
cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
xpt_free_path(dpath);
|
||||
|
@ -87,6 +87,7 @@ typedef enum {
|
||||
PROBE_SETPM,
|
||||
PROBE_SETAPST,
|
||||
PROBE_SETDMAAA,
|
||||
PROBE_SETAN,
|
||||
PROBE_SET_MULTI,
|
||||
PROBE_INQUIRY,
|
||||
PROBE_FULL_INQUIRY,
|
||||
@ -103,6 +104,7 @@ static char *probe_action_text[] = {
|
||||
"PROBE_SETPM",
|
||||
"PROBE_SETAPST",
|
||||
"PROBE_SETDMAAA",
|
||||
"PROBE_SETAN",
|
||||
"PROBE_SET_MULTI",
|
||||
"PROBE_INQUIRY",
|
||||
"PROBE_FULL_INQUIRY",
|
||||
@ -436,6 +438,19 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
(softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
|
||||
0, 0x02);
|
||||
break;
|
||||
case PROBE_SETAN:
|
||||
cam_fill_ataio(ataio,
|
||||
1,
|
||||
probedone,
|
||||
CAM_DIR_NONE,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
30*1000);
|
||||
ata_28bit_cmd(ataio, ATA_SETFEATURES,
|
||||
(softc->caps & CTS_SATA_CAPS_H_AN) ? 0x10 : 0x90,
|
||||
0, 0x05);
|
||||
break;
|
||||
case PROBE_SET_MULTI:
|
||||
{
|
||||
u_int sectors, bytecount;
|
||||
@ -1027,6 +1042,16 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case PROBE_SETDMAAA:
|
||||
if ((ident_buf->satasupport & ATA_SUPPORT_ASYNCNOTIF) &&
|
||||
(!(softc->caps & CTS_SATA_CAPS_H_AN)) !=
|
||||
(!(ident_buf->sataenabled & ATA_SUPPORT_ASYNCNOTIF))) {
|
||||
PROBE_SET_ACTION(softc, PROBE_SETAN);
|
||||
xpt_release_ccb(done_ccb);
|
||||
xpt_schedule(periph, priority);
|
||||
return;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case PROBE_SETAN:
|
||||
notsata:
|
||||
if (path->device->protocol == PROTO_ATA) {
|
||||
PROBE_SET_ACTION(softc, PROBE_SET_MULTI);
|
||||
|
@ -889,6 +889,7 @@ struct ccb_trans_settings_sata {
|
||||
#define CTS_SATA_CAPS_H_PMREQ 0x00000001
|
||||
#define CTS_SATA_CAPS_H_APST 0x00000002
|
||||
#define CTS_SATA_CAPS_H_DMAAA 0x00000010 /* Auto-activation */
|
||||
#define CTS_SATA_CAPS_H_AN 0x00000020 /* Async. notification */
|
||||
#define CTS_SATA_CAPS_D 0xffff0000
|
||||
#define CTS_SATA_CAPS_D_PMREQ 0x00010000
|
||||
#define CTS_SATA_CAPS_D_APST 0x00020000
|
||||
|
@ -914,7 +914,8 @@ ahci_ch_attach(device_t dev)
|
||||
CTS_SATA_CAPS_H_APST |
|
||||
CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
|
||||
}
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA;
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA |
|
||||
CTS_SATA_CAPS_H_AN;
|
||||
}
|
||||
rid = ch->unit;
|
||||
if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
@ -2721,6 +2722,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb)
|
||||
if ((ch->caps & AHCI_CAP_SNCQ) &&
|
||||
(ch->quirks & AHCI_Q_NOAA) == 0)
|
||||
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
|
||||
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
|
||||
cts->xport_specific.sata.caps &=
|
||||
ch->user[ccb->ccb_h.target_id].caps;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
|
@ -138,6 +138,7 @@ mvs_ch_attach(device_t dev)
|
||||
CTS_SATA_CAPS_H_APST |
|
||||
CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
|
||||
}
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_AN;
|
||||
}
|
||||
rid = ch->unit;
|
||||
if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
@ -861,6 +862,8 @@ mvs_legacy_intr(device_t dev)
|
||||
if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
|
||||
device_printf(dev, "timeout waiting for read DRQ\n");
|
||||
et = MVS_ERR_TIMEOUT;
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
ch->toslots |= (1 << slot->slot);
|
||||
goto end_finished;
|
||||
}
|
||||
ATA_INSW_STRM(ch->r_mem, ATA_DATA,
|
||||
@ -880,6 +883,8 @@ mvs_legacy_intr(device_t dev)
|
||||
device_printf(dev,
|
||||
"timeout waiting for write DRQ\n");
|
||||
et = MVS_ERR_TIMEOUT;
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
ch->toslots |= (1 << slot->slot);
|
||||
goto end_finished;
|
||||
}
|
||||
ATA_OUTSW_STRM(ch->r_mem, ATA_DATA,
|
||||
@ -1325,6 +1330,8 @@ mvs_legacy_execute_transaction(struct mvs_slot *slot)
|
||||
if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) {
|
||||
device_printf(dev,
|
||||
"timeout waiting for write DRQ\n");
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
ch->toslots |= (1 << slot->slot);
|
||||
mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
@ -1351,6 +1358,8 @@ mvs_legacy_execute_transaction(struct mvs_slot *slot)
|
||||
/* Wait for ready to write ATAPI command block */
|
||||
if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) {
|
||||
device_printf(dev, "timeout waiting for ATAPI !BUSY\n");
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
ch->toslots |= (1 << slot->slot);
|
||||
mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
@ -1367,6 +1376,8 @@ mvs_legacy_execute_transaction(struct mvs_slot *slot)
|
||||
if (timeout <= 0) {
|
||||
device_printf(dev,
|
||||
"timeout waiting for ATAPI command ready\n");
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
ch->toslots |= (1 << slot->slot);
|
||||
mvs_end_transaction(slot, MVS_ERR_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
@ -2205,6 +2216,7 @@ mvsaction(struct cam_sim *sim, union ccb *ccb)
|
||||
cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
|
||||
// if (ch->pm_level)
|
||||
// cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
|
||||
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
|
||||
cts->xport_specific.sata.caps &=
|
||||
ch->user[ccb->ccb_h.target_id].caps;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
@ -2212,6 +2224,9 @@ mvsaction(struct cam_sim *sim, union ccb *ccb)
|
||||
cts->xport_specific.sata.revision = d->revision;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
|
||||
cts->xport_specific.sata.caps = d->caps;
|
||||
if (cts->type == CTS_TYPE_CURRENT_SETTINGS/* &&
|
||||
(ch->quirks & MVS_Q_GENIIE) == 0*/)
|
||||
cts->xport_specific.sata.caps &= ~CTS_SATA_CAPS_H_AN;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
}
|
||||
cts->xport_specific.sata.mode = d->mode;
|
||||
|
@ -474,6 +474,7 @@ siis_ch_attach(device_t dev)
|
||||
ch->curr[i] = ch->user[i];
|
||||
if (ch->pm_level)
|
||||
ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ;
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_AN;
|
||||
}
|
||||
mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
|
||||
rid = ch->unit;
|
||||
@ -1869,6 +1870,7 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
|
||||
cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
|
||||
if (ch->pm_level)
|
||||
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
|
||||
cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_AN;
|
||||
cts->xport_specific.sata.caps &=
|
||||
ch->user[ccb->ccb_h.target_id].caps;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
@ -1876,6 +1878,9 @@ siisaction(struct cam_sim *sim, union ccb *ccb)
|
||||
cts->xport_specific.sata.revision = d->revision;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
|
||||
cts->xport_specific.sata.caps = d->caps;
|
||||
if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
|
||||
(ch->quirks & SIIS_Q_SNTF) == 0)
|
||||
cts->xport_specific.sata.caps &= ~CTS_SATA_CAPS_H_AN;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
}
|
||||
cts->xport_specific.sata.mode = d->mode;
|
||||
|
@ -135,6 +135,7 @@ struct ata_params {
|
||||
#define ATA_SUPPORT_AUTOACTIVATE 0x0004
|
||||
#define ATA_SUPPORT_IFPWRMNGT 0x0008
|
||||
#define ATA_SUPPORT_INORDERDATA 0x0010
|
||||
#define ATA_SUPPORT_ASYNCNOTIF 0x0020
|
||||
#define ATA_SUPPORT_SOFTSETPRESERVE 0x0040
|
||||
/*79*/ u_int16_t sataenabled;
|
||||
#define ATA_ENABLED_DAPST 0x0080
|
||||
|
Loading…
Reference in New Issue
Block a user