changeset 10663:4d59e1faf654

6881565 sata hba interfaces need to keep backward compatibility
author Xiao-Yu Zhang <Xiao-Yu.Zhang@Sun.COM>
date Mon, 28 Sep 2009 14:30:40 +0800
parents fd0d1bbdb9a0
children e29b5b8a591c
files usr/src/uts/common/io/sata/adapters/ahci/ahci.c usr/src/uts/common/io/sata/impl/sata.c usr/src/uts/common/sys/sata/impl/sata.h usr/src/uts/common/sys/sata/sata_hba.h
diffstat 4 files changed, 155 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/adapters/ahci/ahci.c	Mon Sep 28 10:58:29 2009 +0800
+++ b/usr/src/uts/common/io/sata/adapters/ahci/ahci.c	Mon Sep 28 14:30:40 2009 +0800
@@ -110,7 +110,7 @@
 static	int ahci_update_pmult_pscr(ahci_ctl_t *, ahci_addr_t *,
     sata_device_t *);
 static	int ahci_update_pmult_gscr(ahci_ctl_t *, ahci_addr_t *,
-    sata_device_t *);
+    sata_pmult_gscr_t *);
 static	int ahci_initialize_pmult(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *,
     sata_device_t *);
 static	int ahci_initialize_pmport(ahci_ctl_t *, ahci_port_t *, ahci_addr_t *);
@@ -1087,7 +1087,7 @@
 	/* Allocate memory for the sata_hba_tran  */
 	sata_hba_tran = kmem_zalloc(sizeof (sata_hba_tran_t), KM_SLEEP);
 
-	sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV_3;
+	sata_hba_tran->sata_tran_hba_rev = SATA_TRAN_HBA_REV;
 	sata_hba_tran->sata_tran_hba_dip = ahci_ctlp->ahcictl_dip;
 	sata_hba_tran->sata_tran_hba_dma_attr =
 	    &ahci_ctlp->ahcictl_buffer_dma_attr;
@@ -1254,7 +1254,7 @@
 		/* port mutliplier is removed. */
 		AHCIDBG(AHCIDBG_PMULT, ahci_ctlp,
 		    "ahci_tran_probe_port: "
-		    "port-pmult is removed from port %s", portstr);
+		    "pmult is removed from port %s", portstr);
 		mutex_exit(&ahci_portp->ahciport_mutex);
 		return (SATA_FAILURE);
 	}
@@ -1264,8 +1264,9 @@
 	 * 1. A controller port.
 	 *    A controller port should be ready here.
 	 * 2. A port multiplier.
-	 *    If it has not been initialized, initialized it. If it is
-	 *    initilaized, we need check the status of all its device ports.
+	 *    SATA_ADDR_PMULT_SPEC - if it is not initialized yet, initialize
+	 *    it and register the port multiplier to the framework.
+	 *    SATA_ADDR_PMULT - check the status of all its device ports.
 	 * 3. A port multiplier port.
 	 *    If it has not been initialized, initialized it.
 	 *
@@ -1273,29 +1274,22 @@
 	 * initialization because we cannot do these time-consuming jobs in an
 	 * interrupt context.
 	 */
