summaryrefslogtreecommitdiff
path: root/sys/arch/wgrisc/dev
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>1997-02-23 21:59:34 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>1997-02-23 21:59:34 +0000
commit428fe47992a7779523cc4d7f505b729b49b8ec7d (patch)
tree6c980a072bd0dd7e5684beaa70b14f0dfd189a20 /sys/arch/wgrisc/dev
parentb5d84b14e4aa07dac44d1522848b7fbaf98bdeca (diff)
First cut of Flash memory disk. Needs more work though...
Diffstat (limited to 'sys/arch/wgrisc/dev')
-rw-r--r--sys/arch/wgrisc/dev/flash.c363
-rw-r--r--sys/arch/wgrisc/dev/flashreg.h112
2 files changed, 475 insertions, 0 deletions
diff --git a/sys/arch/wgrisc/dev/flash.c b/sys/arch/wgrisc/dev/flash.c
new file mode 100644
index 00000000000..89bbf9c7b44
--- /dev/null
+++ b/sys/arch/wgrisc/dev/flash.c
@@ -0,0 +1,363 @@
+/* $OpenBSD: flash.c,v 1.1 1997/02/23 21:59:27 pefo Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Per Fogelstrom for Willowglen Singapore.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/ioctl.h>
+#include <sys/proc.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/buf.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+#include <sys/device.h>
+#include <machine/autoconf.h>
+#include <machine/cpu.h>
+#include <machine/pio.h>
+
+#include <wgrisc/riscbus/riscbus.h>
+#include <wgrisc/dev/flashreg.h>
+#include <wgrisc/wgrisc/wgrisctype.h>
+
+extern int cputype;
+
+void flashattach __P((struct device *, struct device *, void *));
+int flashmatch __P((struct device *, void *, void *));
+
+struct flashtype {
+ char *fl_name;
+ int fl_size;
+ int fl_blksz;
+ u_char fl_manf;
+ u_char fl_type;
+};
+struct flashtype flashlist[] = {
+ { "Samsung KM29N16000", 2097152, 4096, 0xec, 0x64 },
+ { NULL },
+};
+
+struct flashsoftc {
+ struct device sc_dev;
+ int sc_prot;
+ size_t sc_size;
+ int sc_present;
+ struct flashtype *sc_ftype;
+};
+
+struct cfattach flash_ca = {
+ sizeof(struct flashsoftc), flashmatch, flashattach
+};
+struct cfdriver flash_cd = {
+ NULL, "flash", DV_DISK, 0 /* Yes! We want is as root device */
+};
+
+int
+flashmatch(parent, cf, args)
+ struct device *parent;
+ void *cf;
+ void *args;
+{
+ struct confargs *ca = args;
+
+ if(!BUS_MATCHNAME(ca, "flash"))
+ return(0);
+ return(1);
+}
+
+void
+flashattach(parent, self, args)
+ struct device *parent, *self;
+ void *args;
+{
+ struct confargs *ca = args;
+ struct flashsoftc *sc = (struct flashsoftc *)self;
+ struct flashtype *flist;
+ int i, manf, type;
+
+ switch(cputype) {
+ case WGRISC9100: /* WGRISC9100 can have 4 chips */
+ sc->sc_present = 0;
+ sc->sc_ftype = NULL;
+ OUT_FL_CTRL(0, 0); /* All CS lines high */
+ for(i = 0; i < 4; i++) {
+ OUT_FL_CLE(FL_READID, (1 << i));
+ OUT_FL_ALE1(0, (1 << i));
+ manf = IN_FL_DATA;
+ type = IN_FL_DATA;
+ flist = flashlist;
+ while(flist->fl_name != 0) {
+ if(flist->fl_manf == manf &&
+ flist->fl_type == type) {
+ sc->sc_present |= 1 << i;
+ sc->sc_size += flist->fl_size;
+ if(sc->sc_ftype == NULL) {
+ sc->sc_ftype = flist;
+ }
+ else if(sc->sc_ftype == flist) {
+ }
+/* XXX Protection test type dependent ? */
+ OUT_FL_CLE(FL_READSTAT, (1 << i));
+ if(!(IN_FL_DATA & FLST_UNPROT)) {
+ sc->sc_prot = 1;
+ }
+ break;
+ }
+ flist++;
+ }
+ }
+ break;
+
+ default:
+ printf("flash: Unknown cputype '%d'", cputype);
+ }
+ if(sc->sc_ftype != NULL) {
+ printf(" %s, %d*%d bytes%s.", sc->sc_ftype->fl_name,
+ sc->sc_size / sc->sc_ftype->fl_size,
+ sc->sc_ftype->fl_size,
+ sc->sc_prot ? " Write protected" : "");
+ }
+ else {
+ printf("WARNING! Flash type not identified!");
+ }
+ printf("\n");
+}
+
+static int
+flashgetblk(sc, blk, offs, cnt)
+ struct flashsoftc *sc;
+ char *blk;
+ size_t offs;
+ size_t cnt;
+{
+ int chip;
+ int blkadr;
+
+ chip = 1 << (offs / sc->sc_ftype->fl_size);
+ blkadr = offs % sc->sc_ftype->fl_size;
+
+ OUT_FL_CLE(FL_READ1, chip);
+ OUT_FL_ALE3(blkadr, chip);
+ WAIT_FL_RDY;
+ while(cnt--) {
+ *blk++ = IN_FL_DATA;
+ }
+ return(0);
+}
+
+static int
+flashputblk(sc, blk, offs, cnt)
+ struct flashsoftc *sc;
+ char *blk;
+ size_t offs;
+ size_t cnt;
+{
+ int chip;
+ int blkadr;
+
+ chip = 1 << (offs / sc->sc_ftype->fl_size);
+ blkadr = offs % sc->sc_ftype->fl_size;
+
+ OUT_FL_CLE(FL_SEQDI, chip);
+ OUT_FL_ALE3(blkadr, chip);
+ while(cnt--) {
+ OUT_FL_DATA(*blk);
+ blk++;
+ }
+ OUT_FL_CLE(FL_PGPROG, chip);
+ WAIT_FL_RDY;
+ OUT_FL_CLE(FL_READSTAT, chip);
+ if(IN_FL_DATA & FLST_ERROR) {
+ return(-1);
+ }
+ return(0);
+}
+
+static int
+flasheraseblk(sc, offs)
+ struct flashsoftc *sc;
+ size_t offs;
+{
+ int chip;
+ int blkadr;
+
+ chip = 1 << (offs / sc->sc_ftype->fl_size);
+ blkadr = offs % sc->sc_ftype->fl_size;
+
+ OUT_FL_CLE(FL_BLERASE, chip);
+ OUT_FL_ALE2(blkadr, chip);
+ OUT_FL_CLE(FL_REERASE, chip);
+ WAIT_FL_RDY;
+ OUT_FL_CLE(FL_READSTAT, chip);
+ if(IN_FL_DATA & FLST_ERROR) {
+ return(-1);
+ }
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+flashopen(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ if (minor(dev) >= flash_cd.cd_ndevs || flash_cd.cd_devs[minor(dev)] == NULL)
+ return (ENODEV);
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+flashclose(dev, flag, mode, p)
+ dev_t dev;
+ int flag, mode;
+ struct proc *p;
+{
+ return(0);
+}
+
+/*ARGSUSED*/
+int
+flashioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_char *data;
+ int cmd, flag;
+ struct proc *p;
+{
+ int unit = minor(dev);
+ struct flashsoftc *sc = (struct flashsoftc *) flash_cd.cd_devs[unit];
+ int error = 0;
+
+ switch (cmd) {
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return(error);
+}
+
+void
+flashstrategy(bp)
+ struct buf *bp;
+{
+ int unit = minor(bp->b_dev);
+ struct flashsoftc *sc = (struct flashsoftc *) flash_cd.cd_devs[unit];
+ int error = 0;
+ size_t offs, xfer, cnt;
+ caddr_t buf;
+
+ offs = bp->b_blkno << DEV_BSHIFT; /* Start address */
+ buf = bp->b_data;
+ bp->b_resid = bp->b_bcount;
+ if(offs < sc->sc_size) {
+ xfer = bp->b_resid;
+ if(offs + xfer > sc->sc_size) {
+ xfer = sc->sc_size - offs;
+ }
+ if(bp->b_flags & B_READ) {
+ bp->b_resid -= xfer;
+ while(xfer > 0) {
+ cnt = (xfer > 256) ? 256 : xfer;
+ flashgetblk(sc, buf, offs, cnt);
+ xfer -= cnt;
+ offs += cnt;
+ buf += cnt;
+ }
+ }
+ else {
+ while(xfer > 0) {
+ if((offs & (sc->sc_ftype->fl_blksz - 1)) == 0 &&
+ (xfer >= sc->sc_ftype->fl_blksz)) {
+ if(flasheraseblk(sc, offs))
+ error = EIO;
+ }
+ cnt = (xfer > 256) ? 256 : xfer;
+ if(flashputblk(sc, buf, offs, cnt))
+ error = EIO;
+ xfer -= cnt;
+ buf += cnt;
+ offs += cnt;
+ bp->b_resid -= cnt;
+ }
+ }
+ }
+ else if(!(bp->b_flags & B_READ)) { /* No space for write */
+ error = EIO;
+ }
+ if(error) {
+ bp->b_error = error;
+ bp->b_flags |= B_ERROR;
+ }
+
+ biodone(bp);
+}
+
+/*ARGSUSED*/
+int
+flashread(dev, uio, ioflag)
+ dev_t dev;
+ struct uio *uio;
+ int ioflag;
+{
+ return (physio(flashstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+/*ARGSUSED*/
+int
+flashwrite(dev, uio, ioflag)
+ dev_t dev;
+ struct uio *uio;
+ int ioflag;
+{
+ return (physio(flashstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+int
+flashdump(dev, blkno, va, size)
+ dev_t dev;
+ daddr_t blkno;
+ caddr_t va;
+ size_t size;
+{
+ return(ENODEV);
+}
+
+int
+flashsize(dev)
+ dev_t dev;
+{
+ return(0);
+}
diff --git a/sys/arch/wgrisc/dev/flashreg.h b/sys/arch/wgrisc/dev/flashreg.h
new file mode 100644
index 00000000000..d06eb7688ef
--- /dev/null
+++ b/sys/arch/wgrisc/dev/flashreg.h
@@ -0,0 +1,112 @@
+/* $OpenBSD: flashreg.h,v 1.1 1997/02/23 21:59:28 pefo Exp $ */
+
+/*
+ * Copyright (c) 1997 Per Fogelstrom
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Per Fogelstrom for Willowglen Singapore.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Definitions for the Samsung KM29N16000 2M/8 NAND Flash Memory.
+ */
+
+/* Commands */
+
+#define FL_SEQDI 0x80 /* Sequential data input */
+#define FL_READ1 0x00 /* Read 1 (normal read */
+#define FL_READ2 0x50 /* Read 2 (extended read */
+#define FL_READID 0x90 /* Read chip id */
+#define FL_RESET 0xff /* Chip control reset */
+#define FL_PGPROG 0x10 /* Page program */
+#define FL_BLERASE 0x60 /* Block erase */
+#define FL_SUERASE 0xb0 /* Suspend erase */
+#define FL_REERASE 0xd0 /* Resume erase */
+#define FL_READSTAT 0x70 /* Read status */
+#define FL_READREG 0xe0 /* Read register */
+
+/* Status */
+#define FLST_ERROR 0x01 /* Error in Program/Erase */
+#define FLST_ESUSP 0x20 /* Erase suspended */
+#define FLST_RDY 0x40 /* Ready */
+#define FLST_UNPROT 0x80 /* Memory not wr protected */
+
+/* Handy macros */
+#define FLC_ALE 0x80 /* Control reg ALE bit */
+#define FLC_CLE 0x40 /* Control reg CLE bit */
+#define FLC_NCS 0x3f /* CS bits */
+
+#define WAIT_FL_RDY \
+ while((inb(RISC_STATUS) & 0x10) == 0)
+
+#define OUT_FL_CTRL(x, cs) \
+ do { \
+ outb(RISC_FLASH_CTRL, (x) | (FLC_NCS ^ (cs))); \
+ wbflush(); \
+ } while(0)
+
+#define OUT_FL_DATA(x) \
+ outb(RISC_FLASH_WRITE, (x))
+
+#define IN_FL_DATA \
+ inb(RISC_FLASH_READ)
+
+#define OUT_FL_CLE(cmd, cs) \
+ do { \
+ OUT_FL_CTRL(FLC_CLE, (cs)); \
+ OUT_FL_DATA(cmd); \
+ OUT_FL_CTRL(0, cs); \
+ } while(0);
+
+#define OUT_FL_ALE1(addr, cs) \
+ do { \
+ register int _a = addr; \
+ OUT_FL_CTRL(FLC_ALE, (cs)); \
+ OUT_FL_DATA(_a); \
+ OUT_FL_CTRL(0, cs); \
+ } while(0);
+
+#define OUT_FL_ALE2(addr, cs) \
+ do { \
+ register int _a = addr; \
+ OUT_FL_CTRL(FLC_ALE, (cs)); \
+ OUT_FL_DATA(_a >> 8); \
+ OUT_FL_DATA(_a >> 16); \
+ OUT_FL_CTRL(0, cs); \
+ } while(0);
+
+#define OUT_FL_ALE3(addr, cs) \
+ do { \
+ register int _a = addr; \
+ OUT_FL_CTRL(FLC_ALE, (cs)); \
+ OUT_FL_DATA(_a); \
+ OUT_FL_DATA(_a >> 8); \
+ OUT_FL_DATA(_a >> 16); \
+ OUT_FL_CTRL(0, cs); \
+ } while(0);
+