svn commit: r203376 - in head: sbin/camcontrol sys/cam sys/cam/ata sys/dev/ahci sys/dev/ata sys/dev/siis

Alexander Motin mav at FreeBSD.org
Tue Feb 2 11:09:28 UTC 2010


Author: mav
Date: Tue Feb  2 11:09:28 2010
New Revision: 203376
URL: http://svn.freebsd.org/changeset/base/203376

Log:
  - Give ATA/SATA SIMs info about ATAPI packet size, supported by device.
  - Make ATA XPT to reject longer SCSI CDBs then supported by device, or
  any SCSI CDBs, if device doesn't support ATAPI.

Modified:
  head/sbin/camcontrol/camcontrol.c
  head/sys/cam/ata/ata_xpt.c
  head/sys/cam/cam_ccb.h
  head/sys/dev/ahci/ahci.c
  head/sys/dev/ahci/ahci.h
  head/sys/dev/ata/ata-all.c
  head/sys/dev/ata/ata-all.h
  head/sys/dev/siis/siis.c
  head/sys/dev/siis/siis.h

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sbin/camcontrol/camcontrol.c	Tue Feb  2 11:09:28 2010	(r203376)
@@ -1010,8 +1010,10 @@ camxferrate(struct cam_device *device)
 		printf(" (");
 		if (ata->valid & CTS_ATA_VALID_MODE)
 			printf("%s, ", ata_mode2string(ata->mode));
+		if ((ata->valid & CTS_ATA_VALID_ATAPI) && ata->atapi != 0)
+			printf("ATAPI %dbytes, ", ata->atapi);
 		if (ata->valid & CTS_ATA_VALID_BYTECOUNT)
-			printf("PIO size %dbytes", ata->bytecount);
+			printf("PIO %dbytes", ata->bytecount);
 		printf(")");
 	} else if (ccb->cts.transport == XPORT_SATA) {
 		struct ccb_trans_settings_sata *sata =
@@ -1022,8 +1024,10 @@ camxferrate(struct cam_device *device)
 			printf("SATA %d.x, ", sata->revision);
 		if (sata->valid & CTS_SATA_VALID_MODE)
 			printf("%s, ", ata_mode2string(sata->mode));
+		if ((sata->valid & CTS_SATA_VALID_ATAPI) && sata->atapi != 0)
+			printf("ATAPI %dbytes, ", sata->atapi);
 		if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
-			printf("PIO size %dbytes", sata->bytecount);
+			printf("PIO %dbytes", sata->bytecount);
 		printf(")");
 	}
 
@@ -2800,6 +2804,10 @@ cts_print(struct cam_device *device, str
 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
 				ata_mode2string(ata->mode));
 		}
+		if ((ata->valid & CTS_ATA_VALID_ATAPI) != 0) {
+			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
+				ata->atapi);
+		}
 		if ((ata->valid & CTS_ATA_VALID_BYTECOUNT) != 0) {
 			fprintf(stdout, "%sPIO transaction length: %d\n",
 				pathstr, ata->bytecount);
@@ -2817,6 +2825,10 @@ cts_print(struct cam_device *device, str
 			fprintf(stdout, "%sATA mode: %s\n", pathstr,
 				ata_mode2string(sata->mode));
 		}
+		if ((sata->valid & CTS_SATA_VALID_ATAPI) != 0) {
+			fprintf(stdout, "%sATAPI packet length: %d\n", pathstr,
+				sata->atapi);
+		}
 		if ((sata->valid & CTS_SATA_VALID_BYTECOUNT) != 0) {
 			fprintf(stdout, "%sPIO transaction length: %d\n",
 				pathstr, sata->bytecount);

Modified: head/sys/cam/ata/ata_xpt.c
==============================================================================
--- head/sys/cam/ata/ata_xpt.c	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/cam/ata/ata_xpt.c	Tue Feb  2 11:09:28 2010	(r203376)
@@ -1334,7 +1334,20 @@ ata_device_transport(struct cam_path *pa
 	cts.protocol = path->device->protocol;
 	cts.protocol_version = path->device->protocol_version;
 	cts.proto_specific.valid = 0;
-	cts.xport_specific.valid = 0;
+	if (ident_buf) {
+		if (path->device->transport == XPORT_ATA) {
+			cts.xport_specific.ata.atapi = 
+			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 :
+			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0;
+			cts.xport_specific.ata.valid = CTS_ATA_VALID_ATAPI;
+		} else {
+			cts.xport_specific.sata.atapi = 
+			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_16) ? 16 :
+			    ((ident_buf->config & ATA_PROTO_MASK) == ATA_PROTO_ATAPI_12) ? 12 : 0;
+			cts.xport_specific.sata.valid = CTS_SATA_VALID_ATAPI;
+		}
+	} else
+		cts.xport_specific.valid = 0;
 	xpt_action((union ccb *)&cts);
 }
 
@@ -1366,6 +1379,27 @@ ata_action(union ccb *start_ccb)
 		(*(sim->sim_action))(sim, start_ccb);
 		break;
 	}
