svn commit: r199698 - in stable/8/sys/dev: ahci ata ata/chipsets

Alexander Motin mav at FreeBSD.org
Mon Nov 23 08:56:19 UTC 2009


Author: mav
Date: Mon Nov 23 08:56:17 2009
New Revision: 199698
URL: http://svn.freebsd.org/changeset/base/199698

Log:
  MFC r199259, r199262, r199322:
  Change the way in which AHCI+PATA combined controllers, such as JMicron
  are handled. Instead of trying to attach two different drivers to
  single device, wrapping each call, make one of them (atajmicron)
  attach do device solely, but create child device for AHCI driver,
  passing it all required resources. It is quite easy, as none of
  resources are shared, except IRQ.
  Add support for AHCI SATA parts of alike SATA+PATA MArvell controllers.
  Add IDs of Marvell 88SX6102, 88SX6111. 88SX6141 controllers.
  
  As result, it:
  - makes drivers operation more independent and straitforward,
  - allows to use new ahci(4) driver with such devices, adding support for
  new features, such as PMP and NCQ, same time keeping legacy PATA support,
  - will allow to just drop old ataahci driver, when it's time come.

Modified:
  stable/8/sys/dev/ahci/ahci.c
  stable/8/sys/dev/ahci/ahci.h
  stable/8/sys/dev/ata/ata-pci.c
  stable/8/sys/dev/ata/ata-pci.h
  stable/8/sys/dev/ata/chipsets/ata-ahci.c
  stable/8/sys/dev/ata/chipsets/ata-jmicron.c
  stable/8/sys/dev/ata/chipsets/ata-marvell.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/ahci/ahci.c
