Author: marius
Date: Sat Apr  6 13:39:02 2013
New Revision: 249199
URL: http://svnweb.freebsd.org/changeset/base/249199

Log:
  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

Modified:
  head/sys/cam/ata/ata_all.h
  head/sys/cam/ata/ata_da.c
  head/sys/cam/ata/ata_xpt.c
  head/sys/cam/cam_ccb.h
  head/sys/dev/ata/ata-all.c

Modified: head/sys/cam/ata/ata_all.h
==============================================================================
--- head/sys/cam/ata/ata_all.h  Sat Apr  6 13:25:18 2013        (r249198)
+++ head/sys/cam/ata/ata_all.h  Sat Apr  6 13:39:02 2013        (r249199)
@@ -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 */

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c   Sat Apr  6 13:25:18 2013        (r249198)
+++ head/sys/cam/ata/ata_da.c   Sat Apr  6 13:39:02 2013        (r249199)
@@ -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 c
                        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, v
        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, unio
                        } 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);

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c  Sat Apr  6 13:25:18 2013        (r249198)
+++ head/sys/cam/ata/ata_xpt.c  Sat Apr  6 13:39:02 2013        (r249199)
@@ -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 *p
        }
        printf("\n");
 }
-

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h      Sat Apr  6 13:25:18 2013        (r249198)
+++ head/sys/cam/cam_ccb.h      Sat Apr  6 13:39:02 2013        (r249199)
@@ -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 {

Modified: head/sys/dev/ata/ata-all.c
==============================================================================
--- head/sys/dev/ata/ata-all.c  Sat Apr  6 13:25:18 2013        (r249198)
+++ head/sys/dev/ata/ata-all.c  Sat Apr  6 13:39:02 2013        (r249199)
@@ -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
                                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
                                }
                                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
                        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;
                }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to