Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 May 2010 10:49:37 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 177549 for review
Message-ID:  <201005011049.o41Anb8n082602@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@177549?ac=10

Change 177549 by mav@mav_mavtest on 2010/05/01 10:49:14

	Make SATA XPT negotiate some SATA-specific capabilities between
	the device and the SIM.

Affected files ...

.. //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.c#40 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#87 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#41 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#109 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#39 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.c#40 (text+ko) ====

@@ -123,7 +123,7 @@
 };
 
 #ifndef MINIMALISTIC
-static const char scsicmd_opts[] = "a:c:i:o:r";
+static const char scsicmd_opts[] = "a:c:dfi:o:r";
 static const char readdefect_opts[] = "f:GP";
 static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
 #endif
@@ -2184,6 +2184,8 @@
 	int c, data_bytes = 0;
 	int cdb_len = 0;
 	int atacmd_len = 0;
+	int dmacmd = 0;
+	int fpdmacmd = 0;
 	int need_res = 0;
 	char *datastr = NULL, *tstr, *resstr = NULL;
 	int error = 0;
@@ -2246,6 +2248,12 @@
 			 */
 			optind += hook.got;
 			break;
+		case 'd':
+			dmacmd = 1;
+			break;
+		case 'f':
+			fpdmacmd = 1;
+			break;
 		case 'i':
 			if (arglist & CAM_ARG_CMD_OUT) {
 				warnx("command must either be "
@@ -2422,6 +2430,10 @@
 		bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len);
 		if (need_res)
 			ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT;
+		if (dmacmd)
+			ccb->ataio.cmd.flags |= CAM_ATAIO_DMA;
+		if (fpdmacmd)
+			ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA;
 
 		cam_fill_ataio(&ccb->ataio,
 		      /*retries*/ retry_count,
@@ -2843,6 +2855,10 @@
 			fprintf(stdout, "%sNumber of tags: %d\n", pathstr,
 				sata->tags);
 		}
+		if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) {
+			fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr,
+				sata->caps);
+		}
 	}
 	if (cts->protocol == PROTO_SCSI) {
 		struct ccb_trans_settings_scsi *scsi=

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#87 (text+ko) ====

@@ -88,6 +88,9 @@
 	PROBE_IDENTIFY,
 	PROBE_SPINUP,
 	PROBE_SETMODE,
+	PROBE_SETPM,
+	PROBE_SETAPST,
+	PROBE_SETDMAAA,
 	PROBE_SET_MULTI,
 	PROBE_INQUIRY,
 	PROBE_FULL_INQUIRY,
@@ -101,6 +104,9 @@
 	"PROBE_IDENTIFY",
 	"PROBE_SPINUP",
 	"PROBE_SETMODE",
+	"PROBE_SETPM",
+	"PROBE_SETAPST",
+	"PROBE_SETDMAAA",
 	"PROBE_SET_MULTI",
 	"PROBE_INQUIRY",
 	"PROBE_FULL_INQUIRY",
@@ -132,6 +138,7 @@
 	uint32_t	pm_prv;
 	int		restart;
 	int		spinup;
+	u_int		caps;
 	struct cam_periph *periph;
 } probe_softc;
 
@@ -393,6 +400,45 @@
 		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
 		break;
 	}
