diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/isf/isf.c | 741 | ||||
-rw-r--r-- | sys/dev/isf/isf.h | 96 | ||||
-rw-r--r-- | sys/dev/isf/isf_fdt.c | 124 | ||||
-rw-r--r-- | sys/dev/isf/isf_nexus.c | 118 |
4 files changed, 0 insertions, 1079 deletions
diff --git a/sys/dev/isf/isf.c b/sys/dev/isf/isf.c deleted file mode 100644 index eaaad15..0000000 --- a/sys/dev/isf/isf.c +++ /dev/null @@ -1,741 +0,0 @@ -/*- - * Copyright (c) 2012 Robert N. M. Watson - * Copyright (c) 2012 SRI International - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/module.h> -#include <sys/kernel.h> -#include <sys/systm.h> - -#include <sys/bus.h> -#include <sys/conf.h> -#include <sys/endian.h> -#include <sys/bio.h> -#include <sys/kthread.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/mutex.h> -#include <sys/rman.h> -#include <sys/taskqueue.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <geom/geom_disk.h> - -#include <dev/isf/isf.h> - -/* Read Mode */ -#define ISF_CMD_RA 0xFF /* Read Array mode */ -#define ISF_CMD_RSR 0x70 /* Read Status Register mode */ -#define ISF_CMD_RDI 0x90 /* Read Device ID/Config Reg mode */ -#define ISF_CMD_RQ 0x98 /* Read Query mode */ -#define ISF_CMD_CSR 0x50 /* Clear Status Register */ - -/* Write Mode */ -#define ISF_CMD_WPS 0x40 /* Word Program Setup */ -#define ISF_CMD_BPS 0xE8 /* Buffered Program Setup */ -#define ISF_CMD_BPC 0xD0 /* Buffered Program Confirm */ - -/* Erase Mode */ -#define ISF_CMD_BES 0x20 /* Block Erase Setup */ -#define ISF_CMD_BEC 0xD0 /* Block Erase Confirm */ - -/* Block Locking/Unlocking */ -#define ISF_CMD_LBS 0x60 /* Lock Block Setup */ -#define ISF_CMD_LB 0x01 /* Lock Block */ -#define ISF_CMD_UB 0xD0 /* Unlock Block */ - -/* - * Read Device Identifier registers. - * - * NOTE: ISF_RDIR_BLC is relative to the block base address. - */ -#define ISF_REG_MC 0x00 /* Manufacture Code */ -#define ISF_REG_ID 0x01 /* Device ID Code */ -#define ISF_REG_BLC 0x02 /* Block Lock Configuration */ -#define ISF_REG_RCR 0x05 /* Read Configuration Register */ - -/* - * Protection Registers - */ -#define ISF_REG_L0 0x80 /* Lock Register 0 */ -#define ISF_REG_FPP 0x81 /* 64-bit Factory Protection Register */ -#define ISF_REG_UPP 0x85 /* 64-bit User Protection Register */ -#define ISF_REG_L1 0x89 /* Lock Register 1 */ -#define ISF_REG_PP1 0x8A /* 128-bit Protection Register 1 */ -#define ISF_REG_PP2 0x92 /* 128-bit Protection Register 2 */ -#define ISF_REG_PP3 0x9A /* 128-bit Protection Register 3 */ -#define ISF_REG_PP4 0xA2 /* 128-bit Protection Register 4 */ -#define ISF_REG_PP5 0xAA /* 128-bit Protection Register 5 */ -#define ISF_REG_PP6 0xB2 /* 128-bit Protection Register 6 */ -#define ISF_REG_PP7 0xBA /* 128-bit Protection Register 7 */ -#define ISF_REG_PP8 0xC2 /* 128-bit Protection Register 8 */ -#define ISF_REG_PP9 0xCA /* 128-bit Protection Register 9 */ -#define ISF_REG_PP10 0xD2 /* 128-bit Protection Register 10 */ -#define ISF_REG_PP11 0xDA /* 128-bit Protection Register 11 */ -#define ISF_REG_PP12 0xE2 /* 128-bit Protection Register 12 */ -#define ISF_REG_PP13 0xEA /* 128-bit Protection Register 13 */ -#define ISF_REG_PP14 0xF2 /* 128-bit Protection Register 14 */ -#define ISF_REG_PP15 0xFA /* 128-bit Protection Register 15 */ -#define ISF_REG_PP16 0x102 /* 128-bit Protection Register 16 */ - -#define ISF_SR_BWS (1 << 0) /* BEFP Status */ -#define ISF_SR_BLS (1 << 1) /* Block-Locked Status */ -#define ISF_SR_PSS (1 << 2) /* Program Suspend Status */ -#define ISF_SR_VPPS (1 << 3) /* Vpp Status */ -#define ISF_SR_PS (1 << 4) /* Program Status */ -#define ISF_SR_ES (1 << 5) /* Erase Status */ -#define ISF_SR_ESS (1 << 6) /* Erase Suspend Status */ -#define ISF_SR_DWS (1 << 7) /* Device Write Status */ -#define ISF_SR_FSC_MASK (ISF_SR_VPPS | ISF_SR_PS | ISF_SR_BLS) - -#define ISF_BUFFER_PROGRAM - -MALLOC_DEFINE(M_ISF, "isf_data", "Intel StrateFlash driver"); -static int isf_debug = 0; - -static struct isf_chips { - uint16_t chip_id; - size_t chip_size; - const char *chip_desc; -} chip_ids[] = { - { 0x8817, 0x0800000, "64-Mbit Top Parameter" }, - { 0x881A, 0x0800000, "64-Mbit Bottom Parameter" }, - { 0x8818, 0x1000000, "128-Mbit Top Parameter" }, - { 0x881B, 0x1000000, "128-Mbit Bottom Parameter" }, - { 0x8919, 0x2000000, "256-Mbit Top Parameter" }, - { 0x891C, 0x2000000, "256-Mbit Bottom Parameter" }, - { 0x8961, 0x2000000, "512-Mbit package (half)" }, - { 0x0000, 0x0000000, NULL } -}; - -static void isf_task(void *arg); - -/* - * Device driver for the Intel StrataFlash NOR flash device. This - * implementation is known to work with 256Mb instances of the device, but may - * also work with other 64/128/512Mb parts without much work. Multiple - * device instances should be used when multiple parts are in the same - * physical package, due to variable block size support in the StrataFlash - * part. - */ -devclass_t isf_devclass; - -static uint16_t -isf_read_reg(struct isf_softc *sc, uint16_t reg) -{ - - if (isf_debug) - device_printf(sc->isf_dev, "isf_read_reg(0x%02x)\n", reg); - return (le16toh(bus_read_2(sc->isf_res, reg * 2))); -} - -static uint64_t -isf_read_reg64(struct isf_softc *sc, uint16_t reg) -{ - uint64_t val; - uint16_t *val16 = (uint16_t *)&val; - - if (isf_debug) - device_printf(sc->isf_dev, "isf_read_reg64(0x%02x)\n", reg); - val16[0] = bus_read_2(sc->isf_res, reg * 2); - val16[1] = bus_read_2(sc->isf_res, (reg+1) * 2); - val16[2] = bus_read_2(sc->isf_res, (reg+2) * 2); - val16[3] = bus_read_2(sc->isf_res, (reg+3) * 2); - - return(le64toh(val)); -} - -static uint16_t -isf_read_off(struct isf_softc *sc, off_t off) -{ - - KASSERT(off >= 0, ("%s: negative offset\n", __func__)); - KASSERT(off < sc->isf_disk->d_mediasize, - ("%s: offset out side address space 0x%08jx \n", __func__, - (intmax_t)off)); - - if (isf_debug) - device_printf(sc->isf_dev, "isf_read_off(0x%08jx)\n", - (intmax_t)off); - return (le16toh(bus_read_2(sc->isf_res, off))); -} - -static void -isf_write_cmd(struct isf_softc *sc, off_t off, uint16_t cmd) -{ - - if (isf_debug) - device_printf(sc->isf_dev, "isf_write_cmd(0x%08jx, 0x%02x)\n", - off, cmd); - bus_write_2(sc->isf_res, off, htole16(cmd)); -} - -static uint16_t -isf_read_status(struct isf_softc *sc, off_t off) -{ - - isf_write_cmd(sc, off/2, ISF_CMD_RSR); - return isf_read_off(sc, off); -} - -static void -isf_clear_status(struct isf_softc *sc) -{ - - isf_write_cmd(sc, 0, ISF_CMD_CSR); -} - -static int -isf_full_status_check(struct isf_softc *sc, off_t off) -{ - int error = 0; - uint16_t status; - - status = isf_read_status(sc, off); - if (status & ISF_SR_VPPS) { - device_printf(sc->isf_dev, "Vpp Range Error\n"); - error = EIO; - } else if (status & ISF_SR_PS) { - device_printf(sc->isf_dev, "Program Error\n"); - error = EIO; - } else if (status & ISF_SR_BLS) { - device_printf(sc->isf_dev, "Device Protect Error\n"); - error = EIO; - } - isf_clear_status(sc); - - return(error); -} - -static int -isf_full_erase_status_check(struct isf_softc *sc, off_t off) -{ - int error = 0; - uint16_t status; - - status = isf_read_status(sc, off); - if (status & ISF_SR_VPPS) { - device_printf(sc->isf_dev, "Vpp Range Error\n"); - error = EIO; - } else if (status & (ISF_SR_PS|ISF_SR_ES)) { - device_printf(sc->isf_dev, "Command Sequence Error\n"); - error = EIO; - } else if (status & ISF_SR_ES) { - device_printf(sc->isf_dev, "Block Erase Error\n"); - error = EIO; - } else if (status & ISF_SR_BLS) { - device_printf(sc->isf_dev, "Block Locked Error\n"); - error = EIO; - } - isf_clear_status(sc); - - return(error); -} - -static void -isf_unlock_block(struct isf_softc *sc, off_t off) -{ - - isf_write_cmd(sc, off, ISF_CMD_LBS); - isf_write_cmd(sc, off, ISF_CMD_UB); - isf_write_cmd(sc, off, ISF_CMD_RA); -} - -static void -isf_lock_block(struct isf_softc *sc, off_t off) -{ - - isf_write_cmd(sc, off, ISF_CMD_LBS); - isf_write_cmd(sc, off, ISF_CMD_LB); - isf_write_cmd(sc, off, ISF_CMD_RA); -} - -static void -isf_read(struct isf_softc *sc, off_t off, void *data, size_t len) -{ - - KASSERT((uintptr_t)data % 2 == 0, - ("%s: unaligned data %p", __func__, data)); - KASSERT((len <= ISF_SECTORSIZE) && (len % 2 == 0), - ("%s: invalid length %ju", __func__, len)); - KASSERT(off % ISF_SECTORSIZE == 0, - ("%s: invalid offset %ju\n", __func__, off)); - - /* - * It is not permitted to read blocks that are in the process of - * being erased, but we know they will be all 1's after the - * erase so just report that value if asked about a block that - * is being erased. - */ - if (sc->isf_bstate[off / ISF_ERASE_BLOCK] == BS_ERASING) - memset(data, 0xFF, len); - else - bus_read_region_2(sc->isf_res, off, (uint16_t *)data, len / 2); -} - -static int -isf_write(struct isf_softc *sc, off_t off, void *data, size_t len) -{ - int cycles, error = 0; - uint16_t *dp; - uint16_t status; - off_t coff; - - KASSERT((uintptr_t)data % 2 == 0, - ("%s: unaligned data %p", __func__, data)); - KASSERT((len <= ISF_SECTORSIZE) && (len % 2 == 0), - ("%s: invalid length %ju", __func__, len)); - KASSERT(off % ISF_SECTORSIZE == 0, - ("%s: invalid offset %ju\n", __func__, off)); - KASSERT(!sc->isf_erasing, - ("%s: trying to write while erasing\n", __func__)); - KASSERT(sc->isf_bstate[off / ISF_ERASE_BLOCK] != BS_ERASING, - ("%s: block being erased at %ju\n", __func__, off)); - - isf_unlock_block(sc, off); - -#ifdef ISF_BUFFER_PROGRAM - for (dp = data, coff = off; dp - (uint16_t *)data < len / 2; - dp += 32, coff += 64) { - isf_clear_status(sc); - isf_write_cmd(sc, coff, ISF_CMD_BPS); - cycles = 0xFFFF; - while ( !(isf_read_off(sc, coff) & ISF_SR_DWS) ) { - if (cycles-- == 0) { - device_printf(sc->isf_dev, "timeout waiting" - " for write to start at 0x08%jx\n", - (intmax_t)coff); - return (EIO); - } - isf_write_cmd(sc, coff, ISF_CMD_BPS); - } - - /* When writing N blocks, send N-1 as the count */ - isf_write_cmd(sc, coff, 31); - bus_write_region_2(sc->isf_res, coff, dp, 32); - - isf_write_cmd(sc, coff, ISF_CMD_BPC); - - status = isf_read_off(sc, coff); - cycles = 0xFFFFF; - while ( !(status & ISF_SR_DWS) ) { - if (cycles-- == 0) { - device_printf(sc->isf_dev, "timeout waiting" - " for write to complete at 0x08%jx\n", - (intmax_t)coff); - error = EIO; - break; - } - status = isf_read_off(sc, coff); - } - isf_full_status_check(sc, off); - - isf_write_cmd(sc, coff, ISF_CMD_RA); - } -#else - for (dp = data, coff = off; dp - (uint16_t *)data < len / 2; - dp++, coff += 2) { - isf_write_cmd(sc, coff, ISF_CMD_WPS); - bus_write_2(sc->isf_res, coff, *dp); - status = isf_read_off(sc, coff); - cycles=0xFFFFF; - while ( !(status & ISF_SR_DWS) ) { - if (cycles-- == 0) { - device_printf(sc->isf_dev, "timeout waiting" - " for write to complete at 0x08%jx\n", - (intmax_t)coff); - error = EIO; - break; - } - status = isf_read_off(sc, coff); - } - - } - isf_full_status_check(sc, off); - isf_write_cmd(sc, coff, ISF_CMD_RA); -#endif - - isf_lock_block(sc, off); - - return error; -} - -static void -isf_erase_at(struct isf_softc *sc, off_t off) -{ - int cycles; - uint16_t status; - - isf_unlock_block(sc, off); - isf_clear_status(sc); - - isf_write_cmd(sc, off, ISF_CMD_BES); - isf_write_cmd(sc, off, ISF_CMD_BEC); - - cycles=0xFFFFFF; - status = isf_read_off(sc, off); - while ( !(status & ISF_SR_DWS) ) { -#ifdef NOTYET - ISF_SLEEP(sc, sc, hz); -#endif - if (cycles-- == 0) { - device_printf(sc->isf_dev, - "Giving up on erase\n"); - break; - } - status = isf_read_off(sc, off); - } - - isf_full_erase_status_check(sc, off); - - isf_lock_block(sc, off); - - isf_write_cmd(sc, off, ISF_CMD_RA); -} - -static void -isf_erase_range(struct isf_softc *sc, off_t blk_off, size_t size) -{ - off_t off; - off_t ms = sc->isf_disk->d_mediasize; - - KASSERT(blk_off % ISF_ERASE_BLOCK == 0, - ("%s: invalid offset %ju\n", __func__, blk_off)); - - ISF_LOCK_ASSERT(sc); - - for (off = blk_off; off < blk_off + size; off += ISF_ERASE_BLOCK) { - sc->isf_bstate[off / ISF_ERASE_BLOCK] = BS_ERASING; - - /* - * The first or last 128K is four blocks depending which - * part this is. For now, just assume both are and - * erase four times. - */ - if (off == 0 || ms - off == ISF_ERASE_BLOCK) { - isf_erase_at(sc, off); - isf_erase_at(sc, off + 0x08000); - isf_erase_at(sc, off + 0x10000); - isf_erase_at(sc, off + 0x18000); - } else - isf_erase_at(sc, off); - - sc->isf_bstate[off / ISF_ERASE_BLOCK] = BS_STEADY; - } -} - -/* - * disk(9) methods. - */ -static int -isf_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag, - struct thread *td) -{ - int error = 0; - struct isf_softc *sc = disk->d_drv1; - struct isf_range *ir; - - switch (cmd) { - case ISF_ERASE: - ir = data; - if (ir->ir_off % ISF_ERASE_BLOCK != 0 || - ir->ir_off >= disk->d_mediasize || - ir->ir_size == 0 || - ir->ir_size % ISF_ERASE_BLOCK != 0 || - ir->ir_off + ir->ir_size > disk->d_mediasize) { - error = EINVAL; - break; - } - ISF_LOCK(sc); - if (sc->isf_erasing) { - ISF_UNLOCK(sc); - error = EBUSY; - break; - } - sc->isf_erasing = 1; - isf_erase_range(sc, ir->ir_off, ir->ir_size); - sc->isf_erasing = 0; - ISF_UNLOCK(sc); - break; - default: - error = EINVAL; - } - - return (error); -} - -static void -isf_disk_strategy(struct bio *bp) -{ - struct isf_softc *sc = bp->bio_disk->d_drv1; - - /* - * We advertise a block size and maximum I/O size up the stack; catch - * any attempts to not follow the rules. - */ - KASSERT(bp->bio_bcount == ISF_SECTORSIZE, - ("%s: I/O size not %d", __func__, ISF_SECTORSIZE)); - - ISF_LOCK(sc); - bioq_disksort(&sc->isf_bioq, bp); - ISF_WAKEUP(sc); - ISF_UNLOCK(sc); -} - -static void -isf_task(void *arg) -{ - struct isf_softc *sc = arg; - struct bio *bp; - int ss = sc->isf_disk->d_sectorsize; - int error, i; - - for (;;) { - ISF_LOCK(sc); - do { - bp = bioq_first(&sc->isf_bioq); - if (bp == NULL) { - if (sc->isf_doomed) - kproc_exit(0); - else - ISF_SLEEP(sc, sc, 0); - } - } while (bp == NULL); - bioq_remove(&sc->isf_bioq, bp); - - error = 0; - switch (bp->bio_cmd) { - case BIO_READ: - isf_read(sc, bp->bio_pblkno * ss, bp->bio_data, - bp->bio_bcount); - break; - - case BIO_WRITE: - /* - * In principle one could suspend the in-progress - * erase, process any pending writes to other - * blocks and then proceed, but that seems - * overly complex for the likely usage modes. - */ - if (sc->isf_erasing) { - error = EBUSY; - break; - } - - /* - * Read in the block we want to write and check that - * we're only setting bits to 0. If an erase would - * be required return an I/O error. - */ - isf_read(sc, bp->bio_pblkno * ss, sc->isf_rbuf, - bp->bio_bcount); - for (i = 0; i < bp->bio_bcount / 2; i++) - if ((sc->isf_rbuf[i] & - ((uint16_t *)bp->bio_data)[i]) != - ((uint16_t *)bp->bio_data)[i]) { - device_printf(sc->isf_dev, "write" - " requires erase at 0x%08jx\n", - bp->bio_pblkno * ss); - error = EIO; - break; - } - if (error != 0) - break; - - error = isf_write(sc, bp->bio_pblkno * ss, - bp->bio_data, bp->bio_bcount); - break; - - default: - panic("%s: unsupported I/O operation %d", __func__, - bp->bio_cmd); - } - if (error == 0) - biodone(bp); - else - biofinish(bp, NULL, error); - ISF_UNLOCK(sc); - } -} - -static void -isf_dump_info(struct isf_softc *sc) -{ - int i; - int32_t reg; - - isf_write_cmd(sc, 0, ISF_CMD_RDI); - device_printf(sc->isf_dev, "manufacturer code: 0x%04x\n", - isf_read_reg(sc, ISF_REG_MC)); - device_printf(sc->isf_dev, "device id code: 0x%04x\n", - isf_read_reg(sc, ISF_REG_ID)); - device_printf(sc->isf_dev, "read config register: 0x%04x\n", - isf_read_reg(sc, ISF_REG_RCR)); - - device_printf(sc->isf_dev, "lock register 0: 0x%04x\n", - isf_read_reg(sc, ISF_REG_L0)); - device_printf(sc->isf_dev, "lock register 1: 0x%04x\n", - isf_read_reg(sc, ISF_REG_L1)); - - device_printf(sc->isf_dev, "factory PPR: 0x%016jx\n", - (uintmax_t)isf_read_reg64(sc, ISF_REG_FPP)); - device_printf(sc->isf_dev, "user PPR (64-bit): 0x%016jx\n", - (uintmax_t)isf_read_reg64(sc, ISF_REG_UPP)); - - for (reg = ISF_REG_PP1, i = 1; reg <= ISF_REG_PP16; reg += 8, i++) { - /* XXX: big-endian ordering of uint64_t's */ - device_printf(sc->isf_dev, - "user PPR [%02d]: 0x%016jx%016jx\n", i, - (uintmax_t)isf_read_reg64(sc, reg+4), - (uintmax_t)isf_read_reg64(sc, reg)); - } - - isf_write_cmd(sc, 0, ISF_CMD_RA); -} - -static void -isf_disk_insert(struct isf_softc *sc, off_t mediasize) -{ - struct disk *disk; - - sc->isf_doomed = 0; - sc->isf_erasing = 0; - sc->isf_bstate = malloc(sizeof(*sc->isf_bstate) * - (mediasize / ISF_ERASE_BLOCK), M_ISF, M_ZERO | M_WAITOK); - kproc_create(&isf_task, sc, &sc->isf_proc, 0, 0, "isf"); - - disk = disk_alloc(); - disk->d_drv1 = sc; - disk->d_name = "isf"; - disk->d_unit = sc->isf_unit; - disk->d_strategy = isf_disk_strategy; - disk->d_ioctl = isf_disk_ioctl; - disk->d_sectorsize = ISF_SECTORSIZE; - disk->d_mediasize = mediasize; - disk->d_maxsize = ISF_SECTORSIZE; - sc->isf_disk = disk; - - if (bootverbose) - isf_dump_info(sc); - - disk_create(disk, DISK_VERSION); - device_printf(sc->isf_dev, "%juM flash device\n", - (uintmax_t)disk->d_mediasize / (1024 * 1024)); - -} - -static void -isf_disk_remove(struct isf_softc *sc) -{ - struct disk *disk; - - ISF_LOCK_ASSERT(sc); - KASSERT(sc->isf_disk != NULL, ("%s: isf_disk NULL", __func__)); - - sc->isf_doomed = 1; - ISF_WAKEUP(sc); - ISF_SLEEP(sc, sc->isf_proc, 0); - - /* - * XXXRW: Is it OK to call disk_destroy() under the mutex, or should - * we be deferring that to the calling context once it is released? - */ - disk = sc->isf_disk; - disk_gone(disk); - disk_destroy(disk); - sc->isf_disk = NULL; - free(sc->isf_bstate, M_ISF); - device_printf(sc->isf_dev, "flash device removed\n"); -} - -int -isf_attach(struct isf_softc *sc) -{ - uint16_t id; - u_long start, size; - struct isf_chips *cp = chip_ids; - - start = rman_get_start(sc->isf_res); - if (start % 2 != 0) { - device_printf(sc->isf_dev, - "Unsupported flash start alignment %lu\n", - start); - return (ENXIO); - } - - isf_write_cmd(sc, 0, ISF_CMD_RDI); - id = isf_read_reg(sc, ISF_REG_ID); - while (cp->chip_id != id) - cp++; - if (cp->chip_desc == NULL) { - device_printf(sc->isf_dev, - "Unsupported device ID 0x%04x\n", id); - return (ENXIO); - } - isf_write_cmd(sc, 0, ISF_CMD_RA); - - size = rman_get_size(sc->isf_res); - if (size != cp->chip_size) { - device_printf(sc->isf_dev, - "Unsupported flash size %lu\n", size); - return (ENXIO); - } - - bioq_init(&sc->isf_bioq); - ISF_LOCK_INIT(sc); - sc->isf_disk = NULL; - isf_disk_insert(sc, size); - return(0); -} - -void -isf_detach(struct isf_softc *sc) -{ - - /* - * Simulate a disk removal if one is present to deal with any pending - * or queued I/O. This will occur as a result of a device driver - * detach -- the Intel StrataFlash has no notion of removal itself. - * - * XXXRW: Is the locking here right? - */ - ISF_LOCK(sc); - isf_disk_remove(sc); - bioq_flush(&sc->isf_bioq, NULL, ENXIO); - KASSERT(bioq_first(&sc->isf_bioq) == NULL, - ("%s: non-empty bioq", __func__)); - ISF_UNLOCK(sc); - ISF_LOCK_DESTROY(sc); -} diff --git a/sys/dev/isf/isf.h b/sys/dev/isf/isf.h deleted file mode 100644 index bfcca07..0000000 --- a/sys/dev/isf/isf.h +++ /dev/null @@ -1,96 +0,0 @@ -/*- - * Copyright (c) 2012 Robert N. M. Watson - * Copyright (c) 2012 SRI International - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. - * - * $FreeBSD$ - */ - -#ifndef _DEV_ISF_H_ -#define _DEV_ISF_H_ - -struct isf_range { - off_t ir_off; /* Offset of range to delete (set to 0xFF) */ - size_t ir_size; /* Size of range */ -}; - -#define ISF_ERASE _IOW('I', 1, struct isf_range) - -/* - * Ordinary read and write operations are limited to 512 bytes. - * We support erasing 128K blocks and ignore the fact that portions of the - * flash are in fact divided into 32K blocks. - */ -#define ISF_SECTORSIZE (512) -#define ISF_ERASE_BLOCK (128 * 1024) - -#ifdef _KERNEL -MALLOC_DECLARE(M_ISF); - -enum bstate { - BS_STEADY = 0, - BS_ERASING -}; - -struct isf_softc { - device_t isf_dev; - int isf_unit; - struct resource *isf_res; - int isf_rid; - struct mtx isf_lock; - struct disk *isf_disk; - struct proc *isf_proc; - int isf_doomed; - - /* - * Fields relating to in-progress and pending I/O, if any. - */ - struct bio_queue_head isf_bioq; - uint16_t isf_rbuf[ISF_SECTORSIZE / 2]; - int isf_erasing; - enum bstate *isf_bstate; -}; - -#define ISF_LOCK(sc) mtx_lock(&(sc)->isf_lock) -#define ISF_LOCK_ASSERT(sc) mtx_assert(&(sc)->isf_lock, MA_OWNED) -#define ISF_LOCK_DESTROY(sc) mtx_destroy(&(sc)->isf_lock) -#define ISF_LOCK_INIT(sc) mtx_init(&(sc)->isf_lock, "isf", NULL, \ - MTX_DEF) -#define ISF_SLEEP(sc, wait, timo) mtx_sleep((wait), \ - &(sc)->isf_lock, PRIBIO, \ - "isf", (timo)) -#define ISF_UNLOCK(sc) mtx_unlock(&(sc)->isf_lock) -#define ISF_WAKEUP(sc) wakeup((sc)) - -int isf_attach(struct isf_softc *sc); -void isf_detach(struct isf_softc *sc); - -extern devclass_t isf_devclass; -#endif /* _KERNEL */ - -#endif /* _DEV_ISF_H_ */ diff --git a/sys/dev/isf/isf_fdt.c b/sys/dev/isf/isf_fdt.c deleted file mode 100644 index f4c20a2..0000000 --- a/sys/dev/isf/isf_fdt.c +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * Copyright (c) 2012 Robert N. M. Watson - * Copyright (c) 2012 SRI International - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/condvar.h> -#include <sys/conf.h> -#include <sys/bio.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/rman.h> -#include <sys/systm.h> -#include <sys/taskqueue.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <geom/geom_disk.h> - -#include <dev/fdt/fdt_common.h> -#include <dev/ofw/openfirm.h> -#include <dev/ofw/ofw_bus.h> -#include <dev/ofw/ofw_bus_subr.h> - -#include <dev/isf/isf.h> - -/* - * FDT bus attachment for the Intel Strata Flash devices. - */ -static int -isf_fdt_probe(device_t dev) -{ - - if (ofw_bus_is_compatible(dev, "intel,strataflash")) { - device_set_desc(dev, "Intel StrataFlash NOR flash device"); - return (BUS_PROBE_DEFAULT); - } - return (ENXIO); -} - -static int -isf_fdt_attach(device_t dev) -{ - int error; - struct isf_softc *sc; - - sc = device_get_softc(dev); - sc->isf_dev = dev; - sc->isf_unit = device_get_unit(dev); - sc->isf_rid = 0; - sc->isf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->isf_rid, RF_ACTIVE); - if (sc->isf_res == NULL) { - device_printf(dev, "couldn't map memory\n"); - return (ENXIO); - } - error = isf_attach(sc); - if (error) - bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, - sc->isf_res); - return (error); -} - -static int -isf_fdt_detach(device_t dev) -{ - struct isf_softc *sc; - - sc = device_get_softc(dev); - KASSERT(sc->isf_res != NULL, ("%s: resources not allocated", - __func__)); - isf_detach(sc); - bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, sc->isf_res); - return (0); -} - -static device_method_t isf_fdt_methods[] = { - DEVMETHOD(device_probe, isf_fdt_probe), - DEVMETHOD(device_attach, isf_fdt_attach), - DEVMETHOD(device_detach, isf_fdt_detach), - { 0, 0 } -}; - -static driver_t isf_fdt_driver = { - "isf", - isf_fdt_methods, - sizeof(struct isf_softc), -}; - -DRIVER_MODULE(isf, simplebus, isf_fdt_driver, isf_devclass, 0, 0); diff --git a/sys/dev/isf/isf_nexus.c b/sys/dev/isf/isf_nexus.c deleted file mode 100644 index 7631453..0000000 --- a/sys/dev/isf/isf_nexus.c +++ /dev/null @@ -1,118 +0,0 @@ -/*- - * Copyright (c) 2012 Robert N. M. Watson - * Copyright (c) 2012 SRI International - * All rights reserved. - * - * This software was developed by SRI International and the University of - * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) - * ("CTSRD"), as part of the DARPA CRASH research programme. - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/condvar.h> -#include <sys/conf.h> -#include <sys/bio.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/malloc.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/rman.h> -#include <sys/systm.h> -#include <sys/taskqueue.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <geom/geom_disk.h> - -#include <dev/isf/isf.h> - -/* - * Nexus bus attachment for the Intel Strata Flash devices. Appropriate for - * most Altera FPGA SoC-style configurations in which the part will be exposed - * to the processor via a memory-mapped Avalon bus. - */ -static int -isf_nexus_probe(device_t dev) -{ - - device_set_desc(dev, "Intel StrataFlash NOR flash device"); - return (BUS_PROBE_DEFAULT); -} - -static int -isf_nexus_attach(device_t dev) -{ - int error; - struct isf_softc *sc; - - sc = device_get_softc(dev); - sc->isf_dev = dev; - sc->isf_unit = device_get_unit(dev); - sc->isf_rid = 0; - sc->isf_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->isf_rid, RF_ACTIVE); - if (sc->isf_res == NULL) { - device_printf(dev, "couldn't map memory\n"); - return (ENXIO); - } - error = isf_attach(sc); - if (error) - bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, - sc->isf_res); - return (error); -} - -static int -isf_nexus_detach(device_t dev) -{ - struct isf_softc *sc; - - sc = device_get_softc(dev); - KASSERT(sc->isf_res != NULL, ("%s: resources not allocated", - __func__)); - isf_detach(sc); - bus_release_resource(dev, SYS_RES_MEMORY, sc->isf_rid, sc->isf_res); - return (0); -} - -static device_method_t isf_nexus_methods[] = { - DEVMETHOD(device_probe, isf_nexus_probe), - DEVMETHOD(device_attach, isf_nexus_attach), - DEVMETHOD(device_detach, isf_nexus_detach), - { 0, 0 } -}; - -static driver_t isf_nexus_driver = { - "isf", - isf_nexus_methods, - sizeof(struct isf_softc), -}; - -DRIVER_MODULE(isf, nexus, isf_nexus_driver, isf_devclass, 0, 0); |