SD card reader driver [IBM x60s - Ricoh] and MMC detach patch

Andrea Bittau a.bittau at cs.ucl.ac.uk
Sat Feb 3 02:19:56 UTC 2007


Here is a [usable?] SD card reader driver that uses the freebsd mmc stuff:
http://darkircop.org/sdh.tgz

I tested it on an IBM/Lenovo Thinkpad x60s.  It has this controller:
sdh0 at pci21:0:2: class=0x080500 card=0x201d17aa chip=0x08221180 rev=0x18 hdr=0x00
    vendor   = 'Ricoh Company, Ltd.'
    device   = 'SD Bus Host Adapter'
    class    = base peripheral
I'm running 7-current.

The driver can do 1MB in ~30 seconds (with DMA, transferring single 512 blocks).
It's not great, but at least it's a starting point.  It should work fine,
although doing stuff like pulling the card out half way through a transfer will
most likely mess things up.

I also have a patch that will allow mmc and mmcsd to be compiled as modules, and
to be detached.  To use my driver, you need to apply that patch [mmc.diff].  I
attach it to this e-mail to ease review.

---

Index: conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.1171
diff -u -p -r1.1171 files
--- conf/files	5 Jan 2007 01:46:26 -0000	1.1171
+++ conf/files	3 Feb 2007 01:49:30 -0000
@@ -754,8 +754,8 @@ dev/mlx/mlx_disk.c		optional mlx
 dev/mlx/mlx_pci.c		optional mlx pci
 dev/mly/mly.c			optional mly
 dev/mmc/mmc.c			optional mmc
-dev/mmc/mmcbr_if.m		optional mmc
-dev/mmc/mmcbus_if.m		optional mmc
+dev/mmc/mmcbr_if.m		standard
+dev/mmc/mmcbus_if.m		standard
 dev/mmc/mmcsd.c			optional mmcsd
 dev/mpt/mpt.c			optional mpt
 dev/mpt/mpt_cam.c		optional mpt
Index: conf/kmod.mk
===================================================================
RCS file: /home/ncvs/src/sys/conf/kmod.mk,v
retrieving revision 1.213
diff -u -p -r1.213 kmod.mk
--- conf/kmod.mk	20 Oct 2006 07:31:15 -0000	1.213
+++ conf/kmod.mk	3 Feb 2007 01:49:30 -0000
@@ -318,7 +318,7 @@ ${_src}:
 
 MFILES?= dev/acpica/acpi_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \
 	dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \
-	dev/mmc/mmcbr_if.m mmc/mmcbus_if.m \
+	dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \
 	dev/mii/miibus_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 \
Index: dev/mmc/mmc.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mmc/mmc.c,v
retrieving revision 1.1
diff -u -p -r1.1 mmc.c
--- dev/mmc/mmc.c	20 Oct 2006 06:39:59 -0000	1.1
+++ dev/mmc/mmc.c	3 Feb 2007 01:49:37 -0000
@@ -117,7 +117,26 @@ mmc_attach(device_t dev)
 static int
 mmc_detach(device_t dev)
 {
-	return (EBUSY);	/* XXX */
+	struct mmc_softc *sc = device_get_softc(dev);
+	device_t *kids;
+	int i, nkid;
+
+	/* kill children [ph33r].  -sorbo */
+	if (device_get_children(sc->dev, &kids, &nkid) != 0)
+		return 0;
+	for (i = 0; i < nkid; i++) {
+		device_t kid = kids[i];
+		void *ivar = device_get_ivars(kid);
+		
+		device_detach(kid);
+		device_delete_child(sc->dev, kid);
+		free(ivar, M_DEVBUF);
+	}
+	free(kids, M_TEMP);
+
+	MMC_LOCK_DESTROY(sc);
+
+	return 0;
 }
 
 static int
@@ -553,6 +572,8 @@ mmc_discover_cards(struct mmc_softc *sc)
 
 	while (1) {
 		ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, M_WAITOK);
+		if (!ivar)
+			return;
 		err = mmc_all_send_cid(sc, ivar->raw_cid);
 		if (err == MMC_ERR_TIMEOUT)
 			break;
