svn commit: r214016 - in head/sys: arm/mv dev/ata dev/ata/chipsets

Alexander Motin mav at FreeBSD.org
Mon Oct 18 11:30:14 UTC 2010


Author: mav
Date: Mon Oct 18 11:30:13 2010
New Revision: 214016
URL: http://svn.freebsd.org/changeset/base/214016

Log:
  Set of legacy mode SATA enchancements:
  - Implement proper combined mode decoding for Intel controllers to properly
  identify SATA and PATA channels and associate ATA channels with SATA ports.
  This fixes wrong reporting and in some cases hard resets to wrong SATA ports.
  - Improve SATA registers support to handle hot-plug events and potentially
  interface errors. For ICH5/6300ESB chipsets these registers accessible via
  PCI config space. For later ones they may be accessible via PCI BAR(5).
  - For controllers not generating interrupts on hot-plug events, implement
  periodic status polling. Use it to detect hot-plug on Intel and VIA
  controllers. Same probably could also be used for Serverworks and SIS.

Modified:
  head/sys/arm/mv/mv_sata.c
  head/sys/dev/ata/ata-all.c
  head/sys/dev/ata/ata-all.h
  head/sys/dev/ata/ata-pci.c
  head/sys/dev/ata/ata-sata.c
  head/sys/dev/ata/chipsets/ata-ahci.c
  head/sys/dev/ata/chipsets/ata-intel.c
  head/sys/dev/ata/chipsets/ata-marvell.c
  head/sys/dev/ata/chipsets/ata-nvidia.c
  head/sys/dev/ata/chipsets/ata-promise.c
  head/sys/dev/ata/chipsets/ata-siliconimage.c
  head/sys/dev/ata/chipsets/ata-via.c

Modified: head/sys/arm/mv/mv_sata.c
==============================================================================
--- head/sys/arm/mv/mv_sata.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/arm/mv/mv_sata.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -710,7 +710,7 @@ sata_channel_status(device_t dev)
 	if ((icr & SATA_ICR_DEV(ch->unit)) || iecr) {
 		/* Disable EDMA before accessing SATA registers */
 		sata_edma_ctrl(dev, 0);
-		ata_sata_phy_check_events(dev);
+		ata_sata_phy_check_events(dev, -1);
 
 		/* Ack device and error interrupt */
 		SATA_OUTL(sc, SATA_ICR, ~SATA_ICR_DEV(ch->unit));

Modified: head/sys/dev/ata/ata-all.c
==============================================================================
--- head/sys/dev/ata/ata-all.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/ata-all.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -83,6 +83,7 @@ static void bswap(int8_t *, int);
 static void btrim(int8_t *, int);
 static void bpack(int8_t *, int8_t *, int);
 static void ata_interrupt_locked(void *data);
+static void ata_periodic_poll(void *data);
 
 /* global vars */
 MALLOC_DEFINE(M_ATA, "ata_generic", "ATA driver generic layer");
@@ -173,6 +174,7 @@ ata_attach(device_t dev)
 		ch->curr[i] = ch->user[i];
 	}
 #endif
+	callout_init(&ch->poll_callout, 1);
 
     /* reset the controller HW, the channel and device(s) */
     while (ATA_LOCKING(dev, ATA_LF_LOCK) != ch->unit)
@@ -200,6 +202,8 @@ ata_attach(device_t dev)
 	device_printf(dev, "unable to setup interrupt\n");
 	return error;
     }
+    if (ch->flags & ATA_PERIODIC_POLL)
+	callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch);
 
 #ifndef ATA_CAM
     /* probe and attach devices on this channel unless we are in early boot */
@@ -246,6 +250,8 @@ err2:
 err1:
 	bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq);
 	mtx_unlock(&ch->state_mtx);
+	if (ch->flags & ATA_PERIODIC_POLL)
+		callout_drain(&ch->poll_callout);
 	return (error);
 #endif
 }
@@ -267,6 +273,8 @@ ata_detach(device_t dev)
     mtx_lock(&ch->state_mtx);
     ch->state |= ATA_STALL_QUEUE;
     mtx_unlock(&ch->state_mtx);
+    if (ch->flags & ATA_PERIODIC_POLL)
+	callout_drain(&ch->poll_callout);
 
 #ifndef ATA_CAM
     /* detach & delete all children */
@@ -454,6 +462,8 @@ ata_suspend(device_t dev)
     if (!dev || !(ch = device_get_softc(dev)))
 	return ENXIO;
 
+    if (ch->flags & ATA_PERIODIC_POLL)
+	callout_drain(&ch->poll_callout);
 #ifdef ATA_CAM
 	mtx_lock(&ch->state_mtx);
 	xpt_freeze_simq(ch->sim, 1);
@@ -498,6 +508,8 @@ ata_resume(device_t dev)
     /* kick off requests on the queue */
     ata_start(dev);
 #endif
+    if (ch->flags & ATA_PERIODIC_POLL)
+	callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch);
     return error;
 }
 
@@ -564,6 +576,15 @@ ata_interrupt_locked(void *data)
 #endif
 }
 
