svn commit: r249199 - in head/sys: cam cam/ata dev/ata

Marius Strobl marius at FreeBSD.org
Sat Apr 6 13:39:04 UTC 2013


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


More information about the svn-src-all mailing list