Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Nov 2009 12:01:26 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 170892 for review
Message-ID:  <200911211201.nALC1QOS084723@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/chv.cgi?CH=170892

Change 170892 by mav@mav_mavtest on 2009/11/21 12:00:40

	Improve transfer settings API between ATA XPT and SIM:
	- give SIM number of supported tags per device. It allows to properly handle
	devices with lower number of tags supported. Change slot allocation logic in
	ahci(4) and siis(4) to handle this limitation as effectively as possible.
	- negotiate ATA PIO and DMA modes with SIM.
	- make SATA SIMs store/report devices connection speed (SATA revision). As side
	effect it allows PMP to report connection speeds for devices connected to it.

Affected files ...

.. //depot/projects/scottl-camlock/src/sbin/camcontrol/camcontrol.c#30 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.c#23 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#23 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_pmp.c#20 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_xpt.c#59 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_ccb.h#32 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#130 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#82 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#28 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.c#35 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.h#24 edit
.. //depot/projects/scottl-camlock/src/sys/dev/siis/siis.c#21 edit
.. //depot/projects/scottl-camlock/src/sys/dev/siis/siis.h#6 edit

Differences ...

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

@@ -226,6 +226,12 @@
 static int atapm(struct cam_device *device, int argc, char **argv,
 			    char *combinedopt, int retry_count, int timeout);
 #endif /* MINIMALISTIC */
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
 
 camcontrol_optret
 getoption(char *arg, cam_cmdmask *cmdnum, cam_argmask *argnum, 
@@ -950,21 +956,29 @@
 
 		if (sas->valid & CTS_SAS_VALID_SPEED)
 			speed = sas->bitrate;
+	} else if (ccb->cts.transport == XPORT_ATA) {
+		struct ccb_trans_settings_ata *ata =
+		    &ccb->cts.xport_specific.ata;
+
+		if (ata->valid & CTS_ATA_VALID_PIOMODE)
+			speed = ata_mode2speed(ata->piomode);
+		if (ata->valid & CTS_ATA_VALID_DMAMODE)
+			speed = max(speed, ata_mode2speed(ata->dmamode));
 	} else if (ccb->cts.transport == XPORT_SATA) {
-		struct ccb_trans_settings_sata *sata =
+		struct	ccb_trans_settings_sata *sata =
 		    &ccb->cts.xport_specific.sata;
 
-		if (sata->valid & CTS_SATA_VALID_SPEED)
-			speed = sata->bitrate;
+		if (sata->valid & CTS_SATA_VALID_REVISION)
+			speed = ata_revision2speed(sata->revision);
 	}
 
 	mb = speed / 1000;
 	if (mb > 0) {
-		fprintf(stdout, "%s%d: %d.%03dMB/s transfers ",
+		fprintf(stdout, "%s%d: %d.%03dMB/s transfers",
 			device->device_name, device->dev_unit_num,
 			mb, speed % 1000);
 	} else {
-		fprintf(stdout, "%s%d: %dKB/s transfers ",
+		fprintf(stdout, "%s%d: %dKB/s transfers",
 			device->device_name, device->dev_unit_num,
 			speed);
 	}
@@ -975,7 +989,7 @@
 
 		if (((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)
 		 && (spi->sync_offset != 0))
-			fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
+			fprintf(stdout, " (%d.%03dMHz, offset %d", freq / 1000,
 				freq % 1000, spi->sync_offset);
 
 		if (((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
@@ -995,18 +1009,28 @@
 		struct ccb_trans_settings_ata *ata =
 		    &ccb->cts.xport_specific.ata;
 
-		if (ata->valid & CTS_ATA_VALID_BYTECOUNT) {
-			fprintf(stdout, "(PIO size %dbytes)",
-			    ata->bytecount);
-		}
+		printf(" (");
+		if (ata->valid & CTS_ATA_VALID_PIOMODE)
+			printf("%s, ", ata_mode2string(ata->piomode));
+		if (ata->valid & CTS_ATA_VALID_DMAMODE)
+			printf("%s, ", ata_mode2string(ata->dmamode));
+		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
+			printf("PIO size %dbytes", ata->bytecount);
+		printf(")");
 	} else if (ccb->cts.transport == XPORT_SATA) {
 		struct ccb_trans_settings_sata *sata =
 		    &ccb->cts.xport_specific.sata;
 
-		if (sata->valid & CTS_SATA_VALID_BYTECOUNT) {
-			fprintf(stdout, "(PIO size %dbytes)",
-			    sata->bytecount);
-		}
+		printf(" (");
+		if (sata->valid & CTS_SATA_VALID_REVISION)
+			printf("SATA %d.x, ", sata->revision);
+		if (sata->valid & CTS_SATA_VALID_PIOMODE)
+			printf("%s, ", ata_mode2string(sata->piomode));
+		if (sata->valid & CTS_SATA_VALID_DMAMODE)
+			printf("%s, ", ata_mode2string(sata->dmamode));
+		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
+			printf("PIO size %dbytes", sata->bytecount);
+		printf(")");
 	}
 
 	if (ccb->cts.protocol == PROTO_SCSI) {

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

@@ -501,22 +501,122 @@
 }
 
 int
-ata_max_mode(struct ata_params *ap, int mode, int maxmode)
+ata_max_piomode(struct ata_params *ap, int maxmode)
+{
+
+	if (maxmode == 0)
+		return (ata_max_pmode(ap));
+	return (min(maxmode, ata_max_pmode(ap)));
+}
+
+int
+ata_max_dmamode(struct ata_params *ap, int maxmode)
 {
 
-    if (maxmode && mode > maxmode)
-	mode = maxmode;
+	if (maxmode == 0 && ata_max_umode(ap) > 0)
+		return (ata_max_umode(ap));
+	if (maxmode >= ATA_UDMA0 && ata_max_umode(ap) > 0)
+		return (min(maxmode, ata_max_umode(ap)));
+	if (maxmode == 0 && ata_max_wmode(ap) > 0)
+		return (ata_max_wmode(ap));
+	if (ata_max_wmode(ap) > 0)
+		return (min(maxmode, ata_max_wmode(ap)));
+	return (-1);
+}
 
-    if (mode >= ATA_UDMA0 && ata_max_umode(ap) > 0)
-	return (min(mode, ata_max_umode(ap)));
+char *
+ata_mode2string(int mode)
+{
+    switch (mode) {
+    case -1: return "UNSUPPORTED";
+    case 0: return "NONE";
+    case ATA_PIO0: return "PIO0";
+    case ATA_PIO1: return "PIO1";
+    case ATA_PIO2: return "PIO2";
+    case ATA_PIO3: return "PIO3";
+    case ATA_PIO4: return "PIO4";
+    case ATA_WDMA0: return "WDMA0";
+    case ATA_WDMA1: return "WDMA1";
+    case ATA_WDMA2: return "WDMA2";
+    case ATA_UDMA0: return "UDMA0";
+    case ATA_UDMA1: return "UDMA1";
+    case ATA_UDMA2: return "UDMA2";
+    case ATA_UDMA3: return "UDMA3";
+    case ATA_UDMA4: return "UDMA4";
+    case ATA_UDMA5: return "UDMA5";
+    case ATA_UDMA6: return "UDMA6";
+    default:
+	if (mode & ATA_DMA_MASK)
+	    return "BIOSDMA";
+	else
+	    return "BIOSPIO";
+    }
+}
 
-    if (mode >= ATA_WDMA0 && ata_max_wmode(ap) > 0)
-	return (min(mode, ata_max_wmode(ap)));
+u_int
+ata_mode2speed(int mode)
+{
+	switch (mode) {
+	case ATA_PIO0:
+	default:
+		return (3300);
+	case ATA_PIO1:
+		return (5200);
+	case ATA_PIO2:
+		return (8300);
+	case ATA_PIO3:
+		return (11100);
+	case ATA_PIO4:
+		return (16700);
+	case ATA_WDMA0:
+		return (4200);
+	case ATA_WDMA1:
+		return (13300);
+	case ATA_WDMA2:
+		return (16700);
+	case ATA_UDMA0:
+		return (16700);
+	case ATA_UDMA1:
+		return (25000);
+	case ATA_UDMA2:
+		return (33300);
+	case ATA_UDMA3:
+		return (44400);
+	case ATA_UDMA4:
+		return (66700);
+	case ATA_UDMA5:
+		return (100000);
+	case ATA_UDMA6:
+		return (133000);
+	}
+}
 
-    if (mode > ata_max_pmode(ap))
-	return (min(mode, ata_max_pmode(ap)));
+u_int
+ata_revision2speed(int revision)
+{
+	switch (revision) {
+	case 1:
+	default:
+		return (150000);
+	case 2:
+		return (300000);
+	case 3:
+		return (600000);
+	}
+}
 
-    return (mode);
+int
+ata_speed2revision(u_int speed)
+{
+	switch (speed) {
+	case 150000:
+	default:
+		return (1);
+	case 300000:
+		return (2);
+	case 600000:
+		return (3);
+	}
 }
 
 int

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#23 (text+ko) ====

@@ -113,7 +113,13 @@
 int	ata_max_pmode(struct ata_params *ap);
 int	ata_max_wmode(struct ata_params *ap);
 int	ata_max_umode(struct ata_params *ap);
-int	ata_max_mode(struct ata_params *ap, int mode, int maxmode);
+int	ata_max_piomode(struct ata_params *ap, int maxmode);
+int	ata_max_dmamode(struct ata_params *ap, int maxmode);
+
+char *	ata_mode2string(int mode);
+u_int	ata_mode2speed(int mode);
+u_int	ata_revision2speed(int revision);
+int	ata_speed2revision(u_int speed);
 
 int	ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
 int	ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);

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

@@ -516,6 +516,7 @@
 static void
 pmpdone(struct cam_periph *periph, union ccb *done_ccb)
 {
+	struct ccb_trans_settings cts;
 	struct pmp_softc *softc;
 	struct ccb_ataio *ataio;
 	union ccb *work_ccb;
@@ -635,6 +636,19 @@
 		    done_ccb->ataio.res.sector_count;
 		if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) {
 			printf("PM status: %d - %08x\n", softc->pm_step, res);
+			/* Report device speed. */
+			if (xpt_create_path(&dpath, periph,
+			    xpt_path_path_id(periph->path),
+			    softc->pm_step, 0) == CAM_REQ_CMP) {
+				bzero(&cts, sizeof(cts));
+				xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NORMAL);
+				cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+				cts.type = CTS_TYPE_CURRENT_SETTINGS;
+				cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
+				cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION;
+				xpt_action((union ccb *)&cts);
+				xpt_free_path(dpath);
+			}
 			softc->found |= (1 << softc->pm_step);
 			softc->pm_step++;
 		} else {

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

@@ -275,7 +275,7 @@
 static void
 probestart(struct cam_periph *periph, union ccb *start_ccb)
 {
-	/* Probe the device that our peripheral driver points to */
+	struct ccb_trans_settings cts;
 	struct ccb_ataio *ataio;
 	struct ccb_scsiio *csio;
 	probe_softc *softc;
@@ -333,6 +333,73 @@
 			ata_28bit_cmd(ataio, ATA_ATAPI_IDENTIFY, 0, 0, 0);
 		break;
 	case PROBE_SETMODE:
+	{
+		int piomode, dmamode, wantpio, wantdma, mode;
+
+		wantpio = 0;
+		wantdma = 0;
+		/* Fetch user modes from SIM. */
+		bzero(&cts, sizeof(cts));
+		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+		cts.type = CTS_TYPE_USER_SETTINGS;
+		xpt_action((union ccb *)&cts);
+		if (path->device->transport == XPORT_ATA) {
+			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_PIOMODE)
+				wantpio = cts.xport_specific.ata.piomode;
+			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_DMAMODE)
+				wantdma = cts.xport_specific.ata.dmamode;
+		} else {
+			if (cts.xport_specific.ata.valid & CTS_SATA_VALID_PIOMODE)
+				wantpio = cts.xport_specific.sata.piomode;
+			if (cts.xport_specific.ata.valid & CTS_SATA_VALID_DMAMODE)
+				wantdma = cts.xport_specific.sata.dmamode;
+		}
+negotiate:
+		/* Honor device capabilities. */
+		wantpio = piomode = ata_max_piomode(ident_buf, wantpio);
+		wantdma = dmamode = ata_max_dmamode(ident_buf, wantdma);
+		/* Report modes to SIM. */
+		bzero(&cts, sizeof(cts));
+		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+		cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+		cts.type = CTS_TYPE_CURRENT_SETTINGS;
+		if (path->device->transport == XPORT_ATA) {
+			cts.xport_specific.ata.piomode = piomode;
+			cts.xport_specific.ata.dmamode = dmamode;
+			cts.xport_specific.ata.valid =
+			    CTS_ATA_VALID_PIOMODE | CTS_ATA_VALID_DMAMODE;
+		} else {
+			cts.xport_specific.sata.piomode = piomode;
+			cts.xport_specific.sata.dmamode = dmamode;
+			cts.xport_specific.sata.valid =
+			    CTS_SATA_VALID_PIOMODE | CTS_SATA_VALID_DMAMODE;
+		}
+		xpt_action((union ccb *)&cts);
+		/* Fetch user modes from SIM. */
+		bzero(&cts, sizeof(cts));
+		xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+		cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+		cts.type = CTS_TYPE_CURRENT_SETTINGS;
+		xpt_action((union ccb *)&cts);
+		if (path->device->transport == XPORT_ATA) {
+			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_PIOMODE)
+				piomode = cts.xport_specific.ata.piomode;
+			if (cts.xport_specific.ata.valid & CTS_ATA_VALID_DMAMODE)
+				dmamode = cts.xport_specific.ata.dmamode;
+		} else {
+			if (cts.xport_specific.ata.valid & CTS_SATA_VALID_PIOMODE)
+				piomode = cts.xport_specific.sata.piomode;
+			if (cts.xport_specific.ata.valid & CTS_SATA_VALID_DMAMODE)
+				dmamode = cts.xport_specific.sata.dmamode;
+		}
+		/* If SIM disagree - renegotiate. */
+		if (piomode != wantpio || dmamode != wantdma)
+			goto negotiate;
+		if (dmamode > 0)
+			mode = dmamode;
+		else
+			mode = piomode;
 		cam_fill_ataio(ataio,
 		      1,
 		      probedone,
@@ -341,12 +408,11 @@
 		      /*data_ptr*/NULL,
 		      /*dxfer_len*/0,
 		      30 * 1000);
-		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0,
-		    ata_max_mode(ident_buf, ATA_UDMA6, ATA_UDMA6));
+		ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode);
 		break;
+	}
 	case PROBE_SET_MULTI:
 	{
-		struct ccb_trans_settings cts;
 		u_int sectors;
 
 		sectors = max(1, min(ident_buf->sectors_intr & 0xff, 16));
@@ -564,6 +630,7 @@
 static void
 probedone(struct cam_periph *periph, union ccb *done_ccb)
 {
+	struct ccb_trans_settings cts;
 	struct ata_params *ident_buf;
 	probe_softc *softc;
 	struct cam_path *path;
@@ -619,9 +686,7 @@
 			PROBE_SET_ACTION(softc, PROBE_IDENTIFY);
 		} else if (sign == 0x9669 &&
 		    done_ccb->ccb_h.target_id == 15) {
-			struct ccb_trans_settings cts;
-
-				/* Report SIM that PM is present. */
+			/* Report SIM that PM is present. */
 			bzero(&cts, sizeof(cts));
 			xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
 			cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
@@ -716,11 +781,17 @@
 			    ATA_QUEUE_LEN(ident_buf->queue) + 1;
 		}
 		ata_find_quirk(path->device);
-		/* XXX: If not all tags allowed, we must to tell SIM which are. */
-		if (path->device->mintags < path->bus->sim->max_tagged_dev_openings)
-			path->device->mintags = path->device->maxtags = 0;
 		if (path->device->mintags != 0 &&
 		    path->bus->sim->max_tagged_dev_openings != 0) {
+			/* Report SIM which tags are allowed. */
+			bzero(&cts, sizeof(cts));
+			xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
+			cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+			cts.type = CTS_TYPE_CURRENT_SETTINGS;
+			cts.xport_specific.sata.tags = path->device->maxtags;
+			cts.xport_specific.sata.valid = CTS_SATA_VALID_TAGS;
+			xpt_action((union ccb *)&cts);
+			/* Reconfigure queues for tagged queueing. */
 			xpt_start_tags(path);
 		}
 		ata_device_transport(path);

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

@@ -818,20 +818,28 @@
 
 struct ccb_trans_settings_ata {
 	u_int     	valid;		/* Which fields to honor */
-#define	CTS_ATA_VALID_MODE		0x01
+#define	CTS_ATA_VALID_PIOMODE		0x01
+#define	CTS_ATA_VALID_DMAMODE		0x02
 #define	CTS_ATA_VALID_BYTECOUNT		0x04
-	u_int32_t 	mode;
+	int	 	piomode;	/* PIO mode */
+	int	 	dmamode;	/* DMA mode */
 	u_int 		bytecount;	/* Length of PIO transaction */
 };
 
 struct ccb_trans_settings_sata {
 	u_int     	valid;		/* Which fields to honor */
-#define	CTS_SATA_VALID_SPEED		0x01
-#define	CTS_SATA_VALID_PM		0x02
+#define	CTS_SATA_VALID_PIOMODE		0x01
+#define	CTS_SATA_VALID_DMAMODE		0x02
 #define	CTS_SATA_VALID_BYTECOUNT	0x04
-	u_int32_t 	bitrate;	/* Mbps */
+#define	CTS_SATA_VALID_REVISION		0x08
+#define	CTS_SATA_VALID_PM		0x10
+#define	CTS_SATA_VALID_TAGS		0x20
+	int	 	piomode;	/* Legacy PATA PIO mode */
+	int	 	dmamode;	/* Legacy PATA DMA mode */
+	u_int 		bytecount;	/* Length of PIO transaction */
+	u_int	 	revision;	/* SATA revision */
 	u_int 		pm_present;	/* PM is present (XPT->SIM) */
-	u_int 		bytecount;	/* Length of PIO transaction */
+	u_int 		tags;		/* Number of allowed tags */
 };
 
 /* Get/Set transfer rate/width/disconnection/tag queueing settings */

==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#130 (text+ko) ====

@@ -1140,12 +1140,21 @@
 		if (sas->valid & CTS_SAS_VALID_SPEED)
 			speed = sas->bitrate;
 	}