==============================================================================
--- stable/8/sys/dev/ahci/ahci.c	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ahci/ahci.c	Mon Nov 23 08:56:17 2009	(r199698)
@@ -99,7 +99,14 @@ MALLOC_DEFINE(M_AHCI, "AHCI driver", "AH
 static struct {
 	uint32_t	id;
 	const char	*name;
-	int		flags;
+	int		quirks;
+#define AHCI_Q_NOFORCE	1
+#define AHCI_Q_NOPMP	2
+#define AHCI_Q_NONCQ	4
+#define AHCI_Q_1CH	8
+#define AHCI_Q_2CH	16
+#define AHCI_Q_4CH	32
+#define AHCI_Q_EDGEIS	64
 } ahci_ids[] = {
 	{0x43801002, "ATI IXP600",	0},
 	{0x43901002, "ATI IXP700",	0},
@@ -145,6 +152,15 @@ static struct {
 	{0x3b2b8086, "Intel PCH",	0},
 	{0x3b2c8086, "Intel PCH",	0},
 	{0x3b2f8086, "Intel PCH",	0},
+	{0x2361197b, "JMicron JMB361",	AHCI_Q_NOFORCE},
+	{0x2363197b, "JMicron JMB363",	AHCI_Q_NOFORCE},
+	{0x2365197b, "JMicron JMB365",	AHCI_Q_NOFORCE},
+	{0x2366197b, "JMicron JMB366",	AHCI_Q_NOFORCE},
+	{0x2368197b, "JMicron JMB368",	AHCI_Q_NOFORCE},
+	{0x611111ab, "Marvell 88SX6111", AHCI_Q_NOFORCE|AHCI_Q_1CH|AHCI_Q_EDGEIS},
+	{0x612111ab, "Marvell 88SX6121", AHCI_Q_NOFORCE|AHCI_Q_2CH|AHCI_Q_EDGEIS},
+	{0x614111ab, "Marvell 88SX6141", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
+	{0x614511ab, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS},
 	{0x044c10de, "NVIDIA MCP65",	0},
 	{0x044d10de, "NVIDIA MCP65",	0},
 	{0x044e10de, "NVIDIA MCP65",	0},
@@ -226,9 +242,39 @@ static int
 ahci_probe(device_t dev)
 {
 	char buf[64];
+	int i, valid = 0;
+	uint32_t devid = pci_get_devid(dev);
+
+	/* Is this a possible AHCI candidate? */
+	if (pci_get_class(dev) == PCIC_STORAGE &&
+	    pci_get_subclass(dev) == PCIS_STORAGE_SATA &&
+	    pci_get_progif(dev) == PCIP_STORAGE_SATA_AHCI_1_0)
+		valid = 1;
+	/* Is this a known AHCI chip? */
+	for (i = 0; ahci_ids[i].id != 0; i++) {
+		if (ahci_ids[i].id == devid &&
+		    (valid || !(ahci_ids[i].quirks & AHCI_Q_NOFORCE))) {
+			snprintf(buf, sizeof(buf), "%s AHCI SATA controller",
+			    ahci_ids[i].name);
+			device_set_desc_copy(dev, buf);
+			return (BUS_PROBE_VENDOR);
+		}
+	}
+	if (!valid)
+		return (ENXIO);
+	device_set_desc_copy(dev, "AHCI SATA controller");
+	return (BUS_PROBE_VENDOR);
+}
+
+static int
+ahci_ata_probe(device_t dev)
+{
+	char buf[64];
 	int i;
 	uint32_t devid = pci_get_devid(dev);
 
+	if ((intptr_t)device_get_ivars(dev) >= 0)
+		return (ENXIO);
 	/* Is this a known AHCI chip? */
 	for (i = 0; ahci_ids[i].id != 0; i++) {
 		if (ahci_ids[i].id == devid) {
@@ -238,11 +284,6 @@ ahci_probe(device_t dev)
 			return (BUS_PROBE_VENDOR);
 		}
 	}
-	/* Is this a possible AHCI candidate? */
-	if (pci_get_class(dev) != PCIC_STORAGE ||
-	    pci_get_subclass(dev) != PCIS_STORAGE_SATA ||
-	    pci_get_progif(dev) != PCIP_STORAGE_SATA_AHCI_1_0)
-		return (ENXIO);
 	device_set_desc_copy(dev, "AHCI SATA controller");
 	return (BUS_PROBE_VENDOR);
 }
@@ -252,10 +293,15 @@ ahci_attach(device_t dev)
 {
 	struct ahci_controller *ctlr = device_get_softc(dev);
 	device_t child;
-	int	error, unit, speed;
+	int	error, unit, speed, i;
+	uint32_t devid = pci_get_devid(dev);
 	u_int32_t version;
 
 	ctlr->dev = dev;
+	i = 0;
+	while (ahci_ids[i].id != 0 && ahci_ids[i].id != devid)
+		i++;
+	ctlr->quirks = ahci_ids[i].quirks;
 	resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "ccc", &ctlr->ccc);
 	/* if we have a memory BAR(5) we are likely on an AHCI part */
@@ -282,10 +328,32 @@ ahci_attach(device_t dev)
 		rman_fini(&ctlr->sc_iomem);
 		return (error);
 	};
-	/* Get the number of HW channels */
+	/* Get the HW capabilities */
+	version = ATA_INL(ctlr->r_mem, AHCI_VS);
+	ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
+	if (version >= 0x00010020)
+		ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
 	ctlr->ichannels = ATA_INL(ctlr->r_mem, AHCI_PI);
+	if (ctlr->quirks & AHCI_Q_1CH) {
+		ctlr->caps &= ~AHCI_CAP_NPMASK;
+		ctlr->ichannels &= 0x01;
+	}
+	if (ctlr->quirks & AHCI_Q_2CH) {
+		ctlr->caps &= ~AHCI_CAP_NPMASK;
+		ctlr->caps |= 1;
+		ctlr->ichannels &= 0x03;
+	}
+	if (ctlr->quirks & AHCI_Q_4CH) {
+		ctlr->caps &= ~AHCI_CAP_NPMASK;
+		ctlr->caps |= 3;
+		ctlr->ichannels &= 0x0f;
+	}
 	ctlr->channels = MAX(flsl(ctlr->ichannels),
-	    (ATA_INL(ctlr->r_mem, AHCI_CAP) & AHCI_CAP_NPMASK) + 1);
+	    (ctlr->caps & AHCI_CAP_NPMASK) + 1);
+	if (ctlr->quirks & AHCI_Q_NOPMP)
+		ctlr->caps &= ~AHCI_CAP_SPM;
+	if (ctlr->quirks & AHCI_Q_NONCQ)
+		ctlr->caps &= ~AHCI_CAP_SNCQ;
 	/* Setup interrupts. */
 	if (ahci_setup_interrupt(dev)) {
 		bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
@@ -293,10 +361,6 @@ ahci_attach(device_t dev)
 		return ENXIO;
 	}
 	/* Announce HW capabilities. */
-	version = ATA_INL(ctlr->r_mem, AHCI_VS);
-	ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
-	if (version >= 0x00010020)
-		ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
 	speed = (ctlr->caps & AHCI_CAP_ISS) >> AHCI_CAP_ISS_SHIFT;
 	device_printf(dev,
 		    "AHCI v%x.%02x with %d %sGbps ports, Port Multiplier %s\n",
@@ -531,8 +595,15 @@ ahci_intr(void *data)
 	for (; unit < ctlr->channels; unit++) {
 		if ((is & (1 << unit)) != 0 &&
 		    (arg = ctlr->interrupt[unit].argument)) {
-			ctlr->interrupt[unit].function(arg);
-			ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
+			if (ctlr->quirks & AHCI_Q_EDGEIS) {
+				/* Some controller have edge triggered IS. */
+				ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
+				ctlr->interrupt[unit].function(arg);
+			} else {
+				/* but AHCI declares level triggered IS. */
+				ctlr->interrupt[unit].function(arg);
+				ATA_OUTL(ctlr->r_mem, AHCI_IS, 1 << unit);
+			}
 		}
 	}
 }
@@ -665,6 +736,25 @@ static driver_t ahci_driver = {
         sizeof(struct ahci_controller)
 };
 DRIVER_MODULE(ahci, pci, ahci_driver, ahci_devclass, 0, 0);
+static device_method_t ahci_ata_methods[] = {
+	DEVMETHOD(device_probe,     ahci_ata_probe),
+	DEVMETHOD(device_attach,    ahci_attach),
+	DEVMETHOD(device_detach,    ahci_detach),
+	DEVMETHOD(device_suspend,   ahci_suspend),
+	DEVMETHOD(device_resume,    ahci_resume),
+	DEVMETHOD(bus_print_child,  ahci_print_child),
+	DEVMETHOD(bus_alloc_resource,       ahci_alloc_resource),
+	DEVMETHOD(bus_release_resource,     ahci_release_resource),
+	DEVMETHOD(bus_setup_intr,   ahci_setup_intr),
+	DEVMETHOD(bus_teardown_intr,ahci_teardown_intr),
+	{ 0, 0 }
+};
+static driver_t ahci_ata_driver = {
+        "ahci",
+        ahci_ata_methods,
+        sizeof(struct ahci_controller)
+};
+DRIVER_MODULE(ahci, atapci, ahci_ata_driver, ahci_devclass, 0, 0);
 MODULE_VERSION(ahci, 1);
 MODULE_DEPEND(ahci, cam, 1, 1, 1);
 
@@ -688,6 +778,7 @@ ahci_ch_attach(device_t dev)
 	ch->unit = (intptr_t)device_get_ivars(dev);
 	ch->caps = ctlr->caps;
 	ch->caps2 = ctlr->caps2;
+	ch->quirks = ctlr->quirks;
 	ch->numslots = ((ch->caps & AHCI_CAP_NCS) >> AHCI_CAP_NCS_SHIFT) + 1,
 	mtx_init(&ch->mtx, "AHCI channel lock", NULL, MTX_DEF);
 	resource_int_value(device_get_name(dev),
@@ -858,7 +949,7 @@ static driver_t ahcich_driver = {
         ahcich_methods,
         sizeof(struct ahci_channel)
 };
-DRIVER_MODULE(ahcich, ahci, ahcich_driver, ahci_devclass, 0, 0);
+DRIVER_MODULE(ahcich, ahci, ahcich_driver, ahcich_devclass, 0, 0);
 
 struct ahci_dc_cb_args {
 	bus_addr_t maddr;

Modified: stable/8/sys/dev/ahci/ahci.h
==============================================================================
--- stable/8/sys/dev/ahci/ahci.h	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ahci/ahci.h	Mon Nov 23 08:56:17 2009	(r199698)
@@ -352,6 +352,7 @@ struct ahci_channel {
 	struct cam_path		*path;
 	uint32_t		caps;		/* Controller capabilities */
 	uint32_t		caps2;		/* Controller capabilities */
+	int			quirks;
 	int			numslots;	/* Number of present slots */
 	int			pm_level;	/* power management level */
 	int			sata_rev;	/* Maximum allowed SATA generation */
@@ -391,6 +392,7 @@ struct ahci_controller {
 	} irqs[16];
 	uint32_t		caps;		/* Controller capabilities */
 	uint32_t		caps2;		/* Controller capabilities */
+	int			quirks;
 	int			numirqs;
 	int			channels;
 	int			ichannels;

Modified: stable/8/sys/dev/ata/ata-pci.c
==============================================================================
--- stable/8/sys/dev/ata/ata-pci.c	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ata/ata-pci.c	Mon Nov 23 08:56:17 2009	(r199698)
@@ -189,91 +189,138 @@ ata_pci_resume(device_t dev)
     return error;
 }
 
+int
+ata_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+
+	return (BUS_READ_IVAR(device_get_parent(dev), dev, which, result));
+}
+
+int
+ata_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+
+	return (BUS_WRITE_IVAR(device_get_parent(dev), dev, which, value));
+}
+
+uint32_t
+ata_pci_read_config(device_t dev, device_t child, int reg, int width)
+{
+
+	return (pci_read_config(dev, reg, width));
+}
+
+void
+ata_pci_write_config(device_t dev, device_t child, int reg, 
+    uint32_t val, int width)
+{
+
+	pci_write_config(dev, reg, val, width);
+}
+
 struct resource *
 ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
 		       u_long start, u_long end, u_long count, u_int flags)
 {
-    struct ata_pci_controller *controller = device_get_softc(dev);
-    int unit = ((struct ata_channel *)device_get_softc(child))->unit;
-    struct resource *res = NULL;
-    int myrid;
-
-    if (type == SYS_RES_IOPORT) {
-	switch (*rid) {
-	case ATA_IOADDR_RID:
-	    if (controller->legacy) {
-		start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
-		count = ATA_IOSIZE;
-		end = start + count - 1;
-	    }
-	    myrid = PCIR_BAR(0) + (unit << 3);
-	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
-				     SYS_RES_IOPORT, &myrid,
-				     start, end, count, flags);
-	    break;
-
-	case ATA_CTLADDR_RID:
-	    if (controller->legacy) {
-		start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET;
-		count = ATA_CTLIOSIZE;
-		end = start + count - 1;
-	    }
-	    myrid = PCIR_BAR(1) + (unit << 3);
-	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
-				     SYS_RES_IOPORT, &myrid,
-				     start, end, count, flags);
-	    break;
-	}
-    }
-    if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
-	if (controller->legacy) {
-	    int irq = (unit == 0 ? 14 : 15);
+	struct ata_pci_controller *controller = device_get_softc(dev);
+	struct resource *res = NULL;
+
+	if (device_get_devclass(child) == ata_devclass) {
+		int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+		int myrid;
+
+		if (type == SYS_RES_IOPORT) {
+			switch (*rid) {
+			case ATA_IOADDR_RID:
+			    if (controller->legacy) {
+				start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
+				count = ATA_IOSIZE;
+				end = start + count - 1;
+			    }
+			    myrid = PCIR_BAR(0) + (unit << 3);
+			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+				SYS_RES_IOPORT, &myrid,
+				start, end, count, flags);
+			    break;
+			case ATA_CTLADDR_RID:
+			    if (controller->legacy) {
+				start = (unit ? ATA_SECONDARY : ATA_PRIMARY) +
+				    ATA_CTLOFFSET;
+				count = ATA_CTLIOSIZE;
+				end = start + count - 1;
+			    }
+			    myrid = PCIR_BAR(1) + (unit << 3);
+			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+				SYS_RES_IOPORT, &myrid,
+				start, end, count, flags);
+			    break;
+			}
+		}
+		if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
+			if (controller->legacy) {
+			    int irq = (unit == 0 ? 14 : 15);
 	    
-	    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
-				     SYS_RES_IRQ, rid, irq, irq, 1, flags);
+			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+				SYS_RES_IRQ, rid, irq, irq, 1, flags);
+			} else
+			    res = controller->r_irq;
+		}
+	} else {
+		if (type == SYS_RES_IRQ) {
+			if (*rid != ATA_IRQ_RID)
+				return (NULL);
+			res = controller->r_irq;
+		} else {
+			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
+			     type, rid, start, end, count, flags);
+		}
 	}
