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:
Marius Strobl 2013-04-06 13:39:02 +00:00
parent 367437755d
commit 2e1eb33217
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=249199
5 changed files with 96 additions and 36 deletions

View File

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

View File

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

View File

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

View File

@ -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 {

View File

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