+	case PROBE_SETPM:
+		cam_fill_ataio(ataio,
+		    1,
+		    probedone,
+		    CAM_DIR_NONE,
+		    0,
+		    NULL,
+		    0,
+		    30*1000);
+		ata_28bit_cmd(ataio, ATA_SETFEATURES,
+		    (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90,
+		    0, 0x03);
+		break;
+	case PROBE_SETAPST:
+		cam_fill_ataio(ataio,
+		    1,
+		    probedone,
+		    CAM_DIR_NONE,
+		    0,
+		    NULL,
+		    0,
+		    30*1000);
+		ata_28bit_cmd(ataio, ATA_SETFEATURES,
+		    (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90,
+		    0, 0x07);
+		break;
+	case PROBE_SETDMAAA:
+		cam_fill_ataio(ataio,
+		    1,
+		    probedone,
+		    CAM_DIR_NONE,
+		    0,
+		    NULL,
+		    0,
+		    30*1000);
+		ata_28bit_cmd(ataio, ATA_SETFEATURES,
+		    (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90,
+		    0, 0x02);
+		break;
 	case PROBE_SET_MULTI:
 	{
 		u_int sectors, bytecount;
@@ -879,6 +925,69 @@
 		xpt_schedule(periph, priority);
 		return;
 	case PROBE_SETMODE:
+	{
+		u_int caps = 0;
+
+		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)
+			caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H;
+		if (ident_buf->satacapabilities != 0xffff) {
+			if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV)
+				caps |= CTS_SATA_CAPS_D_PMREQ;
+			if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST)
+				caps |= CTS_SATA_CAPS_D_APST;
+		}
+		/* Mask unwanted 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_USER_SETTINGS;
+		xpt_action((union ccb *)&cts);
+		if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+			caps &= cts.xport_specific.sata.caps;
+		/* 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;
+		xpt_action((union ccb *)&cts);
+		softc->caps = caps;
+		if (ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) {
+			PROBE_SET_ACTION(softc, PROBE_SETPM);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		}
+		/* FALLTHROUGH */
+	}
+	case PROBE_SETPM:
+		if (ident_buf->satacapabilities != 0xffff &&
+		    ident_buf->satacapabilities & ATA_SUPPORT_DAPST) {
+			PROBE_SET_ACTION(softc, PROBE_SETAPST);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		}
+		/* FALLTHROUGH */
+	case PROBE_SETAPST:
+		if (ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) {
+			PROBE_SET_ACTION(softc, PROBE_SETDMAAA);
+			xpt_release_ccb(done_ccb);
+			xpt_schedule(periph, priority);
+			return;
+		}
+		/* FALLTHROUGH */
+	case PROBE_SETDMAAA:
+notsata:
 		if (path->device->protocol == PROTO_ATA) {
 			PROBE_SET_ACTION(softc, PROBE_SET_MULTI);
 		} else {

==== //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#41 (text+ko) ====

@@ -837,12 +837,21 @@
 #define	CTS_SATA_VALID_PM		0x08
 #define	CTS_SATA_VALID_TAGS		0x10
 #define	CTS_SATA_VALID_ATAPI		0x20
+#define	CTS_SATA_VALID_CAPS		0x40
 	int		mode;		/* Legacy PATA mode */
 	u_int 		bytecount;	/* Length of PIO transaction */
 	int		revision;	/* SATA revision */
 	u_int 		pm_present;	/* PM is present (XPT->SIM) */
 	u_int 		tags;		/* Number of allowed tags */
 	u_int 		atapi;		/* Length of ATAPI CDB */
+	u_int 		caps;		/* Device and host SATA caps. */
+#define	CTS_SATA_CAPS_H			0x0000ffff
+#define	CTS_SATA_CAPS_H_PMREQ		0x00000001
+#define	CTS_SATA_CAPS_H_APST		0x00000002
+#define	CTS_SATA_CAPS_H_DMAAA		0x00000010 /* Auto-activation */
+#define	CTS_SATA_CAPS_D			0xffff0000
+#define	CTS_SATA_CAPS_D_PMREQ		0x00010000
+#define	CTS_SATA_CAPS_D_APST		0x00020000
 };
 
 /* Get/Set transfer rate/width/disconnection/tag queueing settings */

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#109 (text+ko) ====

@@ -860,7 +860,14 @@
 		ch->user[i].mode = 0;
 		ch->user[i].bytecount = 8192;
 		ch->user[i].tags = ch->numslots;
+		ch->user[i].caps = 0;
 		ch->curr[i] = ch->user[i];
+		if (ch->pm_level) {
+			ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ |
+			    CTS_SATA_CAPS_H_APST |
+			    CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST;
+		}
+		ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA;
 	}
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -2464,6 +2471,8 @@
 			ch->pm_present = cts->xport_specific.sata.pm_present;
 		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
 			d->atapi = cts->xport_specific.sata.atapi;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
+			d->caps = cts->xport_specific.sata.caps;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		break;
 	}
@@ -2496,9 +2505,23 @@
 				cts->xport_specific.sata.valid |=
 				    CTS_SATA_VALID_REVISION;
 			}
+			cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D;
+			if (ch->pm_level) {
+				if (ch->caps & (AHCI_CAP_PSC | AHCI_CAP_SSC))
+					cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ;
+				if (ch->caps2 & AHCI_CAP2_APST)
+					cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_APST;
+				if (ch->caps & AHCI_CAP_SNCQ)
+					cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA;
+				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.mode = d->mode;
 		cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#39 (text+ko) ====

@@ -372,6 +372,7 @@
 	u_int			bytecount;
 	u_int			atapi;
 	u_int			tags;
+	u_int			caps;
 };
 
 /* structure describing an ATA channel */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005011049.o41Anb8n082602>