1220922Spjd/*- 2220922Spjd * Copyright (C) 2009-2012 Semihalf 3220922Spjd * All rights reserved. 4220922Spjd * 5220922Spjd * Redistribution and use in source and binary forms, with or without 6220922Spjd * modification, are permitted provided that the following conditions 7220922Spjd * are met: 8220922Spjd * 1. Redistributions of source code must retain the above copyright 9220922Spjd * notice, this list of conditions and the following disclaimer. 10220922Spjd * 2. Redistributions in binary form must reproduce the above copyright 11220922Spjd * notice, this list of conditions and the following disclaimer in the 12220922Spjd * documentation and/or other materials provided with the distribution. 13220922Spjd * 14220922Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15220922Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16220922Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17220922Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18220922Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19220922Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20220922Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21220922Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22220922Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23220922Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24220922Spjd * SUCH DAMAGE. 25220922Spjd */ 26220922Spjd 27220922Spjd#include <sys/cdefs.h> 28220922Spjd__FBSDID("$FreeBSD$"); 29220922Spjd 30220922Spjd#include <sys/param.h> 31220922Spjd#include <sys/types.h> 32220922Spjd#include <sys/systm.h> 33220922Spjd#include <sys/kernel.h> 34220922Spjd#include <sys/lock.h> 35220922Spjd#include <sys/malloc.h> 36220922Spjd#include <sys/module.h> 37220922Spjd#include <sys/mutex.h> 38220922Spjd#include <sys/proc.h> 39220922Spjd#include <sys/sched.h> 40220922Spjd#include <sys/kthread.h> 41220922Spjd#include <sys/unistd.h> 42220922Spjd 43220922Spjd#include <dev/nand/nand.h> 44220922Spjd#include <dev/nand/nandsim_chip.h> 45220922Spjd#include <dev/nand/nandsim_log.h> 46220922Spjd#include <dev/nand/nandsim_swap.h> 47220922Spjd 48220922SpjdMALLOC_DEFINE(M_NANDSIM, "NANDsim", "NANDsim dynamic data"); 49220922Spjd 50220922Spjd#define NANDSIM_CHIP_LOCK(chip) mtx_lock(&(chip)->ns_lock) 51220922Spjd#define NANDSIM_CHIP_UNLOCK(chip) mtx_unlock(&(chip)->ns_lock) 52220922Spjd 53220922Spjdstatic nandsim_evh_t erase_evh; 54220922Spjdstatic nandsim_evh_t idle_evh; 55220922Spjdstatic nandsim_evh_t poweron_evh; 56220922Spjdstatic nandsim_evh_t reset_evh; 57220922Spjdstatic nandsim_evh_t read_evh; 58220922Spjdstatic nandsim_evh_t readid_evh; 59220922Spjdstatic nandsim_evh_t readparam_evh; 60221624Spjdstatic nandsim_evh_t write_evh; 61221624Spjd 62220922Spjdstatic void nandsim_loop(void *); 63220922Spjdstatic void nandsim_undefined(struct nandsim_chip *, uint8_t); 64220922Spjdstatic void nandsim_bad_address(struct nandsim_chip *, uint8_t *); 65221624Spjdstatic void nandsim_ignore_address(struct nandsim_chip *, uint8_t); 66221624Spjdstatic void nandsim_sm_error(struct nandsim_chip *); 67220922Spjdstatic void nandsim_start_handler(struct nandsim_chip *, nandsim_evh_t); 68220922Spjd 69220922Spjdstatic void nandsim_callout_eh(void *); 70220922Spjdstatic int nandsim_delay(struct nandsim_chip *, int); 71220922Spjd 72220922Spjdstatic int nandsim_bbm_init(struct nandsim_chip *, uint32_t, uint32_t *); 73220922Spjdstatic int nandsim_blk_state_init(struct nandsim_chip *, uint32_t, uint32_t); 74220922Spjdstatic void nandsim_blk_state_destroy(struct nandsim_chip *); 75220922Spjdstatic int nandchip_is_block_valid(struct nandsim_chip *, int); 76220922Spjd 77220922Spjdstatic void nandchip_set_status(struct nandsim_chip *, uint8_t); 78220922Spjdstatic void nandchip_clear_status(struct nandsim_chip *, uint8_t); 79220922Spjd 80220922Spjdstruct proc *nandsim_proc; 81220922Spjd 82220922Spjdstruct nandsim_chip * 83220922Spjdnandsim_chip_init(struct nandsim_softc* sc, uint8_t chip_num, 84220922Spjd struct sim_chip *sim_chip) 85220922Spjd{ 86220922Spjd struct nandsim_chip *chip; 87220922Spjd struct onfi_params *chip_param; 88220922Spjd char swapfile[20]; 89220922Spjd uint32_t size; 90220922Spjd int error; 91220922Spjd 92220922Spjd chip = malloc(sizeof(*chip), M_NANDSIM, M_WAITOK | M_ZERO); 93220922Spjd if (!chip) 94238116Spjd return (NULL); 95220922Spjd 96220922Spjd mtx_init(&chip->ns_lock, "nandsim lock", NULL, MTX_DEF); 97220922Spjd callout_init(&chip->ns_callout, CALLOUT_MPSAFE); 98220922Spjd STAILQ_INIT(&chip->nandsim_events); 99220922Spjd 100238116Spjd chip->chip_num = chip_num; 101238116Spjd chip->ctrl_num = sim_chip->ctrl_num; 102238116Spjd chip->sc = sc; 103238116Spjd 104238116Spjd if (!sim_chip->is_wp) 105220922Spjd nandchip_set_status(chip, NAND_STATUS_WP); 106220922Spjd 107238116Spjd chip_param = &chip->params; 108220922Spjd 109220922Spjd chip->id.dev_id = sim_chip->device_id; 110220922Spjd chip->id.man_id = sim_chip->manufact_id; 111221624Spjd 112220922Spjd chip->error_ratio = sim_chip->error_ratio; 113220922Spjd chip->wear_level = sim_chip->wear_level; 114220922Spjd chip->prog_delay = sim_chip->prog_time; 115220922Spjd chip->erase_delay = sim_chip->erase_time; 116220922Spjd chip->read_delay = sim_chip->read_time; 117220922Spjd 118220922Spjd chip_param->t_prog = sim_chip->prog_time; 119220922Spjd chip_param->t_bers = sim_chip->erase_time; 120220922Spjd chip_param->t_r = sim_chip->read_time; 121220922Spjd bcopy("onfi", &chip_param->signature, 4); 122220922Spjd 123220922Spjd chip_param->manufacturer_id = sim_chip->manufact_id; 124220922Spjd strncpy(chip_param->manufacturer_name, sim_chip->manufacturer, 12); 125220922Spjd chip_param->manufacturer_name[11] = 0; 126220922Spjd strncpy(chip_param->device_model, sim_chip->device_model, 20); 127220922Spjd chip_param->device_model[19] = 0; 128220922Spjd 129220922Spjd chip_param->bytes_per_page = sim_chip->page_size; 130220922Spjd chip_param->spare_bytes_per_page = sim_chip->oob_size; 131220922Spjd chip_param->pages_per_block = sim_chip->pgs_per_blk; 132220922Spjd chip_param->blocks_per_lun = sim_chip->blks_per_lun; 133221953Strociny chip_param->luns = sim_chip->luns; 134220922Spjd 135220922Spjd init_chip_geom(&chip->cg, chip_param->luns, chip_param->blocks_per_lun, 136220922Spjd chip_param->pages_per_block, chip_param->bytes_per_page, 137220922Spjd chip_param->spare_bytes_per_page); 138220922Spjd 139220922Spjd chip_param->address_cycles = sim_chip->row_addr_cycles | 140220922Spjd (sim_chip->col_addr_cycles << 4); 141220922Spjd chip_param->features = sim_chip->features; 142220922Spjd if (sim_chip->width == 16) 143220922Spjd chip_param->features |= ONFI_FEAT_16BIT; 144220922Spjd 145220922Spjd size = chip_param->blocks_per_lun * chip_param->luns; 146220922Spjd 147220922Spjd error = nandsim_blk_state_init(chip, size, sim_chip->wear_level); 148220922Spjd if (error) { 149220922Spjd mtx_destroy(&chip->ns_lock); 150220922Spjd free(chip, M_NANDSIM); 151220922Spjd return (NULL); 152220922Spjd } 153220922Spjd 154220922Spjd error = nandsim_bbm_init(chip, size, sim_chip->bad_block_map); 155220922Spjd if (error) { 156220922Spjd mtx_destroy(&chip->ns_lock); 157220922Spjd nandsim_blk_state_destroy(chip); 158220922Spjd free(chip, M_NANDSIM); 159220922Spjd return (NULL); 160220922Spjd } 161220922Spjd 162220922Spjd nandsim_start_handler(chip, poweron_evh); 163220922Spjd 164220922Spjd nand_debug(NDBG_SIM,"Create thread for chip%d [%8p]", chip->chip_num, 165221624Spjd chip); 166220922Spjd /* Create chip thread */ 167220922Spjd error = kproc_kthread_add(nandsim_loop, chip, &nandsim_proc, 168220922Spjd &chip->nandsim_td, RFSTOPPED | RFHIGHPID, 169220922Spjd 0, "nandsim", "chip"); 170220922Spjd if (error) { 171220922Spjd mtx_destroy(&chip->ns_lock); 172220922Spjd nandsim_blk_state_destroy(chip); 173220922Spjd free(chip, M_NANDSIM); 174220922Spjd return (NULL); 175220922Spjd } 176220922Spjd 177220922Spjd thread_lock(chip->nandsim_td); 178220922Spjd sched_class(chip->nandsim_td, PRI_REALTIME); 179220922Spjd sched_add(chip->nandsim_td, SRQ_BORING); 180220922Spjd thread_unlock(chip->nandsim_td); 181220922Spjd 182220922Spjd size = (chip_param->bytes_per_page + 183221624Spjd chip_param->spare_bytes_per_page) * 184220922Spjd chip_param->pages_per_block; 185220922Spjd 186220922Spjd sprintf(swapfile, "chip%d%d.swp", chip->ctrl_num, chip->chip_num); 187220922Spjd chip->swap = nandsim_swap_init(swapfile, chip_param->blocks_per_lun * 188220922Spjd chip_param->luns, size); 189220922Spjd if (!chip->swap) 190220922Spjd nandsim_chip_destroy(chip); 191220922Spjd 192220922Spjd /* Wait for new thread to enter main loop */ 193220922Spjd tsleep(chip->nandsim_td, PWAIT, "ns_chip", 1 * hz); 194220922Spjd 195220922Spjd return (chip); 196239184Spjd} 197220922Spjd 198220922Spjdstatic int 199220922Spjdnandsim_blk_state_init(struct nandsim_chip *chip, uint32_t size, 200239184Spjd uint32_t wear_lev) 201239184Spjd{ 202239184Spjd int i; 203239184Spjd 204239184Spjd if (!chip || size == 0) 205239184Spjd return (-1); 206239184Spjd 207239184Spjd chip->blk_state = malloc(size * sizeof(struct nandsim_block_state), 208239184Spjd M_NANDSIM, M_WAITOK | M_ZERO); 209239184Spjd if (!chip->blk_state) { 210220922Spjd return (-1); 211239184Spjd } 212220922Spjd 213220922Spjd for (i = 0; i < size; i++) { 214220922Spjd if (wear_lev) 215220922Spjd chip->blk_state[i].wear_lev = wear_lev; 216220922Spjd else 217220922Spjd chip->blk_state[i].wear_lev = -1; 218220922Spjd } 219220922Spjd 220220922Spjd return (0); 221220922Spjd} 222220922Spjd 223220922Spjdstatic void 224220922Spjdnandsim_blk_state_destroy(struct nandsim_chip *chip) 225220922Spjd{ 226220922Spjd 227220922Spjd if (chip && chip->blk_state) 228220922Spjd free(chip->blk_state, M_NANDSIM); 229220922Spjd} 230220922Spjd 231220922Spjdstatic int 232220922Spjdnandsim_bbm_init(struct nandsim_chip *chip, uint32_t size, 233220923Spjd uint32_t *sim_bbm) 234220923Spjd{ 235220923Spjd uint32_t index; 236220923Spjd int i; 237220923Spjd 238220923Spjd if ((chip == NULL) || (size == 0)) 239220923Spjd return (-1); 240220923Spjd 241220923Spjd if (chip->blk_state == NULL) 242220923Spjd return (-1); 243220922Spjd 244239184Spjd if (sim_bbm == NULL) 245220922Spjd return (0); 246220922Spjd 247220922Spjd for (i = 0; i < MAX_BAD_BLOCKS; i++) { 248220922Spjd index = sim_bbm[i]; 249220922Spjd 250220922Spjd if (index == 0xffffffff) 251220922Spjd break; 252220922Spjd else if (index > size) 253220922Spjd return (-1); 254220922Spjd else 255220922Spjd chip->blk_state[index].is_bad = 1; 256220922Spjd } 257220922Spjd 258220922Spjd return (0); 259220922Spjd} 260220922Spjd 261220922Spjdvoid 262220922Spjdnandsim_chip_destroy(struct nandsim_chip *chip) 263220922Spjd{ 264220922Spjd struct nandsim_ev *ev; 265220922Spjd 266220922Spjd ev = create_event(chip, NANDSIM_EV_EXIT, 0); 267220922Spjd if (ev) 268220922Spjd send_event(ev); 269220922Spjd} 270220922Spjd 271220922Spjdvoid 272220922Spjdnandsim_chip_freeze(struct nandsim_chip *chip) 273220922Spjd{ 274220922Spjd 275220922Spjd chip->flags |= NANDSIM_CHIP_FROZEN; 276220922Spjd} 277220922Spjd 278220922Spjdstatic void 279220922Spjdnandsim_loop(void *arg) 280220922Spjd{ 281220922Spjd struct nandsim_chip *chip = (struct nandsim_chip *)arg; 282220922Spjd struct nandsim_ev *ev; 283220922Spjd 284220922Spjd nand_debug(NDBG_SIM,"Start main loop for chip%d [%8p]", chip->chip_num, 285220922Spjd chip); 286220922Spjd for(;;) { 287220922Spjd NANDSIM_CHIP_LOCK(chip); 288220922Spjd if (!(chip->flags & NANDSIM_CHIP_ACTIVE)) { 289220923Spjd chip->flags |= NANDSIM_CHIP_ACTIVE; 290220923Spjd wakeup(chip->nandsim_td); 291220923Spjd } 292220923Spjd 293221624Spjd if (STAILQ_EMPTY(&chip->nandsim_events)) { 294221624Spjd nand_debug(NDBG_SIM,"Chip%d [%8p] going sleep", 295220923Spjd chip->chip_num, chip); 296220923Spjd msleep(chip, &chip->ns_lock, PRIBIO, "nandev", 0); 297220923Spjd } 298220922Spjd 299220922Spjd ev = STAILQ_FIRST(&chip->nandsim_events); 300220922Spjd STAILQ_REMOVE_HEAD(&chip->nandsim_events, links); 301220922Spjd NANDSIM_CHIP_UNLOCK(chip); 302220922Spjd if (ev->type == NANDSIM_EV_EXIT) { 303220922Spjd NANDSIM_CHIP_LOCK(chip); 304220922Spjd destroy_event(ev); 305220922Spjd wakeup(ev); 306220922Spjd while (!STAILQ_EMPTY(&chip->nandsim_events)) { 307220922Spjd ev = STAILQ_FIRST(&chip->nandsim_events); 308220922Spjd STAILQ_REMOVE_HEAD(&chip->nandsim_events, 309220922Spjd links); 310220922Spjd destroy_event(ev); 311220922Spjd wakeup(ev); 312220922Spjd }; 313220922Spjd NANDSIM_CHIP_UNLOCK(chip); 314220922Spjd nandsim_log(chip, NANDSIM_LOG_SM, "destroyed\n"); 315220922Spjd mtx_destroy(&chip->ns_lock); 316220922Spjd nandsim_blk_state_destroy(chip); 317220922Spjd nandsim_swap_destroy(chip->swap); 318220922Spjd free(chip, M_NANDSIM); 319220922Spjd nandsim_proc = NULL; 320220922Spjd 321220922Spjd kthread_exit(); 322220922Spjd } 323220922Spjd 324220922Spjd if (!(chip->flags & NANDSIM_CHIP_FROZEN)) { 325221624Spjd nand_debug(NDBG_SIM,"Chip [%x] get event [%x]", 326221624Spjd chip->chip_num, ev->type); 327220922Spjd chip->ev_handler(chip, ev->type, ev->data); 328220922Spjd } 329220922Spjd 330220922Spjd wakeup(ev); 331220922Spjd destroy_event(ev); 332220922Spjd } 333220922Spjd 334220922Spjd} 335220922Spjd 336220922Spjdstruct nandsim_ev * 337220922Spjdcreate_event(struct nandsim_chip *chip, uint8_t type, uint8_t data_size) 338221624Spjd{ 339221624Spjd struct nandsim_ev *ev; 340220923Spjd 341220923Spjd ev = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO); 342220923Spjd if (!ev) { 343220922Spjd nand_debug(NDBG_SIM,"Cannot create event"); 344220922Spjd return (NULL); 345220922Spjd } 346220922Spjd 347220922Spjd if (data_size > 0) 348220922Spjd ev->data = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO); 349220922Spjd ev->type = type; 350220922Spjd ev->chip = chip; 351220922Spjd 352220922Spjd return (ev); 353220922Spjd} 354 355void 356destroy_event(struct nandsim_ev *ev) 357{ 358 359 if (ev->data) 360 free(ev->data, M_NANDSIM); 361 free(ev, M_NANDSIM); 362} 363 364int 365send_event(struct nandsim_ev *ev) 366{ 367 struct nandsim_chip *chip = ev->chip; 368 369 if (!(chip->flags & NANDSIM_CHIP_FROZEN)) { 370 nand_debug(NDBG_SIM,"Chip%d [%p] send event %x", 371 chip->chip_num, chip, ev->type); 372 373 NANDSIM_CHIP_LOCK(chip); 374 STAILQ_INSERT_TAIL(&chip->nandsim_events, ev, links); 375 NANDSIM_CHIP_UNLOCK(chip); 376 377 wakeup(chip); 378 if ((ev->type != NANDSIM_EV_TIMEOUT) && chip->nandsim_td && 379 (curthread != chip->nandsim_td)) 380 tsleep(ev, PWAIT, "ns_ev", 5 * hz); 381 } 382 383 return (0); 384} 385 386static void 387nandsim_callout_eh(void *arg) 388{ 389 struct nandsim_ev *ev = (struct nandsim_ev *)arg; 390 391 send_event(ev); 392} 393 394static int 395nandsim_delay(struct nandsim_chip *chip, int timeout) 396{ 397 struct nandsim_ev *ev; 398 struct timeval delay; 399 int tm; 400 401 nand_debug(NDBG_SIM,"Chip[%d] Set delay: %d", chip->chip_num, timeout); 402 403 ev = create_event(chip, NANDSIM_EV_TIMEOUT, 0); 404 if (!ev) 405 return (-1); 406 407 chip->sm_state = NANDSIM_STATE_TIMEOUT; 408 tm = (timeout/10000) * (hz / 100); 409 if (callout_reset(&chip->ns_callout, tm, nandsim_callout_eh, ev)) 410 return (-1); 411 412 delay.tv_sec = chip->read_delay / 1000000; 413 delay.tv_usec = chip->read_delay % 1000000; 414 timevaladd(&chip->delay_tv, &delay); 415 416 return (0); 417} 418 419static void 420nandsim_start_handler(struct nandsim_chip *chip, nandsim_evh_t evh) 421{ 422 struct nandsim_ev *ev; 423 424 chip->ev_handler = evh; 425 426 nand_debug(NDBG_SIM,"Start handler %p for chip%d [%p]", evh, 427 chip->chip_num, chip); 428 ev = create_event(chip, NANDSIM_EV_START, 0); 429 if (!ev) 430 nandsim_sm_error(chip); 431 432 send_event(ev); 433} 434 435static void 436nandchip_set_data(struct nandsim_chip *chip, uint8_t *data, uint32_t len, 437 uint32_t idx) 438{ 439 440 nand_debug(NDBG_SIM,"Chip [%x] data %p [%x] at %x", chip->chip_num, 441 data, len, idx); 442 chip->data.data_ptr = data; 443 chip->data.size = len; 444 chip->data.index = idx; 445} 446 447static int 448nandchip_chip_space(struct nandsim_chip *chip, int32_t row, int32_t column, 449 size_t size, uint8_t writing) 450{ 451 struct block_space *blk_space; 452 uint32_t lun, block, page, offset, block_size; 453 int err; 454 455 block_size = chip->cg.block_size + 456 (chip->cg.oob_size * chip->cg.pgs_per_blk); 457 458 err = nand_row_to_blkpg(&chip->cg, row, &lun, &block, &page); 459 if (err) { 460 nand_debug(NDBG_SIM,"cannot get address\n"); 461 return (-1); 462 } 463 464 if (!nandchip_is_block_valid(chip, block)) { 465 nandchip_set_data(chip, NULL, 0, 0); 466 return (-1); 467 } 468 469 blk_space = get_bs(chip->swap, block, writing); 470 if (!blk_space) { 471 nandchip_set_data(chip, NULL, 0, 0); 472 return (-1); 473 } 474 475 if (size > block_size) 476 size = block_size; 477 478 if (size == block_size) { 479 offset = 0; 480 column = 0; 481 } else 482 offset = page * (chip->cg.page_size + chip->cg.oob_size); 483 484 nandchip_set_data(chip, &blk_space->blk_ptr[offset], size, column); 485 486 return (0); 487} 488 489static int 490nandchip_get_addr_byte(struct nandsim_chip *chip, void *data, uint32_t *value) 491{ 492 int ncycles = 0; 493 uint8_t byte; 494 uint8_t *buffer; 495 496 buffer = (uint8_t *)value; 497 byte = *((uint8_t *)data); 498 499 KASSERT((chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW || 500 chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL), 501 ("unexpected state")); 502 503 if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) { 504 ncycles = chip->params.address_cycles & 0xf; 505 buffer[chip->sm_addr_cycle++] = byte; 506 } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) { 507 ncycles = (chip->params.address_cycles >> 4) & 0xf; 508 buffer[chip->sm_addr_cycle++] = byte; 509 } 510 511 nand_debug(NDBG_SIM, "Chip [%x] read addr byte: %02x (%d of %d)\n", 512 chip->chip_num, byte, chip->sm_addr_cycle, ncycles); 513 514 if (chip->sm_addr_cycle == ncycles) { 515 chip->sm_addr_cycle = 0; 516 return (0); 517 } 518 519 return (1); 520} 521 522static int 523nandchip_is_block_valid(struct nandsim_chip *chip, int block_num) 524{ 525 526 if (!chip || !chip->blk_state) 527 return (0); 528 529 if (chip->blk_state[block_num].wear_lev == 0 || 530 chip->blk_state[block_num].is_bad) 531 return (0); 532 533 return (1); 534} 535 536static void 537nandchip_set_status(struct nandsim_chip *chip, uint8_t flags) 538{ 539 540 chip->chip_status |= flags; 541} 542 543static void 544nandchip_clear_status(struct nandsim_chip *chip, uint8_t flags) 545{ 546 547 chip->chip_status &= ~flags; 548} 549 550uint8_t 551nandchip_get_status(struct nandsim_chip *chip) 552{ 553 return (chip->chip_status); 554} 555 556void 557nandsim_chip_timeout(struct nandsim_chip *chip) 558{ 559 struct timeval tv; 560 561 getmicrotime(&tv); 562 563 if (chip->sm_state == NANDSIM_STATE_TIMEOUT && 564 timevalcmp(&tv, &chip->delay_tv, >=)) { 565 nandchip_set_status(chip, NAND_STATUS_RDY); 566 } 567} 568void 569poweron_evh(struct nandsim_chip *chip, uint32_t type, void *data) 570{ 571 uint8_t cmd; 572 573 if (type == NANDSIM_EV_START) 574 chip->sm_state = NANDSIM_STATE_IDLE; 575 else if (type == NANDSIM_EV_CMD) { 576 cmd = *(uint8_t *)data; 577 switch(cmd) { 578 case NAND_CMD_RESET: 579 nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n"); 580 nandsim_start_handler(chip, reset_evh); 581 break; 582 default: 583 nandsim_undefined(chip, type); 584 break; 585 } 586 } else 587 nandsim_undefined(chip, type); 588} 589 590void 591idle_evh(struct nandsim_chip *chip, uint32_t type, void *data) 592{ 593 uint8_t cmd; 594 595 if (type == NANDSIM_EV_START) { 596 nandsim_log(chip, NANDSIM_LOG_SM, "in IDLE state\n"); 597 chip->sm_state = NANDSIM_STATE_WAIT_CMD; 598 } else if (type == NANDSIM_EV_CMD) { 599 nandchip_clear_status(chip, NAND_STATUS_FAIL); 600 getmicrotime(&chip->delay_tv); 601 cmd = *(uint8_t *)data; 602 switch(cmd) { 603 case NAND_CMD_READ_ID: 604 nandsim_start_handler(chip, readid_evh); 605 break; 606 case NAND_CMD_READ_PARAMETER: 607 nandsim_start_handler(chip, readparam_evh); 608 break; 609 case NAND_CMD_READ: 610 nandsim_start_handler(chip, read_evh); 611 break; 612 case NAND_CMD_PROG: 613 nandsim_start_handler(chip, write_evh); 614 break; 615 case NAND_CMD_ERASE: 616 nandsim_start_handler(chip, erase_evh); 617 break; 618 default: 619 nandsim_undefined(chip, type); 620 break; 621 } 622 } else 623 nandsim_undefined(chip, type); 624} 625 626void 627readid_evh(struct nandsim_chip *chip, uint32_t type, void *data) 628{ 629 struct onfi_params *params; 630 uint8_t addr; 631 632 params = &chip->params; 633 634 if (type == NANDSIM_EV_START) { 635 nandsim_log(chip, NANDSIM_LOG_SM, "in READID state\n"); 636 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE; 637 } else if (type == NANDSIM_EV_ADDR) { 638 639 addr = *((uint8_t *)data); 640 641 if (addr == 0x0) 642 nandchip_set_data(chip, (uint8_t *)&chip->id, 2, 0); 643 else if (addr == ONFI_SIG_ADDR) 644 nandchip_set_data(chip, (uint8_t *)¶ms->signature, 645 4, 0); 646 else 647 nandsim_bad_address(chip, &addr); 648 649 nandsim_start_handler(chip, idle_evh); 650 } else 651 nandsim_undefined(chip, type); 652} 653 654void 655readparam_evh(struct nandsim_chip *chip, uint32_t type, void *data) 656{ 657 struct onfi_params *params; 658 uint8_t addr; 659 660 params = &chip->params; 661 662 if (type == NANDSIM_EV_START) { 663 nandsim_log(chip, NANDSIM_LOG_SM, "in READPARAM state\n"); 664 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_BYTE; 665 } else if (type == NANDSIM_EV_ADDR) { 666 addr = *((uint8_t *)data); 667 668 if (addr == 0) { 669 nandchip_set_data(chip, (uint8_t *)params, 670 sizeof(*params), 0); 671 } else 672 nandsim_bad_address(chip, &addr); 673 674 nandsim_start_handler(chip, idle_evh); 675 } else 676 nandsim_undefined(chip, type); 677} 678 679void 680read_evh(struct nandsim_chip *chip, uint32_t type, void *data) 681{ 682 static uint32_t column = 0, row = 0; 683 uint32_t size; 684 uint8_t cmd; 685 686 size = chip->cg.page_size + chip->cg.oob_size; 687 688 switch (type) { 689 case NANDSIM_EV_START: 690 nandsim_log(chip, NANDSIM_LOG_SM, "in READ state\n"); 691 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL; 692 break; 693 case NANDSIM_EV_ADDR: 694 if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) { 695 if (nandchip_get_addr_byte(chip, data, &column)) 696 break; 697 698 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW; 699 } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) { 700 if (nandchip_get_addr_byte(chip, data, &row)) 701 break; 702 703 chip->sm_state = NANDSIM_STATE_WAIT_CMD; 704 } else 705 nandsim_ignore_address(chip, *((uint8_t *)data)); 706 break; 707 case NANDSIM_EV_CMD: 708 cmd = *(uint8_t *)data; 709 if (chip->sm_state == NANDSIM_STATE_WAIT_CMD && 710 cmd == NAND_CMD_READ_END) { 711 if (chip->read_delay != 0 && 712 nandsim_delay(chip, chip->read_delay) == 0) 713 nandchip_clear_status(chip, NAND_STATUS_RDY); 714 else { 715 nandchip_chip_space(chip, row, column, size, 0); 716 nandchip_set_status(chip, NAND_STATUS_RDY); 717 nandsim_start_handler(chip, idle_evh); 718 } 719 } else 720 nandsim_undefined(chip, type); 721 break; 722 case NANDSIM_EV_TIMEOUT: 723 if (chip->sm_state == NANDSIM_STATE_TIMEOUT) { 724 nandchip_chip_space(chip, row, column, size, 0); 725 nandchip_set_status(chip, NAND_STATUS_RDY); 726 nandsim_start_handler(chip, idle_evh); 727 } else 728 nandsim_undefined(chip, type); 729 break; 730 } 731} 732void 733write_evh(struct nandsim_chip *chip, uint32_t type, void *data) 734{ 735 static uint32_t column, row; 736 uint32_t size; 737 uint8_t cmd; 738 int err; 739 740 size = chip->cg.page_size + chip->cg.oob_size; 741 742 switch(type) { 743 case NANDSIM_EV_START: 744 nandsim_log(chip, NANDSIM_LOG_SM, "in WRITE state\n"); 745 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_COL; 746 break; 747 case NANDSIM_EV_ADDR: 748 if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_COL) { 749 if (nandchip_get_addr_byte(chip, data, &column)) 750 break; 751 752 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW; 753 } else if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) { 754 if (nandchip_get_addr_byte(chip, data, &row)) 755 break; 756 757 err = nandchip_chip_space(chip, row, column, size, 1); 758 if (err == -1) 759 nandchip_set_status(chip, NAND_STATUS_FAIL); 760 761 chip->sm_state = NANDSIM_STATE_WAIT_CMD; 762 } else 763 nandsim_ignore_address(chip, *((uint8_t *)data)); 764 break; 765 case NANDSIM_EV_CMD: 766 cmd = *(uint8_t *)data; 767 if (chip->sm_state == NANDSIM_STATE_WAIT_CMD && 768 cmd == NAND_CMD_PROG_END) { 769 if (chip->prog_delay != 0 && 770 nandsim_delay(chip, chip->prog_delay) == 0) 771 nandchip_clear_status(chip, NAND_STATUS_RDY); 772 else { 773 nandchip_set_status(chip, NAND_STATUS_RDY); 774 nandsim_start_handler(chip, idle_evh); 775 } 776 } else 777 nandsim_undefined(chip, type); 778 break; 779 case NANDSIM_EV_TIMEOUT: 780 if (chip->sm_state == NANDSIM_STATE_TIMEOUT) { 781 nandsim_start_handler(chip, idle_evh); 782 nandchip_set_status(chip, NAND_STATUS_RDY); 783 } else 784 nandsim_undefined(chip, type); 785 break; 786 } 787} 788 789void 790erase_evh(struct nandsim_chip *chip, uint32_t type, void *data) 791{ 792 static uint32_t row, block_size; 793 uint32_t lun, block, page; 794 int err; 795 uint8_t cmd; 796 797 block_size = chip->cg.block_size + 798 (chip->cg.oob_size * chip->cg.pgs_per_blk); 799 800 switch (type) { 801 case NANDSIM_EV_START: 802 nandsim_log(chip, NANDSIM_LOG_SM, "in ERASE state\n"); 803 chip->sm_state = NANDSIM_STATE_WAIT_ADDR_ROW; 804 break; 805 case NANDSIM_EV_CMD: 806 cmd = *(uint8_t *)data; 807 if (chip->sm_state == NANDSIM_STATE_WAIT_CMD && 808 cmd == NAND_CMD_ERASE_END) { 809 if (chip->data.data_ptr != NULL && 810 chip->data.size == block_size) 811 memset(chip->data.data_ptr, 0xff, block_size); 812 else 813 nand_debug(NDBG_SIM,"Bad block erase data\n"); 814 815 err = nand_row_to_blkpg(&chip->cg, row, &lun, 816 &block, &page); 817 if (!err) { 818 if (chip->blk_state[block].wear_lev > 0) 819 chip->blk_state[block].wear_lev--; 820 } 821 822 if (chip->erase_delay != 0 && 823 nandsim_delay(chip, chip->erase_delay) == 0) 824 nandchip_clear_status(chip, NAND_STATUS_RDY); 825 else { 826 nandchip_set_status(chip, NAND_STATUS_RDY); 827 nandsim_start_handler(chip, idle_evh); 828 } 829 } else 830 nandsim_undefined(chip, type); 831 break; 832 case NANDSIM_EV_ADDR: 833 if (chip->sm_state == NANDSIM_STATE_WAIT_ADDR_ROW) { 834 if (nandchip_get_addr_byte(chip, data, &row)) 835 break; 836 837 err = nandchip_chip_space(chip, row, 0, block_size, 1); 838 if (err == -1) { 839 nandchip_set_status(chip, NAND_STATUS_FAIL); 840 } 841 chip->sm_state = NANDSIM_STATE_WAIT_CMD; 842 } else 843 nandsim_ignore_address(chip, *((uint8_t *)data)); 844 break; 845 case NANDSIM_EV_TIMEOUT: 846 if (chip->sm_state == NANDSIM_STATE_TIMEOUT) { 847 nandchip_set_status(chip, NAND_STATUS_RDY); 848 nandsim_start_handler(chip, idle_evh); 849 } else 850 nandsim_undefined(chip, type); 851 break; 852 } 853} 854 855void 856reset_evh(struct nandsim_chip *chip, uint32_t type, void *data) 857{ 858 859 if (type == NANDSIM_EV_START) { 860 nandsim_log(chip, NANDSIM_LOG_SM, "in RESET state\n"); 861 chip->sm_state = NANDSIM_STATE_TIMEOUT; 862 nandchip_set_data(chip, NULL, 0, 0); 863 DELAY(500); 864 nandsim_start_handler(chip, idle_evh); 865 } else 866 nandsim_undefined(chip, type); 867} 868 869static void 870nandsim_undefined(struct nandsim_chip *chip, uint8_t type) 871{ 872 873 nandsim_log(chip, NANDSIM_LOG_ERR, 874 "ERR: Chip received ev %x in state %x\n", 875 type, chip->sm_state); 876 nandsim_start_handler(chip, idle_evh); 877} 878 879static void 880nandsim_bad_address(struct nandsim_chip *chip, uint8_t *addr) 881{ 882 883 nandsim_log(chip, NANDSIM_LOG_ERR, 884 "ERR: Chip received out of range address" 885 "%02x%02x - %02x%02x%02x\n", addr[0], addr[1], addr[2], 886 addr[3], addr[4]); 887} 888 889static void 890nandsim_ignore_address(struct nandsim_chip *chip, uint8_t byte) 891{ 892 nandsim_log(chip, NANDSIM_LOG_SM, "ignored address byte: %d\n", byte); 893} 894 895static void 896nandsim_sm_error(struct nandsim_chip *chip) 897{ 898 899 nandsim_log(chip, NANDSIM_LOG_ERR, "ERR: State machine error." 900 "Restart required.\n"); 901} 902