-	else
-	    res = controller->r_irq;
-    }
-    return res;
+	return (res);
 }
 
 int
 ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
 			 struct resource *r)
 {
-    struct ata_pci_controller *controller = device_get_softc(dev);
-    int unit = ((struct ata_channel *)device_get_softc(child))->unit;
-
-    if (type == SYS_RES_IOPORT) {
-	switch (rid) {
-	case ATA_IOADDR_RID:
-	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
-					SYS_RES_IOPORT,
-					PCIR_BAR(0) + (unit << 3), r);
-	    break;
-
-	case ATA_CTLADDR_RID:
-	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
-					SYS_RES_IOPORT,
-					PCIR_BAR(1) + (unit << 3), r);
-	    break;
-	default:
-	    return ENOENT;
-	}
-    }
-    if (type == SYS_RES_IRQ) {
-	if (rid != ATA_IRQ_RID)
-	    return ENOENT;
 
-	if (controller->legacy) {
-	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
-					SYS_RES_IRQ, rid, r);
+	if (device_get_devclass(child) == ata_devclass) {
+		struct ata_pci_controller *controller = device_get_softc(dev);
+		int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+
+	        if (type == SYS_RES_IOPORT) {
+	    		switch (rid) {
+			case ATA_IOADDR_RID:
+		    	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
+				SYS_RES_IOPORT,
+				PCIR_BAR(0) + (unit << 3), r);
+			case ATA_CTLADDR_RID:
+			    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
+				SYS_RES_IOPORT,
+				PCIR_BAR(1) + (unit << 3), r);
+			default:
+			    return ENOENT;
+			}
+		}
+		if (type == SYS_RES_IRQ) {
+			if (rid != ATA_IRQ_RID)
+				return ENOENT;
+			if (controller->legacy) {
+				return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
+				    SYS_RES_IRQ, rid, r);
+			} else  
+				return 0;
+		}
+	} else {
+		if (type == SYS_RES_IRQ) {
+			if (rid != ATA_IRQ_RID)
+				return (ENOENT);
+			return (0);
+		} else {
+			return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
+			    type, rid, r));
+		}
 	}
