static uint16_t nandsim_read_word(device_t dev) { struct nandsim_softc *sc; struct nandsim_chip *chip; uint16_t *data_ptr; uint16_t ret = 0xffff; uint8_t *byte_ret = (uint8_t *)&ret; sc = device_get_softc(dev); chip = sc->active_chip; if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) { if (chip->data.index < chip->data.size - 1) { data_ptr = (uint16_t *)&(chip->data.data_ptr[chip->data.index]); ret = *data_ptr; chip->data.index += 2; byte_corrupt(chip, byte_ret); byte_corrupt(chip, byte_ret + 1); } nandsim_log(chip, NANDSIM_LOG_DATA, "read %04x\n", ret); } return (ret); }
static void nandsim_loop(void *arg) { struct nandsim_chip *chip = (struct nandsim_chip *)arg; struct nandsim_ev *ev; nand_debug(NDBG_SIM,"Start main loop for chip%d [%8p]", chip->chip_num, chip); for(;;) { NANDSIM_CHIP_LOCK(chip); if (!(chip->flags & NANDSIM_CHIP_ACTIVE)) { chip->flags |= NANDSIM_CHIP_ACTIVE; wakeup(chip->nandsim_td); } if (STAILQ_EMPTY(&chip->nandsim_events)) { nand_debug(NDBG_SIM,"Chip%d [%8p] going sleep", chip->chip_num, chip); msleep(chip, &chip->ns_lock, PRIBIO, "nandev", 0); } ev = STAILQ_FIRST(&chip->nandsim_events); STAILQ_REMOVE_HEAD(&chip->nandsim_events, links); NANDSIM_CHIP_UNLOCK(chip); if (ev->type == NANDSIM_EV_EXIT) { NANDSIM_CHIP_LOCK(chip); destroy_event(ev); wakeup(ev); while (!STAILQ_EMPTY(&chip->nandsim_events)) { ev = STAILQ_FIRST(&chip->nandsim_events); STAILQ_REMOVE_HEAD(&chip->nandsim_events, links); destroy_event(ev); wakeup(ev); } NANDSIM_CHIP_UNLOCK(chip); nandsim_log(chip, NANDSIM_LOG_SM, "destroyed\n"); mtx_destroy(&chip->ns_lock); nandsim_blk_state_destroy(chip); nandsim_swap_destroy(chip->swap); free(chip, M_NANDSIM); nandsim_proc = NULL; kthread_exit(); } if (!(chip->flags & NANDSIM_CHIP_FROZEN)) { nand_debug(NDBG_SIM,"Chip [%x] get event [%x]", chip->chip_num, ev->type); chip->ev_handler(chip, ev->type, ev->data); } wakeup(ev); destroy_event(ev); } }
static void nandsim_write_byte(device_t dev, uint8_t byte) { struct nandsim_softc *sc; struct nandsim_chip *chip; sc = device_get_softc(dev); chip = sc->active_chip; if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN) && (chip->data.index < chip->data.size)) { byte_corrupt(chip, &byte); chip->data.data_ptr[chip->data.index] &= byte; chip->data.index++; nandsim_log(chip, NANDSIM_LOG_DATA, "write %02x\n", byte); } }
static int nandsim_select_cs(device_t dev, uint8_t cs) { struct nandsim_softc *sc; sc = device_get_softc(dev); if (cs >= MAX_CS_NUM) return (EINVAL); sc->active_chip = sc->chips[cs]; if (sc->active_chip) nandsim_log(sc->active_chip, NANDSIM_LOG_EV, "Select cs %d\n", cs); return (0); }
static int nandsim_send_command(device_t dev, uint8_t command) { struct nandsim_softc *sc; struct nandsim_chip *chip; struct nandsim_ev *ev; sc = device_get_softc(dev); chip = sc->active_chip; if (chip == NULL) return (0); nandsim_log(chip, NANDSIM_LOG_EV, "Send command %x\n", command); switch (command) { case NAND_CMD_READ_ID: case NAND_CMD_READ_PARAMETER: sc->address_type = ADDR_ID; break; case NAND_CMD_ERASE: sc->address_type = ADDR_ROW; break; case NAND_CMD_READ: case NAND_CMD_PROG: sc->address_type = ADDR_ROWCOL; break; default: sc->address_type = ADDR_NONE; break; } if (command == NAND_CMD_STATUS) chip->flags |= NANDSIM_CHIP_GET_STATUS; else { ev = create_event(chip, NANDSIM_EV_CMD, 1); *(uint8_t *)ev->data = command; send_event(ev); } return (0); }
static int nandsim_send_address(device_t dev, uint8_t addr) { struct nandsim_ev *ev; struct nandsim_softc *sc; struct nandsim_chip *chip; sc = device_get_softc(dev); chip = sc->active_chip; if (chip == NULL) return (0); KASSERT((sc->address_type != ADDR_NONE), ("unexpected address")); nandsim_log(chip, NANDSIM_LOG_EV, "Send addr %x\n", addr); ev = create_event(chip, NANDSIM_EV_ADDR, 1); *((uint8_t *)(ev->data)) = addr; send_event(ev); return (0); }
static void nandsim_write_word(device_t dev, uint16_t word) { struct nandsim_softc *sc; struct nandsim_chip *chip; uint16_t *data_ptr; uint8_t *byte_ptr = (uint8_t *)&word; sc = device_get_softc(dev); chip = sc->active_chip; if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) { if ((chip->data.index + 1) < chip->data.size) { byte_corrupt(chip, byte_ptr); byte_corrupt(chip, byte_ptr + 1); data_ptr = (uint16_t *)&(chip->data.data_ptr[chip->data.index]); *data_ptr &= word; chip->data.index += 2; } nandsim_log(chip, NANDSIM_LOG_DATA, "write %04x\n", word); } }
static uint8_t nandsim_read_byte(device_t dev) { struct nandsim_softc *sc; struct nandsim_chip *chip; uint8_t ret = 0xff; sc = device_get_softc(dev); chip = sc->active_chip; if (chip && !(chip->flags & NANDSIM_CHIP_FROZEN)) { if (chip->flags & NANDSIM_CHIP_GET_STATUS) { nandsim_chip_timeout(chip); ret = nandchip_get_status(chip); chip->flags &= ~NANDSIM_CHIP_GET_STATUS; } else if (chip->data.index < chip->data.size) { ret = chip->data.data_ptr[chip->data.index++]; byte_corrupt(chip, &ret); } nandsim_log(chip, NANDSIM_LOG_DATA, "read %02x\n", ret); } return (ret); }