+	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
+		struct	ccb_trans_settings_ata *ata =
+		    &cts.xport_specific.ata;
+
+		if (ata->valid & CTS_ATA_VALID_PIOMODE)
+			speed = ata_mode2speed(ata->piomode);
+		if (ata->valid & CTS_ATA_VALID_DMAMODE)
+			speed = max(speed, ata_mode2speed(ata->dmamode));
+	}
 	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
 		struct	ccb_trans_settings_sata *sata =
 		    &cts.xport_specific.sata;
 
-		if (sata->valid & CTS_SATA_VALID_SPEED)
-			speed = sata->bitrate;
+		if (sata->valid & CTS_SATA_VALID_REVISION)
+			speed = ata_revision2speed(sata->revision);
 	}
 
 	mb = speed / 1000;
@@ -1195,15 +1204,29 @@
 		struct ccb_trans_settings_ata *ata =
 		    &cts.xport_specific.ata;
 
+		printf(" (");
+		if (ata->valid & CTS_ATA_VALID_PIOMODE)
+			printf("%s, ", ata_mode2string(ata->piomode));
+		if (ata->valid & CTS_ATA_VALID_DMAMODE)
+			printf("%s, ", ata_mode2string(ata->dmamode));
 		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
-			printf(" (PIO size %dbytes)", ata->bytecount);
+			printf("PIO size %dbytes", ata->bytecount);
+		printf(")");
 	}
 	if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
 		struct ccb_trans_settings_sata *sata =
 		    &cts.xport_specific.sata;
 