@@ -571,10 +592,11 @@ mmc_discover_cards(struct mmc_softc *sc)
 			printf("SD CARD: %lld bytes\n", ivar->csd.capacity);
 			child = device_add_child(sc->dev, NULL, -1);
 			device_set_ivars(child, ivar);
-			break;
+			return;
 		}
 		panic("Write MMC card code here");
 	}
+	free(ivar, M_DEVBUF);
 }
 
 static void
@@ -743,3 +765,4 @@ static devclass_t mmc_devclass;
 
 
 DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, 0, 0);
+DRIVER_MODULE(mmc, sdh, mmc_driver, mmc_devclass, 0, 0);
Index: dev/mmc/mmcsd.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/mmc/mmcsd.c,v
retrieving revision 1.1
diff -u -p -r1.1 mmcsd.c
--- dev/mmc/mmcsd.c	20 Oct 2006 06:39:59 -0000	1.1
+++ dev/mmc/mmcsd.c	3 Feb 2007 01:49:37 -0000
@@ -50,6 +50,7 @@ struct mmcsd_softc {
 	struct disk *disk;
 	struct proc *p;
 	struct bio_queue_head bio_queue;
+	int running;
 };
 
 #define	MULTI_BLOCK_READ_BROKEN
@@ -104,6 +105,8 @@ mmcsd_attach(device_t dev)
 	sc->disk->d_unit = device_get_unit(dev);
 	disk_create(sc->disk, DISK_VERSION);
 	bioq_init(&sc->bio_queue);
+
+	sc->running = 1;
 	kthread_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card");
 
 	return (0);
@@ -112,7 +115,27 @@ mmcsd_attach(device_t dev)
 static int
 mmcsd_detach(device_t dev)
 {
-	return (EBUSY);	/* XXX */
+	struct mmcsd_softc *sc = device_get_softc(dev);
+
+	/* kill thread */
+	MMCSD_LOCK(sc);
+	sc->running = 0;
+	wakeup(sc);
+	MMCSD_UNLOCK(sc);
+
+	/* wait for thread to finish.  XXX probably want timeout.  -sorbo */
+	MMCSD_LOCK(sc);
+	while (sc->running != -1)
+		msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0);
+	MMCSD_UNLOCK(sc);
+
+	/* kill disk */
+	disk_destroy(sc->disk);
+	/* XXX destroy anything in queue */
+
+	MMCSD_LOCK_DESTROY(sc);
+
+	return 0;
 }
 
 static int
@@ -153,15 +176,18 @@ mmcsd_task(void *arg)
 	device_t dev;
 
 	dev = sc->dev;
-	for (;;) {
+	while (sc->running) {
 		MMCSD_LOCK(sc);
 		do {
 			bp = bioq_first(&sc->bio_queue);
 			if (bp == NULL)
 				msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
-		} while (bp == NULL);
-		bioq_remove(&sc->bio_queue, bp);
+		} while (bp == NULL && sc->running);
+		if (bp)
+			bioq_remove(&sc->bio_queue, bp);
 		MMCSD_UNLOCK(sc);
+		if (!sc->running)
+			break;
 		MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
 //		printf("mmc_task: request %p for block %lld\n", bp, bp->bio_pblkno);
 		sz = sc->disk->d_sectorsize;
@@ -224,6 +250,14 @@ mmcsd_task(void *arg)
 		MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
 		biodone(bp);
 	}
+
+	/* tell parent we're done */
+	MMCSD_LOCK(sc);
+	sc->running = -1;
+	wakeup(sc);
+	MMCSD_UNLOCK(sc);
+
+	kthread_exit(0);
 }
 
 static device_method_t mmcsd_methods[] = {
Index: modules/Makefile
===================================================================
RCS file: /home/ncvs/src/sys/modules/Makefile,v
retrieving revision 1.517
diff -u -p -r1.517 Makefile
--- modules/Makefile	18 Dec 2006 18:57:41 -0000	1.517
+++ modules/Makefile	3 Feb 2007 01:49:42 -0000
@@ -158,6 +158,8 @@ SUBDIR=	${_3dfx} \
 	mii \
 	mlx \
 	${_mly} \
+	mmc \
+	mmcsd \
 	mpt \
 	mqueue \
 	msdosfs \


More information about the freebsd-mobile mailing list