+static void
+ata_periodic_poll(void *data)
+{
+    struct ata_channel *ch = (struct ata_channel *)data;
+
+    callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch);
+    ata_interrupt(ch);
+}
+
 void
 ata_print_cable(device_t dev, u_int8_t *who)
 {

Modified: head/sys/dev/ata/ata-all.h
==============================================================================
--- head/sys/dev/ata/ata-all.h	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/ata-all.h	Mon Oct 18 11:30:13 2010	(r214016)
@@ -114,13 +114,6 @@
 #define         ATA_SS_IPM_PARTIAL      0x00000200
 #define         ATA_SS_IPM_SLUMBER      0x00000600
 
-#define         ATA_SS_CONWELL_MASK \
-		    (ATA_SS_DET_MASK|ATA_SS_SPD_MASK|ATA_SS_IPM_MASK)
-#define         ATA_SS_CONWELL_GEN1 \
-		    (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN1|ATA_SS_IPM_ACTIVE)
-#define         ATA_SS_CONWELL_GEN2 \
-		    (ATA_SS_DET_PHY_ONLINE|ATA_SS_SPD_GEN2|ATA_SS_IPM_ACTIVE)
-
 #define ATA_SERROR                      14
 #define         ATA_SE_DATA_CORRECTED   0x00000001
 #define         ATA_SE_COMM_CORRECTED   0x00000002
@@ -567,6 +560,7 @@ struct ata_channel {
 #define         ATA_DMA_BEFORE_CMD	0x100
 #define         ATA_KNOWN_PRESENCE	0x200
 #define         ATA_STATUS_IS_LONG	0x400
+#define         ATA_PERIODIC_POLL	0x800
 
     int				pm_level;	/* power management level */
     int                         devices;        /* what is present */
@@ -593,6 +587,7 @@ struct ata_channel {
 	struct ata_cam_device	user[16];       /* User-specified settings */                             
 	struct ata_cam_device	curr[16];       /* Current settings */                                    
 #endif
+	struct callout		poll_callout;	/* Periodic status poll. */
 };
 
 /* disk bay/enclosure related */
@@ -666,7 +661,7 @@ void ata_dmainit(device_t);
 void ata_dmafini(device_t dev);
 
 /* ata-sata.c: */
-void ata_sata_phy_check_events(device_t dev);
+void ata_sata_phy_check_events(device_t dev, int port);
 int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val);
 int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val);
 int ata_sata_phy_reset(device_t dev, int port, int quick);

Modified: head/sys/dev/ata/ata-pci.c
==============================================================================
--- head/sys/dev/ata/ata-pci.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/ata-pci.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -615,6 +615,7 @@ ata_pcichannel_attach(device_t dev)
 	return (0);
     ch->attached = 1;
 