-	else  
-	    return 0;
-    }
-    return EINVAL;
+	return (EINVAL);
 }
 
 int
@@ -281,44 +328,50 @@ ata_pci_setup_intr(device_t dev, device_
 		   int flags, driver_filter_t *filter, driver_intr_t *function, 
 		   void *argument, void **cookiep)
 {
-    struct ata_pci_controller *controller = device_get_softc(dev);
+	struct ata_pci_controller *controller = device_get_softc(dev);
 
-    if (controller->legacy) {
-	return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
+	if (controller->legacy) {
+		return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
 			      flags, filter, function, argument, cookiep);
-    }
-    else {
-	struct ata_pci_controller *controller = device_get_softc(dev);
-	int unit = ((struct ata_channel *)device_get_softc(child))->unit;
+	} else {
+		struct ata_pci_controller *controller = device_get_softc(dev);
+		int unit;
 
-	if (filter != NULL) {
-		printf("ata-pci.c: we cannot use a filter here\n");
-		return (EINVAL);
+	    	if (filter != NULL) {
+			printf("ata-pci.c: we cannot use a filter here\n");
+			return (EINVAL);
+		}
+		if (device_get_devclass(child) == ata_devclass)
+			unit = ((struct ata_channel *)device_get_softc(child))->unit;
+		else
+			unit = ATA_PCI_MAX_CH - 1;
+		controller->interrupt[unit].function = function;
+		controller->interrupt[unit].argument = argument;
+		*cookiep = controller;
+		return 0;
 	}
-	controller->interrupt[unit].function = function;
-	controller->interrupt[unit].argument = argument;
-	*cookiep = controller;
-	return 0;
-    }
 }
 
 int
 ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
 		      void *cookie)
 {
-    struct ata_pci_controller *controller = device_get_softc(dev);
-
-    if (controller->legacy) {
-	return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
-    }
-    else {
 	struct ata_pci_controller *controller = device_get_softc(dev);
-	int unit = ((struct ata_channel *)device_get_softc(child))->unit;
 
-	controller->interrupt[unit].function = NULL;
-	controller->interrupt[unit].argument = NULL;
-	return 0;
-    }
+        if (controller->legacy) {
+		return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
+	} else {
+		struct ata_pci_controller *controller = device_get_softc(dev);
+		int unit;
+
+		if (device_get_devclass(child) == ata_devclass)
+			unit = ((struct ata_channel *)device_get_softc(child))->unit;
+		else
+			unit = ATA_PCI_MAX_CH - 1;
+		controller->interrupt[unit].function = NULL;
+		controller->interrupt[unit].argument = NULL;
+		return 0;
+	}
 }
     
 static void
