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

Alexander Motin mav at FreeBSD.org
Thu Nov 26 08:49:47 UTC 2009


Author: mav
Date: Thu Nov 26 08:49:46 2009
New Revision: 199821
URL: http://svn.freebsd.org/changeset/base/199821

Log:
  MFp4:
  Improve ATA mode/SATA revision control.

Modified:
  head/sbin/camcontrol/camcontrol.8
  head/sbin/camcontrol/camcontrol.c
  head/sys/cam/ata/ata_all.c
  head/sys/cam/ata/ata_all.h
  head/sys/cam/cam_ccb.h
  head/sys/dev/ahci/ahci.c
  head/sys/dev/ahci/ahci.h
  head/sys/dev/siis/siis.c
  head/sys/dev/siis/siis.h

Modified: head/sbin/camcontrol/camcontrol.8
==============================================================================
--- head/sbin/camcontrol/camcontrol.8	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sbin/camcontrol/camcontrol.8	Thu Nov 26 08:49:46 2009	(r199821)
@@ -149,6 +149,7 @@
 .Op generic args
 .Op Fl c
 .Op Fl D Ar enable|disable
+.Op Fl M Ar mode
 .Op Fl O Ar offset
 .Op Fl q
 .Op Fl R Ar syncrate
@@ -705,6 +706,8 @@ Show or set current negotiation settings
 This is the default.
 .It Fl D Ar enable|disable
 Enable or disable disconnection.
+.It Fl M Ar mode
+Set ATA mode.
 .It Fl O Ar offset
 Set the command delay offset.
 .It Fl q

