aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/dev/fla/fla.c
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>1999-08-06 15:59:07 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>1999-08-06 15:59:07 +0000
commitd4ebee28d2226a6174bc6c9e27ae30bc0924cef2 (patch)
treecd6d5ab9b34b5062183a16e52df863cfc96985e7 /sys/contrib/dev/fla/fla.c
parentdc031cf5c2daaf42f5b003c57ec7b90789aba8f3 (diff)
downloadsrc-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.c451
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