+    ch->dev = dev;
     ch->unit = (intptr_t)device_get_ivars(dev);
 
     resource_int_value(device_get_name(dev),

Modified: head/sys/dev/ata/ata-sata.c
==============================================================================
--- head/sys/dev/ata/ata-sata.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/ata-sata.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -48,20 +48,23 @@ __FBSDID("$FreeBSD$");
 #include <ata_if.h>
 
 void
-ata_sata_phy_check_events(device_t dev)
+ata_sata_phy_check_events(device_t dev, int port)
 {
     struct ata_channel *ch = device_get_softc(dev);
-    u_int32_t error = ATA_IDX_INL(ch, ATA_SERROR);
+    u_int32_t error, status;
 
-    /* clear error bits/interrupt */
-    ATA_IDX_OUTL(ch, ATA_SERROR, error);
+    ata_sata_scr_read(ch, port, ATA_SERROR, &error);
+    /* Clear set error bits/interrupt. */
+    if (error)
+	ata_sata_scr_write(ch, port, ATA_SERROR, error);
 
     /* if we have a connection event deal with it */
     if ((error & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
 	if (bootverbose) {
-	    u_int32_t status = ATA_IDX_INL(ch, ATA_SSTATUS);
-	    if (((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1) ||
-		((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)) {
+	    ata_sata_scr_read(ch, port, ATA_SSTATUS, &status);
+	    if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
+		((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
+		((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
 		    device_printf(dev, "CONNECT requested\n");
 	    } else
 		    device_printf(dev, "DISCONNECT requested\n");
@@ -73,69 +76,51 @@ ata_sata_phy_check_events(device_t dev)
 int
 ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val)
 {
-    int r;
 
-    if (port < 0) {
+    if (ch->hw.pm_read != NULL)
+	return (ch->hw.pm_read(ch->dev, port, reg, val));
+    if (ch->r_io[reg].res) {
 	*val = ATA_IDX_INL(ch, reg);
 	return (0);
-    } else {
-	switch (reg) {
-	    case ATA_SSTATUS:
-		r = 0;
-		break;
-	    case ATA_SERROR:
-		r = 1;
-		break;
-	    case ATA_SCONTROL:
-		r = 2;
-		break;
-	    default:
-		return (EINVAL);
-	}
-	return (ch->hw.pm_read(ch->dev, port, r, val));
     }
+    return (-1);
 }
 
 int
 ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
 {
-    int r;
 
-    if (port < 0) {
+    if (ch->hw.pm_write != NULL)
+	return (ch->hw.pm_write(ch->dev, port, reg, val));
+    if (ch->r_io[reg].res) {
 	ATA_IDX_OUTL(ch, reg, val);
 	return (0);
-    } else {
-	switch (reg) {
-	    case ATA_SERROR:
-		r = 1;
-		break;
-	    case ATA_SCONTROL:
-		r = 2;
-		break;
-	    default:
-		return (EINVAL);
-	}
-	return (ch->hw.pm_write(ch->dev, port, r, val));
     }
+    return (-1);
 }
 
 static int
-ata_sata_connect(struct ata_channel *ch, int port)
+ata_sata_connect(struct ata_channel *ch, int port, int quick)
 {
     u_int32_t status;
-    int timeout;
+    int timeout, t;
 
     /* wait up to 1 second for "connect well" */
-    for (timeout = 0; timeout < 100 ; timeout++) {
+    timeout = (quick == 2) ? 0 : 100;
+    t = 0;
+    while (1) {
 	if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
 	    return (0);
-	if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
-	    (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
+	if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
+	    ((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
+	    ((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE))
+	    break;
+	if (++t > timeout)
 	    break;
 	ata_udelay(10000);
     }
-    if (timeout >= 100) {
-	if (bootverbose) {
+    if (bootverbose) {
+	if (t > timeout) {
 	    if (port < 0) {
 		device_printf(ch->dev, "SATA connect timeout status=%08x\n",
 		    status);
@@ -143,23 +128,19 @@ ata_sata_connect(struct ata_channel *ch,
 		device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
 		    port, status);
 	    }
-	}
-	return 0;
-    }
-    if (bootverbose) {
-	if (port < 0) {
+	} else if (port < 0) {
 	    device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
-		timeout * 10, status);
+		t * 10, status);
 	} else {
 	    device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
-		port, timeout * 10, status);
+		port, t * 10, status);
 	}
     }
 
     /* clear SATA error register */
     ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
 
-    return 1;
+    return ((t > timeout) ? 0 : 1);
 }
 
 int
@@ -173,7 +154,7 @@ ata_sata_phy_reset(device_t dev, int por
 	if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
 	    return (0);
 	if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
-	    return ata_sata_connect(ch, port);
+	    return ata_sata_connect(ch, port, quick);
     }
 
     if (bootverbose) {
@@ -203,7 +184,7 @@ ata_sata_phy_reset(device_t dev, int por
 	    if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
 		return (0);
 	    if ((val & ATA_SC_DET_MASK) == 0)
-		return ata_sata_connect(ch, port);
+		return ata_sata_connect(ch, port, 0);
 	}
     }
     return 0;

Modified: head/sys/dev/ata/chipsets/ata-ahci.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-ahci.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-ahci.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -403,7 +403,7 @@ ata_ahci_status(device_t dev)
 
 	/* do we have any PHY events ? */
 	if (istatus & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC))
-	    ata_sata_phy_check_events(dev);
+	    ata_sata_phy_check_events(dev, -1);
 
 	/* do we have a potentially hanging engine to take care of? */
 	/* XXX SOS what todo on NCQ */
@@ -623,6 +623,25 @@ ata_ahci_pm_read(device_t dev, int port,
 	(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
     u_int8_t *fis = ch->dma.work + ATA_AHCI_FB_OFFSET + 0x40;
 
+    if (port < 0) {
+	*result = ATA_IDX_INL(ch, reg);
+	return (0);
+    }
+    if (port < ATA_PM) {
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+    }
     bzero(ctp->cfis, 64);
     ctp->cfis[0] = 0x27;	/* host to device */
     ctp->cfis[1] = 0x8f;	/* command FIS to PM port */
@@ -649,6 +668,25 @@ ata_ahci_pm_write(device_t dev, int port
 	(struct ata_ahci_cmd_tab *)(ch->dma.work + ATA_AHCI_CT_OFFSET);
     int offset = ch->unit << 7;
 
+    if (port < 0) {
+	ATA_IDX_OUTL(ch, reg, value);
+	return (0);
+    }
+    if (port < ATA_PM) {
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+    }
     bzero(ctp->cfis, 64);
     ctp->cfis[0] = 0x27;	/* host to device */
     ctp->cfis[1] = 0x8f;	/* command FIS to PM port */

Modified: head/sys/dev/ata/chipsets/ata-intel.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-intel.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-intel.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -59,6 +59,15 @@ static int ata_intel_old_setmode(device_
 static int ata_intel_new_setmode(device_t dev, int target, int mode);
 static int ata_intel_sch_setmode(device_t dev, int target, int mode);
 static int ata_intel_sata_getrev(device_t dev, int target);
+static int ata_intel_sata_status(device_t dev);
+static int ata_intel_sata_cscr_read(device_t dev, int port,
+    int reg, u_int32_t *result);
+static int ata_intel_sata_sidpr_read(device_t dev, int port,
+    int reg, u_int32_t *result);
+static int ata_intel_sata_cscr_write(device_t dev, int port,
+    int reg, u_int32_t result);
+static int ata_intel_sata_sidpr_write(device_t dev, int port,
+    int reg, u_int32_t result);
 static int ata_intel_31244_ch_attach(device_t dev);
 static int ata_intel_31244_ch_detach(device_t dev);
 static int ata_intel_31244_status(device_t dev);
@@ -67,7 +76,9 @@ static void ata_intel_31244_reset(device
 
 /* misc defines */
 #define INTEL_AHCI	1
-
+#define INTEL_ICH5	2
+#define INTEL_6CH	4
+#define INTEL_6CH2	8
 
 /*
  * Intel chipset support functions
@@ -92,74 +103,74 @@ ata_intel_probe(device_t dev)
      { ATA_I82801DB,     0,          0, 2, ATA_UDMA5, "ICH4" },
      { ATA_I82801DB_1,   0,          0, 2, ATA_UDMA5, "ICH4" },
      { ATA_I82801EB,     0,          0, 2, ATA_UDMA5, "ICH5" },
-     { ATA_I82801EB_S1,  0,          0, 2, ATA_SA150, "ICH5" },
-     { ATA_I82801EB_R1,  0,          0, 2, ATA_SA150, "ICH5" },
+     { ATA_I82801EB_S1,  0, INTEL_ICH5, 2, ATA_SA150, "ICH5" },
+     { ATA_I82801EB_R1,  0, INTEL_ICH5, 2, ATA_SA150, "ICH5" },
      { ATA_I6300ESB,     0,          0, 2, ATA_UDMA5, "6300ESB" },
-     { ATA_I6300ESB_S1,  0,          0, 2, ATA_SA150, "6300ESB" },
-     { ATA_I6300ESB_R1,  0,          0, 2, ATA_SA150, "6300ESB" },
+     { ATA_I6300ESB_S1,  0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" },
+     { ATA_I6300ESB_R1,  0, INTEL_ICH5, 2, ATA_SA150, "6300ESB" },
      { ATA_I82801FB,     0,          0, 2, ATA_UDMA5, "ICH6" },
      { ATA_I82801FB_S1,  0, INTEL_AHCI, 0, ATA_SA150, "ICH6" },
      { ATA_I82801FB_R1,  0, INTEL_AHCI, 0, ATA_SA150, "ICH6" },
      { ATA_I82801FBM,    0, INTEL_AHCI, 0, ATA_SA150, "ICH6M" },
      { ATA_I82801GB,     0,          0, 1, ATA_UDMA5, "ICH7" },
-     { ATA_I82801GB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
-     { ATA_I82801GB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
+     { ATA_I82801GB_S1,  0,          0, 0, ATA_SA300, "ICH7" },
+     { ATA_I82801GB_R1,  0,          0, 0, ATA_SA300, "ICH7" },
      { ATA_I82801GB_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH7" },
-     { ATA_I82801GBM_S1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
-     { ATA_I82801GBM_R1, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
+     { ATA_I82801GBM_S1, 0,          0, 0, ATA_SA150, "ICH7M" },
+     { ATA_I82801GBM_R1, 0,          0, 0, ATA_SA150, "ICH7M" },
      { ATA_I82801GBM_AH, 0, INTEL_AHCI, 0, ATA_SA150, "ICH7M" },
      { ATA_I63XXESB2,    0,          0, 1, ATA_UDMA5, "63XXESB2" },
-     { ATA_I63XXESB2_S1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
+     { ATA_I63XXESB2_S1, 0,          0, 0, ATA_SA300, "63XXESB2" },
      { ATA_I63XXESB2_S2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
      { ATA_I63XXESB2_R1, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
      { ATA_I63XXESB2_R2, 0, INTEL_AHCI, 0, ATA_SA300, "63XXESB2" },
-     { ATA_I82801HB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
-     { ATA_I82801HB_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
+     { ATA_I82801HB_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH8" },
+     { ATA_I82801HB_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH8" },
      { ATA_I82801HB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
      { ATA_I82801HB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
      { ATA_I82801HB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8" },
      { ATA_I82801HBM,    0,          0, 1, ATA_UDMA5, "ICH8M" },
-     { ATA_I82801HBM_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
+     { ATA_I82801HBM_S1, 0, INTEL_6CH,  0, ATA_SA300, "ICH8M" },
      { ATA_I82801HBM_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
      { ATA_I82801HBM_S3, 0, INTEL_AHCI, 0, ATA_SA300, "ICH8M" },
-     { ATA_I82801IB_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
-     { ATA_I82801IB_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
+     { ATA_I82801IB_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH9" },
+     { ATA_I82801IB_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH9" },
      { ATA_I82801IB_AH2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
      { ATA_I82801IB_AH4, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
      { ATA_I82801IB_AH6, 0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
      { ATA_I82801IB_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH9" },
-     { ATA_I82801JIB_S1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
+     { ATA_I82801JIB_S1, 0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
      { ATA_I82801JIB_AH, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
      { ATA_I82801JIB_R1, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_I82801JIB_S2, 0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_I82801JD_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
+     { ATA_I82801JIB_S2, 0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
+     { ATA_I82801JD_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
      { ATA_I82801JD_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
      { ATA_I82801JD_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_I82801JD_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_I82801JI_S1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
+     { ATA_I82801JD_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
+     { ATA_I82801JI_S1,  0, INTEL_6CH,  0, ATA_SA300, "ICH10" },
      { ATA_I82801JI_AH,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
      { ATA_I82801JI_R1,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_I82801JI_S2,  0, INTEL_AHCI, 0, ATA_SA300, "ICH10" },
-     { ATA_5Series_S1,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_5Series_S2,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_I82801JI_S2,  0, INTEL_6CH2, 0, ATA_SA300, "ICH10" },
+     { ATA_5Series_S1,   0, INTEL_6CH,  0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_5Series_S2,   0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_AH1,  0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_AH2,  0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_R1,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_5Series_S3,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_5Series_S4,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_5Series_S3,   0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_5Series_S4,   0, INTEL_6CH,  0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_AH3,  0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_R2,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_5Series_S5,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_5Series_S6,   0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_5Series_S5,   0, INTEL_6CH2, 0, ATA_SA300, "5 Series/3400 Series PCH" },
+     { ATA_5Series_S6,   0, INTEL_6CH,  0, ATA_SA300, "5 Series/3400 Series PCH" },
      { ATA_5Series_AH4,  0, INTEL_AHCI, 0, ATA_SA300, "5 Series/3400 Series PCH" },
-     { ATA_CPT_S1,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
-     { ATA_CPT_S2,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
+     { ATA_CPT_S1,       0, INTEL_6CH,  0, ATA_SA300, "Cougar Point" },
+     { ATA_CPT_S2,       0, INTEL_6CH,  0, ATA_SA300, "Cougar Point" },
      { ATA_CPT_AH1,      0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
      { ATA_CPT_AH2,      0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
      { ATA_CPT_R1,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
      { ATA_CPT_R2,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
-     { ATA_CPT_S3,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
-     { ATA_CPT_S4,       0, INTEL_AHCI, 0, ATA_SA300, "Cougar Point" },
+     { ATA_CPT_S3,       0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" },
+     { ATA_CPT_S4,       0, INTEL_6CH2, 0, ATA_SA300, "Cougar Point" },
      { ATA_I31244,       0,          0, 2, ATA_SA150, "31244" },
      { ATA_ISCH,         0,          0, 1, ATA_UDMA5, "SCH" },
      { 0, 0, 0, 0, 0, 0}};
@@ -183,6 +194,8 @@ ata_intel_chipinit(device_t dev)
     if (ata_setup_interrupt(dev, ata_generic_intr))
 	return ENXIO;
 
+    ctlr->chipset_data = NULL;
+
     /* good old PIIX needs special treatment (not implemented) */
     if (ctlr->chip->chipid == ATA_I82371FB) {
 	ctlr->setmode = ata_intel_old_setmode;
@@ -233,7 +246,7 @@ ata_intel_chipinit(device_t dev)
 	 * if we have AHCI capability and AHCI or RAID mode enabled
 	 * in BIOS we try for AHCI mode
 	 */ 
-	if ((ctlr->chip->cfg1 == INTEL_AHCI) &&
+	if ((ctlr->chip->cfg1 & INTEL_AHCI) &&
 	    (pci_read_config(dev, 0x90, 1) & 0xc0) &&
 	    (ata_ahci_chipinit(dev) != ENXIO))
 	    return 0;
@@ -242,7 +255,8 @@ ata_intel_chipinit(device_t dev)
 	ctlr->r_type2 = SYS_RES_IOPORT;
 	ctlr->r_rid2 = PCIR_BAR(5);
 	if ((ctlr->r_res2 = bus_alloc_resource_any(dev, ctlr->r_type2,
-						   &ctlr->r_rid2, RF_ACTIVE)))
+						   &ctlr->r_rid2, RF_ACTIVE))
+	    || (ctlr->chip->cfg1 & INTEL_ICH5))
 	    ctlr->getrev = ata_intel_sata_getrev;
 	ctlr->setmode = ata_sata_setmode;
     }
@@ -252,63 +266,142 @@ ata_intel_chipinit(device_t dev)
 static int
 ata_intel_ch_attach(device_t dev)
 {
-    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
-    struct ata_channel *ch = device_get_softc(dev);
-
-    /* setup the usual register normal pci style */
-    if (ata_pci_ch_attach(dev))
-	return ENXIO;
-
-    /* if r_res2 is valid it points to SATA interface registers */
-    if (ctlr->r_res2) {
-	ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
-	ch->r_io[ATA_IDX_ADDR].offset = 0x00;
-	ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
-	ch->r_io[ATA_IDX_DATA].offset = 0x04;
-    }
+	struct ata_pci_controller *ctlr;
+	struct ata_channel *ch;
+	u_char *smap;
+	u_int map;
+
+	/* setup the usual register normal pci style */
+	if (ata_pci_ch_attach(dev))
+		return (ENXIO);
+
+	ctlr = device_get_softc(device_get_parent(dev));
+	ch = device_get_softc(dev);
+
+	/* if r_res2 is valid it points to SATA interface registers */
+	if (ctlr->r_res2) {
+		ch->r_io[ATA_IDX_ADDR].res = ctlr->r_res2;
+		ch->r_io[ATA_IDX_ADDR].offset = 0x00;
+		ch->r_io[ATA_IDX_DATA].res = ctlr->r_res2;
+		ch->r_io[ATA_IDX_DATA].offset = 0x04;
+	}
 
-    ch->flags |= ATA_ALWAYS_DMASTAT;
-    if (ctlr->chip->max_dma >= ATA_SA150) {
-	    if (ctlr->chip->cfg1 == 0 &&
-		(pci_read_config(device_get_parent(dev), 0x90, 1) & 0x04) == 0)
-		    ch->flags |= ATA_NO_SLAVE;
-	    ch->flags |= ATA_SATA;
-    } else if (ctlr->chip->chipid != ATA_ISCH)
-	    ch->flags |= ATA_CHECKS_CABLE;
-    return 0;
+	ch->flags |= ATA_ALWAYS_DMASTAT;
+	if (ctlr->chip->max_dma >= ATA_SA150) {
+		smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+		map = pci_read_config(device_get_parent(dev), 0x90, 1);
+		if (ctlr->chip->cfg1 & INTEL_ICH5) {
+			map &= 0x07;
+			if ((map & 0x04) == 0) {
+				ch->flags |= ATA_SATA;
+				ch->flags |= ATA_NO_SLAVE;
+				smap[0] = (map & 0x01) ^ ch->unit;
+				smap[1] = 0;
+			} else if ((map & 0x02) == 0 && ch->unit == 0) {
+				ch->flags |= ATA_SATA;
+				smap[0] = (map & 0x01) ? 1 : 0;
+				smap[1] = (map & 0x01) ? 0 : 1;
+			} else if ((map & 0x02) != 0 && ch->unit == 1) {
+				ch->flags |= ATA_SATA;
+				smap[0] = (map & 0x01) ? 1 : 0;
+				smap[1] = (map & 0x01) ? 0 : 1;
+			}
+		} else if (ctlr->chip->cfg1 & INTEL_6CH2) {
+			ch->flags |= ATA_SATA;
+			ch->flags |= ATA_NO_SLAVE;
+			smap[0] = (ch->unit == 0) ? 4 : 5;
+			smap[1] = 0;
+		} else {
+			map &= 0x03;
+			if (map == 0x00) {
+				ch->flags |= ATA_SATA;
+				smap[ch->unit] = (ch->unit == 0) ? 0x20 : 0x31;
+				smap[0] = (ch->unit == 0) ? 0 : 1;
+				smap[1] = (ch->unit == 0) ? 2 : 3;
+			} else if (map == 0x02 && ch->unit == 0) {
+				ch->flags |= ATA_SATA;
+				smap[0] = 0;
+				smap[1] = 2;
+			} else if (map == 0x01 && ch->unit == 1) {
+				ch->flags |= ATA_SATA;
+				smap[0] = 1;
+				smap[1] = 3;
+			}
+		}
+		if (ch->flags & ATA_SATA) {
+			if ((ctlr->chip->cfg1 & INTEL_ICH5)) {
+				ch->flags |= ATA_PERIODIC_POLL;
+				ch->hw.status = ata_intel_sata_status;
+				ch->hw.pm_read = ata_intel_sata_cscr_read;
+				ch->hw.pm_write = ata_intel_sata_cscr_write;
+			} else if (ctlr->r_res2) {
+				ch->flags |= ATA_PERIODIC_POLL;
+				ch->hw.status = ata_intel_sata_status;
+				ch->hw.pm_read = ata_intel_sata_sidpr_read;
+				ch->hw.pm_write = ata_intel_sata_sidpr_write;
+			}
+			if (ch->hw.pm_write != NULL) {
+				ata_sata_scr_write(ch, 0,
+				    ATA_SERROR, 0xffffffff);
+				if ((ch->flags & ATA_NO_SLAVE) == 0) {
+					ata_sata_scr_write(ch, 1,
+					    ATA_SERROR, 0xffffffff);
+				}
+			}
+		} else
+			ctlr->setmode = ata_intel_new_setmode;
+	} else if (ctlr->chip->chipid != ATA_ISCH)
+		ch->flags |= ATA_CHECKS_CABLE;
+	return (0);
 }
 
 static void
 ata_intel_reset(device_t dev)
 {
-    device_t parent = device_get_parent(dev);
-    struct ata_pci_controller *ctlr = device_get_softc(parent);
-    struct ata_channel *ch = device_get_softc(dev);
-    int mask, timeout;
+	device_t parent = device_get_parent(dev);
+	struct ata_pci_controller *ctlr = device_get_softc(parent);
+	struct ata_channel *ch = device_get_softc(dev);
+	int mask, pmask, timeout, devs;
+	u_char *smap;
 
-    /* ICH6 & ICH7 in compat mode has 4 SATA ports as master/slave on 2 ch's */
-    if (ctlr->chip->cfg1) {
-	mask = (0x0005 << ch->unit);
-    }
-    else {
-	/* ICH5 in compat mode has SATA ports as master/slave on 1 channel */
-	if (pci_read_config(parent, 0x90, 1) & 0x04)
-	    mask = 0x0003;
+	/* In combined mode, skip SATA stuff for PATA channel. */
+	if ((ch->flags & ATA_SATA) == 0)
+		return (ata_generic_reset(dev));
+
+	/* Do hard-reset on respective SATA ports. */
+	smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+	mask = 1 << smap[0];
+	if ((ch->flags & ATA_NO_SLAVE) == 0)
+		mask |= (1 << smap[1]);
+	pci_write_config(parent, 0x92,
+	    pci_read_config(parent, 0x92, 2) & ~mask, 2);
+	DELAY(10);
+	pci_write_config(parent, 0x92,
+	    pci_read_config(parent, 0x92, 2) | mask, 2);
+
+	/* Wait up to 1 sec for "connect well". */
+	if (ctlr->chip->cfg1 & (INTEL_6CH | INTEL_6CH2))
+		pmask = mask << 8;
 	else
-	    mask = (0x0001 << ch->unit);
-    }
-    pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) & ~mask, 2);
-    DELAY(10);
-    pci_write_config(parent, 0x92, pci_read_config(parent, 0x92, 2) | mask, 2);
-
-    /* wait up to 1 sec for "connect well" */
-    for (timeout = 0; timeout < 100 ; timeout++) {
-	if (((pci_read_config(parent, 0x92, 2) & (mask << 4)) == (mask << 4)) &&
-	    (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
-	    break;
-	ata_udelay(10000);
-    }
-    ata_generic_reset(dev);
+		pmask = mask << 4;
+	for (timeout = 0; timeout < 100 ; timeout++) {
+		if (((pci_read_config(parent, 0x92, 2) & pmask) == pmask) &&
+		    (ATA_IDX_INB(ch, ATA_STATUS) != 0xff))
+			break;
+		ata_udelay(10000);
+	}
+
+	/* If any device found, do soft-reset. */
+	if (ch->hw.pm_read != NULL) {
+		devs = ata_sata_phy_reset(dev, 0, 2);
+		if ((ch->flags & ATA_NO_SLAVE) == 0)
+			devs += ata_sata_phy_reset(dev, 1, 2);
+	} else
+		devs = 1;
+	if (devs)
+		ata_generic_reset(dev);
+	else
+		ch->devices = 0;
 }
 
 static int
@@ -339,6 +432,10 @@ ata_intel_new_setmode(device_t dev, int 
 	u_int8_t timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x00, 0x21, 0x23 };
 	u_int8_t utimings[] = { 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02 };
 
+	/* In combined mode, skip PATA stuff for SATA channel. */
+	if (ch->flags & ATA_SATA)
+		return (ata_sata_setmode(dev, target, mode));
+
 	mode = min(mode, ctlr->chip->max_dma);
 	if (ata_dma_check_80pin && mode > ATA_UDMA2 &&
 	    !(reg54 & (0x10 << devno))) {
@@ -421,12 +518,145 @@ static int
 ata_intel_sata_getrev(device_t dev, int target)
 {
 	struct ata_channel *ch = device_get_softc(dev);
-	int devno = (ch->unit << 1) + target;
+	uint32_t status;
+
+	if (ata_sata_scr_read(ch, target, ATA_SSTATUS, &status) == 0)
+		return ((status & 0x0f0) >> 4);
+	return (0xff);
+}
+
+static int
+ata_intel_sata_status(device_t dev)
+{
+	struct ata_channel *ch = device_get_softc(dev);
+
+	ata_sata_phy_check_events(dev, 0);
+	if ((ch->flags & ATA_NO_SLAVE) == 0)
+		ata_sata_phy_check_events(dev, 1);
 
-	/* set ATA_SSTATUS register offset */
-	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, devno * 0x100);
-	/* query SATA STATUS for the speed */
-	return ((ATA_IDX_INL(ch, ATA_IDX_DATA) & 0x0f0) >> 4);
+	return ata_pci_status(dev);
+}
+
+static int
+ata_intel_sata_cscr_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+	struct ata_pci_controller *ctlr;
+	struct ata_channel *ch;
+	device_t parent;
+	u_char *smap;
+
+	parent = device_get_parent(dev);
+	ctlr = device_get_softc(parent);
+	ch = device_get_softc(dev);
+	smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+	port = (port == 1) ? 1 : 0;
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+	pci_write_config(parent, 0xa0,
+	    0x50 + smap[port] * 0x10 + reg * 4, 4);
+	*result = pci_read_config(parent, 0xa4, 4);
+	return (0);
+}
+
+static int
+ata_intel_sata_sidpr_read(device_t dev, int port, int reg, u_int32_t *result)
+{
+	struct ata_pci_controller *ctlr;
+	struct ata_channel *ch;
+	device_t parent;
+
+	parent = device_get_parent(dev);
+	ctlr = device_get_softc(parent);
+	ch = device_get_softc(dev);
+	port = (port == 1) ? 1 : 0;
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 1;
+	    break;
+	case ATA_SERROR:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
+	*result = ATA_IDX_INL(ch, ATA_IDX_DATA);
+	return (0);
+}
+
+static int
+ata_intel_sata_cscr_write(device_t dev, int port, int reg, u_int32_t value)
+{
+	struct ata_pci_controller *ctlr;
+	struct ata_channel *ch;
+	device_t parent;
+	u_char *smap;
+
+	parent = device_get_parent(dev);
+	ctlr = device_get_softc(parent);
+	ch = device_get_softc(dev);
+	smap = (u_char *)&ctlr->chipset_data + ch->unit * 2;
+	port = (port == 1) ? 1 : 0;
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+	pci_write_config(parent, 0xa0,
+	    0x50 + smap[port] * 0x10 + reg * 4, 4);
+	pci_write_config(parent, 0xa4, value, 4);
+	return (0);
+}
+
+static int
+ata_intel_sata_sidpr_write(device_t dev, int port, int reg, u_int32_t value)
+{
+	struct ata_pci_controller *ctlr;
+	struct ata_channel *ch;
+	device_t parent;
+
+	parent = device_get_parent(dev);
+	ctlr = device_get_softc(parent);
+	ch = device_get_softc(dev);
+	port = (port == 1) ? 1 : 0;
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 1;
+	    break;
+	case ATA_SERROR:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+	ATA_IDX_OUTL(ch, ATA_IDX_ADDR, ((ch->unit * 2 + port) << 8) + reg);
+	ATA_IDX_OUTL(ch, ATA_IDX_DATA, value);
+	return (0);
 }
 
 static int
@@ -492,7 +722,7 @@ static int
 ata_intel_31244_status(device_t dev)
 {
     /* do we have any PHY events ? */
-    ata_sata_phy_check_events(dev);
+    ata_sata_phy_check_events(dev, -1);
 
     /* any drive action to take care of ? */
     return ata_pci_status(dev);

Modified: head/sys/dev/ata/chipsets/ata-marvell.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-marvell.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-marvell.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -374,7 +374,7 @@ ata_marvell_edma_status(device_t dev)
 	ATA_OUTL(ctlr->r_res1, 0x02008 + ATA_MV_EDMA_BASE(ch), 0x0);
 
 	/* do we have any PHY events ? */
-	ata_sata_phy_check_events(dev);
+	ata_sata_phy_check_events(dev, -1);
     }
 
     /* do we have any device action ? */

Modified: head/sys/dev/ata/chipsets/ata-nvidia.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-nvidia.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-nvidia.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -281,7 +281,7 @@ ata_nvidia_status(device_t dev)
 
     /* do we have any PHY events ? */
     if (istatus & (0x0c << shift))
-	ata_sata_phy_check_events(dev);
+	ata_sata_phy_check_events(dev, -1);
 
     /* clear interrupt(s) */
     if (ctlr->chip->cfg1 & NVQ)

Modified: head/sys/dev/ata/chipsets/ata-promise.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-promise.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-promise.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -830,6 +830,25 @@ ata_promise_mio_pm_read(device_t dev, in
     struct ata_channel *ch = device_get_softc(dev);
     int timeout = 0;
 
+    if (port < 0) {
+	*result = ATA_IDX_INL(ch, reg);
+	return (0);
+    }
+    if (port < ATA_PM) {
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+    }
     /* set portmultiplier port */
     ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
 
@@ -862,6 +881,25 @@ ata_promise_mio_pm_write(device_t dev, i
     struct ata_channel *ch = device_get_softc(dev);
     int timeout = 0;
 
+    if (port < 0) {
+	ATA_IDX_OUTL(ch, reg, value);
+	return (0);
+    }
+    if (port < ATA_PM) {
+	switch (reg) {
+	case ATA_SSTATUS:
+	    reg = 0;
+	    break;
+	case ATA_SERROR:
+	    reg = 1;
+	    break;
+	case ATA_SCONTROL:
+	    reg = 2;
+	    break;
+	default:
+	    return (EINVAL);
+	}
+    }
     /* set portmultiplier port */
     ATA_OUTB(ctlr->r_res2, 0x4e8 + (ch->unit << 8), 0x0f);
 

Modified: head/sys/dev/ata/chipsets/ata-siliconimage.c
==============================================================================
--- head/sys/dev/ata/chipsets/ata-siliconimage.c	Mon Oct 18 09:44:21 2010	(r214015)
+++ head/sys/dev/ata/chipsets/ata-siliconimage.c	Mon Oct 18 11:30:13 2010	(r214016)
@@ -354,7 +354,7 @@ ata_sii_status(device_t dev)
     /* do we have any PHY events ? */
     if (ctlr->chip->max_dma >= ATA_SA150 &&
 	(ATA_INL(ctlr->r_res2, 0x10 + offset0) & 0x00000010))
-	ata_sata_phy_check_events(dev);
+	ata_sata_phy_check_events(dev, -1);
 
     if (ATA_INL(ctlr->r_res2, 0xa0 + offset1) & 0x00000800)
 	return ata_pci_status(dev);
@@ -510,7 +510,7 @@ ata_siiprb_status(device_t dev)
 	u_int32_t istatus = ATA_INL(ctlr->r_res2, 0x1008 + offset);
 
 	/* do we have any PHY events ? */
-	ata_sata_phy_check_events(dev);
+	ata_sata_phy_check_events(dev, -1);
 
 	/* clear interrupt(s) */
 	ATA_OUTL(ctlr->r_res2, 0x1008 + offset, istatus);
@@ -700,6 +700,25 @@ ata_siiprb_pm_read(device_t dev, int por
     struct ata_siiprb_command *prb = (struct ata_siiprb_command *)ch->dma.work;
     int offset = ch->unit * 0x2000;
 
+    if (port < 0) {
+	*result = ATA_IDX_INL(ch, reg);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list