diff options
author | 2020-01-24 03:01:11 +0000 | |
---|---|---|
committer | 2020-01-24 03:01:11 +0000 | |
commit | 30f926875e3213d675ac2d172c92bb37636eb5fd (patch) | |
tree | d35835817b3736ee5fcc5f7e0df58db98540e302 /sys/dev/flash.c | |
parent | Nuke references to zaurus zombies. (diff) | |
download | wireguard-openbsd-30f926875e3213d675ac2d172c92bb37636eb5fd.tar.xz wireguard-openbsd-30f926875e3213d675ac2d172c92bb37636eb5fd.zip |
Double tap the actual Zaurus zombies.
ok tedu@ jsg@
Diffstat (limited to 'sys/dev/flash.c')
-rw-r--r-- | sys/dev/flash.c | 1062 |
1 files changed, 0 insertions, 1062 deletions
diff --git a/sys/dev/flash.c b/sys/dev/flash.c deleted file mode 100644 index e0069a5c130..00000000000 --- a/sys/dev/flash.c +++ /dev/null @@ -1,1062 +0,0 @@ -/* $OpenBSD: flash.c,v 1.32 2017/05/04 22:47:27 deraadt Exp $ */ - -/* - * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <sys/param.h> -#include <sys/buf.h> -#include <sys/conf.h> -#include <sys/device.h> -#include <sys/disk.h> -#include <sys/disklabel.h> -#include <sys/dkio.h> -#include <sys/kernel.h> -#include <sys/stat.h> -#include <sys/systm.h> - -#include <dev/flashvar.h> - -#include <ufs/ffs/fs.h> /* XXX */ - -/* Samsung command set */ -#define SAMSUNG_CMD_PTRLO 0x00 -#define SAMSUNG_CMD_PTRHI 0x01 -#define SAMSUNG_CMD_PTROOB 0x50 -#define SAMSUNG_CMD_READ 0x30 -#define SAMSUNG_CMD_SEQIN 0x80 -#define SAMSUNG_CMD_WRITE 0x10 -#define SAMSUNG_CMD_ERASE0 0x60 -#define SAMSUNG_CMD_ERASE1 0xd0 -#define SAMSUNG_CMD_STATUS 0x70 -#define STATUS_FAIL (1<<0) -#define STATUS_READY (1<<6) -#define STATUS_NWP (1<<7) -#define SAMSUNG_CMD_READID 0x90 -#define SAMSUNG_CMD_RESET 0xff - -int flash_wait_ready(struct flash_softc *); -int flash_wait_complete(struct flash_softc *); - -/* XXX: these should go elsewhere */ -cdev_decl(flash); -bdev_decl(flash); - -#define flashlookup(unit) \ - (struct flash_softc *)device_lookup(&flash_cd, (unit)) - -void flashminphys(struct buf *); -void flashstart(struct flash_softc *); -void _flashstart(struct flash_softc *, struct buf *); -void flashdone(void *); - -int flashsafestrategy(struct flash_softc *, struct buf *); -void flashgetdefaultlabel(dev_t, struct flash_softc *, - struct disklabel *); -int flashgetdisklabel(dev_t, struct flash_softc *, struct disklabel *, int); - -/* - * Driver attachment glue - */ - -struct flashvendor { - u_int8_t vendor; - const char *name; -}; - -static const struct flashvendor flashvendors[] = { - { FLASH_VENDOR_SAMSUNG, "Samsung" } -}; -#define FLASH_NVENDORS (sizeof(flashvendors) / sizeof(flashvendors[0])) - -static const struct flashdev flashdevs[] = { - { FLASH_DEVICE_SAMSUNG_K9F2808U0C, "K9F2808U0C 16Mx8 3.3V", - 512, 16, 32, 32768 }, - { FLASH_DEVICE_SAMSUNG_K9F1G08U0A, "K9F1G08U0A 128Mx8 3.3V", - 2048, 64, 64, 65536 }, -}; -#define FLASH_NDEVS (sizeof(flashdevs) / sizeof(flashdevs[0])) - -struct cfdriver flash_cd = { - NULL, "flash", DV_DISK -}; - -void -flashattach(struct flash_softc *sc, struct flash_ctl_tag *tag, - void *cookie) -{ - u_int8_t vendor, device; - u_int16_t id; - int i; - - sc->sc_tag = tag; - sc->sc_cookie = cookie; - - if (sc->sc_maxwaitready <= 0) - sc->sc_maxwaitready = 1000; /* 1ms */ - if (sc->sc_maxwaitcomplete <= 0) - sc->sc_maxwaitcomplete = 200000; /* 200ms */ - - flash_chip_enable(sc); - - /* Identify the flash device. */ - if (flash_chip_identify(sc, &vendor, &device) != 0) { - printf(": identification failed\n"); - flash_chip_disable(sc); - return; - } - id = (vendor << 8) | device; - - /* Look up device characteristics, abort if not recognized. */ - for (i = 0; i < FLASH_NVENDORS; i++) { - if (flashvendors[i].vendor == vendor) { - printf(": %s", flashvendors[i].name); - break; - } - } - if (i == FLASH_NVENDORS) - printf(": vendor 0x%02x", vendor); - for (i = 0; i < FLASH_NDEVS; i++) { - if (flashdevs[i].id == id) { - printf(" %s\n", flashdevs[i].longname); - break; - } - } - if (i == FLASH_NDEVS) { - /* Need to add this device to flashdevs first. */ - printf(" device 0x%02x\n", device); - flash_chip_disable(sc); - return; - } - sc->sc_flashdev = &flashdevs[i]; - - /* Check if the device really works or fail early. */ - if (flash_chip_reset(sc) != 0) { - printf("%s: reset failed\n", sc->sc_dev.dv_xname); - flash_chip_disable(sc); - return; - } - - flash_chip_disable(sc); - - /* - * Initialize and attach the disk structure. - */ - sc->sc_dk.dk_name = sc->sc_dev.dv_xname; - bufq_init(&sc->sc_bufq, BUFQ_FIFO); - disk_attach(&sc->sc_dev, &sc->sc_dk); - - /* XXX establish shutdown hook to finish any commands. */ -} - -int -flashdetach(struct device *self, int flags) -{ - struct flash_softc *sc = (struct flash_softc *)self; - - /* Detach disk. */ - disk_detach(&sc->sc_dk); - - /* XXX more resources need to be freed here. */ - return 0; -} - -/* - * Flash controller and chip functions - */ - -u_int8_t -flash_reg8_read(struct flash_softc *sc, int reg) -{ - return sc->sc_tag->reg8_read(sc->sc_cookie, reg); -} - -void -flash_reg8_read_page(struct flash_softc *sc, caddr_t data, caddr_t oob) -{ - int i; - - for (i = 0; i < sc->sc_flashdev->pagesize; i++) - data[i] = flash_reg8_read(sc, FLASH_REG_DATA); - - if (oob != NULL) - for (i = 0; i < sc->sc_flashdev->oobsize; i++) - oob[i] = flash_reg8_read(sc, FLASH_REG_DATA); -} - -void -flash_reg8_write(struct flash_softc *sc, int reg, u_int8_t value) -{ - sc->sc_tag->reg8_write(sc->sc_cookie, reg, value); -} - -void -flash_reg8_write_page(struct flash_softc *sc, caddr_t data, caddr_t oob) -{ - int i; - - for (i = 0; i < sc->sc_flashdev->pagesize; i++) - flash_reg8_write(sc, FLASH_REG_DATA, data[i]); - - if (oob != NULL) - for (i = 0; i < sc->sc_flashdev->oobsize; i++) - flash_reg8_write(sc, FLASH_REG_DATA, oob[i]); -} - -/* - * Wait for the "Ready/Busy" signal to go high, indicating that the - * device is ready to accept another command. - */ -int -flash_wait_ready(struct flash_softc *sc) -{ - int timo = sc->sc_maxwaitready; - u_int8_t ready; - - ready = flash_reg8_read(sc, FLASH_REG_READY); - while (ready == 0 && timo-- > 0) { - delay(1); - ready = flash_reg8_read(sc, FLASH_REG_READY); - } - return (ready == 0 ? EIO : 0); -} - -/* - * Similar to flash_wait_ready() but looks at IO 6 and IO 0 signals - * besides R/B to decide whether the last operation was successful. - */ -int -flash_wait_complete(struct flash_softc *sc) -{ - int timo = sc->sc_maxwaitcomplete; - u_int8_t status; - - (void)flash_wait_ready(sc); - - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_STATUS); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - - status = flash_reg8_read(sc, FLASH_REG_DATA); - while ((status & STATUS_READY) == 0 && timo-- > 0) { - if (flash_reg8_read(sc, FLASH_REG_READY)) - break; - delay(1); - status = flash_reg8_read(sc, FLASH_REG_DATA); - } - - status = flash_reg8_read(sc, FLASH_REG_DATA); - return ((status & STATUS_FAIL) != 0 ? EIO : 0); -} - -void -flash_chip_enable(struct flash_softc *sc) -{ - /* XXX aquire the lock. */ - flash_reg8_write(sc, FLASH_REG_CE, 1); -} - -void -flash_chip_disable(struct flash_softc *sc) -{ - flash_reg8_write(sc, FLASH_REG_CE, 0); - /* XXX release the lock. */ -} - -int -flash_chip_reset(struct flash_softc *sc) -{ - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_RESET); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - - return flash_wait_ready(sc); -} - -int -flash_chip_identify(struct flash_softc *sc, u_int8_t *vendor, - u_int8_t *device) -{ - int error; - - (void)flash_wait_ready(sc); - - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READID); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - - error = flash_wait_ready(sc); - if (error == 0) { - *vendor = flash_reg8_read(sc, FLASH_REG_DATA); - *device = flash_reg8_read(sc, FLASH_REG_DATA); - } - return error; -} - -int -flash_chip_erase_block(struct flash_softc *sc, long blkno) -{ - long pageno = blkno * sc->sc_flashdev->blkpages; - int error; - - (void)flash_wait_ready(sc); - - /* Disable write-protection. */ - flash_reg8_write(sc, FLASH_REG_WP, 0); - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_ERASE0); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_ROW, pageno); - flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_ERASE1); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - error = flash_wait_complete(sc); - - /* Re-enable write-protection. */ - flash_reg8_write(sc, FLASH_REG_WP, 1); - - return error; -} - -int -flash_chip_read_block(struct flash_softc *sc, long blkno, caddr_t data) -{ - long pageno; - long blkend; - int error; - - pageno = blkno * sc->sc_flashdev->blkpages; - blkend = pageno + sc->sc_flashdev->blkpages; - - while (pageno < blkend) { - error = flash_chip_read_page(sc, pageno, data, NULL); - if (error != 0) - return error; - data += sc->sc_flashdev->pagesize; - pageno++; - } - return 0; -} - -int -flash_chip_read_page(struct flash_softc *sc, long pageno, caddr_t data, - caddr_t oob) -{ - int error; - - (void)flash_wait_ready(sc); - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_ROW, pageno); - flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READ); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - if ((error = flash_wait_ready(sc)) != 0) - return error; - - /* Support hardware ECC calculation. */ - if (sc->sc_tag->regx_read_page) { - error = sc->sc_tag->regx_read_page(sc->sc_cookie, data, - oob); - if (error != 0) - return error; - } else - flash_reg8_read_page(sc, data, oob); - - return 0; -} - -int -flash_chip_read_oob(struct flash_softc *sc, long pageno, caddr_t oob) -{ - u_int8_t *p = (u_int8_t *)oob; - int error; - int i; - - (void)flash_wait_ready(sc); - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTROOB); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_COL, 0x08); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_ROW, pageno); - flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READ); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - if ((error = flash_wait_ready(sc)) != 0) - return error; - - for (i = 0; i < sc->sc_flashdev->oobsize; i++) - p[i] = flash_reg8_read(sc, FLASH_REG_DATA); - - return 0; -} - -int -flash_chip_write_block(struct flash_softc *sc, long blkno, caddr_t data, - caddr_t oob) -{ - long pageno; - long blkend; - caddr_t p; - int error; - - pageno = blkno * sc->sc_flashdev->blkpages; - blkend = pageno + sc->sc_flashdev->blkpages; - - p = data; - while (pageno < blkend) { - error = flash_chip_write_page(sc, pageno, p, oob); - if (error != 0) - return error; - p += sc->sc_flashdev->pagesize; - pageno++; - } - - /* Verify the newly written block. */ - return flash_chip_verify_block(sc, blkno, data, oob); -} - -int -flash_chip_write_page(struct flash_softc *sc, long pageno, caddr_t data, - caddr_t oob) -{ - int error; - - (void)flash_wait_ready(sc); - - /* Disable write-protection. */ - flash_reg8_write(sc, FLASH_REG_WP, 0); - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_SEQIN); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_COL, 0x00); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_ALE, 1); - flash_reg8_write(sc, FLASH_REG_ROW, pageno); - flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8); - flash_reg8_write(sc, FLASH_REG_ALE, 0); - break; - } - - /* Support hardware ECC calculation. */ - if (sc->sc_tag->regx_write_page) { - error = sc->sc_tag->regx_write_page(sc->sc_cookie, data, - oob); - if (error != 0) - return error; - } else - flash_reg8_write_page(sc, data, oob); - - switch (sc->sc_flashdev->id) { - case FLASH_DEVICE_SAMSUNG_K9F2808U0C: - case FLASH_DEVICE_SAMSUNG_K9F1G08U0A: - flash_reg8_write(sc, FLASH_REG_CLE, 1); - flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_WRITE); - flash_reg8_write(sc, FLASH_REG_CLE, 0); - break; - } - - /* - * Wait for the write operation to complete although this can - * take up to 700 us for the K9F1G08U0A flash type. - */ - error = flash_wait_complete(sc); - - /* Re-enable write-protection. */ - flash_reg8_write(sc, FLASH_REG_WP, 1); - - return error; -} - -int -flash_chip_verify_block(struct flash_softc *sc, long blkno, caddr_t data, - caddr_t oob) -{ - long pageno; - long blkend; - int error; - - pageno = blkno * sc->sc_flashdev->blkpages; - blkend = pageno + sc->sc_flashdev->blkpages; - - while (pageno < blkend) { - error = flash_chip_verify_page(sc, pageno, data, oob); - if (error != 0) { - printf("block %ld page %ld verify failed\n", - blkno, pageno); - return error; - } - data += sc->sc_flashdev->pagesize; - pageno++; - } - return 0; -} - -int -flash_chip_verify_page(struct flash_softc *sc, long pageno, caddr_t data, - caddr_t oob) -{ - static u_char rbuf[FLASH_MAXPAGESIZE]; - static u_char roob[FLASH_MAXOOBSIZE]; - int error; - - error = flash_chip_read_page(sc, pageno, rbuf, - oob == NULL ? NULL : roob); - if (error != 0) - return error; - - if (memcmp((const void *)&rbuf[0], (const void *)data, - sc->sc_flashdev->pagesize) != 0) - return EIO; - - if (oob != NULL && memcmp((const void *)&roob[0], - (const void *)oob, sc->sc_flashdev->oobsize) != 0) - return EIO; - - return 0; -} - -/* - * Block device functions - */ - -int -flashopen(dev_t dev, int oflags, int devtype, struct proc *p) -{ - struct flash_softc *sc; - int error; - int part; - - sc = flashlookup(flashunit(dev)); - if (sc == NULL) - return ENXIO; - - if ((error = disk_lock(&sc->sc_dk)) != 0) { - device_unref(&sc->sc_dev); - return error; - } - - /* - * If no partition is open load the partition info if it is - * not already valid. If partitions are already open, allow - * opens only for the same kind of device. - */ - if (sc->sc_dk.dk_openmask == 0) { - if ((sc->sc_flags & FDK_LOADED) == 0 || - ((sc->sc_flags & FDK_SAFE) == 0) != - (flashsafe(dev) == 0)) { - sc->sc_flags &= ~FDK_SAFE; - sc->sc_flags |= FDK_LOADED; - if (flashsafe(dev)) - sc->sc_flags |= FDK_SAFE; - if ((error = flashgetdisklabel(dev, sc, - sc->sc_dk.dk_label, 0)) != 0) { - disk_unlock(&sc->sc_dk); - device_unref(&sc->sc_dev); - return error; - } - } - } else if (((sc->sc_flags & FDK_SAFE) == 0) != - (flashsafe(dev) == 0)) { - disk_unlock(&sc->sc_dk); - device_unref(&sc->sc_dev); - return EBUSY; - } - - /* Check that the partition exists. */ - part = flashpart(dev); - if (part != RAW_PART && - (part >= sc->sc_dk.dk_label->d_npartitions || - sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) { - disk_unlock(&sc->sc_dk); - device_unref(&sc->sc_dev); - return ENXIO; - } - - /* Prevent our unit from being deconfigured while open. */ - switch (devtype) { - case S_IFCHR: - sc->sc_dk.dk_copenmask |= (1 << part); - break; - case S_IFBLK: - sc->sc_dk.dk_bopenmask |= (1 << part); - break; - } - sc->sc_dk.dk_openmask = - sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; - - disk_unlock(&sc->sc_dk); - device_unref(&sc->sc_dev); - return 0; -} - -int -flashclose(dev_t dev, int fflag, int devtype, struct proc *p) -{ - struct flash_softc *sc; - int part; - - sc = flashlookup(flashunit(dev)); - if (sc == NULL) - return ENXIO; - - disk_lock_nointr(&sc->sc_dk); - - /* Close one open partition. */ - part = flashpart(dev); - switch (devtype) { - case S_IFCHR: - sc->sc_dk.dk_copenmask &= ~(1 << part); - break; - case S_IFBLK: - sc->sc_dk.dk_bopenmask &= ~(1 << part); - break; - } - sc->sc_dk.dk_openmask = - sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask; - - if (sc->sc_dk.dk_openmask == 0) { - /* XXX wait for I/O to complete? */ - } - - disk_unlock(&sc->sc_dk); - device_unref(&sc->sc_dev); - return 0; -} - -/* - * Queue the transfer of one or more flash pages. - */ -void -flashstrategy(struct buf *bp) -{ - struct flash_softc *sc; - int s; - - sc = flashlookup(flashunit(bp->b_dev)); - if (sc == NULL) { - bp->b_error = ENXIO; - goto bad; - } - - /* If the device has been invalidated, error out. */ - if ((sc->sc_flags & FDK_LOADED) == 0) { - bp->b_error = EIO; - goto bad; - } - - /* Translate logical block numbers to physical. */ - if (flashsafe(bp->b_dev) && flashsafestrategy(sc, bp) <= 0) { - if (bp->b_flags & B_ERROR) - bp->b_resid = bp->b_bcount; - goto done; - } - - /* Validate the request. */ - if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) - goto done; - - /* Queue the transfer. */ - bufq_queue(&sc->sc_bufq, bp); - - s = splbio(); - flashstart(sc); - splx(s); - - device_unref(&sc->sc_dev); - return; - - bad: - bp->b_flags |= B_ERROR; - bp->b_resid = bp->b_bcount; - done: - s = splbio(); - biodone(bp); - splx(s); - if (sc != NULL) - device_unref(&sc->sc_dev); -} - -int -flashioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p) -{ - struct flash_softc *sc; - int error = 0; - - sc = flashlookup(flashunit(dev)); - if (sc == NULL) - return ENXIO; - - if ((sc->sc_flags & FDK_LOADED) == 0) { - device_unref(&sc->sc_dev); - return EIO; - } - - switch (cmd) { - case DIOCGPDINFO: - flashgetdisklabel(dev, sc, (struct disklabel *)data, 1); - break; - - case DIOCGDINFO: - *(struct disklabel *)data = *sc->sc_dk.dk_label; - break; - - default: - error = ENOTTY; - break; - } - - device_unref(&sc->sc_dev); - return error; -} - -int -flashdump(dev_t dev, daddr_t blkno, caddr_t va, size_t size) -{ - printf("flashdump\n"); - return ENODEV; -} - -daddr_t -flashsize(dev_t dev) -{ - printf("flashsize\n"); - return ENODEV; -} - -void -flashstart(struct flash_softc *sc) -{ - struct buf *bp; - - while ((bp = bufq_dequeue(&sc->sc_bufq)) != NULL) { - /* Transfer this buffer now. */ - _flashstart(sc, bp); - } -} - -void -_flashstart(struct flash_softc *sc, struct buf *bp) -{ - struct disklabel *lp; - int part; - daddr_t offset; - long pgno; - - part = flashpart(bp->b_dev); - - lp = sc->sc_dk.dk_label; - offset = DL_SECTOBLK(lp, DL_GETPOFFSET(&lp->d_partitions[part])) + - bp->b_blkno; - pgno = offset / (sc->sc_flashdev->pagesize / DEV_BSIZE); - - /* - * If the requested page is exactly at the end of flash and it - * is an "unsafe" device, return EOF, else error out. - */ - if (!flashsafe(bp->b_dev) && pgno == sc->sc_flashdev->capacity) { - bp->b_resid = bp->b_bcount; - biodone(bp); - return; - } else if (pgno >= sc->sc_flashdev->capacity) { - bp->b_error = EINVAL; - bp->b_flags |= B_ERROR; - biodone(bp); - return; - } - - sc->sc_bp = bp; - - /* Instrumentation. */ - disk_busy(&sc->sc_dk); - - /* XXX this should be done asynchronously. */ - flash_chip_enable(sc); - if ((bp->b_flags & B_READ) != 0) - bp->b_error = flash_chip_read_page(sc, pgno, bp->b_data, - NULL); - else - bp->b_error = flash_chip_write_page(sc, pgno, bp->b_data, - NULL); - if (bp->b_error == 0) - bp->b_resid = bp->b_bcount - sc->sc_flashdev->pagesize; - flash_chip_disable(sc); - flashdone(sc); -} - -void -flashdone(void *v) -{ - struct flash_softc *sc = v; - struct buf *bp = sc->sc_bp; - - /* Instrumentation. */ - disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid, - bp->b_blkno, (bp->b_flags & B_READ) != 0); - - if (bp->b_error != 0) - bp->b_flags |= B_ERROR; - - biodone(bp); - flashstart(sc); -} - -void -flashgetdefaultlabel(dev_t dev, struct flash_softc *sc, - struct disklabel *lp) -{ - size_t len; - - bzero(lp, sizeof(struct disklabel)); - - lp->d_type = 0; - strncpy(lp->d_typename, "NAND flash", sizeof(lp->d_typename)); - - /* Use the product name up to the first space. */ - strncpy(lp->d_packname, sc->sc_flashdev->longname, - sizeof(lp->d_packname)); - for (len = 0; len < sizeof(lp->d_packname); len++) - if (lp->d_packname[len] == ' ') { - lp->d_packname[len] = '\0'; - break; - } - - /* Fake the disk geometry. */ - lp->d_ncylinders = 1; - lp->d_ntracks = 16; - lp->d_secsize = sc->sc_flashdev->pagesize; - lp->d_nsectors = sc->sc_flashdev->capacity / lp->d_ntracks - / lp->d_ncylinders; - lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; - DL_SETDSIZE(lp, (u_int64_t)lp->d_ncylinders * lp->d_secpercyl); - - lp->d_version = 1; - - /* XXX these values assume ffs. */ - lp->d_bbsize = BBSIZE; - lp->d_sbsize = SBSIZE; - - /* Wrap it up. */ - lp->d_magic = DISKMAGIC; - lp->d_magic2 = DISKMAGIC; - lp->d_checksum = dkcksum(lp); -} - -int -flashgetdisklabel(dev_t dev, struct flash_softc *sc, - struct disklabel *lp, int spoofonly) -{ - dev_t labeldev; - - flashgetdefaultlabel(dev, sc, lp); - - if (sc->sc_tag->default_disklabel != NULL) - sc->sc_tag->default_disklabel(sc->sc_cookie, dev, lp); - - /* Call the generic disklabel extraction routine. */ - labeldev = flashlabeldev(dev); - return readdisklabel(labeldev, flashstrategy, lp, spoofonly); -} - -/* - * Character device functions - */ - -void -flashminphys(struct buf *bp) -{ - struct flash_softc *sc; - - sc = flashlookup(flashunit(bp->b_dev)); - - if (bp->b_bcount > sc->sc_flashdev->pagesize) - bp->b_bcount = sc->sc_flashdev->pagesize; -} - -int -flashread(dev_t dev, struct uio *uio, int ioflag) -{ - return physio(flashstrategy, dev, B_READ, flashminphys, uio); -} - -int -flashwrite(dev_t dev, struct uio *uio, int ioflag) -{ - return physio(flashstrategy, dev, B_WRITE, flashminphys, uio); -} - -/* - * Physical access strategy "fixup" routines for transparent bad - * blocks management, wear-leveling, etc. - */ - -/* - * Call the machine-specific routine if there is any or use just a - * default strategy for bad blocks management. - */ -int -flashsafestrategy(struct flash_softc *sc, struct buf *bp) -{ - if (sc->sc_tag->safe_strategy) { - return sc->sc_tag->safe_strategy(sc->sc_cookie, bp); - } - - /* XXX no default bad blocks management strategy yet */ - return 1; -} - -void dumppage(u_char *); -void dumppage(u_char *buf) -{ - int i; - for (i = 0; i < 512; i++) { - if ((i % 16) == 0) - printf("%04x: ", i); - if ((i % 16) == 8) - printf(" "); - printf(" %02x", buf[i]); - if ((i % 16) == 15) - printf("\n"); - } - if ((i % 16) != 0) - printf("\n"); -} |