+		printf(" (");
+		if (sata->valid & CTS_SATA_VALID_REVISION)
+			printf("SATA %d.x, ", sata->revision);
+		if (sata->valid & CTS_SATA_VALID_PIOMODE)
+			printf("%s, ", ata_mode2string(sata->piomode));
+		if (sata->valid & CTS_SATA_VALID_DMAMODE)
+			printf("%s, ", ata_mode2string(sata->dmamode));
 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
-			printf(" (PIO size %dbytes)", sata->bytecount);
+			printf("PIO size %dbytes", sata->bytecount);
+		printf(")");
 	}
 	if (path->device->inq_flags & SID_CmdQue
 	 || path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {

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

@@ -772,7 +772,7 @@
 	struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
 	struct ahci_channel *ch = device_get_softc(dev);
 	struct cam_devq *devq;
-	int rid, error;
+	int rid, error, i;
 
 	ch->dev = dev;
 	ch->unit = (intptr_t)device_get_ivars(dev);
@@ -785,6 +785,14 @@
 	    device_get_unit(dev), "pm_level", &ch->pm_level);
 	if (ch->pm_level > 3)
 		callout_init_mtx(&ch->pm_timer, &ch->mtx, 0);
+	for (i = 0; i < 16; i++) {
+		ch->user[i].revision = 0;
+		ch->user[i].piomode = 0;
+		ch->user[i].dmamode = 0;
+		ch->user[i].bytecount = 8192;
+		ch->user[i].tags = 2;
+		ch->curr[i] = ch->user[i];
+	}
 	/* Limit speed for my onboard JMicron external port.
 	 * It is not eSATA really. */
 	if (pci_get_devid(ctlr->dev) == 0x2363197b &&
@@ -1271,6 +1279,10 @@
 		if (ch->numtslots != 0 &&
 		    ch->taggedtarget != ccb->ccb_h.target_id)
 			return (1);
+		/* Tagged command while we have no supported tag free. */
+		if (((~ch->oslots) & (0xffffffff >> (32 -
+		    ch->curr[ccb->ccb_h.target_id].tags))) == 0)
+			return (1);
 	} else {
 		/* Untagged command while tagged are active. */
 		if (ch->numrslots != 0 && ch->numtslots != 0)
@@ -1294,15 +1306,21 @@
 {
 	struct ahci_channel *ch = device_get_softc(dev);
 	struct ahci_slot *slot;
-	int tag;
+	int tag, tags;
 
 	/* Choose empty slot. */
+	tags = ch->numslots;
+	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
+	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA))
+		tags = ch->curr[ccb->ccb_h.target_id].tags;
 	tag = ch->lastslot;
-	while (ch->slot[tag].state != AHCI_SLOT_EMPTY) {
-		if (++tag >= ch->numslots)
+	while (1) {
+		if (tag >= tags)
 			tag = 0;
-		KASSERT(tag != ch->lastslot, ("ahci: ALL SLOTS BUSY!"));
-	}
+		if (ch->slot[tag].state == AHCI_SLOT_EMPTY)
+			break;
+		tag++;
+	};
 	ch->lastslot = tag;
 	/* Occupy chosen slot. */
 	slot = &ch->slot[tag];
@@ -1311,6 +1329,7 @@
 	if (ch->numrslots == 0 && ch->pm_level > 3)
 		callout_stop(&ch->pm_timer);
 	/* Update channel stats. */
+	ch->oslots |= (1 << slot->slot);
 	ch->numrslots++;
 	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
 	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
@@ -1631,6 +1650,7 @@
 		ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
 	}
 	/* Free slot. */