@@ -510,12 +563,16 @@ static device_method_t ata_pci_methods[]
     DEVMETHOD(device_shutdown,          bus_generic_shutdown),
 
     /* bus methods */
+    DEVMETHOD(bus_read_ivar,		ata_pci_read_ivar),
+    DEVMETHOD(bus_write_ivar,		ata_pci_write_ivar),
     DEVMETHOD(bus_alloc_resource,       ata_pci_alloc_resource),
     DEVMETHOD(bus_release_resource,     ata_pci_release_resource),
     DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
     DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
     DEVMETHOD(bus_setup_intr,           ata_pci_setup_intr),
     DEVMETHOD(bus_teardown_intr,        ata_pci_teardown_intr),
+    DEVMETHOD(pci_read_config,		ata_pci_read_config),
+    DEVMETHOD(pci_write_config,		ata_pci_write_config),
 
     { 0, 0 }
 };
@@ -537,6 +594,8 @@ ata_pcichannel_probe(device_t dev)
 {
     char buffer[32];
 
+    if ((intptr_t)device_get_ivars(dev) < 0)
+	    return (ENXIO);
     sprintf(buffer, "ATA channel %d", (int)(intptr_t)device_get_ivars(dev));
     device_set_desc_copy(dev, buffer);
 
@@ -711,7 +770,7 @@ ata_generic_intr(void *data)
     struct ata_channel *ch;
     int unit;
 
-    for (unit = 0; unit < ctlr->channels; unit++) {
+    for (unit = 0; unit < ATA_PCI_MAX_CH; unit++) {
 	if ((ch = ctlr->interrupt[unit].argument))
 	    ctlr->interrupt[unit].function(ch);
     }

Modified: stable/8/sys/dev/ata/ata-pci.h
==============================================================================
--- stable/8/sys/dev/ata/ata-pci.h	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ata/ata-pci.h	Mon Nov 23 08:56:17 2009	(r199698)
@@ -36,6 +36,8 @@ struct ata_chip_id {
     char                *text;
 };
 
+#define ATA_PCI_MAX_CH	8
+
 /* structure describing a PCI ATA controller */
 struct ata_pci_controller {
     device_t            dev;
@@ -65,7 +67,7 @@ struct ata_pci_controller {
     struct {
     void                (*function)(void *);
     void                *argument;
-    } interrupt[8];     /* XXX SOS max ch# for now */
+    } interrupt[ATA_PCI_MAX_CH];
     void                *chipset_data;
 };
 
@@ -225,7 +227,10 @@ struct ata_pci_controller {
 #define ATA_M88SX6081           0x608111ab
 #define ATA_M88SX7042           0x704211ab
 #define ATA_M88SX6101           0x610111ab
+#define ATA_M88SX6102           0x610211ab
+#define ATA_M88SX6111           0x611111ab
 #define ATA_M88SX6121           0x612111ab
+#define ATA_M88SX6141           0x614111ab
 #define ATA_M88SX6145           0x614511ab
 
 #define ATA_MICRON_ID           0x1042
@@ -483,6 +488,11 @@ int ata_pci_attach(device_t dev);
 int ata_pci_detach(device_t dev);
 int ata_pci_suspend(device_t dev);
 int ata_pci_resume(device_t dev);
+int ata_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
+int ata_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
+uint32_t ata_pci_read_config(device_t dev, device_t child, int reg, int width);
+void ata_pci_write_config(device_t dev, device_t child, int reg, 
+    uint32_t val, int width);
 struct resource * ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
 int ata_pci_release_resource(device_t dev, device_t child, int type, int rid, struct resource *r);
 int ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_filter_t *filter, driver_intr_t *function, void *argument, void **cookiep);
@@ -506,12 +516,6 @@ int ata_mode2idx(int mode);
 
 /* global prototypes from chipsets/ata-*.c */
 int ata_ahci_chipinit(device_t);
-int ata_ahci_ch_attach(device_t dev);
-int ata_ahci_ch_detach(device_t dev);
-int ata_ahci_ch_suspend(device_t dev);
-int ata_ahci_ch_resume(device_t dev);
-int ata_ahci_ctlr_reset(device_t dev);
-void ata_ahci_reset(device_t dev);
 int ata_marvell_edma_chipinit(device_t);
 int ata_sii_chipinit(device_t);
 
@@ -527,12 +531,16 @@ static device_method_t __CONCAT(dname,_m
     DEVMETHOD(device_suspend,   ata_pci_suspend), \
     DEVMETHOD(device_resume,    ata_pci_resume), \
     DEVMETHOD(device_shutdown,  bus_generic_shutdown), \
+    DEVMETHOD(bus_read_ivar,		ata_pci_read_ivar), \
+    DEVMETHOD(bus_write_ivar,		ata_pci_write_ivar), \
     DEVMETHOD(bus_alloc_resource,       ata_pci_alloc_resource), \
     DEVMETHOD(bus_release_resource,     ata_pci_release_resource), \
     DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource), \
     DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource), \
     DEVMETHOD(bus_setup_intr,           ata_pci_setup_intr), \
     DEVMETHOD(bus_teardown_intr,        ata_pci_teardown_intr), \
+    DEVMETHOD(pci_read_config,		ata_pci_read_config), \
+    DEVMETHOD(pci_write_config,		ata_pci_write_config), \
     { 0, 0 } \
 }; \
 static driver_t __CONCAT(dname,_driver) = { \

Modified: stable/8/sys/dev/ata/chipsets/ata-ahci.c
==============================================================================
--- stable/8/sys/dev/ata/chipsets/ata-ahci.c	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ata/chipsets/ata-ahci.c	Mon Nov 23 08:56:17 2009	(r199698)
@@ -52,6 +52,12 @@ __FBSDID("$FreeBSD$");
 #include <ata_if.h>
 
 /* local prototypes */
+static int ata_ahci_ch_attach(device_t dev);
+static int ata_ahci_ch_detach(device_t dev);
+static int ata_ahci_ch_suspend(device_t dev);
+static int ata_ahci_ch_resume(device_t dev);
+static int ata_ahci_ctlr_reset(device_t dev);
+static void ata_ahci_reset(device_t dev);
 static int ata_ahci_suspend(device_t dev);
 static int ata_ahci_status(device_t dev);
 static int ata_ahci_begin_transaction(struct ata_request *request);
@@ -97,6 +103,49 @@ ata_ahci_probe(device_t dev)
     return (BUS_PROBE_GENERIC);
 }
 
