summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2013-04-06 13:39:02 +0000
committermarius <marius@FreeBSD.org>2013-04-06 13:39:02 +0000
commit053dbbe97a5e84a0c6e577d1dabc0ddb5924c17f (patch)
tree5dc4e16e55847be970e650459a546653fcc5dfe1
parent060b59e700abcb69e41867ccb7bb7f4335334e03 (diff)
downloadFreeBSD-src-053dbbe97a5e84a0c6e577d1dabc0ddb5924c17f.zip
FreeBSD-src-053dbbe97a5e84a0c6e577d1dabc0ddb5924c17f.tar.gz
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
-rw-r--r--sys/cam/ata/ata_all.h5
-rw-r--r--sys/cam/ata/ata_da.c41
-rw-r--r--sys/cam/ata/ata_xpt.c51
-rw-r--r--sys/cam/cam_ccb.h5
-rw-r--r--sys/dev/ata/ata-all.c30
5 files changed, 96 insertions, 36 deletions
diff --git a/sys/cam/ata/ata_all.h b/sys/cam/ata/ata_all.h
index 848a8fc..25732b6 100644
--- a/sys/cam/ata/ata_all.h
+++ b/sys/cam/ata/ata_all.h
@@ -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 */
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c
index 13a442f..00a2d28 100644
--- a/sys/cam/ata/ata_da.c
+++ b/sys/cam/ata/ata_da.c
@@ -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);
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c
index 2e3aa24..a9100cd 100644
--- a/sys/cam/ata/ata_xpt.c
+++ b/sys/cam/ata/ata_xpt.c
@@ -965,19 +965,22 @@ noerror:
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 @@ noerror:
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 @@ notsata:
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 @@ notsata:
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");
}
-
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 17dda0a..a2c041a 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -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 {
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c
index 3327a9d..8ca1cc4 100644
--- a/sys/dev/ata/ata-all.c
+++ b/sys/dev/ata/ata-all.c
@@ -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;
}
OpenPOWER on IntegriCloud