diff options
author | Poul-Henning Kamp <phk@FreeBSD.org> | 1999-08-06 15:59:07 +0000 |
---|---|---|
committer | Poul-Henning Kamp <phk@FreeBSD.org> | 1999-08-06 15:59:07 +0000 |
commit | d4ebee28d2226a6174bc6c9e27ae30bc0924cef2 (patch) | |
tree | cd6d5ab9b34b5062183a16e52df863cfc96985e7 /sys/contrib/dev/fla/fla.c | |
parent | dc031cf5c2daaf42f5b003c57ec7b90789aba8f3 (diff) | |
download | src-d4ebee28d2226a6174bc6c9e27ae30bc0924cef2.tar.gz src-d4ebee28d2226a6174bc6c9e27ae30bc0924cef2.zip |
Add driver support for M-systems DiskOnChip Products.
Sponsored by: M-systems Inc. http://www.m-sys.com
Notes
Notes:
svn path=/head/; revision=49467
Diffstat (limited to 'sys/contrib/dev/fla/fla.c')
-rw-r--r-- | sys/contrib/dev/fla/fla.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/sys/contrib/dev/fla/fla.c b/sys/contrib/dev/fla/fla.c new file mode 100644 index 000000000000..052a994aab09 --- /dev/null +++ b/sys/contrib/dev/fla/fla.c @@ -0,0 +1,451 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id: fla.c,v 1.3 1999/08/06 15:22:09 phk Exp $ + * + */ + +#include "fla.h" +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sysctl.h> +#include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/disklabel.h> +#include <sys/diskslice.h> +#include <sys/module.h> +#include <sys/conf.h> +#include <machine/bus.h> +#include <machine/clock.h> +#include <machine/resource.h> + +#include <vm/vm.h> +#include <vm/pmap.h> +#include <vm/vm_param.h> + +#if __FreeBSD_version > 400000 /* XXX ? */ +#include <sys/bus.h> +#include <isa/isareg.h> +#include <isa/isavar.h> + +#define dev2ul(foo) ((unsigned long)dev2udev(foo)) +#endif + +#if __FreeBSD_version < 400000 /* XXX ? */ +#include <i386/isa/isa_device.h> + +#define dev2ul(foo) ((unsigned long)foo) + +static int +physread(dev_t dev, struct uio *uio, int ioflag) +{ + return(physio(cdevsw[major(dev)]->d_strategy, + NULL, dev, 1, minphys, uio)); +} + +static int +physwrite(dev_t dev, struct uio *uio, int ioflag) +{ + return(physio(cdevsw[major(dev)]->d_strategy, + NULL, dev, 0, minphys, uio)); +} + +#define nopoll seltrue +#define noparms NULL +#endif + +#include <../../contrib/dev/fla/msysosak.h> + +MALLOC_DEFINE(M_FLA, "fla driver", "fla driver storage"); + +static int fla_debug = 0; +SYSCTL_INT(_debug, OID_AUTO, fladebug, CTLFLAG_RW, &fla_debug, 0, ""); + +#define CDEV_MAJOR 102 +#define BDEV_MAJOR 28 + +static d_strategy_t flastrategy; +static d_open_t flaopen; +static d_close_t flaclose; +static d_ioctl_t flaioctl; +static d_psize_t flapsize; + +static struct cdevsw fla_cdevsw = { + /* open */ flaopen, + /* close */ flaclose, + /* read */ physread, + /* write */ physwrite, + /* ioctl */ flaioctl, + /* stop */ nostop, + /* reset */ noreset, + /* devtotty */ nodevtotty, + /* poll */ nopoll, + /* mmap */ nommap, + /* strategy */ flastrategy, + /* name */ "fla", + /* parms */ noparms, + /* maj */ CDEV_MAJOR, + /* dump */ nodump, + /* psize */ flapsize, + /* flags */ D_DISK | D_CANFREE, + /* maxio */ 0, + /* bmaj */ BDEV_MAJOR +}; + + + +void * +doc2k_malloc(int bytes) +{ + return malloc(bytes, M_FLA, M_WAITOK); +} + +void +doc2k_free(void *ptr) +{ + free(ptr, M_FLA); +} + +void +doc2k_delay(unsigned msec) +{ + DELAY(1000 * msec); +} + +void +doc2k_memcpy(void *dst, const void *src, unsigned len) +{ + bcopy(src, dst, len); +} + +int +doc2k_memcmp(const void *dst, const void *src, unsigned len) +{ + return (bcmp(src, dst, len)); +} + +void +doc2k_memset(void *dst, int c, unsigned len) +{ + u_char *p = dst; + while (len--) + *p++ = c; +} + +static struct fla_s { + unsigned nsect; + struct doc2k_stat ds; + struct diskslices *dk_slices; + struct buf_queue_head buf_queue; +} softc[NFLA]; + +static int +flaopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit; + struct fla_s *sc; + int error; + struct disklabel dk_dd; + + if (fla_debug) + printf("flaopen(%lx %x %x %p)\n", + dev2ul(dev), flag, fmt, p); + unit = dkunit(dev); + if (unit >= NFLA) + return (ENXIO); + sc = &softc[unit]; + if (!sc->nsect) + return (ENXIO); + bzero(&dk_dd, sizeof(dk_dd)); + error = doc2k_size(unit, &dk_dd.d_secperunit, + &dk_dd.d_ncylinders, &dk_dd.d_ntracks, &dk_dd.d_nsectors); + dk_dd.d_secsize = DEV_BSIZE; + dk_dd.d_secpercyl = dk_dd.d_ntracks * dk_dd.d_nsectors; + + error = dsopen("fla", dev, fmt, 0, &sc->dk_slices, &dk_dd, + flastrategy, NULL, &fla_cdevsw); + return (error); +} + +static int +flaclose(dev_t dev, int flags, int fmt, struct proc *p) +{ + int unit; + struct fla_s *sc; + + if (fla_debug) + printf("flaclose(%lx %x %x %p)\n", + dev2ul(dev), flags, fmt, p); + unit = dkunit(dev); + sc = &softc[unit]; + dsclose(dev, fmt, sc->dk_slices); + return (0); +} + +static int +flaioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p) +{ + int unit, error; + struct fla_s *sc; + + if (fla_debug) + printf("flaioctl(%lx %lx %p %x %p)\n", + dev2ul(dev), cmd, addr, flags, p); + unit = dkunit(dev); + sc = &softc[unit]; + error = dsioctl("fla", dev, cmd, addr, flags, &sc->dk_slices, + flastrategy, NULL); + if (error == ENOIOCTL) + error = ENOTTY; + return (error); +} + +static void +flastrategy(struct buf *bp) +{ + int unit, error; + u_long ef; + struct fla_s *sc; + static int busy; + enum doc2k_work what; + + if (fla_debug) + printf("flastrategy(%p) %lx %lx, %d, %ld, %p)\n", + bp, dev2ul(bp->b_dev), bp->b_flags, bp->b_blkno, + bp->b_bcount / DEV_BSIZE, bp->b_data); + unit = dkunit(bp->b_dev); + sc = &softc[unit]; + + if (dscheck(bp, sc->dk_slices) <= 0) { + biodone(bp); + return; + } + + ef = read_eflags(); + disable_intr(); + + bufqdisksort(&sc->buf_queue, bp); + + if (busy) { + write_eflags(ef); + return; + } + + busy++; + + while (1) { + bp = bufq_first(&sc->buf_queue); + if (bp) + bufq_remove(&sc->buf_queue, bp); + + write_eflags(ef); + if (!bp) + break; + + bp->b_resid = bp->b_bcount; + unit = dkunit(bp->b_dev); + + if (bp->b_flags & B_FREEBUF) + what = DOC2K_ERASE; + else if (bp->b_flags & B_READ) + what = DOC2K_READ; + else + what = DOC2K_WRITE; + + error = doc2k_rwe( unit, what, bp->b_pblkno, + bp->b_bcount / DEV_BSIZE, bp->b_data); + + if (fla_debug || error) { + printf("fla%d: %d = rwe(%p, %d, %d, %d, %ld, %p)\n", + unit, error, bp, unit, what, bp->b_pblkno, + bp->b_bcount / DEV_BSIZE, bp->b_data); + } + if (error) { + bp->b_error = EIO; + bp->b_flags |= B_ERROR; + } else { + bp->b_resid = 0; + } + biodone(bp); + + ef = read_eflags(); + disable_intr(); + } + busy = 0; + return; +} + +static int +flapsize(dev_t dev) +{ + int unit; + struct fla_s *sc; + + if (fla_debug) + printf("flapsize(%lx)\n", dev2ul(dev)); + unit = dkunit(dev); + sc = &softc[unit]; + if (!sc->nsect) + return 0; + + return (dssize(dev, &sc->dk_slices, flaopen, flaclose)); +} + +static int +flarealprobe(int unit) +{ + struct fla_s *sc; + int i; + + sc = &softc[unit]; + + /* This is slightly ugly */ + i = doc2k_probe(unit, KERNBASE + 0xc0000, KERNBASE + 0xe0000); + if (i) + return (ENXIO); + + i = doc2k_info(unit, &sc->ds); + if (i) + return (ENXIO); + + return (0); +} + + +static int +flarealattach(int unit) +{ + int i, j, k, l, m, error; + struct fla_s *sc; + + sc = &softc[unit]; + + error = doc2k_open(unit); + if (error) { + printf("doc2k_open(%d) -> err %d\n", unit, error); + return (EIO); + } + + error = doc2k_size(unit, &sc->nsect, &i, &j, &k ); + if (error) { + printf("doc2k_size(%d) -> err %d\n", unit, error); + return (EIO); + } + + printf("fla%d: <%s %s>\n", unit, sc->ds.product, sc->ds.model); + + m = 1024L * 1024L / DEV_BSIZE; + l = (sc->nsect * 10 + m/2) / m; + printf("fla%d: %d.%01dMB (%u sectors)," + " %d cyls, %d heads, %d S/T, 512 B/S\n", + unit, l / 10, l % 10, sc->nsect, i, j, k); + + if (bootverbose) + printf("fla%d: JEDEC=0x%x unitsize=%ld mediasize=%ld" + " chipsize=%ld interleave=%d window=%lx\n", + unit, sc->ds.type, sc->ds.unitSize, sc->ds.mediaSize, + sc->ds.chipSize, sc->ds.interleaving, sc->ds.window); + + bufq_init(&sc->buf_queue); + + return (0); +} + + +#if __FreeBSD_version > 400000 /* XXX ? */ + +static int +flaprobe (device_t dev) +{ + int unit; + struct fla_s *sc; + device_t bus; + int i; + + unit = device_get_unit(dev); + sc = &softc[unit]; + i = flarealprobe(unit); + if (i) + return (i); + + bus = device_get_parent(dev); + ISA_SET_RESOURCE(bus, dev, SYS_RES_MEMORY, 0, + sc->ds.window - KERNBASE, 8192); + + return (0); +} + + +static int +flaattach (device_t dev) +{ + int unit, i; + + unit = device_get_unit(dev); + i = flarealattach(unit); + return (i); +} + +static device_method_t fla_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, flaprobe), + DEVMETHOD(device_attach, flaattach), + {0, 0} +}; + +static driver_t fladriver = { + "fla", + fla_methods, + sizeof(struct fla_s), +}; + +static devclass_t fla_devclass; + +DEV_DRIVER_MODULE(fla, isa, fladriver, fla_devclass, fla_cdevsw, 0, 0); +#endif + + +#if __FreeBSD_version < 400000 /* XXX ? */ + +static int +flaprobe (struct isa_device *dvp) +{ + int unit; + struct fla_s *sc; + int i; + + unit = dvp->id_unit; + sc = &softc[unit]; + i = flarealprobe(unit); + if (i) + return (0); + + dvp->id_maddr = (caddr_t)sc->ds.window; + dvp->id_msize = 8192; + + cdevsw_add_generic(BDEV_MAJOR, CDEV_MAJOR, &fla_cdevsw); + return (-1); +} + + +static int +flaattach (struct isa_device *dvp) +{ + int unit, i; + + unit = dvp->id_unit; + i = flarealattach(unit); + return (i); +} + +struct isa_driver fladriver = { + flaprobe, flaattach, "fla", +}; + +#endif |