+static int
+ata_ahci_ata_probe(device_t dev)
+{
+    struct ata_pci_controller *ctlr = device_get_softc(dev);
+
+    if ((intptr_t)device_get_ivars(dev) >= 0)
+	    return (ENXIO);
+    device_set_desc_copy(dev, "AHCI SATA controller");
+    ctlr->chipinit = ata_ahci_chipinit;
+    return (BUS_PROBE_GENERIC);
+}
+
+static int
+ata_ahci_ata_attach(device_t dev)
+{
+    struct ata_pci_controller *ctlr = device_get_softc(dev);
+    device_t child;
+    int unit;
+
+    /* do chipset specific setups only needed once */
+    ctlr->legacy = 0;
+    ctlr->ichannels = -1;
+    ctlr->ch_attach = ata_pci_ch_attach;
+    ctlr->ch_detach = ata_pci_ch_detach;
+    ctlr->dev = dev;
+    if (ctlr->chipinit(dev))
+	return ENXIO;
+    /* attach all channels on this controller */
+    for (unit = 0; unit < ctlr->channels; unit++) {
+	if ((ctlr->ichannels & (1 << unit)) == 0)
+	    continue;
+	child = device_add_child(dev, "ata",
+	    ((unit == 0 || unit == 1) && ctlr->legacy) ?
+	    unit : devclass_find_free_unit(ata_devclass, 2));
+	if (child == NULL)
+	    device_printf(dev, "failed to add ata child device\n");
+	else
+	    device_set_ivars(child, (void *)(intptr_t)unit);
+    }
+    bus_generic_attach(dev);
+    return 0;
+}
+
 int
 ata_ahci_chipinit(device_t dev)
 {
@@ -129,9 +178,15 @@ ata_ahci_chipinit(device_t dev)
 
     /* get the number of HW channels */
     ctlr->ichannels = ATA_INL(ctlr->r_res2, ATA_AHCI_PI);
-    ctlr->channels =
-	MAX(flsl(ctlr->ichannels),
+    ctlr->channels = MAX(flsl(ctlr->ichannels),
 	    (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_NPMASK) + 1);
+    if (pci_get_devid(dev) == ATA_M88SX6111)
+	    ctlr->channels = 1;
+    else if (pci_get_devid(dev) == ATA_M88SX6121)
+	    ctlr->channels = 2;
+    else if (pci_get_devid(dev) == ATA_M88SX6141 ||
+	pci_get_devid(dev) == ATA_M88SX6145)
+	    ctlr->channels = 4;
 
     ctlr->reset = ata_ahci_reset;
     ctlr->ch_attach = ata_ahci_ch_attach;
@@ -183,7 +238,7 @@ ata_ahci_chipinit(device_t dev)
 	return 0;
 }
 
-int
+static int
 ata_ahci_ctlr_reset(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
@@ -228,7 +283,7 @@ ata_ahci_suspend(device_t dev)
     return 0;
 }
 
-int
+static int
 ata_ahci_ch_attach(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -259,7 +314,7 @@ ata_ahci_ch_attach(device_t dev)
     return 0;
 }
 
-int
+static int
 ata_ahci_ch_detach(device_t dev)
 {
 
@@ -268,7 +323,7 @@ ata_ahci_ch_detach(device_t dev)
     return (0);
 }
 
-int
+static int
 ata_ahci_ch_suspend(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -293,7 +348,7 @@ ata_ahci_ch_suspend(device_t dev)
     return (0);
 }
 
-int
+static int
 ata_ahci_ch_resume(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -813,7 +868,7 @@ ata_ahci_softreset(device_t dev, int por
     return ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
 }
 
-void
+static void
 ata_ahci_reset(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
@@ -845,9 +900,12 @@ ata_ahci_reset(device_t dev)
 	      ((ch->pm_level == 0) ? ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC : 0) |
 	      ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB |
 	      ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR));
-
-    /* only probe for PortMultiplier if HW has support */
-    if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) {
+    /*
+     * Only probe for PortMultiplier if HW has support.
+     * Ignore Marvell, which is not working,
+     */
+    if ((ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) &&
+	    pci_get_vendor(ctlr->dev) != 0x11ab) {
 	signature = ata_ahci_softreset(dev, ATA_PM);
 	/* Workaround for some ATI chips, failing to soft-reset
 	 * when port multiplicator supported, but absent.
@@ -924,3 +982,26 @@ ata_ahci_setup_fis(struct ata_ahci_cmd_t
 }
 
 ATA_DECLARE_DRIVER(ata_ahci);
+static device_method_t ata_ahci_ata_methods[] = {
+    DEVMETHOD(device_probe,     ata_ahci_ata_probe),
+    DEVMETHOD(device_attach,    ata_ahci_ata_attach),
+    DEVMETHOD(device_detach,    ata_pci_detach),
+    DEVMETHOD(device_suspend,   ata_pci_suspend),
+    DEVMETHOD(device_resume,    ata_pci_resume),
+    DEVMETHOD(device_shutdown,  bus_generic_shutdown),
+    DEVMETHOD(bus_read_ivar,		ata_pci_read_ivar),
+    DEVMETHOD(bus_write_ivar,		ata_pci_write_ivar),
+    DEVMETHOD(bus_alloc_resource,       ata_pci_alloc_resource),
+    DEVMETHOD(bus_release_resource,     ata_pci_release_resource),
+    DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
+    DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
+    DEVMETHOD(bus_setup_intr,           ata_pci_setup_intr),
+    DEVMETHOD(bus_teardown_intr,        ata_pci_teardown_intr),
+    { 0, 0 }
+};
+static driver_t ata_ahci_ata_driver = {
+        "atapci",
+        ata_ahci_ata_methods,
+        sizeof(struct ata_pci_controller)
+};
+DRIVER_MODULE(ata_ahci_ata, atapci, ata_ahci_ata_driver, ata_pci_devclass, 0, 0);

Modified: stable/8/sys/dev/ata/chipsets/ata-jmicron.c
==============================================================================
--- stable/8/sys/dev/ata/chipsets/ata-jmicron.c	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ata/chipsets/ata-jmicron.c	Mon Nov 23 08:56:17 2009	(r199698)
@@ -53,11 +53,6 @@ __FBSDID("$FreeBSD$");
 
 /* local prototypes */
 static int ata_jmicron_chipinit(device_t dev);
-static int ata_jmicron_ch_attach(device_t dev);
-static int ata_jmicron_ch_detach(device_t dev);
-static int ata_jmicron_ch_suspend(device_t dev);
-static int ata_jmicron_ch_resume(device_t dev);
-static void ata_jmicron_reset(device_t dev);
 static void ata_jmicron_setmode(device_t dev, int mode);
 
 /*
@@ -70,10 +65,10 @@ ata_jmicron_probe(device_t dev)
     struct ata_chip_id *idx;
     static struct ata_chip_id ids[] =
     {{ ATA_JMB360, 0, 1, 0, ATA_SA300, "JMB360" },
-     { ATA_JMB361, 0, 1, 1, ATA_SA300, "JMB361" },
-     { ATA_JMB363, 0, 2, 1, ATA_SA300, "JMB363" },
-     { ATA_JMB365, 0, 1, 2, ATA_SA300, "JMB365" },
-     { ATA_JMB366, 0, 2, 2, ATA_SA300, "JMB366" },
+     { ATA_JMB361, 0, 1, 1, ATA_UDMA6, "JMB361" },
+     { ATA_JMB363, 0, 2, 1, ATA_UDMA6, "JMB363" },
+     { ATA_JMB365, 0, 1, 2, ATA_UDMA6, "JMB365" },
+     { ATA_JMB366, 0, 2, 2, ATA_UDMA6, "JMB366" },
      { ATA_JMB368, 0, 0, 1, ATA_UDMA6, "JMB368" },
      { 0, 0, 0, 0, 0, 0}};
     char buffer[64];
@@ -101,7 +96,7 @@ static int
 ata_jmicron_chipinit(device_t dev)
 {
     struct ata_pci_controller *ctlr = device_get_softc(dev);
-    int error;
+    device_t child;
 
     if (ata_setup_interrupt(dev, ata_generic_intr))
 	return ENXIO;
@@ -123,116 +118,35 @@ ata_jmicron_chipinit(device_t dev)
 	/* set controller configuration to a combined setup we support */
 	pci_write_config(dev, 0x40, 0x80c0a131, 4);
 	pci_write_config(dev, 0x80, 0x01200000, 4);
-
-	if (ctlr->chip->cfg1 && (error = ata_ahci_chipinit(dev)))
-	    return error;
-
-	ctlr->ch_attach = ata_jmicron_ch_attach;
-	ctlr->ch_detach = ata_jmicron_ch_detach;
-	ctlr->ch_suspend = ata_jmicron_ch_suspend;
-	ctlr->ch_resume = ata_jmicron_ch_resume;
-	ctlr->reset = ata_jmicron_reset;
+	/* Create AHCI subdevice if AHCI part present. */
+	if (ctlr->chip->cfg1) {
+	    	child = device_add_child(dev, NULL, -1);
+		if (child != NULL) {
+		    device_set_ivars(child, (void *)(intptr_t)-1);
+		    bus_generic_attach(dev);
+		}
+	}
+	ctlr->ch_attach = ata_pci_ch_attach;
+	ctlr->ch_detach = ata_pci_ch_detach;
+	ctlr->reset = ata_generic_reset;
 	ctlr->setmode = ata_jmicron_setmode;
-
-	/* set the number of HW channels */ 
-	ctlr->channels = ctlr->chip->cfg1 + ctlr->chip->cfg2;
-	ctlr->ichannels |= ((0xffffffffU >> (32 - ctlr->chip->cfg2))
-	    << ctlr->chip->cfg1);
+	ctlr->channels = ctlr->chip->cfg2;
     }
     return 0;
 }
 
