Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Oct 2012 01:10:44 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241600 - in head: . sys/conf sys/dev/mmc sys/dev/sdhci sys/modules sys/modules/sdhci sys/modules/sdhci_pci
Message-ID:  <201210160110.q9G1AiH0012464@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Tue Oct 16 01:10:43 2012
New Revision: 241600
URL: http://svn.freebsd.org/changeset/base/241600

Log:
  Split sdhci driver in two parts: sdhci and sdhci_pci.
  sdchi encapsulates a generic SD Host Controller logic that relies on
  actual hardware driver for register access.
  
  sdhci_pci implements driver for PCI SDHC controllers using new SDHCI
  interface
  
  No kernel config modifications are required, but if you load sdhc
  as a module you must switch to sdhci_pci instead.

Added:
  head/sys/dev/sdhci/sdhci_if.m   (contents, props changed)
  head/sys/dev/sdhci/sdhci_pci.c   (contents, props changed)
  head/sys/modules/sdhci_pci/
  head/sys/modules/sdhci_pci/Makefile   (contents, props changed)
Modified:
  head/UPDATING
  head/sys/conf/files
  head/sys/conf/kmod.mk
  head/sys/dev/mmc/mmc.c
  head/sys/dev/sdhci/sdhci.c
  head/sys/dev/sdhci/sdhci.h
  head/sys/modules/Makefile
  head/sys/modules/sdhci/Makefile

Modified: head/UPDATING
==============================================================================
--- head/UPDATING	Mon Oct 15 21:53:26 2012	(r241599)
+++ head/UPDATING	Tue Oct 16 01:10:43 2012	(r241600)
@@ -24,6 +24,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10
 	disable the most expensive debugging functionality run
 	"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
 
+20121015:
+	The sdhci driver was split in two parts: sdhci (generic SD Host
+	Controller logic) and sdhci_pci (actual hardware driver).
+	No kernel config modifications are required, but if you
+	load sdhc as a module you must switch to sdhci_pci instead.
+
 20121014:
 	Import the FUSE kernel and userland support into base system.
 

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Mon Oct 15 21:53:26 2012	(r241599)
+++ head/sys/conf/files	Tue Oct 16 01:10:43 2012	(r241600)
@@ -1905,7 +1905,9 @@ dev/scc/scc_dev_sab82532.c	optional scc
 dev/scc/scc_dev_z8530.c		optional scc
 dev/scd/scd.c			optional scd isa
 dev/scd/scd_isa.c		optional scd isa
-dev/sdhci/sdhci.c		optional sdhci pci
+dev/sdhci/sdhci.c		optional sdhci
+dev/sdhci/sdhci_if.m		optional sdhci
+dev/sdhci/sdhci_pci.c		optional sdhci pci
 dev/sf/if_sf.c			optional sf pci
 dev/sge/if_sge.c		optional sge pci
 dev/si/si.c			optional si

Modified: head/sys/conf/kmod.mk
==============================================================================
--- head/sys/conf/kmod.mk	Mon Oct 15 21:53:26 2012	(r241599)
+++ head/sys/conf/kmod.mk	Tue Oct 16 01:10:43 2012	(r241600)
@@ -345,7 +345,8 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_s
 	dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
 	dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \
 	dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \
-	dev/pci/pcib_if.m dev/ppbus/ppbus_if.m dev/smbus/smbus_if.m \
+	dev/pci/pcib_if.m dev/ppbus/ppbus_if.m \
+	dev/sdhci/sdhci_if.m dev/smbus/smbus_if.m \
 	dev/sound/pci/hda/hdac_if.m \
 	dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \
 	dev/sound/pcm/feeder_if.m dev/sound/pcm/mixer_if.m \

Modified: head/sys/dev/mmc/mmc.c
==============================================================================
--- head/sys/dev/mmc/mmc.c	Mon Oct 15 21:53:26 2012	(r241599)
+++ head/sys/dev/mmc/mmc.c	Tue Oct 16 01:10:43 2012	(r241600)
@@ -1730,4 +1730,4 @@ static devclass_t mmc_devclass;
 
 DRIVER_MODULE(mmc, ti_mmchs, mmc_driver, mmc_devclass, NULL, NULL);
 DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
-DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
+DRIVER_MODULE(mmc, sdhci_pci, mmc_driver, mmc_devclass, NULL, NULL);

Modified: head/sys/dev/sdhci/sdhci.c
==============================================================================
--- head/sys/dev/sdhci/sdhci.c	Mon Oct 15 21:53:26 2012	(r241599)
+++ head/sys/dev/sdhci/sdhci.c	Tue Oct 16 01:10:43 2012	(r241600)
@@ -39,9 +39,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
 
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
 #include <machine/bus.h>
 #include <machine/resource.h>
 #include <machine/stdarg.h>
@@ -52,104 +49,12 @@ __FBSDID("$FreeBSD$");
 
 #include "mmcbr_if.h"
 #include "sdhci.h"