+	ch->oslots &= ~(1 << slot->slot);
 	ch->rslots &= ~(1 << slot->slot);
 	ch->aslots &= ~(1 << slot->slot);
 	slot->state = AHCI_SLOT_EMPTY;
@@ -1660,7 +1680,7 @@
 	} else
 		xpt_done(ccb);
 	/* Unfreeze frozen command. */
-	if (ch->frozen && ch->numrslots == 0) {
+	if (ch->frozen && !ahci_check_collision(dev, ch->frozen)) {
 		union ccb *fccb = ch->frozen;
 		ch->frozen = NULL;
 		ahci_begin_transaction(dev, fccb);
@@ -2121,10 +2141,24 @@
 	case XPT_SET_TRAN_SETTINGS:
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct	ahci_device *d; 
 
-		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) {
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else
+			d = &ch->user[ccb->ccb_h.target_id];
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
+			d->revision = cts->xport_specific.sata.revision;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PIOMODE)
+			d->piomode = cts->xport_specific.sata.piomode;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_DMAMODE)
+			d->dmamode = cts->xport_specific.sata.dmamode;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
+			d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
+			d->tags = min(ch->numslots, cts->xport_specific.sata.tags);
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM)
 			ch->pm_present = cts->xport_specific.sata.pm_present;