Modified: head/sbin/camcontrol/camcontrol.c
==============================================================================
--- head/sbin/camcontrol/camcontrol.c	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sbin/camcontrol/camcontrol.c	Thu Nov 26 08:49:46 2009	(r199821)
@@ -125,7 +125,7 @@ struct camcontrol_opts {
 #ifndef MINIMALISTIC
 static const char scsicmd_opts[] = "a:c:i:o:r";
 static const char readdefect_opts[] = "f:GP";
-static const char negotiate_opts[] = "acD:O:qR:T:UW:";
+static const char negotiate_opts[] = "acD:M:O:qR:T:UW:";
 #endif
 
 struct camcontrol_opts option_table[] = {
@@ -3112,6 +3112,7 @@ ratecontrol(struct cam_device *device, i
 	int user_settings = 0;
 	int retval = 0;
 	int disc_enable = -1, tag_enable = -1;
+	int mode = -1;
 	int offset = -1;
 	double syncrate = -1;
 	int bus_width = -1;
@@ -3120,12 +3121,10 @@ ratecontrol(struct cam_device *device, i
 	struct ccb_pathinq cpi;
 
 	ccb = cam_getccb(device);
-
 	if (ccb == NULL) {
 		warnx("ratecontrol: error allocating ccb");
 		return(1);
 	}
-
 	while ((c = getopt(argc, argv, combinedopt)) != -1) {
 		switch(c){
 		case 'a':
@@ -3146,6 +3145,15 @@ ratecontrol(struct cam_device *device, i
 			}
 			change_settings = 1;
 			break;
+		case 'M':
+			mode = ata_string2mode(optarg);
+			if (mode < 0) {
+				warnx("unknown mode '%s'", optarg);
+				retval = 1;
+				goto ratecontrol_bailout;
+			}
+			change_settings = 1;
+			break;
 		case 'O':
 			offset = strtol(optarg, NULL, 0);
 			if (offset < 0) {
@@ -3160,7 +3168,6 @@ ratecontrol(struct cam_device *device, i
 			break;
 		case 'R':
 			syncrate = atof(optarg);
-
 			if (syncrate < 0) {
 				warnx("sync rate %f is < 0", syncrate);
 				retval = 1;
@@ -3196,17 +3203,14 @@ ratecontrol(struct cam_device *device, i
 			break;
 		}
 	}
-
 	bzero(&(&ccb->ccb_h)[1],
 	      sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
-
 	/*
 	 * Grab path inquiry information, so we can determine whether
 	 * or not the initiator is capable of the things that the user
 	 * requests.
 	 */
 	ccb->ccb_h.func_code = XPT_PATH_INQ;
-
 	if (cam_send_ccb(device, ccb) < 0) {
 		perror("error sending XPT_PATH_INQ CCB");
 		if (arglist & CAM_ARG_VERBOSE) {
@@ -3216,7 +3220,6 @@ ratecontrol(struct cam_device *device, i
 		retval = 1;
 		goto ratecontrol_bailout;
 	}
-
 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 		warnx("XPT_PATH_INQ CCB failed");
 		if (arglist & CAM_ARG_VERBOSE) {
@@ -3226,17 +3229,14 @@ ratecontrol(struct cam_device *device, i
 		retval = 1;
 		goto ratecontrol_bailout;
 	}
-
 	bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq));
-
 	bzero(&(&ccb->ccb_h)[1],
 	      sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
-
-	if (quiet == 0)
-		fprintf(stdout, "Current Parameters:\n");
-
+	if (quiet == 0) {
+		fprintf(stdout, "%s parameters:\n",
+		    user_settings ? "User" : "Current");
+	}
 	retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
-
 	if (retval != 0)
 		goto ratecontrol_bailout;
 
@@ -3246,16 +3246,20 @@ ratecontrol(struct cam_device *device, i
 	if (change_settings) {
 		int didsettings = 0;
 		struct ccb_trans_settings_spi *spi = NULL;
+		struct ccb_trans_settings_ata *ata = NULL;
+		struct ccb_trans_settings_sata *sata = NULL;
 		struct ccb_trans_settings_scsi *scsi = NULL;
 
-		if (ccb->cts.transport == XPORT_SPI) {
+		if (ccb->cts.transport == XPORT_SPI)
 			spi = &ccb->cts.xport_specific.spi;
-			spi->valid = 0;
-		}
-		if (ccb->cts.protocol == PROTO_SCSI) {
+		if (ccb->cts.transport == XPORT_ATA)
+			ata = &ccb->cts.xport_specific.ata;
+		if (ccb->cts.transport == XPORT_SATA)
+			sata = &ccb->cts.xport_specific.sata;
+		if (ccb->cts.protocol == PROTO_SCSI)
 			scsi = &ccb->cts.proto_specific.scsi;
-			scsi->valid = 0;
-		}
+		ccb->cts.xport_specific.valid = 0;
+		ccb->cts.proto_specific.valid = 0;
 		if (spi && disc_enable != -1) {
 			spi->valid |= CTS_SPI_VALID_DISC;
 			if (disc_enable == 0)
@@ -3263,7 +3267,6 @@ ratecontrol(struct cam_device *device, i
 			else
 				spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
 		}
-
 		if (scsi && tag_enable != -1) {
 			if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
 				warnx("HBA does not support tagged queueing, "
@@ -3271,21 +3274,16 @@ ratecontrol(struct cam_device *device, i
 				retval = 1;
 				goto ratecontrol_bailout;
 			}
-
 			scsi->valid |= CTS_SCSI_VALID_TQ;
-
 			if (tag_enable == 0)
 				scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
 			else
 				scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
 			didsettings++;
 		}
-
 		if (spi && offset != -1) {
 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
-				warnx("HBA at %s%d is not cable of changing "
-				      "offset", cpi.dev_name,
-				      cpi.unit_number);
+				warnx("HBA is not capable of changing offset");
 				retval = 1;
 				goto ratecontrol_bailout;
 			}
@@ -3293,28 +3291,23 @@ ratecontrol(struct cam_device *device, i
 			spi->sync_offset = offset;
 			didsettings++;
 		}
-
 		if (spi && syncrate != -1) {
 			int prelim_sync_period;
 			u_int freq;
 
 			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
-				warnx("HBA at %s%d is not cable of changing "
-				      "transfer rates", cpi.dev_name,
-				      cpi.unit_number);
+				warnx("HBA is not capable of changing "
+				      "transfer rates");
 				retval = 1;
 				goto ratecontrol_bailout;
 			}
-
 			spi->valid |= CTS_SPI_VALID_SYNC_RATE;
-
 			/*
 			 * The sync rate the user gives us is in MHz.
 			 * We need to translate it into KHz for this
 			 * calculation.
 			 */
 			syncrate *= 1000;
-
 			/*
 			 * Next, we calculate a "preliminary" sync period
 			 * in tenths of a nanosecond.
@@ -3323,14 +3316,43 @@ ratecontrol(struct cam_device *device, i
 				prelim_sync_period = 0;
 			else
 				prelim_sync_period = 10000000 / syncrate;
-
 			spi->sync_period =
 				scsi_calc_syncparam(prelim_sync_period);
-
 			freq = scsi_calc_syncsrate(spi->sync_period);
 			didsettings++;
 		}
-
+		if (sata && syncrate != -1) {
+			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
+				warnx("HBA is not capable of changing "
+				      "transfer rates");
+				retval = 1;
+				goto ratecontrol_bailout;
+			}
+			sata->revision = ata_speed2revision(syncrate * 100);
+			if (sata->revision < 0) {
+				warnx("Invalid rate %f", syncrate);
+				retval = 1;
+				goto ratecontrol_bailout;
+			}
+			sata->valid |= CTS_SATA_VALID_REVISION;
+			didsettings++;
+		}
+		if ((ata || sata) && mode != -1) {
+			if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
+				warnx("HBA is not capable of changing "
+				      "transfer rates");
+				retval = 1;
+				goto ratecontrol_bailout;
+			}
+			if (ata) {
+				ata->mode = mode;
+				ata->valid |= CTS_ATA_VALID_MODE;
+			} else {
+				sata->mode = mode;
+				sata->valid |= CTS_SATA_VALID_MODE;
+			}
+			didsettings++;
+		}
 		/*
 		 * The bus_width argument goes like this:
 		 * 0 == 8 bit
@@ -3341,7 +3363,6 @@ ratecontrol(struct cam_device *device, i
 		 * number.
 		 */
 		if (spi && bus_width != -1) {
-
 			/*
 			 * We might as well validate things here with a
 			 * decipherable error message, rather than what
@@ -3365,17 +3386,19 @@ ratecontrol(struct cam_device *device, i
 				retval = 1;
 				goto ratecontrol_bailout;
 			}
-
 			spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
 			spi->bus_width = bus_width >> 4;
 			didsettings++;
 		}
-
 		if  (didsettings == 0) {
 			goto ratecontrol_bailout;
 		}
+		if  (!user_settings && (ata || sata)) {
+			warnx("You can modify only user settings for ATA/SATA");
+			retval = 1;
+			goto ratecontrol_bailout;
+		}
 		ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
-
 		if (cam_send_ccb(device, ccb) < 0) {
 			perror("error sending XPT_SET_TRAN_SETTINGS CCB");
 			if (arglist & CAM_ARG_VERBOSE) {
@@ -3385,7 +3408,6 @@ ratecontrol(struct cam_device *device, i
 			retval = 1;
 			goto ratecontrol_bailout;
 		}
-
 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 			warnx("XPT_SET_TRANS_SETTINGS CCB failed");
 			if (arglist & CAM_ARG_VERBOSE) {
@@ -3396,11 +3418,9 @@ ratecontrol(struct cam_device *device, i
 			goto ratecontrol_bailout;
 		}
 	}
-
 	if (send_tur) {
 		retval = testunitready(device, retry_count, timeout,
 				       (arglist & CAM_ARG_VERBOSE) ? 0 : 1);
-
 		/*
 		 * If the TUR didn't succeed, just bail.
 		 */
@@ -3409,7 +3429,6 @@ ratecontrol(struct cam_device *device, i
 				fprintf(stderr, "Test Unit Ready failed\n");
 			goto ratecontrol_bailout;
 		}
-
 		/*
 		 * If the user wants things quiet, there's no sense in
 		 * getting the transfer settings, if we're not going
@@ -3417,13 +3436,11 @@ ratecontrol(struct cam_device *device, i
 		 */
 		if (quiet != 0)
 			goto ratecontrol_bailout;
-
-		fprintf(stdout, "New Parameters:\n");
+		fprintf(stdout, "New parameters:\n");
 		retval = get_print_cts(device, user_settings, 0, NULL);
 	}
 
 ratecontrol_bailout:
-
 	cam_freeccb(ccb);
 	return(retval);
 }
@@ -4310,8 +4327,8 @@ usage(int verbose)
 "                              <all|bus[:target[:lun]]|off>\n"
 "        camcontrol tags       [dev_id][generic args] [-N tags] [-q] [-v]\n"
 "        camcontrol negotiate  [dev_id][generic args] [-a][-c]\n"
-"                              [-D <enable|disable>][-O offset][-q]\n"
-"                              [-R syncrate][-v][-T <enable|disable>]\n"
+"                              [-D <enable|disable>][-M mode][-O offset]\n"
+"                              [-q][-R syncrate][-v][-T <enable|disable>]\n"
 "                              [-U][-W bus_width]\n"
 "        camcontrol format     [dev_id][generic args][-q][-r][-w][-y]\n"
 "        camcontrol idle       [dev_id][generic args][-t time]\n"
@@ -4402,6 +4419,7 @@ usage(int verbose)
 "-a                send a test unit ready after negotiation\n"
 "-c                report/set current negotiation settings\n"
 "-D <arg>          \"enable\" or \"disable\" disconnection\n"
+"-M mode           set ATA mode\n"
 "-O offset         set command delay offset\n"
 "-q                be quiet, don't report anything\n"
 "-R syncrate       synchronization rate in MHz\n"

Modified: head/sys/cam/ata/ata_all.c
==============================================================================
--- head/sys/cam/ata/ata_all.c	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/cam/ata/ata_all.c	Thu Nov 26 08:49:46 2009	(r199821)
@@ -532,6 +532,35 @@ ata_mode2string(int mode)
     }
 }
 
+int
+ata_string2mode(char *str)
+{
+	if (!strcasecmp(str, "PIO0")) return (ATA_PIO0);
+	if (!strcasecmp(str, "PIO1")) return (ATA_PIO1);
+	if (!strcasecmp(str, "PIO2")) return (ATA_PIO2);
+	if (!strcasecmp(str, "PIO3")) return (ATA_PIO3);
+	if (!strcasecmp(str, "PIO4")) return (ATA_PIO4);
+	if (!strcasecmp(str, "WDMA0")) return (ATA_WDMA0);
+	if (!strcasecmp(str, "WDMA1")) return (ATA_WDMA1);
+	if (!strcasecmp(str, "WDMA2")) return (ATA_WDMA2);
+	if (!strcasecmp(str, "UDMA0")) return (ATA_UDMA0);
+	if (!strcasecmp(str, "UDMA16")) return (ATA_UDMA0);
+	if (!strcasecmp(str, "UDMA1")) return (ATA_UDMA1);
+	if (!strcasecmp(str, "UDMA25")) return (ATA_UDMA1);
+	if (!strcasecmp(str, "UDMA2")) return (ATA_UDMA2);
+	if (!strcasecmp(str, "UDMA33")) return (ATA_UDMA2);
+	if (!strcasecmp(str, "UDMA3")) return (ATA_UDMA3);
+	if (!strcasecmp(str, "UDMA44")) return (ATA_UDMA3);
+	if (!strcasecmp(str, "UDMA4")) return (ATA_UDMA4);
+	if (!strcasecmp(str, "UDMA66")) return (ATA_UDMA4);
+	if (!strcasecmp(str, "UDMA5")) return (ATA_UDMA5);
+	if (!strcasecmp(str, "UDMA100")) return (ATA_UDMA5);
+	if (!strcasecmp(str, "UDMA6")) return (ATA_UDMA6);
+	if (!strcasecmp(str, "UDMA133")) return (ATA_UDMA6);
+	return (-1);
+}
+
+
 u_int
 ata_mode2speed(int mode)
 {
@@ -588,13 +617,16 @@ int
 ata_speed2revision(u_int speed)
 {
 	switch (speed) {
+	case 0:
+		return (0);
 	case 150000:
-	default:
 		return (1);
 	case 300000:
 		return (2);
 	case 600000:
 		return (3);
+	default:
+		return (-1);
 	}
 }
 

Modified: head/sys/cam/ata/ata_all.h
==============================================================================
--- head/sys/cam/ata/ata_all.h	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/cam/ata/ata_all.h	Thu Nov 26 08:49:46 2009	(r199821)
@@ -115,6 +115,7 @@ int	ata_max_umode(struct ata_params *ap)
 int	ata_max_mode(struct ata_params *ap, int maxmode);
 
 char *	ata_mode2string(int mode);
+int	ata_string2mode(char *str);
 u_int	ata_mode2speed(int mode);
 u_int	ata_revision2speed(int revision);
 int	ata_speed2revision(u_int speed);

Modified: head/sys/cam/cam_ccb.h
==============================================================================
--- head/sys/cam/cam_ccb.h	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/cam/cam_ccb.h	Thu Nov 26 08:49:46 2009	(r199821)
@@ -820,7 +820,7 @@ struct ccb_trans_settings_ata {
 	u_int     	valid;		/* Which fields to honor */
 #define	CTS_ATA_VALID_MODE		0x01
 #define	CTS_ATA_VALID_BYTECOUNT		0x02
-	int	 	mode;		/* Mode */
+	int		mode;		/* Mode */
 	u_int 		bytecount;	/* Length of PIO transaction */
 };
 
@@ -831,9 +831,9 @@ struct ccb_trans_settings_sata {
 #define	CTS_SATA_VALID_REVISION		0x04
 #define	CTS_SATA_VALID_PM		0x08
 #define	CTS_SATA_VALID_TAGS		0x10
-	int	 	mode;		/* Legacy PATA mode */
+	int		mode;		/* Legacy PATA mode */
 	u_int 		bytecount;	/* Length of PIO transaction */
-	u_int	 	revision;	/* SATA revision */
+	int		revision;	/* SATA revision */
 	u_int 		pm_present;	/* PM is present (XPT->SIM) */
 	u_int 		tags;		/* Number of allowed tags */
 };

Modified: head/sys/dev/ahci/ahci.c
==============================================================================
--- head/sys/dev/ahci/ahci.c	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/dev/ahci/ahci.c	Thu Nov 26 08:49:46 2009	(r199821)
@@ -72,7 +72,7 @@ static void ahci_dmasetprd(void *arg, bu
 static void ahci_execute_transaction(struct ahci_slot *slot);
 static void ahci_timeout(struct ahci_slot *slot);
 static void ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et);
-static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
+static int ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
 static void ahci_dmainit(device_t dev);
 static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
 static void ahci_dmafini(device_t dev);
@@ -776,7 +776,7 @@ ahci_ch_attach(device_t dev)
 	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, i;
+	int rid, error, i, sata_rev = 0;
 
 	ch->dev = dev;
 	ch->unit = (intptr_t)device_get_ivars(dev);
@@ -789,22 +789,22 @@ ahci_ch_attach(device_t dev)
 	    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].mode = 0;
-		ch->user[i].bytecount = 8192;
-		ch->user[i].tags = ch->numslots;
-		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 &&
 	    pci_get_subvendor(ctlr->dev) == 0x1043 &&
 	    pci_get_subdevice(ctlr->dev) == 0x81e4 &&
 	    ch->unit == 0)
-		ch->sata_rev = 1;
+		sata_rev = 1;
 	resource_int_value(device_get_name(dev),
-	    device_get_unit(dev), "sata_rev", &ch->sata_rev);
+	    device_get_unit(dev), "sata_rev", &sata_rev);
+	for (i = 0; i < 16; i++) {
+		ch->user[i].revision = sata_rev;
+		ch->user[i].mode = 0;
+		ch->user[i].bytecount = 8192;
+		ch->user[i].tags = ch->numslots;
+		ch->curr[i] = ch->user[i];
+	}
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 	    &rid, RF_ACTIVE)))
@@ -1410,7 +1410,7 @@ ahci_execute_transaction(struct ahci_slo
 	ctp = (struct ahci_cmd_tab *)
 		(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
 	/* Setup the FIS for this request */
-	if (!(fis_size = ahci_setup_fis(ctp, ccb, slot->slot))) {
+	if (!(fis_size = ahci_setup_fis(dev, ctp, ccb, slot->slot))) {
 		device_printf(ch->dev, "Setting up SATA FIS failed\n");
 		ahci_end_transaction(slot, AHCI_ERR_INVALID);
 		return;
@@ -1983,8 +1983,9 @@ ahci_reset(device_t dev)
 }
 
 static int
-ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag)
+ahci_setup_fis(device_t dev, struct ahci_cmd_tab *ctp, union ccb *ccb, int tag)
 {
+	struct ahci_channel *ch = device_get_softc(dev);
 	u_int8_t *fis = &ctp->cfis[0];
 
 	bzero(ctp->cfis, 64);
@@ -1993,7 +1994,8 @@ ahci_setup_fis(struct ahci_cmd_tab *ctp,
 	if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
 		fis[1] |= 0x80;
 		fis[2] = ATA_PACKET_CMD;
-		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
+		    ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
 			fis[3] = ATA_F_DMA;
 		else {
 			fis[5] = ccb->csio.dxfer_len;
@@ -2073,6 +2075,7 @@ static int
 ahci_sata_phy_reset(device_t dev, int quick)
 {
 	struct ahci_channel *ch = device_get_softc(dev);
+	int sata_rev;
 	uint32_t val;
 
 	if (quick) {
@@ -2083,11 +2086,12 @@ ahci_sata_phy_reset(device_t dev, int qu
 
 	if (bootverbose)
 		device_printf(dev, "hardware reset ...\n");
-	if (ch->sata_rev == 1)
+	sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
+	if (sata_rev == 1)
 		val = ATA_SC_SPD_SPEED_GEN1;
-	else if (ch->sata_rev == 2)
+	else if (sata_rev == 2)
 		val = ATA_SC_SPD_SPEED_GEN2;
-	else if (ch->sata_rev == 3)
+	else if (sata_rev == 3)
 		val = ATA_SC_SPD_SPEED_GEN3;
 	else
 		val = 0;

Modified: head/sys/dev/ahci/ahci.h
==============================================================================
--- head/sys/dev/ahci/ahci.h	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/dev/ahci/ahci.h	Thu Nov 26 08:49:46 2009	(r199821)
@@ -341,7 +341,7 @@ struct ahci_slot {
 };
 
 struct ahci_device {
-	u_int			revision;
+	int			revision;
 	int			mode;
 	u_int			bytecount;
 	u_int			tags;
@@ -362,7 +362,6 @@ struct ahci_channel {
 	int			quirks;
 	int			numslots;	/* Number of present slots */
 	int			pm_level;	/* power management level */
-	int			sata_rev;	/* Maximum allowed SATA generation */
 
 	struct ahci_slot	slot[AHCI_MAX_SLOTS];
 	union ccb		*hold[AHCI_MAX_SLOTS];

Modified: head/sys/dev/siis/siis.c
==============================================================================
--- head/sys/dev/siis/siis.c	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/dev/siis/siis.c	Thu Nov 26 08:49:46 2009	(r199821)
@@ -69,7 +69,7 @@ static void siis_dmasetprd(void *arg, bu
 static void siis_execute_transaction(struct siis_slot *slot);
 static void siis_timeout(struct siis_slot *slot);
 static void siis_end_transaction(struct siis_slot *slot, enum siis_err_type et);
-static int siis_setup_fis(struct siis_cmd *ctp, union ccb *ccb, int tag);
+static int siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag);
 static void siis_dmainit(device_t dev);
 static void siis_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
 static void siis_dmafini(device_t dev);
@@ -415,21 +415,21 @@ siis_ch_attach(device_t dev)
 {
 	struct siis_channel *ch = device_get_softc(dev);
 	struct cam_devq *devq;
-	int rid, error, i;
+	int rid, error, i, sata_rev = 0;
 
 	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);
+	resource_int_value(device_get_name(dev),
+	    device_get_unit(dev), "sata_rev", &sata_rev);
 	for (i = 0; i < 16; i++) {
-		ch->user[i].revision = 0;
+		ch->user[i].revision = sata_rev;
 		ch->user[i].mode = 0;
 		ch->user[i].bytecount = 8192;
 		ch->user[i].tags = SIIS_MAX_SLOTS;
 		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);
 	rid = ch->unit;
 	if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
@@ -974,7 +974,7 @@ siis_execute_transaction(struct siis_slo
 			ctp->control |= htole16(SIIS_PRB_PACKET_WRITE);
 	}
 	/* Setup the FIS for this request */
-	if (!siis_setup_fis(ctp, ccb, slot->slot)) {
+	if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) {
 		device_printf(ch->dev, "Setting up SATA FIS failed\n");
 		if (!ch->readlog)
 			xpt_freeze_simq(ch->sim, 1);
@@ -1346,7 +1346,7 @@ static void
 siis_reset(device_t dev)
 {
 	struct siis_channel *ch = device_get_softc(dev);
-	int i, retry = 0;
+	int i, retry = 0, sata_rev;
 	uint32_t val;
 
 	if (bootverbose)
@@ -1390,11 +1390,12 @@ siis_reset(device_t dev)
 	/* Disable port interrupts */
 	ATA_OUTL(ch->r_mem, SIIS_P_IECLR, 0x0000FFFF);
 	/* Set speed limit. */
-	if (ch->sata_rev == 1)
+	sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
+	if (sata_rev == 1)
 		val = ATA_SC_SPD_SPEED_GEN1;
-	else if (ch->sata_rev == 2)
+	else if (sata_rev == 2)
 		val = ATA_SC_SPD_SPEED_GEN2;
-	else if (ch->sata_rev == 3)
+	else if (sata_rev == 3)
 		val = ATA_SC_SPD_SPEED_GEN3;
 	else
 		val = 0;
@@ -1446,8 +1447,9 @@ retry:
 }
 
 static int
-siis_setup_fis(struct siis_cmd *ctp, union ccb *ccb, int tag)
+siis_setup_fis(device_t dev, struct siis_cmd *ctp, union ccb *ccb, int tag)
 {
+	struct siis_channel *ch = device_get_softc(dev);
 	u_int8_t *fis = &ctp->fis[0];
 
 	bzero(fis, 24);
@@ -1456,7 +1458,8 @@ siis_setup_fis(struct siis_cmd *ctp, uni
 	if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
 		fis[1] |= 0x80;
 		fis[2] = ATA_PACKET_CMD;
-		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
+		if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE &&
+		    ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA)
 			fis[3] = ATA_F_DMA;
 		else {
 			fis[5] = ccb->csio.dxfer_len;

Modified: head/sys/dev/siis/siis.h
==============================================================================
--- head/sys/dev/siis/siis.h	Thu Nov 26 08:29:02 2009	(r199820)
+++ head/sys/dev/siis/siis.h	Thu Nov 26 08:49:46 2009	(r199821)
@@ -347,7 +347,7 @@ struct siis_slot {
 };
 
 struct siis_device {
-	u_int			revision;
+	int			revision;
 	int			mode;
 	u_int			bytecount;
 	u_int			tags;
@@ -364,7 +364,6 @@ struct siis_channel {
 	struct cam_sim		*sim;
 	struct cam_path		*path;
 	int			pm_level;	/* power management level */
-	int			sata_rev;	/* Maximum allowed SATA generation */
 
 	struct siis_slot	slot[SIIS_MAX_SLOTS];
 	union ccb		*hold[SIIS_MAX_SLOTS];


More information about the svn-src-head mailing list