12c16c8d7SNathan Whitehorn /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
371e3c308SPedro F. Giffuni *
42c16c8d7SNathan Whitehorn * Copyright (c) 2008 Nathan Whitehorn. All rights reserved.
52c16c8d7SNathan Whitehorn *
62c16c8d7SNathan Whitehorn * Redistribution and use in source and binary forms, with or without
72c16c8d7SNathan Whitehorn * modification, are permitted provided that the following conditions
82c16c8d7SNathan Whitehorn * are met:
92c16c8d7SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright
102c16c8d7SNathan Whitehorn * notice, this list of conditions and the following disclaimer.
112c16c8d7SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright
122c16c8d7SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the
132c16c8d7SNathan Whitehorn * documentation and/or other materials provided with the distribution.
142c16c8d7SNathan Whitehorn *
152c16c8d7SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
162c16c8d7SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
172c16c8d7SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
182c16c8d7SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
192c16c8d7SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
202c16c8d7SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
212c16c8d7SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
222c16c8d7SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
232c16c8d7SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
242c16c8d7SNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252c16c8d7SNathan Whitehorn *
262c16c8d7SNathan Whitehorn */
272c16c8d7SNathan Whitehorn
282c16c8d7SNathan Whitehorn #include <sys/param.h>
292c16c8d7SNathan Whitehorn #include <sys/systm.h>
302c16c8d7SNathan Whitehorn #include <sys/bio.h>
312c16c8d7SNathan Whitehorn #include <sys/bus.h>
322c16c8d7SNathan Whitehorn #include <sys/conf.h>
332c16c8d7SNathan Whitehorn #include <sys/kernel.h>
342c16c8d7SNathan Whitehorn #include <sys/kthread.h>
352c16c8d7SNathan Whitehorn #include <sys/lock.h>
362c16c8d7SNathan Whitehorn #include <sys/malloc.h>
372c16c8d7SNathan Whitehorn #include <sys/module.h>
382c16c8d7SNathan Whitehorn #include <sys/mutex.h>
392c16c8d7SNathan Whitehorn #include <geom/geom_disk.h>
402c16c8d7SNathan Whitehorn
412c16c8d7SNathan Whitehorn #include <powerpc/mambo/mambocall.h>
422c16c8d7SNathan Whitehorn
432c16c8d7SNathan Whitehorn struct mambodisk_softc {
442c16c8d7SNathan Whitehorn device_t dev;
452c16c8d7SNathan Whitehorn struct mtx sc_mtx;
462c16c8d7SNathan Whitehorn struct disk *disk;
472c16c8d7SNathan Whitehorn struct proc *p;
482c16c8d7SNathan Whitehorn struct bio_queue_head bio_queue;
492c16c8d7SNathan Whitehorn int running;
502c16c8d7SNathan Whitehorn int maxblocks;
512c16c8d7SNathan Whitehorn };
522c16c8d7SNathan Whitehorn
532c16c8d7SNathan Whitehorn #define MAMBO_DISK_READ 116
542c16c8d7SNathan Whitehorn #define MAMBO_DISK_WRITE 117
552c16c8d7SNathan Whitehorn #define MAMBO_DISK_INFO 118
562c16c8d7SNathan Whitehorn
572c16c8d7SNathan Whitehorn #define MAMBO_INFO_STATUS 1
582c16c8d7SNathan Whitehorn #define MAMBO_INFO_BLKSZ 2
592c16c8d7SNathan Whitehorn #define MAMBO_INFO_DEVSZ 3
602c16c8d7SNathan Whitehorn
612c16c8d7SNathan Whitehorn /* bus entry points */
622c16c8d7SNathan Whitehorn static void mambodisk_identify(driver_t *driver, device_t parent);
632c16c8d7SNathan Whitehorn static int mambodisk_probe(device_t dev);
642c16c8d7SNathan Whitehorn static int mambodisk_attach(device_t dev);
652c16c8d7SNathan Whitehorn
662c16c8d7SNathan Whitehorn /* disk routines */
672c16c8d7SNathan Whitehorn static int mambodisk_open(struct disk *dp);
682c16c8d7SNathan Whitehorn static int mambodisk_close(struct disk *dp);
692c16c8d7SNathan Whitehorn static void mambodisk_strategy(struct bio *bp);
702c16c8d7SNathan Whitehorn static void mambodisk_task(void *arg);
712c16c8d7SNathan Whitehorn
722c16c8d7SNathan Whitehorn #define MBODISK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
732c16c8d7SNathan Whitehorn #define MBODISK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
742c16c8d7SNathan Whitehorn #define MBODISK_LOCK_INIT(_sc) \
752c16c8d7SNathan Whitehorn mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
762c16c8d7SNathan Whitehorn "mambodisk", MTX_DEF)
772c16c8d7SNathan Whitehorn #define MBODISK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
782c16c8d7SNathan Whitehorn #define MBODISK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
792c16c8d7SNathan Whitehorn #define MBODISK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
802c16c8d7SNathan Whitehorn
812c16c8d7SNathan Whitehorn static void
mambodisk_identify(driver_t * driver,device_t parent)822c16c8d7SNathan Whitehorn mambodisk_identify(driver_t *driver, device_t parent)
832c16c8d7SNathan Whitehorn {
842c16c8d7SNathan Whitehorn int i = 0;
852c16c8d7SNathan Whitehorn
862c16c8d7SNathan Whitehorn for (i = 0; mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,i) > 0; i++)
872c16c8d7SNathan Whitehorn BUS_ADD_CHILD(parent,0,"mambodisk",i);
882c16c8d7SNathan Whitehorn }
892c16c8d7SNathan Whitehorn
902c16c8d7SNathan Whitehorn static int
mambodisk_probe(device_t dev)912c16c8d7SNathan Whitehorn mambodisk_probe(device_t dev)
922c16c8d7SNathan Whitehorn {
932c16c8d7SNathan Whitehorn device_set_desc(dev, "Mambo Simulated Block Device");
942c16c8d7SNathan Whitehorn return (0);
952c16c8d7SNathan Whitehorn }
962c16c8d7SNathan Whitehorn
972c16c8d7SNathan Whitehorn static int
mambodisk_attach(device_t dev)982c16c8d7SNathan Whitehorn mambodisk_attach(device_t dev)
992c16c8d7SNathan Whitehorn {
1002c16c8d7SNathan Whitehorn struct mambodisk_softc *sc;
1012c16c8d7SNathan Whitehorn struct disk *d;
1022c16c8d7SNathan Whitehorn intmax_t mb;
1032c16c8d7SNathan Whitehorn char unit;
1042c16c8d7SNathan Whitehorn
1052c16c8d7SNathan Whitehorn sc = device_get_softc(dev);
1062c16c8d7SNathan Whitehorn sc->dev = dev;
1072c16c8d7SNathan Whitehorn MBODISK_LOCK_INIT(sc);
1082c16c8d7SNathan Whitehorn
1092c16c8d7SNathan Whitehorn d = sc->disk = disk_alloc();
1102c16c8d7SNathan Whitehorn d->d_open = mambodisk_open;
1112c16c8d7SNathan Whitehorn d->d_close = mambodisk_close;
1122c16c8d7SNathan Whitehorn d->d_strategy = mambodisk_strategy;
1132c16c8d7SNathan Whitehorn d->d_name = "mambodisk";
1142c16c8d7SNathan Whitehorn d->d_drv1 = sc;
115cd853791SKonstantin Belousov d->d_maxsize = maxphys; /* Maybe ask bridge? */
1162c16c8d7SNathan Whitehorn
1172c16c8d7SNathan Whitehorn d->d_sectorsize = 512;
1182c16c8d7SNathan Whitehorn sc->maxblocks = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_BLKSZ,d->d_unit)
1192c16c8d7SNathan Whitehorn / 512;
1202c16c8d7SNathan Whitehorn
1212c16c8d7SNathan Whitehorn d->d_unit = device_get_unit(dev);
1222c16c8d7SNathan Whitehorn d->d_mediasize = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,d->d_unit)
1232c16c8d7SNathan Whitehorn * 1024ULL; /* Mambo gives size in KB */
1242c16c8d7SNathan Whitehorn
1252c16c8d7SNathan Whitehorn mb = d->d_mediasize >> 20; /* 1MiB == 1 << 20 */
1262c16c8d7SNathan Whitehorn unit = 'M';
1272c16c8d7SNathan Whitehorn if (mb >= 10240) { /* 1GiB = 1024 MiB */
1282c16c8d7SNathan Whitehorn unit = 'G';
1292c16c8d7SNathan Whitehorn mb /= 1024;
1302c16c8d7SNathan Whitehorn }
1312c16c8d7SNathan Whitehorn device_printf(dev, "%ju%cB, %d byte sectors\n", mb, unit,
1322c16c8d7SNathan Whitehorn d->d_sectorsize);
1332c16c8d7SNathan Whitehorn disk_create(d, DISK_VERSION);
1342c16c8d7SNathan Whitehorn bioq_init(&sc->bio_queue);
1352c16c8d7SNathan Whitehorn
1362c16c8d7SNathan Whitehorn sc->running = 1;
1372c16c8d7SNathan Whitehorn kproc_create(&mambodisk_task, sc, &sc->p, 0, 0, "task: mambo hd");
1382c16c8d7SNathan Whitehorn
1392c16c8d7SNathan Whitehorn return (0);
1402c16c8d7SNathan Whitehorn }
1412c16c8d7SNathan Whitehorn
1422c16c8d7SNathan Whitehorn static int
mambodisk_detach(device_t dev)1432c16c8d7SNathan Whitehorn mambodisk_detach(device_t dev)
1442c16c8d7SNathan Whitehorn {
1452c16c8d7SNathan Whitehorn struct mambodisk_softc *sc = device_get_softc(dev);
1462c16c8d7SNathan Whitehorn
1472c16c8d7SNathan Whitehorn /* kill thread */
1482c16c8d7SNathan Whitehorn MBODISK_LOCK(sc);
1492c16c8d7SNathan Whitehorn sc->running = 0;
1502c16c8d7SNathan Whitehorn wakeup(sc);
1512c16c8d7SNathan Whitehorn MBODISK_UNLOCK(sc);
1522c16c8d7SNathan Whitehorn
1532c16c8d7SNathan Whitehorn /* wait for thread to finish. XXX probably want timeout. -sorbo */
1542c16c8d7SNathan Whitehorn MBODISK_LOCK(sc);
1552c16c8d7SNathan Whitehorn while (sc->running != -1)
1562c16c8d7SNathan Whitehorn msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0);
1572c16c8d7SNathan Whitehorn MBODISK_UNLOCK(sc);
1582c16c8d7SNathan Whitehorn
1592c16c8d7SNathan Whitehorn /* kill disk */
1602c16c8d7SNathan Whitehorn disk_destroy(sc->disk);
1612c16c8d7SNathan Whitehorn /* XXX destroy anything in queue */
1622c16c8d7SNathan Whitehorn
1632c16c8d7SNathan Whitehorn MBODISK_LOCK_DESTROY(sc);
1642c16c8d7SNathan Whitehorn
1652c16c8d7SNathan Whitehorn return (0);
1662c16c8d7SNathan Whitehorn }
1672c16c8d7SNathan Whitehorn
1682c16c8d7SNathan Whitehorn static int
mambodisk_open(struct disk * dp)1692c16c8d7SNathan Whitehorn mambodisk_open(struct disk *dp)
1702c16c8d7SNathan Whitehorn {
1712c16c8d7SNathan Whitehorn return (0);
1722c16c8d7SNathan Whitehorn }
1732c16c8d7SNathan Whitehorn
1742c16c8d7SNathan Whitehorn static int
mambodisk_close(struct disk * dp)1752c16c8d7SNathan Whitehorn mambodisk_close(struct disk *dp)
1762c16c8d7SNathan Whitehorn {
1772c16c8d7SNathan Whitehorn return (0);
1782c16c8d7SNathan Whitehorn }
1792c16c8d7SNathan Whitehorn
1802c16c8d7SNathan Whitehorn static void
mambodisk_strategy(struct bio * bp)1812c16c8d7SNathan Whitehorn mambodisk_strategy(struct bio *bp)
1822c16c8d7SNathan Whitehorn {
1832c16c8d7SNathan Whitehorn struct mambodisk_softc *sc;
1842c16c8d7SNathan Whitehorn
1852c16c8d7SNathan Whitehorn sc = (struct mambodisk_softc *)bp->bio_disk->d_drv1;
1862c16c8d7SNathan Whitehorn MBODISK_LOCK(sc);
1872c16c8d7SNathan Whitehorn bioq_disksort(&sc->bio_queue, bp);
1882c16c8d7SNathan Whitehorn wakeup(sc);
1892c16c8d7SNathan Whitehorn MBODISK_UNLOCK(sc);
1902c16c8d7SNathan Whitehorn }
1912c16c8d7SNathan Whitehorn
1922c16c8d7SNathan Whitehorn static void
mambodisk_task(void * arg)1932c16c8d7SNathan Whitehorn mambodisk_task(void *arg)
1942c16c8d7SNathan Whitehorn {
1952c16c8d7SNathan Whitehorn struct mambodisk_softc *sc = (struct mambodisk_softc*)arg;
1962c16c8d7SNathan Whitehorn struct bio *bp;
1972c16c8d7SNathan Whitehorn size_t sz;
1982c16c8d7SNathan Whitehorn int result;
1992c16c8d7SNathan Whitehorn daddr_t block, end;
2002c16c8d7SNathan Whitehorn device_t dev;
2012c16c8d7SNathan Whitehorn u_long unit;
2022c16c8d7SNathan Whitehorn
2032c16c8d7SNathan Whitehorn dev = sc->dev;
2042c16c8d7SNathan Whitehorn unit = device_get_unit(dev);
2052c16c8d7SNathan Whitehorn
2062c16c8d7SNathan Whitehorn while (sc->running) {
2072c16c8d7SNathan Whitehorn MBODISK_LOCK(sc);
2082c16c8d7SNathan Whitehorn do {
2092c16c8d7SNathan Whitehorn bp = bioq_first(&sc->bio_queue);
2102c16c8d7SNathan Whitehorn if (bp == NULL)
2112c16c8d7SNathan Whitehorn msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
2122c16c8d7SNathan Whitehorn } while (bp == NULL && sc->running);
2132c16c8d7SNathan Whitehorn if (bp)
2142c16c8d7SNathan Whitehorn bioq_remove(&sc->bio_queue, bp);
2152c16c8d7SNathan Whitehorn MBODISK_UNLOCK(sc);
2162c16c8d7SNathan Whitehorn if (!sc->running)
2172c16c8d7SNathan Whitehorn break;
2182c16c8d7SNathan Whitehorn sz = sc->disk->d_sectorsize;
2192c16c8d7SNathan Whitehorn end = bp->bio_pblkno + (bp->bio_bcount / sz);
2202c16c8d7SNathan Whitehorn for (block = bp->bio_pblkno; block < end;) {
2212c16c8d7SNathan Whitehorn u_long numblocks;
2222c16c8d7SNathan Whitehorn char *vaddr = bp->bio_data +
2232c16c8d7SNathan Whitehorn (block - bp->bio_pblkno) * sz;
2242c16c8d7SNathan Whitehorn
2252c16c8d7SNathan Whitehorn numblocks = end - block;
2262c16c8d7SNathan Whitehorn if (numblocks > sc->maxblocks)
2272c16c8d7SNathan Whitehorn numblocks = sc->maxblocks;
2282c16c8d7SNathan Whitehorn
2292c16c8d7SNathan Whitehorn if (bp->bio_cmd == BIO_READ) {
2302c16c8d7SNathan Whitehorn result = mambocall(MAMBO_DISK_READ, vaddr,
2312c16c8d7SNathan Whitehorn (u_long)block, (numblocks << 16) | unit);
2322c16c8d7SNathan Whitehorn } else if (bp->bio_cmd == BIO_WRITE) {
2332c16c8d7SNathan Whitehorn result = mambocall(MAMBO_DISK_WRITE, vaddr,
2342c16c8d7SNathan Whitehorn (u_long)block, (numblocks << 16) | unit);
2352c16c8d7SNathan Whitehorn } else {
2362c16c8d7SNathan Whitehorn result = 1;
2372c16c8d7SNathan Whitehorn }
2382c16c8d7SNathan Whitehorn
2392c16c8d7SNathan Whitehorn if (result)
2402c16c8d7SNathan Whitehorn break;
2412c16c8d7SNathan Whitehorn
2422c16c8d7SNathan Whitehorn block += numblocks;
2432c16c8d7SNathan Whitehorn }
2442c16c8d7SNathan Whitehorn if (block < end) {
2452c16c8d7SNathan Whitehorn bp->bio_error = EIO;
2462c16c8d7SNathan Whitehorn bp->bio_resid = (end - block) * sz;
2472c16c8d7SNathan Whitehorn bp->bio_flags |= BIO_ERROR;
2482c16c8d7SNathan Whitehorn }
2492c16c8d7SNathan Whitehorn biodone(bp);
2502c16c8d7SNathan Whitehorn }
2512c16c8d7SNathan Whitehorn
2522c16c8d7SNathan Whitehorn /* tell parent we're done */
2532c16c8d7SNathan Whitehorn MBODISK_LOCK(sc);
2542c16c8d7SNathan Whitehorn sc->running = -1;
2552c16c8d7SNathan Whitehorn wakeup(sc);
2562c16c8d7SNathan Whitehorn MBODISK_UNLOCK(sc);
2572c16c8d7SNathan Whitehorn
2582c16c8d7SNathan Whitehorn kproc_exit(0);
2592c16c8d7SNathan Whitehorn }
2602c16c8d7SNathan Whitehorn
2612c16c8d7SNathan Whitehorn static device_method_t mambodisk_methods[] = {
2622c16c8d7SNathan Whitehorn DEVMETHOD(device_identify, mambodisk_identify),
2632c16c8d7SNathan Whitehorn DEVMETHOD(device_probe, mambodisk_probe),
2642c16c8d7SNathan Whitehorn DEVMETHOD(device_attach, mambodisk_attach),
2652c16c8d7SNathan Whitehorn DEVMETHOD(device_detach, mambodisk_detach),
2662c16c8d7SNathan Whitehorn {0, 0},
2672c16c8d7SNathan Whitehorn };
2682c16c8d7SNathan Whitehorn
2692c16c8d7SNathan Whitehorn static driver_t mambodisk_driver = {
2702c16c8d7SNathan Whitehorn "mambodisk",
2712c16c8d7SNathan Whitehorn mambodisk_methods,
2722c16c8d7SNathan Whitehorn sizeof(struct mambodisk_softc),
2732c16c8d7SNathan Whitehorn };
2742c16c8d7SNathan Whitehorn
275f6a99df5SJohn Baldwin DRIVER_MODULE(mambodisk, mambo, mambodisk_driver, 0, 0);
276