Unbreak ATA_NO_48BIT_DMA with ATA_CAM by treating 48-bit DMA as an
optional property with PATA transport. Reviewed by: mav MFC after: 3 days
This commit is contained in:
parent
060b59e700
commit
053dbbe97a
@ -35,8 +35,9 @@ struct ccb_ataio;
|
||||
struct cam_periph;
|
||||
union ccb;
|
||||
|
||||
#define SID_AEN 0x04 /* Abuse inq_flags bit to track enabled AEN. */
|
||||
#define SID_DMA 0x10 /* Abuse inq_flags bit to track enabled DMA. */
|
||||
#define SID_DMA48 0x01 /* Abuse inq_flags bit to track enabled DMA48. */
|
||||
#define SID_AEN 0x04 /* Abuse inq_flags bit to track enabled AEN. */
|
||||
#define SID_DMA 0x10 /* Abuse inq_flags bit to track enabled DMA. */
|
||||
|
||||
struct ata_cmd {
|
||||
u_int8_t flags; /* ATA command flags */
|
||||
|
@ -75,18 +75,19 @@ typedef enum {
|
||||
} ada_state;
|
||||
|
||||
typedef enum {
|
||||
ADA_FLAG_PACK_INVALID = 0x001,
|
||||
ADA_FLAG_CAN_48BIT = 0x002,
|
||||
ADA_FLAG_CAN_FLUSHCACHE = 0x004,
|
||||
ADA_FLAG_CAN_NCQ = 0x008,
|
||||
ADA_FLAG_CAN_DMA = 0x010,
|
||||
ADA_FLAG_NEED_OTAG = 0x020,
|
||||
ADA_FLAG_WENT_IDLE = 0x040,
|
||||
ADA_FLAG_CAN_TRIM = 0x080,
|
||||
ADA_FLAG_OPEN = 0x100,
|
||||
ADA_FLAG_SCTX_INIT = 0x200,
|
||||
ADA_FLAG_CAN_CFA = 0x400,
|
||||
ADA_FLAG_CAN_POWERMGT = 0x800
|
||||
ADA_FLAG_PACK_INVALID = 0x0001,
|
||||
ADA_FLAG_CAN_48BIT = 0x0002,
|
||||
ADA_FLAG_CAN_FLUSHCACHE = 0x0004,
|
||||
ADA_FLAG_CAN_NCQ = 0x0008,
|
||||
ADA_FLAG_CAN_DMA = 0x0010,
|
||||
ADA_FLAG_NEED_OTAG = 0x0020,
|
||||
ADA_FLAG_WENT_IDLE = 0x0040,
|
||||
ADA_FLAG_CAN_TRIM = 0x0080,
|
||||
ADA_FLAG_OPEN = 0x0100,
|
||||
ADA_FLAG_SCTX_INIT = 0x0200,
|
||||
ADA_FLAG_CAN_CFA = 0x0400,
|
||||
ADA_FLAG_CAN_POWERMGT = 0x0800,
|
||||
ADA_FLAG_CAN_DMA48 = 0x1000
|
||||
} ada_flags;
|
||||
|
||||
typedef enum {
|
||||
@ -899,6 +900,15 @@ adaasync(void *callback_arg, u_int32_t code,
|
||||
softc->flags |= ADA_FLAG_CAN_DMA;
|
||||
else
|
||||
softc->flags &= ~ADA_FLAG_CAN_DMA;
|
||||
if (cgd.ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) {
|
||||
softc->flags |= ADA_FLAG_CAN_48BIT;
|
||||
if (cgd.inq_flags & SID_DMA48)
|
||||
softc->flags |= ADA_FLAG_CAN_DMA48;
|
||||
else
|
||||
softc->flags &= ~ADA_FLAG_CAN_DMA48;
|
||||
} else
|
||||
softc->flags &= ~(ADA_FLAG_CAN_48BIT |
|
||||
ADA_FLAG_CAN_DMA48);
|
||||
if ((cgd.ident_data.satacapabilities & ATA_SUPPORT_NCQ) &&
|
||||
(cgd.inq_flags & SID_DMA) && (cgd.inq_flags & SID_CmdQue))
|
||||
softc->flags |= ADA_FLAG_CAN_NCQ;
|
||||
@ -1067,8 +1077,11 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
if ((cgd->ident_data.capabilities1 & ATA_SUPPORT_DMA) &&
|
||||
(cgd->inq_flags & SID_DMA))
|
||||
softc->flags |= ADA_FLAG_CAN_DMA;
|
||||
if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48)
|
||||
if (cgd->ident_data.support.command2 & ATA_SUPPORT_ADDRESS48) {
|
||||
softc->flags |= ADA_FLAG_CAN_48BIT;
|
||||
if (cgd->inq_flags & SID_DMA48)
|
||||
softc->flags |= ADA_FLAG_CAN_DMA48;
|
||||
}
|
||||
if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
|
||||
softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
|
||||
if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
|
||||
@ -1455,7 +1468,7 @@ adastart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
} else if ((softc->flags & ADA_FLAG_CAN_48BIT) &&
|
||||
(lba + count >= ATA_MAX_28BIT_LBA ||
|
||||
count > 256)) {
|
||||
if (softc->flags & ADA_FLAG_CAN_DMA) {
|
||||
if (softc->flags & ADA_FLAG_CAN_DMA48) {
|
||||
if (bp->bio_cmd == BIO_READ) {
|
||||
ata_48bit_cmd(ataio, ATA_READ_DMA48,
|
||||
0, lba, count);
|
||||
|
@ -965,19 +965,22 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
xpt_schedule(periph, priority);
|
||||
return;
|
||||
case PROBE_SETMODE:
|
||||
if (path->device->transport != XPORT_SATA)
|
||||
goto notsata;
|
||||
/* Set supported bits. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
|
||||
if (path->device->transport == XPORT_SATA &&
|
||||
cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
|
||||
caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
|
||||
else if (path->device->transport == XPORT_ATA &&
|
||||
cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS)
|
||||
caps = cts.xport_specific.ata.caps & CTS_ATA_CAPS_H;
|
||||
else
|
||||
caps = 0;
|
||||
if (ident_buf->satacapabilities != 0xffff) {
|
||||
if (path->device->transport == XPORT_SATA &&
|
||||
ident_buf->satacapabilities != 0xffff) {
|
||||
if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV)
|
||||
caps |= CTS_SATA_CAPS_D_PMREQ;
|
||||
if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST)
|
||||
@ -989,19 +992,42 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
|
||||
if (path->device->transport == XPORT_SATA &&
|
||||
cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
|
||||
caps &= cts.xport_specific.sata.caps;
|
||||
else if (path->device->transport == XPORT_ATA &&
|
||||
cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS)
|
||||
caps &= cts.xport_specific.ata.caps;
|
||||
else
|
||||
caps = 0;
|
||||
/*
|
||||
* Remember what transport thinks about 48-bit DMA. If
|
||||
* capability information is not provided or transport is
|
||||
* SATA, we take support for granted.
|
||||
*/
|
||||
if (!(path->device->inq_flags & SID_DMA) ||
|
||||
(path->device->transport == XPORT_ATA &&
|
||||
(cts.xport_specific.ata.valid & CTS_ATA_VALID_CAPS) &&
|
||||
!(caps & CTS_ATA_CAPS_H_DMA48)))
|
||||
path->device->inq_flags &= ~SID_DMA48;
|
||||
else
|
||||
path->device->inq_flags |= SID_DMA48;
|
||||
/* Store result to SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.xport_specific.sata.caps = caps;
|
||||
cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
|
||||
if (path->device->transport == XPORT_SATA) {
|
||||
cts.xport_specific.sata.caps = caps;
|
||||
cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
|
||||
} else {
|
||||
cts.xport_specific.ata.caps = caps;
|
||||
cts.xport_specific.ata.valid = CTS_ATA_VALID_CAPS;
|
||||
}
|
||||
xpt_action((union ccb *)&cts);
|
||||
softc->caps = caps;
|
||||
if (path->device->transport != XPORT_SATA)
|
||||
goto notsata;
|
||||
if ((ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) &&
|
||||
(!(softc->caps & CTS_SATA_CAPS_H_PMREQ)) !=
|
||||
(!(ident_buf->sataenabled & ATA_SUPPORT_IFPWRMNGT))) {
|
||||
@ -1154,6 +1180,11 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
caps &= cts.xport_specific.sata.caps;
|
||||
else
|
||||
caps = 0;
|
||||
/* Remember what transport thinks about AEN. */
|
||||
if (caps & CTS_SATA_CAPS_H_AN)
|
||||
path->device->inq_flags |= SID_AEN;
|
||||
else
|
||||
path->device->inq_flags &= ~SID_AEN;
|
||||
/* Store result to SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
@ -1163,11 +1194,6 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
softc->caps = caps;
|
||||
/* Remember what transport thinks about AEN. */
|
||||
if (softc->caps & CTS_SATA_CAPS_H_AN)
|
||||
path->device->inq_flags |= SID_AEN;
|
||||
else
|
||||
path->device->inq_flags &= ~SID_AEN;
|
||||
xpt_async(AC_GETDEV_CHANGED, path, NULL);
|
||||
if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) {
|
||||
path->device->flags &= ~CAM_DEV_UNCONFIGURED;
|
||||
@ -2077,4 +2103,3 @@ ata_announce_periph(struct cam_periph *periph)
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
@ -896,9 +896,14 @@ struct ccb_trans_settings_pata {
|
||||
#define CTS_ATA_VALID_MODE 0x01
|
||||
#define CTS_ATA_VALID_BYTECOUNT 0x02
|
||||
#define CTS_ATA_VALID_ATAPI 0x20
|
||||
#define CTS_ATA_VALID_CAPS 0x40
|
||||
int mode; /* Mode */
|
||||
u_int bytecount; /* Length of PIO transaction */
|
||||
u_int atapi; /* Length of ATAPI CDB */
|
||||
u_int caps; /* Device and host SATA caps. */
|
||||
#define CTS_ATA_CAPS_H 0x0000ffff
|
||||
#define CTS_ATA_CAPS_H_DMA48 0x00000001 /* 48-bit DMA */
|
||||
#define CTS_ATA_CAPS_D 0xffff0000
|
||||
};
|
||||
|
||||
struct ccb_trans_settings_sata {
|
||||
|
@ -136,10 +136,15 @@ ata_attach(device_t dev)
|
||||
ch->user[i].bytecount = MAXPHYS;
|
||||
ch->user[i].caps = 0;
|
||||
ch->curr[i] = ch->user[i];
|
||||
if (ch->pm_level > 0)
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_PMREQ;
|
||||
if (ch->pm_level > 1)
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_D_PMREQ;
|
||||
if (ch->flags & ATA_SATA) {
|
||||
if (ch->pm_level > 0)
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_H_PMREQ;
|
||||
if (ch->pm_level > 1)
|
||||
ch->user[i].caps |= CTS_SATA_CAPS_D_PMREQ;
|
||||
} else {
|
||||
if (!(ch->flags & ATA_NO_48BIT_DMA))
|
||||
ch->user[i].caps |= CTS_ATA_CAPS_H_DMA48;
|
||||
}
|
||||
}
|
||||
callout_init(&ch->poll_callout, 1);
|
||||
|
||||
@ -835,6 +840,8 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
|
||||
d->bytecount = cts->xport_specific.ata.bytecount;
|
||||
if (cts->xport_specific.ata.valid & CTS_ATA_VALID_ATAPI)
|
||||
d->atapi = cts->xport_specific.ata.atapi;
|
||||
if (cts->xport_specific.ata.valid & CTS_ATA_VALID_CAPS)
|
||||
d->caps = cts->xport_specific.ata.caps;
|
||||
}
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
break;
|
||||
@ -875,14 +882,12 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
|
||||
}
|
||||
cts->xport_specific.sata.caps &=
|
||||
ch->user[ccb->ccb_h.target_id].caps;
|
||||
cts->xport_specific.sata.valid |=
|
||||
CTS_SATA_VALID_CAPS;
|
||||
} else {
|
||||
cts->xport_specific.sata.revision = d->revision;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
|
||||
cts->xport_specific.sata.caps = d->caps;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
}
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
|
||||
cts->xport_specific.sata.atapi = d->atapi;
|
||||
cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
|
||||
} else {
|
||||
@ -893,6 +898,17 @@ ataaction(struct cam_sim *sim, union ccb *ccb)
|
||||
cts->xport_specific.ata.valid |= CTS_ATA_VALID_MODE;
|
||||
cts->xport_specific.ata.bytecount = d->bytecount;
|
||||
cts->xport_specific.ata.valid |= CTS_ATA_VALID_BYTECOUNT;
|
||||
if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
|
||||
cts->xport_specific.ata.caps =
|
||||
d->caps & CTS_ATA_CAPS_D;
|
||||
if (!(ch->flags & ATA_NO_48BIT_DMA))
|
||||
cts->xport_specific.ata.caps |=
|
||||
CTS_ATA_CAPS_H_DMA48;
|
||||
cts->xport_specific.ata.caps &=
|
||||
ch->user[ccb->ccb_h.target_id].caps;
|
||||
} else
|
||||
cts->xport_specific.ata.caps = d->caps;
|
||||
cts->xport_specific.ata.valid |= CTS_ATA_VALID_CAPS;
|
||||
cts->xport_specific.ata.atapi = d->atapi;
|
||||
cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user