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

Andrea Bittau <[email protected]>
Newsgroups gmane.os.freebsd.devel.mobile
Message-ID <[email protected]>
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@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 \
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-mobile
To unsubscribe, send any mail to "[email protected]"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.