-		}
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;
@@ -2133,36 +2167,43 @@
 	/* Get default/user set transfer settings for the target */
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct  ahci_device *d;
 		uint32_t status;
 
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else
+			d = &ch->user[ccb->ccb_h.target_id];
 		cts->protocol = PROTO_ATA;
 		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cts->transport = XPORT_SATA;
 		cts->transport_version = XPORT_VERSION_UNSPECIFIED;
 		cts->proto_specific.valid = 0;
 		cts->xport_specific.sata.valid = 0;
-		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS &&
+		    (ccb->ccb_h.target_id == 15 ||
+		    (ccb->ccb_h.target_id == 0 && !ch->pm_present))) {
 			status = ATA_INL(ch->r_mem, AHCI_P_SSTS) & ATA_SS_SPD_MASK;
-		else
-			status = ATA_INL(ch->r_mem, AHCI_P_SCTL) & ATA_SC_SPD_MASK;
-		if (status & ATA_SS_SPD_GEN3) {
-			cts->xport_specific.sata.bitrate = 600000;
-			cts->xport_specific.sata.valid |= CTS_SATA_VALID_SPEED;
-		} else if (status & ATA_SS_SPD_GEN2) {
-			cts->xport_specific.sata.bitrate = 300000;
-			cts->xport_specific.sata.valid |= CTS_SATA_VALID_SPEED;
-		} else if (status & ATA_SS_SPD_GEN1) {
-			cts->xport_specific.sata.bitrate = 150000;
-			cts->xport_specific.sata.valid |= CTS_SATA_VALID_SPEED;
+			if (status & 0x0f0) {
+				cts->xport_specific.sata.revision =
+				    (status & 0x0f0) >> 4;
+				cts->xport_specific.sata.valid |=
+				    CTS_SATA_VALID_REVISION;
+			}
+		} else if (d->revision) {
+			cts->xport_specific.sata.revision = d->revision;
+			cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
 		}
-		if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
-			cts->xport_specific.sata.pm_present =
-			    (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_PMA) ?
-			    1 : 0;
-		} else {
-			cts->xport_specific.sata.pm_present = ch->pm_present;
-		}
+		cts->xport_specific.sata.piomode = d->piomode;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_PIOMODE;
+		cts->xport_specific.sata.dmamode = d->dmamode;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_DMAMODE;
+		cts->xport_specific.sata.bytecount = d->bytecount;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
+		cts->xport_specific.sata.pm_present = ch->pm_present;
 		cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM;
