From owner-p4-projects@FreeBSD.ORG Sat Sep 2 21:33:52 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3F88F16A4E2; Sat, 2 Sep 2006 21:33:52 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1B35F16A4E0 for ; Sat, 2 Sep 2006 21:33:52 +0000 (UTC) (envelope-from ticso@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id AFC6D43D49 for ; Sat, 2 Sep 2006 21:33:51 +0000 (GMT) (envelope-from ticso@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k82LXptO075625 for ; Sat, 2 Sep 2006 21:33:51 GMT (envelope-from ticso@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k82LXpcY075621 for perforce@freebsd.org; Sat, 2 Sep 2006 21:33:51 GMT (envelope-from ticso@freebsd.org) Date: Sat, 2 Sep 2006 21:33:51 GMT Message-Id: <200609022133.k82LXpcY075621@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ticso@freebsd.org using -f From: Bernd Walter To: Perforce Change Reviews Cc: Subject: PERFORCE change 105561 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Sep 2006 21:33:52 -0000 http://perforce.freebsd.org/chv.cgi?CH=105561 Change 105561 by ticso@ticso on 2006/09/02 21:33:45 add bio_queue and interrupt support Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_qdmmc.c#2 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_qdmmc.c#2 (text+ko) ==== @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,9 @@ bus_dmamap_t map; struct disk *disk; /* XXX support only one card for */ int nb_cards; + struct proc *p; struct { + struct bio_queue_head bio_queue; char name[7]; uint32_t addr; uint32_t CID[4]; @@ -101,6 +104,7 @@ static int at91_qdmmc_open(struct disk *dp); static int at91_qdmmc_close(struct disk *dp); static void at91_qdmmc_strategy(struct bio *bp); +static void at91_qdmmc_task(void *arg); #define AT91_QDMMC_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) #define AT91_QDMMC_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) @@ -301,11 +305,14 @@ /* declare clockrate to 5MHz - XXX the card may allow more */ sc->cards[card].mode = 5 * MCI_MR_CLKDIV | MCI_MR_PWSDIV | (MCI_MR_PWSDIV << 1 | AT91C_MCI_MR_PDCMODE); sc->cards[card].mode = 75 * MCI_MR_CLKDIV | MCI_MR_PWSDIV | (MCI_MR_PWSDIV << 1); + + bioq_init(&sc->cards[0].bio_queue); } if (sc->nb_cards == 0) { printf("No MMC cards found\n"); goto out; } else { + AT91_QDMMC_LOCK(sc); /* * Register the (XXX) first media as a disk */ @@ -318,13 +325,16 @@ sc->disk->d_drv1 = sc; sc->disk->d_maxsize = DFLTPHYS; sc->disk->d_unit = 0; - sc->disk->d_flags = DISKFLAG_NEEDSGIANT; + //sc->disk->d_flags = DISKFLAG_NEEDSGIANT; disk_create(sc->disk, DISK_VERSION); } /* set clockrate to 5MHz - XXX the card may allow more */ WR4(sc, MCI_MR, 5 * MCI_MR_CLKDIV | MCI_MR_PWSDIV | (MCI_MR_PWSDIV << 1) | AT91C_MCI_MR_PDCMODE); + AT91_QDMMC_UNLOCK(sc); + + kthread_create(&at91_qdmmc_task, sc, &sc->p, 0, 0, "task: at91_qdmmc"); out:; if (err) at91_qdmmc_deactivate(dev); @@ -396,12 +406,14 @@ //printf("at91_qdmmc_open: called\n"); sc = (struct at91_qdmmc_softc *)dp->d_drv1; + AT91_QDMMC_LOCK(sc); sc->disk->d_sectorsize = sc->cards[0].sector_size; sc->disk->d_mediasize = sc->cards[0].size; //softc->disk->d_fwsectors = softc->params.secs_per_track; //softc->disk->d_fwheads = softc->params.heads; //sc->disk->d_devstat->block_size = sc->cards[0].sector_size; //softc->disk->d_devstat->flags &= ~DEVSTAT_BS_UNAVAILABLE; + AT91_QDMMC_UNLOCK(sc); return 0; } @@ -413,152 +425,180 @@ //printf("at91_qdmmc_close: called\n"); sc = (struct at91_qdmmc_softc *)dp->d_drv1; + AT91_QDMMC_LOCK(sc); + AT91_QDMMC_UNLOCK(sc); + // XXX do nothing since we don't lock for now return 0; } -// XXX in fact we should queue the transfer static void at91_qdmmc_strategy(struct bio *bp) { struct at91_qdmmc_softc *sc; - int status; - bus_addr_t addr; - int map = 0; //printf("at91_qdmmc_strategy: called\n"); sc = (struct at91_qdmmc_softc *)bp->bio_disk->d_drv1; + AT91_QDMMC_LOCK(sc); + bioq_disksort(&sc->cards[0].bio_queue, bp); + wakeup(sc); + AT91_QDMMC_UNLOCK(sc); +} + +static void at91_qdmmc_task(void *arg) { + struct at91_qdmmc_softc *sc = (struct at91_qdmmc_softc*)arg; + struct bio *bp; + int status; + bus_addr_t addr; + int map = 0; + uint32_t *tmpbuf; - if (bp->bio_cmd == BIO_READ) { - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, (sc->cards[0].addr) << 16); - //printf("at91_qdmmc_strategy: select_card-status = 0x%x\n", status); - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SET_BLOCKLEN_CMD, sc->cards[0].sector_size); - //printf("at91_qdmmc_strategy: set_blocklen-status = 0x%x\n", status); - //printf("at91_qdmmc_strategy: read block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); - uint32_t block; - // Init Mode Register - WR4(sc, MCI_MR, sc->cards[0].mode | (sc->cards[0].sector_size << 16)); - //printf("mode 0x%x\n", RD4(sc, MCI_MR)); - for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sc->cards[0].sector_size); block++) { + tmpbuf = malloc(sc->cards[0].sector_size, M_DEVBUF, M_WAITOK); + AT91_QDMMC_LOCK(sc); + //printf("at91_qdmmc_task: start\n"); + for (;;) { + do { + bp = bioq_first(&sc->cards[0].bio_queue); + if (bp == NULL) + msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0); + } while (bp == NULL); + bioq_remove(&sc->cards[0].bio_queue, bp); + //printf("at91_qdmmc_task: request %p\n", bp); + if (bp->bio_cmd == BIO_READ) { + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, (sc->cards[0].addr) << 16); + //printf("at91_qdmmc_task: select_card-status = 0x%x\n", status); + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SET_BLOCKLEN_CMD, sc->cards[0].sector_size); + //printf("at91_qdmmc_task: set_blocklen-status = 0x%x\n", status); + //printf("at91_qdmmc_task: read block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); + uint32_t block; + // Init Mode Register + WR4(sc, MCI_MR, sc->cards[0].mode | (sc->cards[0].sector_size << 16)); + //printf("mode 0x%x\n", RD4(sc, MCI_MR)); + for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sc->cards[0].sector_size); block++) { - WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); + WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); - char *paddr = bp->bio_data + (block - bp->bio_pblkno) * sc->cards[0].sector_size; + char *paddr = bp->bio_data + (block - bp->bio_pblkno) * sc->cards[0].sector_size; - if (bus_dmamap_load(sc->dmatag, sc->map, paddr, - sc->cards[0].sector_size, at91_getaddr, &addr, 0) != 0) - goto out; - map = 1; + if (bus_dmamap_load(sc->dmatag, sc->map, paddr, + sc->cards[0].sector_size, at91_getaddr, &addr, 0) != 0) + goto out; + map = 1; - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREREAD); - WR4(sc, PDC_RPR, addr); - WR4(sc, PDC_RCR, sc->cards[0].sector_size / 4); - WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); + bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREREAD); + WR4(sc, PDC_RPR, addr); + WR4(sc, PDC_RCR, sc->cards[0].sector_size / 4); + WR4(sc, PDC_PTCR, PDC_PTCR_RXTEN); + WR4(sc, MCI_IER, MCI_SR_RXBUFF); - //printf("status = 0x%x, paddr = %p, RPR = 0x%x, RCR = 0x%x\n", status, paddr, - // RD4(sc, PDC_RPR), RD4(sc, PDC_RCR)); - status = at91_qdmmc_SendCommand(sc->dev, AT91C_READ_SINGLE_BLOCK_CMD, block * sc->cards[0].sector_size); - //printf("at91_qdmmc_strategy: read-status = 0x%x\n", status); + //printf("status = 0x%x, paddr = %p, RPR = 0x%x, RCR = 0x%x\n", status, paddr, + // RD4(sc, PDC_RPR), RD4(sc, PDC_RCR)); + status = at91_qdmmc_SendCommand(sc->dev, AT91C_READ_SINGLE_BLOCK_CMD, block * sc->cards[0].sector_size); + //printf("at91_qdmmc_task: read-status = 0x%x\n", status); - // wait for completion - // XXX should be done as an ISR of some sort. - while ((RD4(sc, MCI_SR) & MCI_SR_ENDRX) == 0) - DELAY(700); + // wait for completion + msleep(sc, &sc->sc_mtx, PRIBIO, "endrx", 0); + // safety check + while ((RD4(sc, MCI_SR) & MCI_SR_ENDRX) == 0) + DELAY(700); - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(sc->dmatag, sc->map); - map = 0; + bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->dmatag, sc->map); + map = 0; - /* Fix Byteorder (Atmel Errata) */ - uint32_t* base = (uint32_t*)paddr; - for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { - uint32_t tmp = base[i]; - base[i] = (((tmp >> 24) & 0xff)) | - (((tmp >> 16) & 0xff) << 8) | - (((tmp >> 8) & 0xff) << 16) | - ((tmp & 0xff) << 24); + /* Fix Byteorder (Atmel Errata) */ + uint32_t* base = (uint32_t*)paddr; + for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { + uint32_t tmp = base[i]; + base[i] = (((tmp >> 24) & 0xff)) | + (((tmp >> 16) & 0xff) << 8) | + (((tmp >> 8) & 0xff) << 16) | + ((tmp & 0xff) << 24); + } } + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, 0); + //printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); + + // Reset Mode Register + WR4(sc, MCI_MR, sc->cards[0].mode); + biodone(bp); + continue; } - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, 0); - //printf("at91_qdmmc_strategy: deselect_card-status = 0x%x\n", status); + if (bp->bio_cmd == BIO_WRITE) { + //printf("at91_qdmmc_task: write block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); + uint32_t block; + //uint32_t *tmpbuf; + + // Init Mode Register + WR4(sc, MCI_MR, sc->cards[0].mode | (sc->cards[0].sector_size << 16)); + // printf("mode 0x%x\n", RD4(sc, MCI_MR)); - // Reset Mode Register - WR4(sc, MCI_MR, sc->cards[0].mode); - biodone(bp); - return; - } - if (bp->bio_cmd == BIO_WRITE) { - //printf("at91_qdmmc_strategy: write block %lld, bcount %ld\n", bp->bio_pblkno, bp->bio_bcount); - uint32_t block; - uint32_t *tmpbuf; + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, (sc->cards[0].addr) << 16); + // printf("at91_qdmmc_task: select_card-status = 0x%x\n", status); + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SET_BLOCKLEN_CMD, sc->cards[0].sector_size); + // printf("at91_qdmmc_task: set_blocklen-status = 0x%x\n", status); - // Init Mode Register - WR4(sc, MCI_MR, sc->cards[0].mode | (sc->cards[0].sector_size << 16)); - // printf("mode 0x%x\n", RD4(sc, MCI_MR)); + //tmpbuf = malloc(sc->cards[0].sector_size, M_DEVBUF, M_WAITOK); + for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sc->cards[0].sector_size); block++) { + char *paddr = bp->bio_data + (block - bp->bio_pblkno) * sc->cards[0].sector_size; - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, (sc->cards[0].addr) << 16); - // printf("at91_qdmmc_strategy: select_card-status = 0x%x\n", status); - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SET_BLOCKLEN_CMD, sc->cards[0].sector_size); - // printf("at91_qdmmc_strategy: set_blocklen-status = 0x%x\n", status); + /* Fix Byteorder (Atmel Errata) */ + uint32_t* base = (uint32_t*)paddr; + for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { + uint32_t tmp = base[i]; + tmpbuf[i] = (((tmp >> 24) & 0xff)) | + (((tmp >> 16) & 0xff) << 8) | + (((tmp >> 8) & 0xff) << 16) | + ((tmp & 0xff) << 24); + } - tmpbuf = malloc(sc->cards[0].sector_size, M_DEVBUF, M_WAITOK); - for (block = bp->bio_pblkno; block < bp->bio_pblkno + (bp->bio_bcount / sc->cards[0].sector_size); block++) { - char *paddr = bp->bio_data + (block - bp->bio_pblkno) * sc->cards[0].sector_size; + WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); - /* Fix Byteorder (Atmel Errata) */ - uint32_t* base = (uint32_t*)paddr; - for (int i = 0; i < sc->cards[0].sector_size / 4; i++) { - uint32_t tmp = base[i]; - tmpbuf[i] = (((tmp >> 24) & 0xff)) | - (((tmp >> 16) & 0xff) << 8) | - (((tmp >> 8) & 0xff) << 16) | - ((tmp & 0xff) << 24); - } + if (bus_dmamap_load(sc->dmatag, sc->map, tmpbuf, + sc->cards[0].sector_size, at91_getaddr, &addr, 0) != 0) + goto out; + map = 1; - WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS); + bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREWRITE); + WR4(sc, PDC_TPR, addr); + WR4(sc, PDC_TCR, sc->cards[0].sector_size / 4); - if (bus_dmamap_load(sc->dmatag, sc->map, tmpbuf, - sc->cards[0].sector_size, at91_getaddr, &addr, 0) != 0) - goto out; - map = 1; + // printf("status = 0x%x, tmpbuf = %p, TPR = 0x%x, TCR = 0x%x\n", status, tmpbuf, + // RD4(sc, PDC_TPR), RD4(sc, PDC_TCR)); + status = at91_qdmmc_SendCommand(sc->dev, AT91C_WRITE_BLOCK_CMD, block * sc->cards[0].sector_size); + // printf("at91_qdmmc_task: write-status = 0x%x\n", status); + WR4(sc, MCI_IER, MCI_SR_NOTBUSY); + WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREWRITE); - WR4(sc, PDC_TPR, addr); - WR4(sc, PDC_TCR, sc->cards[0].sector_size / 4); + // wait for completion + msleep(sc, &sc->sc_mtx, PRIBIO, "notbusy", 0); + // XXX don't know why this safety check is required + while ((RD4(sc, MCI_SR) & MCI_SR_NOTBUSY) == 0) + DELAY(700); - // printf("status = 0x%x, tmpbuf = %p, TPR = 0x%x, TCR = 0x%x\n", status, tmpbuf, - // RD4(sc, PDC_TPR), RD4(sc, PDC_TCR)); - status = at91_qdmmc_SendCommand(sc->dev, AT91C_WRITE_BLOCK_CMD, block * sc->cards[0].sector_size); - // printf("at91_qdmmc_strategy: write-status = 0x%x\n", status); - WR4(sc, PDC_PTCR, PDC_PTCR_TXTEN); + bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->dmatag, sc->map); + map = 0; + } + //free(tmpbuf, M_DEVBUF); - // wait for completion - // XXX should be done as an ISR of some sort. - while ((RD4(sc, MCI_SR) & MCI_SR_NOTBUSY) == 0) - DELAY(700); + status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, 0); + //printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); - bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->dmatag, sc->map); - map = 0; + // Reset Mode Register + WR4(sc, MCI_MR, sc->cards[0].mode); + biodone(bp); + continue; } - free(tmpbuf, M_DEVBUF); +out: + if (map) + bus_dmamap_unload(sc->dmatag, sc->map); status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, 0); - //printf("at91_qdmmc_strategy: deselect_card-status = 0x%x\n", status); - - // Reset Mode Register - WR4(sc, MCI_MR, sc->cards[0].mode); - biodone(bp); - return; + //printf("at91_qdmmc_task: deselect_card-status = 0x%x\n", status); + AT91_QDMMC_UNLOCK(sc); + biofinish(bp, NULL, ENXIO); } - -out: - if (map) - bus_dmamap_unload(sc->dmatag, sc->map); - status = at91_qdmmc_SendCommand(sc->dev, AT91C_SEL_DESEL_CARD_CMD, 0); - printf("at91_qdmmc_strategy: deselect_card-status = 0x%x\n", status); - biofinish(bp, NULL, ENXIO); - return; } static device_method_t at91_qdmmc_methods[] = { @@ -581,5 +621,11 @@ static void at91_qdmmc_intr(void *arg) { - // TODO + struct at91_qdmmc_softc *sc = (struct at91_qdmmc_softc*)arg; + + AT91_QDMMC_LOCK(sc); + //printf("i 0x%x\n", RD4(sc, MCI_SR)); + wakeup(sc); + WR4(sc, MCI_IDR, 0xffffffff); + AT91_QDMMC_UNLOCK(sc); }