+	case XPT_SCSI_IO:
+	{
+		struct cam_ed *device;
+		u_int	maxlen = 0;
+
+		device = start_ccb->ccb_h.path->device;
+		if (device->protocol == PROTO_SCSI &&
+		    (device->flags & CAM_DEV_IDENTIFY_DATA_VALID)) {
+			uint16_t p =
+			    device->ident_data.config & ATA_PROTO_MASK;
+
+			maxlen = (p == ATA_PROTO_ATAPI_16) ? 16 :
+			    (p == ATA_PROTO_ATAPI_12) ? 12 : 0;
+		}
+		if (start_ccb->csio.cdb_len > maxlen) {
+			start_ccb->ccb_h.status = CAM_REQ_INVALID;
+			xpt_done(start_ccb);
+			break;
+		}
+		/* FALLTHROUGH */
+	}
 	default:
 		xpt_action_default(start_ccb);
 		break;

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/cam/cam_ccb.h	Tue Feb  2 11:09:28 2010	(r203376)
@@ -823,8 +823,10 @@ struct ccb_trans_settings_ata {
 	u_int     	valid;		/* Which fields to honor */
 #define	CTS_ATA_VALID_MODE		0x01
 #define	CTS_ATA_VALID_BYTECOUNT		0x02
+#define	CTS_ATA_VALID_ATAPI		0x20
 	int		mode;		/* Mode */
 	u_int 		bytecount;	/* Length of PIO transaction */
+	u_int 		atapi;		/* Length of ATAPI CDB */
 };
 
 struct ccb_trans_settings_sata {
@@ -834,11 +836,13 @@ struct ccb_trans_settings_sata {
 #define	CTS_SATA_VALID_REVISION		0x04
 #define	CTS_SATA_VALID_PM		0x08
 #define	CTS_SATA_VALID_TAGS		0x10
+#define	CTS_SATA_VALID_ATAPI		0x20
 	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 */
 };
 
 /* Get/Set transfer rate/width/disconnection/tag queueing settings */

Modified: head/sys/dev/ahci/ahci.c
==============================================================================
--- head/sys/dev/ahci/ahci.c	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/ahci/ahci.c	Tue Feb  2 11:09:28 2010	(r203376)
@@ -2358,6 +2358,8 @@ ahciaction(struct cam_sim *sim, union cc
 			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;
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
+			d->atapi = cts->xport_specific.sata.atapi;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;
@@ -2401,6 +2403,8 @@ ahciaction(struct cam_sim *sim, union cc
 		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;
+		cts->xport_specific.sata.atapi = d->atapi;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;

Modified: head/sys/dev/ahci/ahci.h
==============================================================================
--- head/sys/dev/ahci/ahci.h	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/ahci/ahci.h	Tue Feb  2 11:09:28 2010	(r203376)
@@ -370,6 +370,7 @@ struct ahci_device {
 	int			revision;
 	int			mode;
 	u_int			bytecount;
+	u_int			atapi;
 	u_int			tags;
 };
 

Modified: head/sys/dev/ata/ata-all.c
==============================================================================
--- head/sys/dev/ata/ata-all.c	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/ata/ata-all.c	Tue Feb  2 11:09:28 2010	(r203376)
@@ -1348,6 +1348,8 @@ ata_cam_begin_transaction(device_t dev, 
 		    ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes,
 		    request->u.atapi.ccb, ccb->csio.cdb_len);
 		request->flags |= ATA_R_ATAPI;
+		if (ch->curr[ccb->ccb_h.target_id].atapi == 16)
+			request->flags |= ATA_R_ATAPI16;
 		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
 		    ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
 			request->flags |= ATA_R_DMA;
@@ -1358,7 +1360,6 @@ ata_cam_begin_transaction(device_t dev, 
 	}
 	request->transfersize = min(request->bytecount,
 	    ch->curr[ccb->ccb_h.target_id].bytecount);
-//	request->callback = ad_done;
 	request->retries = 0;
 	request->timeout = (ccb->ccb_h.timeout + 999) / 1000;
 	callout_init_mtx(&request->callout, &ch->state_mtx, CALLOUT_RETURNUNLOCKED);
@@ -1491,7 +1492,7 @@ ataaction(struct cam_sim *sim, union ccb
 		if (ch->flags & ATA_SATA) {
 			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
 				d->revision = cts->xport_specific.sata.revision;
-			if (cts->xport_specific.ata.valid & CTS_SATA_VALID_MODE) {
+			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) {
 				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
 					d->mode = ATA_SETMODE(ch->dev,
 					    ccb->ccb_h.target_id,
@@ -1499,8 +1500,10 @@ ataaction(struct cam_sim *sim, union ccb
 				} else
 					d->mode = cts->xport_specific.sata.mode;
 			}
-			if (cts->xport_specific.ata.valid & CTS_SATA_VALID_BYTECOUNT)
+			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_ATAPI)
+				d->atapi = cts->xport_specific.sata.atapi;
 		} else {
 			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_MODE) {
 				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
@@ -1512,6 +1515,8 @@ ataaction(struct cam_sim *sim, union ccb
 			}
 			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
 				d->bytecount = cts->xport_specific.ata.bytecount;
+			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_ATAPI)
+				d->atapi = cts->xport_specific.ata.atapi;
 		}
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
@@ -1541,6 +1546,8 @@ ataaction(struct cam_sim *sim, union ccb
 			} else
 				cts->xport_specific.sata.revision = d->revision;
 			cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
+			cts->xport_specific.sata.atapi = d->atapi;
+			cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
 		} else {
 			cts->transport = XPORT_ATA;
 			cts->transport_version = XPORT_VERSION_UNSPECIFIED;
@@ -1548,6 +1555,8 @@ 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;
+			cts->xport_specific.ata.atapi = d->atapi;
+			cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI;
 		}
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);

Modified: head/sys/dev/ata/ata-all.h
==============================================================================
--- head/sys/dev/ata/ata-all.h	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/ata/ata-all.h	Tue Feb  2 11:09:28 2010	(r203376)
@@ -539,6 +539,7 @@ struct ata_cam_device {
 	u_int			revision;
 	int			mode;
 	u_int			bytecount;
+	u_int			atapi;
 };
 #endif
 

Modified: head/sys/dev/siis/siis.c
==============================================================================
--- head/sys/dev/siis/siis.c	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/siis/siis.c	Tue Feb  2 11:09:28 2010	(r203376)
@@ -1659,6 +1659,8 @@ siisaction(struct cam_sim *sim, union cc
 			else
 				ATA_OUTL(ch->r_mem, SIIS_P_CTLCLR, SIIS_P_CTL_PME);
 		}
+		if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS)
+			d->atapi = cts->xport_specific.sata.atapi;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;
@@ -1702,6 +1704,8 @@ siisaction(struct cam_sim *sim, union cc
 		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;
+		cts->xport_specific.sata.atapi = d->atapi;
+		cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
 		ccb->ccb_h.status = CAM_REQ_CMP;
 		xpt_done(ccb);
 		break;

Modified: head/sys/dev/siis/siis.h
==============================================================================
--- head/sys/dev/siis/siis.h	Tue Feb  2 10:58:41 2010	(r203375)
+++ head/sys/dev/siis/siis.h	Tue Feb  2 11:09:28 2010	(r203376)
@@ -356,6 +356,7 @@ struct siis_device {
 	int			revision;
 	int			mode;
 	u_int			bytecount;
+	u_int			atapi;
 	u_int			tags;
 };
 


More information about the svn-src-all mailing list