-static int
-ata_jmicron_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);
-    int error;
-
-    if (ch->unit >= ctlr->chip->cfg1) {
-	ch->unit -= ctlr->chip->cfg1;
-	error = ata_pci_ch_attach(dev);
-	ch->unit += ctlr->chip->cfg1;
-    }
-    else
-	error = ata_ahci_ch_attach(dev);
-    return error;
-}
-
-static int
-ata_jmicron_ch_detach(device_t dev)
-{
-    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
-    struct ata_channel *ch = device_get_softc(dev);
-    int error;
-
-    if (ch->unit >= ctlr->chip->cfg1) {
-	ch->unit -= ctlr->chip->cfg1;
-	error = ata_pci_ch_detach(dev);
-	ch->unit += ctlr->chip->cfg1;
-    }
-    else
-	error = ata_ahci_ch_detach(dev);
-
-    return (error);
-}
-
-static int
-ata_jmicron_ch_suspend(device_t dev)
-{
-    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
-    struct ata_channel *ch = device_get_softc(dev);
-    int error = 0;
-
-    if (ch->unit < ctlr->chip->cfg1)
-	error = ata_ahci_ch_suspend(dev);
-    return error;
-}
-
-static int
-ata_jmicron_ch_resume(device_t dev)
-{
-    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
-    struct ata_channel *ch = device_get_softc(dev);
-    int error = 0;
-
-    if (ch->unit < ctlr->chip->cfg1)
-	error = ata_ahci_ch_resume(dev);
-    return (error);
-}
-
-static void
-ata_jmicron_reset(device_t dev)
-{
-    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
-    struct ata_channel *ch = device_get_softc(dev);
-
-    if (ch->unit >= ctlr->chip->cfg1)
-	ata_generic_reset(dev);
-    else
-	ata_ahci_reset(dev);
-}
-
 static void
 ata_jmicron_setmode(device_t dev, int mode)
 {
-    struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev));
-    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
-
-    if (pci_read_config(dev, 0xdf, 1) & 0x40 || ch->unit >= ctlr->chip->cfg1) {
 	struct ata_device *atadev = device_get_softc(dev);
 
 	/* check for 80pin cable present */
 	if (pci_read_config(dev, 0x40, 1) & 0x08)
-	    mode = ata_limit_mode(dev, mode, ATA_UDMA2);
+		mode = ata_limit_mode(dev, mode, ATA_UDMA2);
 	else
-	    mode = ata_limit_mode(dev, mode, ATA_UDMA6);
-
+		mode = ata_limit_mode(dev, mode, ATA_UDMA6);
 	if (!ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
-	    atadev->mode = mode;
-    }
-    else
-	ata_sata_setmode(dev, mode);
+		atadev->mode = mode;
 }
 
 ATA_DECLARE_DRIVER(ata_jmicron);