+		cts->xport_specific.sata.tags = d->tags;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;

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

@@ -340,6 +340,14 @@
     struct callout              timeout;        /* Execution timeout */
 };
 
+struct ahci_device {
+	u_int			revision;
+	int			piomode;
+	int			dmamode;
+	u_int			bytecount;
+	u_int			tags;
+};
+
 /* structure describing an ATA channel */
 struct ahci_channel {
 	device_t		dev;            /* Device handle */
@@ -362,6 +370,7 @@
 	struct mtx		mtx;		/* state lock */
 	int			devices;        /* What is present */
 	int			pm_present;	/* PM presence reported */
+	uint32_t		oslots;		/* Occupied slots */
 	uint32_t		rslots;		/* Running slots */
 	uint32_t		aslots;		/* Slots with atomic commands  */
 	int			numrslots;	/* Number of running slots */
@@ -372,6 +381,9 @@
 	int			taggedtarget;	/* Last tagged target */
 	union ccb		*frozen;	/* Frozen command */
 	struct callout		pm_timer;	/* Power management events */
+
+	struct ahci_device	user[16];	/* User-specified settings */
+	struct ahci_device	curr[16];	/* Current settings */
 };
 
 /* structure describing a AHCI controller */

==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.c#35 (text+ko) ====

@@ -131,7 +131,7 @@
 ata_attach(device_t dev)
 {
     struct ata_channel *ch = device_get_softc(dev);
-    int error, rid;
+    int error, rid, i;
 #ifdef ATA_CAM
     struct cam_devq *devq;
 #endif
@@ -150,8 +150,12 @@
     TAILQ_INIT(&ch->ata_queue);
     TASK_INIT(&ch->conntask, 0, ata_conn_event, dev);
 #ifdef ATA_CAM
-    ch->bytecount[0] = 16 * 512;
-    ch->bytecount[1] = 16 * 512;
+	for (i = 0; i < 16; i++) {
+		ch->user[i].piomode = 0;
+		ch->user[i].dmamode = 0;
+		ch->user[i].bytecount = 8192;
+		ch->curr[i] = ch->user[i];
+	}
 #endif
 
     /* reset the controller HW, the channel and device(s) */
@@ -1280,7 +1284,7 @@
 			request->flags |= ATA_R_WRITE;
 	}
 	request->transfersize = min(request->bytecount,
-	    ch->bytecount[ccb->ccb_h.target_id]);
+	    ch->curr[ccb->ccb_h.target_id].bytecount);
 //	request->callback = ad_done;
 	request->retries = 0;
 	request->timeout = (ccb->ccb_h.timeout + 999) / 1000;