-
-#define DMA_BLOCK_SIZE	4096
-#define DMA_BOUNDARY	0	/* DMA reload every 4K */
-
-/* Controller doesn't honor resets unless we touch the clock register */
-#define SDHCI_QUIRK_CLOCK_BEFORE_RESET			(1<<0)
-/* Controller really supports DMA */
-#define SDHCI_QUIRK_FORCE_DMA				(1<<1)
-/* Controller has unusable DMA engine */
-#define SDHCI_QUIRK_BROKEN_DMA				(1<<2)
-/* Controller doesn't like to be reset when there is no card inserted. */
-#define SDHCI_QUIRK_NO_CARD_NO_RESET			(1<<3)
-/* Controller has flaky internal state so reset it on each ios change */
-#define SDHCI_QUIRK_RESET_ON_IOS			(1<<4)
-/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
-#define SDHCI_QUIRK_32BIT_DMA_SIZE			(1<<5)
-/* Controller needs to be reset after each request to stay stable */
-#define SDHCI_QUIRK_RESET_AFTER_REQUEST			(1<<6)
-/* Controller has an off-by-one issue with timeout value */
-#define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL		(1<<7)
-/* Controller has broken read timings */
-#define SDHCI_QUIRK_BROKEN_TIMINGS			(1<<8)
-/* Controller needs lowered frequency */
-#define	SDHCI_QUIRK_LOWER_FREQUENCY			(1<<9)
-
-static const struct sdhci_device {
-	uint32_t	model;
-	uint16_t	subvendor;
-	char		*desc;
-	u_int		quirks;
-} sdhci_devices[] = {
-	{ 0x08221180, 	0xffff,	"RICOH R5C822 SD",
-	    SDHCI_QUIRK_FORCE_DMA },
-	{ 0xe8221180, 	0xffff,	"RICOH SD",
-	    SDHCI_QUIRK_FORCE_DMA },
-	{ 0xe8231180, 	0xffff,	"RICOH R5CE823 SD",
-	    SDHCI_QUIRK_LOWER_FREQUENCY },
-	{ 0x8034104c, 	0xffff, "TI XX21/XX11 SD",
-	    SDHCI_QUIRK_FORCE_DMA },
-	{ 0x05501524, 	0xffff, "ENE CB712 SD",
-	    SDHCI_QUIRK_BROKEN_TIMINGS },
-	{ 0x05511524, 	0xffff, "ENE CB712 SD 2",
-	    SDHCI_QUIRK_BROKEN_TIMINGS },
-	{ 0x07501524, 	0xffff, "ENE CB714 SD",
-	    SDHCI_QUIRK_RESET_ON_IOS |
-	    SDHCI_QUIRK_BROKEN_TIMINGS },
-	{ 0x07511524, 	0xffff, "ENE CB714 SD 2",
-	    SDHCI_QUIRK_RESET_ON_IOS |
-	    SDHCI_QUIRK_BROKEN_TIMINGS },
-	{ 0x410111ab, 	0xffff, "Marvell CaFe SD",
-	    SDHCI_QUIRK_INCR_TIMEOUT_CONTROL },
-	{ 0x2381197B, 	0xffff,	"JMicron JMB38X SD",
-	    SDHCI_QUIRK_32BIT_DMA_SIZE |
-	    SDHCI_QUIRK_RESET_AFTER_REQUEST },
-	{ 0,		0xffff,	NULL,
-	    0 }
-};
+#include "sdhci_if.h"
 
 struct sdhci_softc;
 