-	if (AHCI_ADDR_IS_PORT(&addr)) {
-		if (ahci_portp->ahciport_device_type == SATA_DTYPE_PMULT) {
-			AHCI_ADDR_SET_PMULT(&pmult_addr, port);
-			port_state = ahci_portp->ahciport_port_state;
-			/* SATA Framework's first probe? */
-			if (!(port_state & SATA_DSTATE_PMULT_INIT)) {
-				/* Initialize registers on a port multiplier */
-				rval_init = ahci_initialize_pmult(ahci_ctlp,
-				    ahci_portp, &pmult_addr, sd);
-				if (rval_init != AHCI_SUCCESS) {
-					AHCIDBG(AHCIDBG_PMULT, ahci_ctlp,
-					    "ahci_tran_probe_port: "
-					    "pmult initialization failed.",
-					    NULL);
-					mutex_exit(&ahci_portp->ahciport_mutex);
-					return (SATA_FAILURE);
-				}
-			}
-		}
-	} else if (AHCI_ADDR_IS_PMULT(&addr)) {
+	if (sd->satadev_addr.qual & SATA_ADDR_PMULT_SPEC) {
+		AHCI_ADDR_SET_PMULT(&pmult_addr, port);
+		/* Initialize registers on a port multiplier */
+		rval_init = ahci_initialize_pmult(ahci_ctlp,
+		    ahci_portp, &pmult_addr, sd);
+		if (rval_init != AHCI_SUCCESS) {
+			AHCIDBG(AHCIDBG_PMULT, ahci_ctlp,
+			    "ahci_tran_probe_port: "
+			    "pmult initialization failed.", NULL);
+			mutex_exit(&ahci_portp->ahciport_mutex);
+			return (SATA_FAILURE);
+		}
+	} else if (sd->satadev_addr.qual & SATA_ADDR_PMULT) {
 		/* Check pmports hotplug events */
 		(void) ahci_probe_pmult(ahci_ctlp, ahci_portp, &addr);
-	} else if (AHCI_ADDR_IS_PMPORT(&addr)) {
+	} else if (sd->satadev_addr.qual & SATA_ADDR_PMPORT) {
 		if (ahci_probe_pmport(ahci_ctlp, ahci_portp,
 		    &addr, sd) != AHCI_SUCCESS) {
 			rval = SATA_FAILURE;
@@ -1393,19 +1387,8 @@
 
 out:
 	/* Register update only fails while probing a pmult/pmport */
-	if (AHCI_ADDR_IS_PORT(&addr)) {
+	if (AHCI_ADDR_IS_PORT(&addr) || AHCI_ADDR_IS_PMULT(&addr)) {
 		ahci_update_sata_registers(ahci_ctlp, port, sd);
-		if (ahci_portp->ahciport_device_type == SATA_DTYPE_PMULT)
-			if (port_state & SATA_STATE_READY)
-				if (ahci_update_pmult_gscr(ahci_ctlp,
-				    &pmult_addr, sd) != AHCI_SUCCESS)
-					rval = SATA_FAILURE;
-	} else if (AHCI_ADDR_IS_PMULT(&addr)) {
-		ahci_update_sata_registers(ahci_ctlp, port, sd);
-		if (port_state & SATA_STATE_READY)
-			if (ahci_update_pmult_gscr(ahci_ctlp,
-			    &addr, sd) != AHCI_SUCCESS)
-				rval = SATA_FAILURE;
 	} else if (AHCI_ADDR_IS_PMPORT(&addr)) {
 		if (port_state & SATA_STATE_READY)
 			if (ahci_update_pmult_pscr(ahci_ctlp,
@@ -1451,8 +1434,7 @@
 {
 	ahci_ctl_t *ahci_ctlp;
 	ahci_port_t *ahci_portp;
-	ahci_addr_t addr, addr_pmult;
-	sata_device_t sdevice;
+	ahci_addr_t addr;
 	uint8_t	cport = spkt->satapkt_device.satadev_addr.cport;
 	uint8_t port;
 	char portstr[10];
@@ -1487,28 +1469,6 @@
 			return (SATA_TRAN_PORT_ERROR);
 		}
 
-		/* Port multiplier and pmport are correctly initialized? */
-		if (!(ahci_portp->ahciport_port_state &
-		    SATA_DSTATE_PMULT_INIT)) {
-			AHCI_ADDR_SET_PMULT(&addr_pmult, port);
-			if (!ddi_in_panic() ||
-			    ahci_initialize_pmult(ahci_ctlp, ahci_portp,
-			    &addr_pmult, &sdevice) != AHCI_SUCCESS) {
-				spkt->satapkt_reason = SATA_PKT_PORT_ERROR;
-				spkt->satapkt_device.satadev_type =
-				    AHCIPORT_GET_DEV_TYPE(ahci_portp, &addr);
-				spkt->satapkt_device.satadev_state =
-				    AHCIPORT_GET_STATE(ahci_portp, &addr);
-				ahci_update_sata_registers(ahci_ctlp, port,
-				    &spkt->satapkt_device);
-				AHCIDBG(AHCIDBG_ERRS, ahci_ctlp,
-				    "ahci_tran_start returning PORT_ERROR "
-				    "while pmult is not initialized "
-				    "at port %d", port);
-				mutex_exit(&ahci_portp->ahciport_mutex);
-				return (SATA_TRAN_PORT_ERROR);
-			}
-		}
 		if (!(AHCIPORT_GET_STATE(ahci_portp, &addr) &
 		    SATA_STATE_READY)) {
 			if (!ddi_in_panic() ||
@@ -4107,12 +4067,12 @@
  */
 static int
 ahci_update_pmult_gscr(ahci_ctl_t *ahci_ctlp, ahci_addr_t *addrp,
-    sata_device_t *sd)
+    sata_pmult_gscr_t *sg)
 {
-	READ_PMULT(addrp, SATA_PMULT_GSCR0, &sd->satadev_gscr.gscr0, err);
-	READ_PMULT(addrp, SATA_PMULT_GSCR1, &sd->satadev_gscr.gscr1, err);
-	READ_PMULT(addrp, SATA_PMULT_GSCR2, &sd->satadev_gscr.gscr2, err);
-	READ_PMULT(addrp, SATA_PMULT_GSCR64, &sd->satadev_gscr.gscr64, err);
+	READ_PMULT(addrp, SATA_PMULT_GSCR0, &sg->gscr0, err);
+	READ_PMULT(addrp, SATA_PMULT_GSCR1, &sg->gscr1, err);
+	READ_PMULT(addrp, SATA_PMULT_GSCR2, &sg->gscr2, err);
+	READ_PMULT(addrp, SATA_PMULT_GSCR64, &sg->gscr64, err);
 
 	return (AHCI_SUCCESS);
 
@@ -4151,6 +4111,7 @@
 ahci_initialize_pmult(ahci_ctl_t *ahci_ctlp, ahci_port_t *ahci_portp,
     ahci_addr_t *addrp, sata_device_t *sd)
 {
+	sata_pmult_gscr_t sg;
 	uint32_t gscr64;
 	uint8_t port = addrp->aa_port;
 
@@ -4193,16 +4154,16 @@
 	/*
 	 * Fetch the number of device ports of the port multiplier
 	 */
-	if (ahci_update_pmult_gscr(ahci_ctlp, addrp, sd) != AHCI_SUCCESS)
+	if (ahci_update_pmult_gscr(ahci_ctlp, addrp, &sg) != AHCI_SUCCESS)
 		return (AHCI_FAILURE);
 
-	/* If it's not in the blacklist, use the value in GSCR2 */
-	if (sata_check_pmult_blacklist(sd) == SATA_FAILURE)
-		sd->satadev_add_info = sd->satadev_gscr.gscr2 &
-		    SATA_PMULT_PORTNUM_MASK;
+	/* Register the port multiplier to SATA Framework. */
+	mutex_exit(&ahci_portp->ahciport_mutex);
+	sata_register_pmult(ahci_ctlp->ahcictl_dip, sd, &sg);
+	mutex_enter(&ahci_portp->ahciport_mutex);
 
 	ahci_portp->ahciport_pmult_info->ahcipmi_num_dev_ports =
-	    sd->satadev_add_info;
+	    sd->satadev_add_info & SATA_PMULT_PORTNUM_MASK;
 
 	AHCIDBG(AHCIDBG_INFO|AHCIDBG_PMULT, ahci_ctlp,
 	    "port %d: pmult sub-port number updated to %x.", port,
@@ -9695,6 +9656,7 @@
 		ahci_addrp->aa_qual = AHCI_ADDR_PORT;
 		break;
 	case SATA_ADDR_PMULT:
+	case SATA_ADDR_PMULT_SPEC:
 		ahci_addrp->aa_qual = AHCI_ADDR_PMULT;
 		break;
 	case SATA_ADDR_DPMPORT:
--- a/usr/src/uts/common/io/sata/impl/sata.c	Mon Sep 28 10:58:29 2009 +0800
+++ b/usr/src/uts/common/io/sata/impl/sata.c	Mon Sep 28 14:30:40 2009 +0800
@@ -131,7 +131,7 @@
 
 #define	LEGACY_HWID_LEN	64	/* Model (40) + Serial (20) + pad */
 
-static char sata_rev_tag[] = {"1.45"};
+static char sata_rev_tag[] = {"1.46"};
 
 /*
  * SATA cb_ops functions
@@ -264,7 +264,7 @@
 static 	int sata_reprobe_port(sata_hba_inst_t *, sata_device_t *, int);
 static 	int sata_reprobe_pmult(sata_hba_inst_t *, sata_device_t *, int);
 static 	int sata_reprobe_pmport(sata_hba_inst_t *, sata_device_t *, int);
-static	void sata_alloc_pmult(sata_hba_inst_t *, sata_device_t *);
+static	int sata_alloc_pmult(sata_hba_inst_t *, sata_device_t *);
 static	void sata_free_pmult(sata_hba_inst_t *, sata_device_t *);
 static 	int sata_add_device(dev_info_t *, sata_hba_inst_t *, sata_device_t *);
 static	int sata_offline_device(sata_hba_inst_t *, sata_device_t *,
@@ -1856,30 +1856,61 @@
 }
 
 /*
- * Search a port multiplier in the blacklist and update the flags if a match
- * is found.
- *
- * Returns:
- * SATA_SUCCESS if any matched entry is found.
- * SATA_FAILURE if no matched entry is found.
- */
-int
-sata_check_pmult_blacklist(sata_device_t *sd)
-{
+ * Register a port multiplier to framework.
+ * 1) Store the GSCR values in the previous allocated pmult_info strctures.
+ * 2) Search in the blacklist and update the number of the device ports of the
+ * port multiplier.
+ *
+ * Void return.
+ */
+void
+sata_register_pmult(dev_info_t *dip, sata_device_t *sd, sata_pmult_gscr_t *sg)
+{
+	sata_hba_inst_t *sata_hba_inst = NULL;
+	sata_pmult_info_t *pmultinfo;
 	sata_pmult_bl_t *blp;
+	int cport = sd->satadev_addr.cport;
+
+	mutex_enter(&sata_mutex);
+	for (sata_hba_inst = sata_hba_list; sata_hba_inst != NULL;
+	    sata_hba_inst = sata_hba_inst->satahba_next) {
+		if (SATA_DIP(sata_hba_inst) == dip)
+			if (sata_hba_inst->satahba_attached == 1)
+				break;
+	}
+	mutex_exit(&sata_mutex);
+	/* HBA not attached? */
+	if (sata_hba_inst == NULL)
+		return;
+
+	/* Number of pmports */
+	sd->satadev_add_info = sg->gscr2 & SATA_PMULT_PORTNUM_MASK;
+
+	/* Check the blacklist */
 	for (blp = sata_pmult_blacklist; blp->bl_gscr0; blp++) {
-		if (sd->satadev_gscr.gscr0 != blp->bl_gscr0 && blp->bl_gscr0)
+		if (sg->gscr0 != blp->bl_gscr0 && blp->bl_gscr0)
 			continue;
-		if (sd->satadev_gscr.gscr1 != blp->bl_gscr1 && blp->bl_gscr1)
+		if (sg->gscr1 != blp->bl_gscr1 && blp->bl_gscr1)
 			continue;
-		if (sd->satadev_gscr.gscr2 != blp->bl_gscr2 && blp->bl_gscr2)
+		if (sg->gscr2 != blp->bl_gscr2 && blp->bl_gscr2)
 			continue;
 
 		cmn_err(CE_WARN, "!Port multiplier is on the blacklist.");
 		sd->satadev_add_info = blp->bl_flags;
-		return (SATA_SUCCESS);
-	}
-	return (SATA_FAILURE);
+		break;
+	}
+
+	/* Register the port multiplier GSCR */
+	mutex_enter(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
+	pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
+	if (pmultinfo != NULL) {
+		pmultinfo->pmult_gscr = *sg;
+		pmultinfo->pmult_num_dev_ports =
+		    sd->satadev_add_info & SATA_PMULT_PORTNUM_MASK;
+		SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
+		    "Port multiplier registered at port %d", cport);
+	}
+	mutex_exit(&(SATA_CPORT_MUTEX(sata_hba_inst, cport)));
 }
 
 /*
@@ -9223,7 +9254,9 @@
 			mutex_exit(&cportinfo->cport_mutex);
 
 			/* Allocate sata_pmult_info and sata_pmport_info */
-			sata_alloc_pmult(sata_hba_inst, &sata_device);
+			if (sata_alloc_pmult(sata_hba_inst, &sata_device) !=
+			    SATA_SUCCESS)
+				continue;
 
 			/* Log the information of the port multiplier */
 			sata_show_pmult_info(sata_hba_inst, &sata_device);
@@ -10041,7 +10074,9 @@
 		    cportinfo->cport_addr.cport);
 
 		mutex_exit(&cportinfo->cport_mutex);
-		sata_alloc_pmult(sata_hba_inst, sata_device);
+		if (sata_alloc_pmult(sata_hba_inst, sata_device) !=
+		    SATA_SUCCESS)
+			return (SATA_FAILURE);
 		sata_show_pmult_info(sata_hba_inst, sata_device);
 		mutex_enter(&cportinfo->cport_mutex);
 
@@ -10236,21 +10271,17 @@
 	 * registers, so it is still necessary to update the information of
 	 * all drives attached to the previous port multiplier afterwards.
 	 */
-	if ((sata_device->satadev_gscr.gscr0 != pmultinfo->pmult_gscr.gscr0) ||
-	    (sata_device->satadev_gscr.gscr1 != pmultinfo->pmult_gscr.gscr1) ||
-	    (sata_device->satadev_gscr.gscr2 != pmultinfo->pmult_gscr.gscr2)) {
-
-		/* Device changed: PMult -> another PMult */
-		mutex_exit(&cportinfo->cport_mutex);
-		sata_free_pmult(sata_hba_inst, sata_device);
-		sata_alloc_pmult(sata_hba_inst, sata_device);
-		mutex_enter(&cportinfo->cport_mutex);
-
-		SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
-		    "SATA port multiplier [changed] at port %d", cport);
-		sata_log(sata_hba_inst, CE_WARN,
-		    "SATA port multiplier detected at port %d", cport);
-	}
+	/* Device changed: PMult -> another PMult */
+	mutex_exit(&cportinfo->cport_mutex);
+	sata_free_pmult(sata_hba_inst, sata_device);
+	if (sata_alloc_pmult(sata_hba_inst, sata_device) != SATA_SUCCESS)
+		return (SATA_FAILURE);
+	mutex_enter(&cportinfo->cport_mutex);
+
+	SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
+	    "SATA port multiplier [changed] at port %d", cport);
+	sata_log(sata_hba_inst, CE_WARN,
+	    "SATA port multiplier detected at port %d", cport);
 
 	/*
 	 * Mark all the port multiplier port behind the port
@@ -10571,16 +10602,18 @@
  *
  * NOTE: No Mutex should be hold.
  */
-static void
+static int
 sata_alloc_pmult(sata_hba_inst_t *sata_hba_inst, sata_device_t *sata_device)
 {
 	dev_info_t *dip = SATA_DIP(sata_hba_inst);
 	sata_cport_info_t *cportinfo = NULL;
 	sata_pmult_info_t *pmultinfo = NULL;
 	sata_pmport_info_t *pmportinfo = NULL;
+	sata_device_t sd;
 	dev_t minor_number;
 	char name[16];
 	uint8_t cport = sata_device->satadev_addr.cport;
+	int rval;
 	int npmport;
 
 	cportinfo = SATA_CPORT_INFO(sata_hba_inst, cport);
@@ -10600,8 +10633,34 @@
 	pmultinfo->pmult_addr = sata_device->satadev_addr;
 	pmultinfo->pmult_addr.qual = SATA_ADDR_PMULT;
 	pmultinfo->pmult_state = SATA_STATE_PROBING;
-	pmultinfo->pmult_gscr = sata_device->satadev_gscr;
-	pmultinfo->pmult_num_dev_ports = sata_device->satadev_add_info;
+
+	/*
+	 * Probe the port multiplier with qualifier SATA_ADDR_PMULT_SPEC,
+	 * The HBA driver should initialize and register the port multiplier,
+	 * sata_register_pmult() will fill following fields,
+	 *   + sata_pmult_info.pmult_gscr
+	 *   + sata_pmult_info.pmult_num_dev_ports
+	 */
+	sd.satadev_addr = sata_device->satadev_addr;
+	sd.satadev_addr.qual = SATA_ADDR_PMULT_SPEC;
+	mutex_exit(&cportinfo->cport_mutex);
+	rval = (*SATA_PROBE_PORT_FUNC(sata_hba_inst))
+	    (SATA_DIP(sata_hba_inst), &sd);
+	mutex_enter(&cportinfo->cport_mutex);
+
+	if (rval != SATA_SUCCESS ||
+	    (sd.satadev_type != SATA_DTYPE_PMULT) ||
+	    !(sd.satadev_state & SATA_DSTATE_PMULT_INIT)) {
+		SATA_CPORTINFO_PMULT_INFO(cportinfo) = NULL;
+		kmem_free(pmultinfo, sizeof (sata_pmult_info_t));
+		cportinfo->cport_state = SATA_PSTATE_FAILED;
+		cportinfo->cport_dev_type = SATA_DTYPE_UNKNOWN;
+		mutex_exit(&cportinfo->cport_mutex);
+		SATADBG1(SATA_DBG_PMULT, sata_hba_inst,
+		    "sata_alloc_pmult: failed to initialize pmult "
+		    "at port %d.", cport)
+		return (SATA_FAILURE);
+	}
 
 	/* Initialize pmport_info structure */
 	for (npmport = 0; npmport < pmultinfo->pmult_num_dev_ports;
@@ -10642,6 +10701,7 @@
 	pmultinfo->pmult_state |= (SATA_STATE_PROBED|SATA_STATE_READY);
 
 	mutex_exit(&cportinfo->cport_mutex);
+	return (SATA_SUCCESS);
 }
 
 /*
@@ -11544,6 +11604,7 @@
 
 /*
  * Log/display port multiplier information
+ * No Mutex should be hold.
  */
 static void
 sata_show_pmult_info(sata_hba_inst_t *sata_hba_inst,
@@ -11551,13 +11612,21 @@
 {
 	_NOTE(ARGUNUSED(sata_hba_inst))
 
+	int cport = sata_device->satadev_addr.cport;
+	sata_pmult_info_t *pmultinfo;
 	char msg_buf[MAXPATHLEN];
 	uint32_t gscr0, gscr1, gscr2, gscr64;
 
-	gscr0 = sata_device->satadev_gscr.gscr0;
-	gscr1 = sata_device->satadev_gscr.gscr1;
-	gscr2 = sata_device->satadev_gscr.gscr2;
-	gscr64 = sata_device->satadev_gscr.gscr64;
+	mutex_enter(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
+	pmultinfo = SATA_PMULT_INFO(sata_hba_inst, cport);
+	if (pmultinfo == NULL)
+		return;
+
+	gscr0 = pmultinfo->pmult_gscr.gscr0;
+	gscr1 = pmultinfo->pmult_gscr.gscr1;
+	gscr2 = pmultinfo->pmult_gscr.gscr2;
+	gscr64 = pmultinfo->pmult_gscr.gscr64;
+	mutex_exit(&SATA_CPORT_MUTEX(sata_hba_inst, cport));
 
 	cmn_err(CE_CONT, "?Port Multiplier %d device-ports found at port %d",
 	    sata_device->satadev_add_info, sata_device->satadev_addr.cport);
@@ -18522,8 +18591,12 @@
 
 			if (SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL) {
 				/* Log the info of new port multiplier */
+				mutex_exit(&SATA_CPORT_INFO(sata_hba_inst,
+				    saddr->cport)->cport_mutex);
 				sata_show_pmult_info(sata_hba_inst,
 				    &sata_device);
+				mutex_enter(&SATA_CPORT_INFO(sata_hba_inst,
+				    saddr->cport)->cport_mutex);
 			}
 
 			ASSERT(SATA_CPORTINFO_PMULT_INFO(cportinfo) != NULL);
--- a/usr/src/uts/common/sys/sata/impl/sata.h	Mon Sep 28 10:58:29 2009 +0800
+++ b/usr/src/uts/common/sys/sata/impl/sata.h	Mon Sep 28 14:30:40 2009 +0800
@@ -835,7 +835,7 @@
 
 #endif
 
-/* sata_rev_tag 1.45 */
+/* sata_rev_tag 1.46 */
 
 #ifdef	__cplusplus
 }
--- a/usr/src/uts/common/sys/sata/sata_hba.h	Mon Sep 28 10:58:29 2009 +0800
+++ b/usr/src/uts/common/sys/sata/sata_hba.h	Mon Sep 28 14:30:40 2009 +0800
@@ -83,6 +83,7 @@
 #define	SATA_ADDR_PMPORT	0x08	/* Port Multiplier's device port */
 #define	SATA_ADDR_CNTRL		0x10	/* Controller */
 #define	SATA_ADDR_PMULT		0x20	/* Port Multiplier */
+#define	SATA_ADDR_PMULT_SPEC	0x40	/* Port Multiplier Specific */
 
 /*
  * SATA port status and control register block.
@@ -114,6 +115,7 @@
 	uint32_t	gscr1;		/* Resrved Information register */
 	uint32_t	gscr2;		/* Port Information register */
 	uint32_t	gscr64;		/* Feature register */
+	uint32_t	resv[4];	/* Reseved */
 };
 
 typedef struct sata_pmult_gscr sata_pmult_gscr_t;
@@ -136,8 +138,7 @@
  *	a value specific for a reported event.
  */
 #define	SATA_DEVICE_REV_1	1
-#define	SATA_DEVICE_REV_2	2
-#define	SATA_DEVICE_REV		SATA_DEVICE_REV_2
+#define	SATA_DEVICE_REV		SATA_DEVICE_REV_1
 
 struct sata_device
 {
@@ -146,9 +147,6 @@
 	uint32_t	satadev_state;		/* Port or device state */
 	uint32_t	satadev_type;		/* Attached device type */
 	struct sata_port_scr satadev_scr; 	/* Port status and ctrl regs */
-	struct sata_pmult_gscr satadev_gscr;	/* Port multiplier specific */
-						/* global status and control */
-						/* registers */
 	uint32_t	satadev_add_info;	/* additional information, */
 						/* function specific */
 };
@@ -746,7 +744,7 @@
 sata_pkt_t *sata_get_rdwr_pmult_pkt(dev_info_t *, sata_device_t *, uint8_t,
     uint32_t, uint32_t);
 void	sata_free_rdwr_pmult_pkt(sata_pkt_t *);
-int	sata_check_pmult_blacklist(sata_device_t *);
+void	sata_register_pmult(dev_info_t *, sata_device_t *, sata_pmult_gscr_t *);
 void	sata_free_dma_resources(sata_pkt_t *);
 
 /*