First cut at making detach work. also add sdh as a possible mmc bridge.
Submitted by: Andrea Bittau (Andrea may have updated patches, but I've tested these)
This commit is contained in:
parent
78f8edfb44
commit
0e1466ac89
@ -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;
|
||||
@ -568,13 +589,15 @@ mmc_discover_cards(struct mmc_softc *sc)
|
||||
// RO check
|
||||
mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
|
||||
mmc_decode_csd(1, ivar->raw_csd, &ivar->csd);
|
||||
printf("SD CARD: %lld bytes\n", ivar->csd.capacity);
|
||||
printf("SD CARD: %lld bytes\n", (long long)
|
||||
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
|
||||
@ -679,9 +702,6 @@ mmc_read_ivar(device_t bus, device_t child, int which, u_char *result)
|
||||
case MMC_IVAR_MEDIA_SIZE:
|
||||
*(int *)result = ivar->csd.capacity;
|
||||
break;
|
||||
case MMC_IVAR_MODE:
|
||||
*(int *)result = ivar->mode;
|
||||
break;
|
||||
case MMC_IVAR_RCA:
|
||||
*(int *)result = ivar->rca;
|
||||
break;
|
||||
@ -743,3 +763,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);
|
||||
|
@ -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[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user