@@ -1405,12 +1409,20 @@
 	case XPT_SET_TRAN_SETTINGS:
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct	ata_cam_device *d; 
 
-		if (ccb->ccb_h.target_id >= 0 && ccb->ccb_h.target_id <= 1 &&
-		    (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)) {
-			ch->bytecount[ccb->ccb_h.target_id] =
-			    cts->xport_specific.ata.bytecount;
-		}
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else
+			d = &ch->user[ccb->ccb_h.target_id];
+//		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
+//			d->revision = cts->xport_specific.sata.revision;
+		if (cts->xport_specific.ata.valid & CTS_ATA_VALID_PIOMODE)
+			d->piomode = cts->xport_specific.ata.piomode;
+		if (cts->xport_specific.ata.valid & CTS_ATA_VALID_DMAMODE)
+			d->dmamode = cts->xport_specific.ata.dmamode;
+		if (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
+			d->bytecount = min(8192, cts->xport_specific.ata.bytecount);
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;
@@ -1418,16 +1430,22 @@
 	case XPT_GET_TRAN_SETTINGS:
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct  ata_cam_device *d;
 
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else
+			d = &ch->user[ccb->ccb_h.target_id];
 		cts->protocol = PROTO_ATA;
 		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
 		cts->transport = XPORT_ATA;
 		cts->transport_version = XPORT_VERSION_UNSPECIFIED;
-		if (ccb->ccb_h.target_id >= 0 && ccb->ccb_h.target_id <= 1) {
-			cts->xport_specific.valid = CTS_ATA_VALID_BYTECOUNT;
-			cts->xport_specific.ata.bytecount = 
-			    ch->bytecount[ccb->ccb_h.target_id];
-		}
+		cts->xport_specific.ata.piomode = d->piomode;
+		cts->xport_specific.ata.valid |= CTS_ATA_VALID_PIOMODE;
+		cts->xport_specific.ata.dmamode = d->dmamode;
+		cts->xport_specific.ata.valid |= CTS_ATA_VALID_DMAMODE;
+		cts->xport_specific.ata.bytecount = d->bytecount;
+		cts->xport_specific.ata.valid |= CTS_ATA_VALID_BYTECOUNT;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;

==== //depot/projects/scottl-camlock/src/sys/dev/ata/ata-all.h#24 (text+ko) ====

@@ -534,6 +534,15 @@
     int                         offset;
 };
 