-struct sdhci_slot {
-	struct sdhci_softc	*sc;
-	device_t	dev;		/* Slot device */
-	u_char		num;		/* Slot number */
-	u_char		opt;		/* Slot options */
-#define SDHCI_HAVE_DMA		1
-	uint32_t	max_clk;	/* Max possible freq */
-	uint32_t	timeout_clk;	/* Timeout freq */
-	struct resource	*mem_res;	/* Memory resource */
-	int		mem_rid;
-	bus_dma_tag_t 	dmatag;
-	bus_dmamap_t 	dmamap;
-	u_char		*dmamem;
-	bus_addr_t	paddr;		/* DMA buffer address */
-	struct task	card_task;	/* Card presence check task */
-	struct callout	card_callout;	/* Card insert delay callout */
-	struct mmc_host host;		/* Host parameters */
-	struct mmc_request *req;	/* Current request */
-	struct mmc_command *curcmd;	/* Current command of current request */
-	
-	uint32_t	intmask;	/* Current interrupt mask */
-	uint32_t	clock;		/* Current clock freq. */
-	size_t		offset;		/* Data buffer offset */
-	uint8_t		hostctrl;	/* Current host control register */
-	u_char		power;		/* Current power */
-	u_char		bus_busy;	/* Bus busy status */
-	u_char		cmd_done;	/* CMD command part done flag */
-	u_char		data_done;	/* DAT command part done flag */
-	u_char		flags;		/* Request execution flags */
-#define CMD_STARTED		1
-#define STOP_STARTED		2
-#define SDHCI_USE_DMA		4	/* Use DMA for this req. */
-	struct mtx	mtx;		/* Slot mutex */
-};
-
 struct sdhci_softc {
 	device_t	dev;		/* Controller device */
-	u_int		quirks;		/* Chip specific quirks */
 	struct resource *irq_res;	/* IRQ resource */
 	int 		irq_rid;
 	void 		*intrhand;	/* Interrupt handle */
@@ -160,63 +65,21 @@ struct sdhci_softc {
 
 static SYSCTL_NODE(_hw, OID_AUTO, sdhci, CTLFLAG_RD, 0, "sdhci driver");
 
-int	sdhci_debug;
+int	sdhci_debug = 0;
 TUNABLE_INT("hw.sdhci.debug", &sdhci_debug);
 SYSCTL_INT(_hw_sdhci, OID_AUTO, debug, CTLFLAG_RW, &sdhci_debug, 0, "Debug level");
 
-static inline uint8_t
-RD1(struct sdhci_slot *slot, bus_size_t off)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	return bus_read_1(slot->mem_res, off);
-}
-
-static inline void
-WR1(struct sdhci_slot *slot, bus_size_t off, uint8_t val)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	bus_write_1(slot->mem_res, off, val);
-}
-
-static inline uint16_t
-RD2(struct sdhci_slot *slot, bus_size_t off)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	return bus_read_2(slot->mem_res, off);
-}
-
-static inline void
-WR2(struct sdhci_slot *slot, bus_size_t off, uint16_t val)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	bus_write_2(slot->mem_res, off, val);
-}
-
-static inline uint32_t
-RD4(struct sdhci_slot *slot, bus_size_t off)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	return bus_read_4(slot->mem_res, off);
-}
-
-static inline void
-WR4(struct sdhci_slot *slot, bus_size_t off, uint32_t val)
-{
-	bus_barrier(slot->mem_res, 0, 0xFF,
-	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
-	bus_write_4(slot->mem_res, off, val);
-}
-
-/* bus entry points */
-static int sdhci_probe(device_t dev);
-static int sdhci_attach(device_t dev);
-static int sdhci_detach(device_t dev);
-static void sdhci_intr(void *);
+#define RD1(slot, off)	SDHCI_READ_1((slot)->bus, (slot), (off))
+#define RD2(slot, off)	SDHCI_READ_2((slot)->bus, (slot), (off))
+#define RD4(slot, off)	SDHCI_READ_4((slot)->bus, (slot), (off))
+#define RD_MULTI_4(slot, off, ptr, count)	\
+    SDHCI_READ_MULTI_4((slot)->bus, (slot), (off), (ptr), (count))
+
+#define WR1(slot, off, val)	SDHCI_WRITE_1((slot)->bus, (slot), (off), (val))
+#define WR2(slot, off, val)	SDHCI_WRITE_2((slot)->bus, (slot), (off), (val))
+#define WR4(slot, off, val)	SDHCI_WRITE_4((slot)->bus, (slot), (off), (val))
+#define WR_MULTI_4(slot, off, ptr, count)	\
+    SDHCI_WRITE_MULTI_4((slot)->bus, (slot), (off), (ptr), (count))
 
 static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
 static void sdhci_start(struct sdhci_slot *slot);
@@ -233,6 +96,16 @@ static void sdhci_card_task(void *, int)
 #define SDHCI_ASSERT_LOCKED(_slot)	mtx_assert(&_slot->mtx, MA_OWNED);
 #define SDHCI_ASSERT_UNLOCKED(_slot)	mtx_assert(&_slot->mtx, MA_NOTOWNED);
 
+static void
+sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+{
+	if (error != 0) {
+		printf("getaddr: error %d\n", error);
+		return;
+	}
+	*(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
 static int
 slot_printf(struct sdhci_slot *slot, const char * fmt, ...)
 {
@@ -240,7 +113,7 @@ slot_printf(struct sdhci_slot *slot, con
 	int retval;
 
     	retval = printf("%s-slot%d: ",
-	    device_get_nameunit(slot->sc->dev), slot->num);
+	    device_get_nameunit(slot->bus), slot->num);
 
 	va_start(ap, fmt);
 	retval += vprintf(fmt, ap);
@@ -249,16 +122,6 @@ slot_printf(struct sdhci_slot *slot, con
 }
 
 static void
-sdhci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
-{
-	if (error != 0) {
-		printf("getaddr: error %d\n", error);
-		return;
-	}
-	*(bus_addr_t *)arg = segs[0].ds_addr;
-}
-
-static void
 sdhci_dumpregs(struct sdhci_slot *slot)
 {
 	slot_printf(slot,
@@ -295,7 +158,7 @@ sdhci_reset(struct sdhci_slot *slot, uin
 	int timeout;
 	uint8_t res;
 
-	if (slot->sc->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
+	if (slot->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
 		if (!(RD4(slot, SDHCI_PRESENT_STATE) &
 			SDHCI_CARD_PRESENT))
 			return;
@@ -303,7 +166,7 @@ sdhci_reset(struct sdhci_slot *slot, uin
 
 	/* Some controllers need this kick or reset won't work. */
 	if ((mask & SDHCI_RESET_ALL) == 0 &&
-	    (slot->sc->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)) {
+	    (slot->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)) {
 		uint32_t clock;
 
 		/* This is to force an update */
@@ -354,24 +217,6 @@ sdhci_init(struct sdhci_slot *slot)
 }
 
 static void
-sdhci_lower_frequency(device_t dev)
-{
-
-	/* Enable SD2.0 mode. */
-	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0xfc, 1);
-	pci_write_config(dev, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20, 1);
-	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0x00, 1);
-
-	/*
-	 * Some SD/MMC cards don't work with the default base
-	 * clock frequency of 200MHz.  Lower it to 50MHz.
-	 */
-	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x01, 1);
-	pci_write_config(dev, SDHC_PCI_BASE_FREQ, 50, 1);
-	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x00, 1);
-}
-
-static void
 sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock)
 {
 	uint32_t res;
@@ -427,6 +272,7 @@ sdhci_set_power(struct sdhci_slot *slot,
 
 	if (slot->power == power)
 		return;
+
 	slot->power = power;
 
 	/* Turn off the power. */
@@ -469,7 +315,7 @@ sdhci_read_block_pio(struct sdhci_slot *
 	slot->offset += left;
 
 	/* If we are too fast, broken controllers return zeroes. */
-	if (slot->sc->quirks & SDHCI_QUIRK_BROKEN_TIMINGS)
+	if (slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS)
 		DELAY(10);
 	/* Handle unalligned and alligned buffer cases. */
 	if ((intptr_t)buffer & 3) {
@@ -483,7 +329,7 @@ sdhci_read_block_pio(struct sdhci_slot *
 			left -= 4;
 		}
 	} else {
-		bus_read_multi_stream_4(slot->mem_res, SDHCI_BUFFER,
+		RD_MULTI_4(slot, SDHCI_BUFFER,
 		    (uint32_t *)buffer, left >> 2);
 		left &= 3;
 	}
@@ -523,7 +369,7 @@ sdhci_write_block_pio(struct sdhci_slot 
 			WR4(slot, SDHCI_BUFFER, data);
 		}
 	} else {
-		bus_write_multi_stream_4(slot->mem_res, SDHCI_BUFFER,
+		WR_MULTI_4(slot, SDHCI_BUFFER,
 		    (uint32_t *)buffer, left >> 2);
 		left &= 3;
 	}
@@ -577,7 +423,7 @@ sdhci_card_task(void *arg, int pending)
 	if (RD4(slot, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) {
 		if (slot->dev == NULL) {
 			/* If card is present - attach mmc bus. */
-			slot->dev = device_add_child(slot->sc->dev, "mmc", -1);
+			slot->dev = device_add_child(slot->bus, "mmc", -1);
 			device_set_ivars(slot->dev, slot);
 			SDHCI_UNLOCK(slot);
 			device_probe_and_attach(slot->dev);
@@ -589,281 +435,171 @@ sdhci_card_task(void *arg, int pending)
 			device_t d = slot->dev;
 			slot->dev = NULL;
 			SDHCI_UNLOCK(slot);
-			device_delete_child(slot->sc->dev, d);
+			device_delete_child(slot->bus, d);
 		} else
 			SDHCI_UNLOCK(slot);
 	}
 }
 
-static int
-sdhci_probe(device_t dev)
+int
+sdhci_init_slot(device_t dev, struct sdhci_slot *slot, int num)
 {
-	uint32_t model;
-	uint16_t subvendor;
-	uint8_t class, subclass;
-	int i, result;
-	
-	model = (uint32_t)pci_get_device(dev) << 16;
-	model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
-	subvendor = pci_get_subvendor(dev);
-	class = pci_get_class(dev);
-	subclass = pci_get_subclass(dev);
-	
-	result = ENXIO;
-	for (i = 0; sdhci_devices[i].model != 0; i++) {
-		if (sdhci_devices[i].model == model &&
-		    (sdhci_devices[i].subvendor == 0xffff ||
-		    sdhci_devices[i].subvendor == subvendor)) {
-			device_set_desc(dev, sdhci_devices[i].desc);
-			result = BUS_PROBE_DEFAULT;
-			break;
-		}
-	}
-	if (result == ENXIO && class == PCIC_BASEPERIPH &&
-	    subclass == PCIS_BASEPERIPH_SDHC) {
-		device_set_desc(dev, "Generic SD HCI");
-		result = BUS_PROBE_GENERIC;
-	}
-	
-	return (result);
-}
+	uint32_t caps;
+	int err;
 
-static int
-sdhci_attach(device_t dev)
-{
-	struct sdhci_softc *sc = device_get_softc(dev);
-	uint32_t model;
-	uint16_t subvendor;
-	uint8_t class, subclass, progif;
-	int err, slots, bar, i;
-
-	sc->dev = dev;
-	model = (uint32_t)pci_get_device(dev) << 16;
-	model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
-	subvendor = pci_get_subvendor(dev);
-	class = pci_get_class(dev);
-	subclass = pci_get_subclass(dev);
-	progif = pci_get_progif(dev);
-	/* Apply chip specific quirks. */
-	for (i = 0; sdhci_devices[i].model != 0; i++) {
-		if (sdhci_devices[i].model == model &&
-		    (sdhci_devices[i].subvendor == 0xffff ||
-		    sdhci_devices[i].subvendor == subvendor)) {
-			sc->quirks = sdhci_devices[i].quirks;
-			break;
-		}
+	SDHCI_LOCK_INIT(slot);
+	slot->num = num;
+	slot->bus = dev;
+
+	/* Allocate DMA tag. */
+	err = bus_dma_tag_create(bus_get_dma_tag(dev),
+	    DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
+	    BUS_SPACE_MAXADDR, NULL, NULL,
+	    DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE,
+	    BUS_DMA_ALLOCNOW, NULL, NULL,
+	    &slot->dmatag);
+	if (err != 0) {
+		device_printf(dev, "Can't create DMA tag\n");
+		SDHCI_LOCK_DESTROY(slot);
+		return (err);
 	}
-	/* Some controllers need to be bumped into the right mode. */
-	if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY)
-		sdhci_lower_frequency(dev);
-	/* Read slots info from PCI registers. */
-	slots = pci_read_config(dev, PCI_SLOT_INFO, 1);
-	bar = PCI_SLOT_INFO_FIRST_BAR(slots);
-	slots = PCI_SLOT_INFO_SLOTS(slots);
-	if (slots > 6 || bar > 5) {
-		device_printf(dev, "Incorrect slots information (%d, %d).\n",
-		    slots, bar);
-		return (EINVAL);
+	/* Allocate DMA memory. */
+	err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
+	    BUS_DMA_NOWAIT, &slot->dmamap);
+	if (err != 0) {
+		device_printf(dev, "Can't alloc DMA memory\n");
+		SDHCI_LOCK_DESTROY(slot);
+		return (err);
+	}
+	/* Map the memory. */
+	err = bus_dmamap_load(slot->dmatag, slot->dmamap,
+	    (void *)slot->dmamem, DMA_BLOCK_SIZE,
+	    sdhci_getaddr, &slot->paddr, 0);
+	if (err != 0 || slot->paddr == 0) {
+		device_printf(dev, "Can't load DMA memory\n");
+		SDHCI_LOCK_DESTROY(slot);
+		if(err)
+			return (err);
+		else
+			return (EFAULT);
 	}
-	/* Allocate IRQ. */
-	sc->irq_rid = 0;
-	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
-	    RF_SHAREABLE | RF_ACTIVE);
-	if (sc->irq_res == NULL) {
-		device_printf(dev, "Can't allocate IRQ\n");
-		return (ENOMEM);
-	}
-	/* Scan all slots. */
-	for (i = 0; i < slots; i++) {
-		struct sdhci_slot *slot = &sc->slots[sc->num_slots];
-		uint32_t caps;
-
-		SDHCI_LOCK_INIT(slot);
-		slot->sc = sc;
-		slot->num = sc->num_slots;
-		/* Allocate memory. */
-		slot->mem_rid = PCIR_BAR(bar + i);
-		slot->mem_res = bus_alloc_resource(dev,
-		    SYS_RES_MEMORY, &slot->mem_rid, 0ul, ~0ul, 0x100, RF_ACTIVE);
-		if (slot->mem_res == NULL) {
-			device_printf(dev, "Can't allocate memory\n");
-			SDHCI_LOCK_DESTROY(slot);
-			continue;
-		}
-		/* Allocate DMA tag. */
-		err = bus_dma_tag_create(bus_get_dma_tag(dev),
-		    DMA_BLOCK_SIZE, 0, BUS_SPACE_MAXADDR_32BIT,
-		    BUS_SPACE_MAXADDR, NULL, NULL,
-		    DMA_BLOCK_SIZE, 1, DMA_BLOCK_SIZE,
-		    BUS_DMA_ALLOCNOW, NULL, NULL,
-		    &slot->dmatag);
-		if (err != 0) {
-			device_printf(dev, "Can't create DMA tag\n");
-			SDHCI_LOCK_DESTROY(slot);
-			continue;
-		}
-		/* Allocate DMA memory. */
-		err = bus_dmamem_alloc(slot->dmatag, (void **)&slot->dmamem,
-		    BUS_DMA_NOWAIT, &slot->dmamap);
-		if (err != 0) {
-			device_printf(dev, "Can't alloc DMA memory\n");
-			SDHCI_LOCK_DESTROY(slot);
-			continue;
-		}
-		/* Map the memory. */
-		err = bus_dmamap_load(slot->dmatag, slot->dmamap,
-		    (void *)slot->dmamem, DMA_BLOCK_SIZE,
-		    sdhci_getaddr, &slot->paddr, 0);
-		if (err != 0 || slot->paddr == 0) {
-			device_printf(dev, "Can't load DMA memory\n");
-			SDHCI_LOCK_DESTROY(slot);
-			continue;
-		}
-		/* Initialize slot. */
-		sdhci_init(slot);
-		caps = RD4(slot, SDHCI_CAPABILITIES);
-		/* Calculate base clock frequency. */
-		slot->max_clk =
-			(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
-		if (slot->max_clk == 0) {
-			device_printf(dev, "Hardware doesn't specify base clock "
-			    "frequency.\n");
-		}
-		slot->max_clk *= 1000000;
-		/* Calculate timeout clock frequency. */
-		slot->timeout_clk =
-			(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
-		if (slot->timeout_clk == 0) {
-			device_printf(dev, "Hardware doesn't specify timeout clock "
-			    "frequency.\n");
-		}
-		if (caps & SDHCI_TIMEOUT_CLK_UNIT)
-			slot->timeout_clk *= 1000;
-
-		slot->host.f_min = slot->max_clk / 256;
-		slot->host.f_max = slot->max_clk;
-		slot->host.host_ocr = 0;
-		if (caps & SDHCI_CAN_VDD_330)
-		    slot->host.host_ocr |= MMC_OCR_320_330 | MMC_OCR_330_340;
-		if (caps & SDHCI_CAN_VDD_300)
-		    slot->host.host_ocr |= MMC_OCR_290_300 | MMC_OCR_300_310;
-		if (caps & SDHCI_CAN_VDD_180)
-		    slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE;
-		if (slot->host.host_ocr == 0) {
-			device_printf(dev, "Hardware doesn't report any "
-			    "support voltages.\n");
-		}
-		slot->host.caps = MMC_CAP_4_BIT_DATA;
-		if (caps & SDHCI_CAN_DO_HISPD)
-			slot->host.caps |= MMC_CAP_HSPEED;
-		/* Decide if we have usable DMA. */
-		if (caps & SDHCI_CAN_DO_DMA)
-			slot->opt |= SDHCI_HAVE_DMA;
-		if (class == PCIC_BASEPERIPH &&
-		    subclass == PCIS_BASEPERIPH_SDHC &&
-		    progif != PCI_SDHCI_IFDMA)
-			slot->opt &= ~SDHCI_HAVE_DMA;
-		if (sc->quirks & SDHCI_QUIRK_BROKEN_DMA)
-			slot->opt &= ~SDHCI_HAVE_DMA;
-		if (sc->quirks & SDHCI_QUIRK_FORCE_DMA)
-			slot->opt |= SDHCI_HAVE_DMA;
-
-		if (bootverbose || sdhci_debug) {
-			slot_printf(slot, "%uMHz%s 4bits%s%s%s %s\n",
-			    slot->max_clk / 1000000,
-			    (caps & SDHCI_CAN_DO_HISPD) ? " HS" : "",
-			    (caps & SDHCI_CAN_VDD_330) ? " 3.3V" : "",
-			    (caps & SDHCI_CAN_VDD_300) ? " 3.0V" : "",
-			    (caps & SDHCI_CAN_VDD_180) ? " 1.8V" : "",
-			    (slot->opt & SDHCI_HAVE_DMA) ? "DMA" : "PIO");
-			sdhci_dumpregs(slot);
-		}
-		
-		TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot);
-		callout_init(&slot->card_callout, 1);
-		sc->num_slots++;
-	}
-	device_printf(dev, "%d slot(s) allocated\n", sc->num_slots);
-	/* Activate the interrupt */
-	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
-	    NULL, sdhci_intr, sc, &sc->intrhand);
-	if (err)
-		device_printf(dev, "Can't setup IRQ\n");
-	pci_enable_busmaster(dev);
-	/* Process cards detection. */
-	for (i = 0; i < sc->num_slots; i++) {
-		struct sdhci_slot *slot = &sc->slots[i];
 
-		sdhci_card_task(slot, 0);
+	/* Initialize slot. */
+	sdhci_init(slot);
+	slot->version = (RD2(slot, SDHCI_HOST_VERSION) 
+		>> SDHCI_SPEC_VER_SHIFT) & SDHCI_SPEC_VER_MASK;
+	caps = RD4(slot, SDHCI_CAPABILITIES);
+	/* Calculate base clock frequency. */
+	slot->max_clk =
+		(caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
+	if (slot->max_clk == 0) {
+		slot->max_clk = 50;
+		device_printf(dev, "Hardware doesn't specify base clock "
+		    "frequency.\n");
+	}
+	slot->max_clk *= 1000000;
+	/* Calculate timeout clock frequency. */
+	slot->timeout_clk =
+		(caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
+	if (slot->timeout_clk == 0) {
+		device_printf(dev, "Hardware doesn't specify timeout clock "
+		    "frequency.\n");
+	}
+	if (caps & SDHCI_TIMEOUT_CLK_UNIT)
+		slot->timeout_clk *= 1000;
+
+	slot->host.f_min = slot->max_clk / 256;
+	slot->host.f_max = slot->max_clk;
+	slot->host.host_ocr = 0;
+	if (caps & SDHCI_CAN_VDD_330)
+	    slot->host.host_ocr |= MMC_OCR_320_330 | MMC_OCR_330_340;
+	if (caps & SDHCI_CAN_VDD_300)
+	    slot->host.host_ocr |= MMC_OCR_290_300 | MMC_OCR_300_310;
+	if (caps & SDHCI_CAN_VDD_180)
+	    slot->host.host_ocr |= MMC_OCR_LOW_VOLTAGE;
+	if (slot->host.host_ocr == 0) {
+		device_printf(dev, "Hardware doesn't report any "
+		    "support voltages.\n");
+	}
+	slot->host.caps = MMC_CAP_4_BIT_DATA;
+	if (caps & SDHCI_CAN_DO_HISPD)
+		slot->host.caps |= MMC_CAP_HSPEED;
+	/* Decide if we have usable DMA. */
+	if (caps & SDHCI_CAN_DO_DMA)
+		slot->opt |= SDHCI_HAVE_DMA;
+
+	if (slot->quirks & SDHCI_QUIRK_BROKEN_DMA)
+		slot->opt &= ~SDHCI_HAVE_DMA;
+	if (slot->quirks & SDHCI_QUIRK_FORCE_DMA)
+		slot->opt |= SDHCI_HAVE_DMA;
+
+	if (bootverbose || sdhci_debug) {
+		slot_printf(slot, "%uMHz%s 4bits%s%s%s %s\n",
+		    slot->max_clk / 1000000,
+		    (caps & SDHCI_CAN_DO_HISPD) ? " HS" : "",
+		    (caps & SDHCI_CAN_VDD_330) ? " 3.3V" : "",
+		    (caps & SDHCI_CAN_VDD_300) ? " 3.0V" : "",
+		    (caps & SDHCI_CAN_VDD_180) ? " 1.8V" : "",
+		    (slot->opt & SDHCI_HAVE_DMA) ? "DMA" : "PIO");
+		sdhci_dumpregs(slot);
 	}
-		
+	
+	TASK_INIT(&slot->card_task, 0, sdhci_card_task, slot);
+	callout_init(&slot->card_callout, 1);
 	return (0);
 }
 
-static int
-sdhci_detach(device_t dev)
+void
+sdhci_start_slot(struct sdhci_slot *slot)
 {
-	struct sdhci_softc *sc = device_get_softc(dev);
-	int i;
+	sdhci_card_task(slot, 0);
+}
 
-	bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
-	bus_release_resource(dev, SYS_RES_IRQ,
-	    sc->irq_rid, sc->irq_res);
-
-	for (i = 0; i < sc->num_slots; i++) {
-		struct sdhci_slot *slot = &sc->slots[i];
-		device_t d;
-
-		callout_drain(&slot->card_callout);
-		taskqueue_drain(taskqueue_swi_giant, &slot->card_task);
-
-		SDHCI_LOCK(slot);
-		d = slot->dev;
-		slot->dev = NULL;
-		SDHCI_UNLOCK(slot);
-		if (d != NULL)
-			device_delete_child(dev, d);
+int
+sdhci_cleanup_slot(struct sdhci_slot *slot)
+{
+	device_t d;
+
+	callout_drain(&slot->card_callout);
+	taskqueue_drain(taskqueue_swi_giant, &slot->card_task);
+
+	SDHCI_LOCK(slot);
+	d = slot->dev;
+	slot->dev = NULL;
+	SDHCI_UNLOCK(slot);
+	if (d != NULL)
+		device_delete_child(slot->bus, d);
+
+	SDHCI_LOCK(slot);
+	sdhci_reset(slot, SDHCI_RESET_ALL);
+	SDHCI_UNLOCK(slot);
+	bus_dmamap_unload(slot->dmatag, slot->dmamap);
+	bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
+	bus_dma_tag_destroy(slot->dmatag);
+
+	SDHCI_LOCK_DESTROY(slot);
 
-		SDHCI_LOCK(slot);
-		sdhci_reset(slot, SDHCI_RESET_ALL);
-		SDHCI_UNLOCK(slot);
-		bus_dmamap_unload(slot->dmatag, slot->dmamap);
-		bus_dmamem_free(slot->dmatag, slot->dmamem, slot->dmamap);
-		bus_dma_tag_destroy(slot->dmatag);
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    slot->mem_rid, slot->mem_res);
-		SDHCI_LOCK_DESTROY(slot);
-	}
 	return (0);
 }
 
-static int
-sdhci_suspend(device_t dev)
+int
+sdhci_generic_suspend(struct sdhci_slot *slot)
 {
-	struct sdhci_softc *sc = device_get_softc(dev);
-	int i, err;
+	sdhci_reset(slot, SDHCI_RESET_ALL);
 
-	err = bus_generic_suspend(dev);
-	if (err)
-		return (err);
-	for (i = 0; i < sc->num_slots; i++)
-		sdhci_reset(&sc->slots[i], SDHCI_RESET_ALL);
 	return (0);
 }
 
-static int
-sdhci_resume(device_t dev)
+int
+sdhci_generic_resume(struct sdhci_slot *slot)
 {
-	struct sdhci_softc *sc = device_get_softc(dev);
-	int i;
+	sdhci_init(slot);
 
-	for (i = 0; i < sc->num_slots; i++)
-		sdhci_init(&sc->slots[i]);
-	return (bus_generic_resume(dev));
+	return (0);
 }
 
-static int
-sdhci_update_ios(device_t brdev, device_t reqdev)
+int
+sdhci_generic_update_ios(device_t brdev, device_t reqdev)
 {
 	struct sdhci_slot *slot = device_get_ivars(reqdev);
 	struct mmc_ios *ios = &slot->host.ios;
@@ -887,7 +623,7 @@ sdhci_update_ios(device_t brdev, device_
 		slot->hostctrl &= ~SDHCI_CTRL_HISPD;
 	WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl);
 	/* Some controllers like reset after bus changes. */
-	if(slot->sc->quirks & SDHCI_QUIRK_RESET_ON_IOS)
+	if(slot->quirks & SDHCI_QUIRK_RESET_ON_IOS)
 		sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
 
 	SDHCI_UNLOCK(slot);
@@ -1009,10 +745,8 @@ sdhci_start_command(struct sdhci_slot *s
 	WR4(slot, SDHCI_ARGUMENT, cmd->arg);
 	/* Set data transfer mode. */
 	sdhci_set_transfer_mode(slot, cmd->data);
-	/* Set command flags. */
-	WR1(slot, SDHCI_COMMAND_FLAGS, flags);
 	/* Start command. */
-	WR1(slot, SDHCI_COMMAND, cmd->opcode);
+	WR2(slot, SDHCI_COMMAND_FLAGS, (cmd->opcode << 8) | (flags & 0xff));
 }
 
 static void
@@ -1075,7 +809,7 @@ sdhci_start_data(struct sdhci_slot *slot
 			break;
 	}
 	/* Compensate for an off-by-one error in the CaFe chip.*/
-	if (slot->sc->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)
+	if (slot->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)
 		div++;
 	if (div >= 0xF) {
 		slot_printf(slot, "Timeout too large!\n");
@@ -1090,11 +824,11 @@ sdhci_start_data(struct sdhci_slot *slot
 	if ((slot->opt & SDHCI_HAVE_DMA))
 		slot->flags |= SDHCI_USE_DMA;
 	/* If data is small, broken DMA may return zeroes instead of data, */
-	if ((slot->sc->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) &&
+	if ((slot->quirks & SDHCI_QUIRK_BROKEN_TIMINGS) &&
 	    (data->len <= 512))
 		slot->flags &= ~SDHCI_USE_DMA;
 	/* Some controllers require even block sizes. */
-	if ((slot->sc->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) &&
+	if ((slot->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) &&
 	    ((data->len) & 0x3))
 		slot->flags &= ~SDHCI_USE_DMA;
 	/* Load DMA buffer. */
@@ -1183,7 +917,7 @@ sdhci_start(struct sdhci_slot *slot)
 	if (sdhci_debug > 1)
 		slot_printf(slot, "result: %d\n", req->cmd->error);
 	if (!req->cmd->error &&
-	    (slot->sc->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
+	    (slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
 		sdhci_reset(slot, SDHCI_RESET_CMD);
 		sdhci_reset(slot, SDHCI_RESET_DATA);
 	}
@@ -1194,8 +928,8 @@ sdhci_start(struct sdhci_slot *slot)
 	req->done(req);
 }
 
-static int
-sdhci_request(device_t brdev, device_t reqdev, struct mmc_request *req)
+int
+sdhci_generic_request(device_t brdev, device_t reqdev, struct mmc_request *req)
 {
 	struct sdhci_slot *slot = device_get_ivars(reqdev);
 
@@ -1216,15 +950,15 @@ sdhci_request(device_t brdev, device_t r
 	SDHCI_UNLOCK(slot);
 	if (dumping) {
 		while (slot->req != NULL) {
-			sdhci_intr(slot->sc);
+			sdhci_generic_intr(slot);
 			DELAY(10);
 		}
 	}
 	return (0);
 }
 
-static int
-sdhci_get_ro(device_t brdev, device_t reqdev)
+int
+sdhci_generic_get_ro(device_t brdev, device_t reqdev)
 {
 	struct sdhci_slot *slot = device_get_ivars(reqdev);
 	uint32_t val;
@@ -1235,8 +969,8 @@ sdhci_get_ro(device_t brdev, device_t re
 	return (!(val & SDHCI_WRITE_PROTECT));
 }
 
-static int
-sdhci_acquire_host(device_t brdev, device_t reqdev)
+int
+sdhci_generic_acquire_host(device_t brdev, device_t reqdev)
 {
 	struct sdhci_slot *slot = device_get_ivars(reqdev);
 	int err = 0;
@@ -1251,8 +985,8 @@ sdhci_acquire_host(device_t brdev, devic
 	return (err);
 }
 
-static int
-sdhci_release_host(device_t brdev, device_t reqdev)
+int
+sdhci_generic_release_host(device_t brdev, device_t reqdev)
 {
 	struct sdhci_slot *slot = device_get_ivars(reqdev);
 
@@ -1382,85 +1116,79 @@ sdhci_acmd_irq(struct sdhci_slot *slot)
 	sdhci_reset(slot, SDHCI_RESET_CMD);
 }
 
-static void
-sdhci_intr(void *arg)
+void
+sdhci_generic_intr(struct sdhci_slot *slot)
 {
-	struct sdhci_softc *sc = (struct sdhci_softc *)arg;
-	int i;
-
-	for (i = 0; i < sc->num_slots; i++) {
-		struct sdhci_slot *slot = &sc->slots[i];
-		uint32_t intmask;
-		
-		SDHCI_LOCK(slot);
-		/* Read slot interrupt status. */
-		intmask = RD4(slot, SDHCI_INT_STATUS);
-		if (intmask == 0 || intmask == 0xffffffff) {
-			SDHCI_UNLOCK(slot);
-			continue;
-		}
-		if (sdhci_debug > 2)
-			slot_printf(slot, "Interrupt %#x\n", intmask);
-
-		/* Handle card presence interrupts. */
-		if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
-			WR4(slot, SDHCI_INT_STATUS, intmask & 
-			    (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE));
-
-			if (intmask & SDHCI_INT_CARD_REMOVE) {
-				if (bootverbose || sdhci_debug)
-					slot_printf(slot, "Card removed\n");
-				callout_stop(&slot->card_callout);
-				taskqueue_enqueue(taskqueue_swi_giant,
-				    &slot->card_task);
-			}
-			if (intmask & SDHCI_INT_CARD_INSERT) {
-				if (bootverbose || sdhci_debug)
-					slot_printf(slot, "Card inserted\n");
-				callout_reset(&slot->card_callout, hz / 2,
-				    sdhci_card_delay, slot);
-			}
-			intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
-		}
-		/* Handle command interrupts. */
-		if (intmask & SDHCI_INT_CMD_MASK) {
-			WR4(slot, SDHCI_INT_STATUS, intmask & SDHCI_INT_CMD_MASK);
-			sdhci_cmd_irq(slot, intmask & SDHCI_INT_CMD_MASK);
-		}
-		/* Handle data interrupts. */
-		if (intmask & SDHCI_INT_DATA_MASK) {
-			WR4(slot, SDHCI_INT_STATUS, intmask & SDHCI_INT_DATA_MASK);
-			sdhci_data_irq(slot, intmask & SDHCI_INT_DATA_MASK);
-		}
-		/* Handle AutoCMD12 error interrupt. */
-		if (intmask & SDHCI_INT_ACMD12ERR) {
-			WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_ACMD12ERR);
-			sdhci_acmd_irq(slot);
-		}
-		intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
-		intmask &= ~SDHCI_INT_ACMD12ERR;
-		intmask &= ~SDHCI_INT_ERROR;
-		/* Handle bus power interrupt. */
-		if (intmask & SDHCI_INT_BUS_POWER) {
-			WR4(slot, SDHCI_INT_STATUS, SDHCI_INT_BUS_POWER);
-			slot_printf(slot,
-			    "Card is consuming too much power!\n");
-			intmask &= ~SDHCI_INT_BUS_POWER;
-		}
-		/* The rest is unknown. */
-		if (intmask) {
-			WR4(slot, SDHCI_INT_STATUS, intmask);
-			slot_printf(slot, "Unexpected interrupt 0x%08x.\n",
-			    intmask);
-			sdhci_dumpregs(slot);
-		}
-		
+	uint32_t intmask;
+	
+	SDHCI_LOCK(slot);
+	/* Read slot interrupt status. */
+	intmask = RD4(slot, SDHCI_INT_STATUS);
+	if (intmask == 0 || intmask == 0xffffffff) {
 		SDHCI_UNLOCK(slot);
+		return;
 	}
+	if (sdhci_debug > 2)
+		slot_printf(slot, "Interrupt %#x\n", intmask);
+
+	/* Handle card presence interrupts. */
+	if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
+		WR4(slot, SDHCI_INT_STATUS, intmask & 
+		    (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE));
+
+		if (intmask & SDHCI_INT_CARD_REMOVE) {
+			if (bootverbose || sdhci_debug)
+				slot_printf(slot, "Card removed\n");
+			callout_stop(&slot->card_callout);
+			taskqueue_enqueue(taskqueue_swi_giant,
+			    &slot->card_task);
+		}
+		if (intmask & SDHCI_INT_CARD_INSERT) {
+			if (bootverbose || sdhci_debug)

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210160110.q9G1AiH0012464>