diff options
author | marius <marius@FreeBSD.org> | 2013-04-06 13:39:02 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2013-04-06 13:39:02 +0000 |
commit | 053dbbe97a5e84a0c6e577d1dabc0ddb5924c17f (patch) | |
tree | 5dc4e16e55847be970e650459a546653fcc5dfe1 | |
parent | 060b59e700abcb69e41867ccb7bb7f4335334e03 (diff) | |
download | FreeBSD-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.h | 5 | ||||
-rw-r--r-- | sys/cam/ata/ata_da.c | 41 | ||||
-rw-r--r-- | sys/cam/ata/ata_xpt.c | 51 | ||||
-rw-r--r-- | sys/cam/cam_ccb.h | 5 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.c | 30 |
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; } |