Modified: stable/8/sys/dev/ata/chipsets/ata-marvell.c
==============================================================================
--- stable/8/sys/dev/ata/chipsets/ata-marvell.c	Mon Nov 23 08:46:26 2009	(r199697)
+++ stable/8/sys/dev/ata/chipsets/ata-marvell.c	Mon Nov 23 08:56:17 2009	(r199698)
@@ -52,9 +52,9 @@ __FBSDID("$FreeBSD$");
 #include <ata_if.h>
 
 /* local prototypes */
-static int ata_marvell_pata_chipinit(device_t dev);
-static int ata_marvell_pata_ch_attach(device_t dev);
-static void ata_marvell_pata_setmode(device_t dev, int mode);
+static int ata_marvell_chipinit(device_t dev);
+static int ata_marvell_ch_attach(device_t dev);
+static void ata_marvell_setmode(device_t dev, int mode);
 static int ata_marvell_edma_ch_attach(device_t dev);
 static int ata_marvell_edma_ch_detach(device_t dev);
 static int ata_marvell_edma_status(device_t dev);
@@ -107,9 +107,12 @@ ata_marvell_probe(device_t dev)
      { ATA_M88SX6042, 0, 4, MV_6042, ATA_SA300, "88SX6042" },
      { ATA_M88SX6081, 0, 8, MV_60XX, ATA_SA300, "88SX6081" },
      { ATA_M88SX7042, 0, 4, MV_7042, ATA_SA300, "88SX7042" },
-     { ATA_M88SX6101, 0, 1, MV_61XX, ATA_UDMA6, "88SX6101" },
-     { ATA_M88SX6121, 0, 1, MV_61XX, ATA_UDMA6, "88SX6121" },
-     { ATA_M88SX6145, 0, 2, MV_61XX, ATA_UDMA6, "88SX6145" },
+     { ATA_M88SX6101, 0, 0, MV_61XX, ATA_UDMA6, "88SX6101" },
+     { ATA_M88SX6102, 0, 0, MV_61XX, ATA_UDMA6, "88SX6102" },
+     { ATA_M88SX6111, 0, 1, MV_61XX, ATA_UDMA6, "88SX6111" },

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


More information about the svn-src-stable mailing list