+#ifdef ATA_CAM
+struct ata_cam_device {
+	u_int			revision;
+	int			piomode;
+	int			dmamode;
+	u_int			bytecount;
+};
+#endif
+
 /* structure describing an ATA channel */
 struct ata_channel {
     device_t                    dev;            /* device handle */
@@ -573,7 +582,8 @@
 #ifdef ATA_CAM
 	struct cam_sim		*sim;
 	struct cam_path		*path;
-	u_int			bytecount[2];	/* Length of PIO transaction */
+	struct ata_cam_device	user[16];       /* User-specified settings */                             
+	struct ata_cam_device	curr[16];       /* Current settings */                                    
 #endif
 };
 

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

@@ -415,12 +415,20 @@
 {
 	struct siis_channel *ch = device_get_softc(dev);
 	struct cam_devq *devq;
-	int rid, error;
+	int rid, error, i;
 
 	ch->dev = dev;
 	ch->unit = (intptr_t)device_get_ivars(dev);
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "pm_level", &ch->pm_level);
+	for (i = 0; i < 16; i++) {
+		ch->user[i].revision = 0;
+		ch->user[i].piomode = 0;
+		ch->user[i].dmamode = 0;
+		ch->user[i].bytecount = 8192;
+		ch->user[i].tags = 2;
+		ch->curr[i] = ch->user[i];
+	}
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "sata_rev", &ch->sata_rev);
 	mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF);
@@ -833,6 +841,13 @@
 
 	mtx_assert(&ch->mtx, MA_OWNED);
 	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
+	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
+		/* Tagged command while we have no supported tag free. */
+		if (((~ch->oslots) & (0x7fffffff >> (31 -
+		    ch->curr[ccb->ccb_h.target_id].tags))) == 0)
+			return (1);
+	}
+	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
 	    (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT))) {
 		/* Atomic command while anything active. */
 		if (ch->numrslots != 0)
@@ -850,21 +865,20 @@
 {
 	struct siis_channel *ch = device_get_softc(dev);
 	struct siis_slot *slot;
-	int tag;
+	int tag, tags;
 
 	mtx_assert(&ch->mtx, MA_OWNED);
 	/* Choose empty slot. */
-	tag = ch->lastslot;
-	while (ch->slot[tag].state != SIIS_SLOT_EMPTY) {
-		if (++tag >= SIIS_MAX_SLOTS)
-			tag = 0;
-		KASSERT(tag != ch->lastslot, ("siis: ALL SLOTS BUSY!"));
-	}
-	ch->lastslot = tag;
+	tags = SIIS_MAX_SLOTS;
+	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
+	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA))
+		tags = ch->curr[ccb->ccb_h.target_id].tags;
+	tag = fls((~ch->oslots) & (0x7fffffff >> (31 - tags))) - 1;
 	/* Occupy chosen slot. */
 	slot = &ch->slot[tag];
 	slot->ccb = ccb;
 	/* Update channel stats. */
+	ch->oslots |= (1 << slot->slot);
 	ch->numrslots++;
 	if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
 	    (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
@@ -1118,6 +1132,7 @@
 		ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
 	}
 	/* Free slot. */
+	ch->oslots &= ~(1 << slot->slot);
 	ch->rslots &= ~(1 << slot->slot);
 	ch->aslots &= ~(1 << slot->slot);
 	if (et != SIIS_ERR_TIMEOUT) {
@@ -1143,7 +1158,7 @@
 	} else
 		xpt_done(ccb);
 	/* Unfreeze frozen command. */
-	if (ch->frozen && ch->numrslots == 0) {
+	if (ch->frozen && !siis_check_collision(dev, ch->frozen)) {
 		union ccb *fccb = ch->frozen;
 		ch->frozen = NULL;
 		siis_begin_transaction(dev, fccb);
@@ -1554,7 +1569,22 @@
 	case XPT_SET_TRAN_SETTINGS:
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct	siis_device *d; 
 
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else
+			d = &ch->user[ccb->ccb_h.target_id];
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
+			d->revision = cts->xport_specific.sata.revision;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PIOMODE)
+			d->piomode = cts->xport_specific.sata.piomode;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_DMAMODE)
+			d->dmamode = cts->xport_specific.sata.dmamode;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
+			d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
+			d->tags = min(SIIS_MAX_SLOTS, cts->xport_specific.sata.tags);
 		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) {
 			ch->pm_present = cts->xport_specific.sata.pm_present;
 			if (ch->pm_present)
@@ -1570,30 +1600,43 @@
 	/* Get default/user set transfer settings for the target */
 	{
 		struct	ccb_trans_settings *cts = &ccb->cts;
+		struct  siis_device *d;
 		uint32_t status;
 
+		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
+			d = &ch->curr[ccb->ccb_h.target_id];
+		else

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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