nandsim_chip.c revision 314667
1/*-
2 * Copyright (C) 2009-2012 Semihalf
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/sys/dev/nand/nandsim_chip.c 314667 2017-03-04 13:03:31Z avg $");
29
30#include <sys/param.h>
31#include <sys/types.h>
32#include <sys/systm.h>
33#include <sys/kernel.h>
34#include <sys/lock.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/mutex.h>
38#include <sys/proc.h>
39#include <sys/sched.h>
40#include <sys/kthread.h>
41#include <sys/unistd.h>
42
43#include <dev/nand/nand.h>
44#include <dev/nand/nandsim_chip.h>
45#include <dev/nand/nandsim_log.h>
46#include <dev/nand/nandsim_swap.h>
47
48MALLOC_DEFINE(M_NANDSIM, "NANDsim", "NANDsim dynamic data");
49
50#define NANDSIM_CHIP_LOCK(chip)		mtx_lock(&(chip)->ns_lock)
51#define	NANDSIM_CHIP_UNLOCK(chip)	mtx_unlock(&(chip)->ns_lock)
52
53static nandsim_evh_t erase_evh;
54static nandsim_evh_t idle_evh;
55static nandsim_evh_t poweron_evh;
56static nandsim_evh_t reset_evh;
57static nandsim_evh_t read_evh;
58static nandsim_evh_t readid_evh;
59static nandsim_evh_t readparam_evh;
60static nandsim_evh_t write_evh;
61
62static void nandsim_loop(void *);
63static void nandsim_undefined(struct nandsim_chip *, uint8_t);
64static void nandsim_bad_address(struct nandsim_chip *, uint8_t *);
65static void nandsim_ignore_address(struct nandsim_chip *, uint8_t);
66static void nandsim_sm_error(struct nandsim_chip *);
67static void nandsim_start_handler(struct nandsim_chip *, nandsim_evh_t);
68
69static void nandsim_callout_eh(void *);
70static int  nandsim_delay(struct nandsim_chip *, int);
71
72static int  nandsim_bbm_init(struct nandsim_chip *, uint32_t, uint32_t *);
73static int  nandsim_blk_state_init(struct nandsim_chip *, uint32_t, uint32_t);
74static void nandsim_blk_state_destroy(struct nandsim_chip *);
75static int  nandchip_is_block_valid(struct nandsim_chip *, int);
76
77static void nandchip_set_status(struct nandsim_chip *, uint8_t);
78static void nandchip_clear_status(struct nandsim_chip *, uint8_t);
79
80struct proc *nandsim_proc;
81
82struct nandsim_chip *
83nandsim_chip_init(struct nandsim_softc* sc, uint8_t chip_num,
84    struct sim_chip *sim_chip)
85{
86	struct nandsim_chip *chip;
87	struct onfi_params *chip_param;
88	char swapfile[20];
89	uint32_t size;
90	int error;
91
92	chip = malloc(sizeof(*chip), M_NANDSIM, M_WAITOK | M_ZERO);
93	if (!chip)
94		return (NULL);
95
96	mtx_init(&chip->ns_lock, "nandsim lock", NULL, MTX_DEF);
97	callout_init(&chip->ns_callout, 1);
98	STAILQ_INIT(&chip->nandsim_events);
99
100	chip->chip_num = chip_num;
101	chip->ctrl_num = sim_chip->ctrl_num;
102	chip->sc = sc;
103
104	if (!sim_chip->is_wp)
105		nandchip_set_status(chip, NAND_STATUS_WP);
106
107	chip_param = &chip->params;
108
109	chip->id.dev_id = sim_chip->device_id;
110	chip->id.man_id = sim_chip->manufact_id;
111
112	chip->error_ratio = sim_chip->error_ratio;
113	chip->wear_level = sim_chip->wear_level;
114	chip->prog_delay = sim_chip->prog_time;
115	chip->erase_delay = sim_chip->erase_time;
116	chip->read_delay = sim_chip->read_time;
117
118	chip_param->t_prog = sim_chip->prog_time;
119	chip_param->t_bers = sim_chip->erase_time;
120	chip_param->t_r = sim_chip->read_time;
121	bcopy("onfi", &chip_param->signature, 4);
122
123	chip_param->manufacturer_id = sim_chip->manufact_id;
124	strncpy(chip_param->manufacturer_name, sim_chip->manufacturer, 12);
125	chip_param->manufacturer_name[11] = 0;
126	strncpy(chip_param->device_model, sim_chip->device_model, 20);
127	chip_param->device_model[19] = 0;
128
129	chip_param->bytes_per_page = sim_chip->page_size;
130	chip_param->spare_bytes_per_page = sim_chip->oob_size;
131	chip_param->pages_per_block = sim_chip->pgs_per_blk;
132	chip_param->blocks_per_lun = sim_chip->blks_per_lun;
133	chip_param->luns = sim_chip->luns;
134
135	init_chip_geom(&chip->cg, chip_param->luns, chip_param->blocks_per_lun,
136	    chip_param->pages_per_block, chip_param->bytes_per_page,
137	    chip_param->spare_bytes_per_page);
138
139	chip_param->address_cycles = sim_chip->row_addr_cycles |
140	    (sim_chip->col_addr_cycles << 4);
141	chip_param->features = sim_chip->features;
142	if (sim_chip->width == 16)
143		chip_param->features |= ONFI_FEAT_16BIT;
144
145	size = chip_param->blocks_per_lun * chip_param->luns;
146
147	error = nandsim_blk_state_init(chip, size, sim_chip->wear_level);
148	if (error) {
149		mtx_destroy(&chip->ns_lock);
150		free(chip, M_NANDSIM);
151		return (NULL);
152	}
153
154	error = nandsim_bbm_init(chip, size, sim_chip->bad_block_map);
155	if (error) {
156		mtx_destroy(&chip->ns_lock);
157		nandsim_blk_state_destroy(chip);
158		free(chip, M_NANDSIM);
159		return (NULL);
160	}
161
162	nandsim_start_handler(chip, poweron_evh);
163
164	nand_debug(NDBG_SIM,"Create thread for chip%d [%8p]", chip->chip_num,
165	    chip);
166	/* Create chip thread */
167	error = kproc_kthread_add(nandsim_loop, chip, &nandsim_proc,
168	    &chip->nandsim_td, RFSTOPPED | RFHIGHPID,
169	    0, "nandsim", "chip");
170	if (error) {
171		mtx_destroy(&chip->ns_lock);
172		nandsim_blk_state_destroy(chip);
173		free(chip, M_NANDSIM);
174		return (NULL);
175	}
176
177	thread_lock(chip->nandsim_td);
178	sched_class(chip->nandsim_td, PRI_REALTIME);
179	sched_add(chip->nandsim_td, SRQ_BORING);
180	thread_unlock(chip->nandsim_td);
181
182	size = (chip_param->bytes_per_page +
183	    chip_param->spare_bytes_per_page) *
184	    chip_param->pages_per_block;
185
186	sprintf(swapfile, "chip%d%d.swp", chip->ctrl_num, chip->chip_num);
187	chip->swap = nandsim_swap_init(swapfile, chip_param->blocks_per_lun *
188	    chip_param->luns, size);
189	if (!chip->swap)
190		nandsim_chip_destroy(chip);
191
192	/* Wait for new thread to enter main loop */
193	tsleep(chip->nandsim_td, PWAIT, "ns_chip", 1 * hz);
194
195	return (chip);
196}
197
198static int
199nandsim_blk_state_init(struct nandsim_chip *chip, uint32_t size,
200    uint32_t wear_lev)
201{
202	int i;
203
204	if (!chip || size == 0)
205		return (-1);
206
207	chip->blk_state = malloc(size * sizeof(struct nandsim_block_state),
208	    M_NANDSIM, M_WAITOK | M_ZERO);
209	if (!chip->blk_state) {
210		return (-1);
211	}
212
213	for (i = 0; i < size; i++) {
214		if (wear_lev)
215			chip->blk_state[i].wear_lev = wear_lev;
216		else
217			chip->blk_state[i].wear_lev = -1;
218	}
219
220	return (0);
221}
222
223static void
224nandsim_blk_state_destroy(struct nandsim_chip *chip)
225{
226
227	if (chip && chip->blk_state)
228		free(chip->blk_state, M_NANDSIM);
229}
230
231static int
232nandsim_bbm_init(struct nandsim_chip *chip, uint32_t size,
233    uint32_t *sim_bbm)
234{
235	uint32_t index;
236	int i;
237
238	if ((chip == NULL) || (size == 0))
239		return (-1);
240
241	if (chip->blk_state == NULL)
242		return (-1);
243
244	if (sim_bbm == NULL)
245		return (0);
246
247	for (i = 0; i < MAX_BAD_BLOCKS; i++) {
248		index = sim_bbm[i];
249
250		if (index == 0xffffffff)
251			break;
252		else if (index > size)
253			return (-1);
254		else
255			chip->blk_state[index].is_bad = 1;
256	}
257
258	return (0);
259}
260
261void
262nandsim_chip_destroy(struct nandsim_chip *chip)
263{
264	struct nandsim_ev *ev;
265
266	ev = create_event(chip, NANDSIM_EV_EXIT, 0);
267	if (ev)
268		send_event(ev);
269}
270
271void
272nandsim_chip_freeze(struct nandsim_chip *chip)
273{
274
275	chip->flags |= NANDSIM_CHIP_FROZEN;
276}
277
278static void
279nandsim_loop(void *arg)
280{
281	struct nandsim_chip *chip = (struct nandsim_chip *)arg;
282	struct nandsim_ev *ev;
283
284	nand_debug(NDBG_SIM,"Start main loop for chip%d [%8p]", chip->chip_num,
285	    chip);
286	for(;;) {
287		NANDSIM_CHIP_LOCK(chip);
288		if (!(chip->flags & NANDSIM_CHIP_ACTIVE)) {
289			chip->flags |= NANDSIM_CHIP_ACTIVE;
290			wakeup(chip->nandsim_td);
291		}
292
293		if (STAILQ_EMPTY(&chip->nandsim_events)) {
294			nand_debug(NDBG_SIM,"Chip%d [%8p] going sleep",
295			    chip->chip_num, chip);
296			msleep(chip, &chip->ns_lock, PRIBIO, "nandev", 0);
297		}
298
299		ev = STAILQ_FIRST(&chip->nandsim_events);
300		STAILQ_REMOVE_HEAD(&chip->nandsim_events, links);
301		NANDSIM_CHIP_UNLOCK(chip);
302		if (ev->type == NANDSIM_EV_EXIT) {
303			NANDSIM_CHIP_LOCK(chip);
304			destroy_event(ev);
305			wakeup(ev);
306			while (!STAILQ_EMPTY(&chip->nandsim_events)) {
307				ev = STAILQ_FIRST(&chip->nandsim_events);
308				STAILQ_REMOVE_HEAD(&chip->nandsim_events,
309				    links);
310				destroy_event(ev);
311				wakeup(ev);
312			};
313			NANDSIM_CHIP_UNLOCK(chip);
314			nandsim_log(chip, NANDSIM_LOG_SM, "destroyed\n");
315			mtx_destroy(&chip->ns_lock);
316			nandsim_blk_state_destroy(chip);
317			nandsim_swap_destroy(chip->swap);
318			free(chip, M_NANDSIM);
319			nandsim_proc = NULL;
320
321			kthread_exit();
322		}
323
324		if (!(chip->flags & NANDSIM_CHIP_FROZEN)) {
325			nand_debug(NDBG_SIM,"Chip [%x] get event [%x]",
326			    chip->chip_num, ev->type);
327			chip->ev_handler(chip, ev->type, ev->data);
328		}
329
330		wakeup(ev);
331		destroy_event(ev);
332	}
333
334}
335
336struct nandsim_ev *
337create_event(struct nandsim_chip *chip, uint8_t type, uint8_t data_size)
338{
339	struct nandsim_ev *ev;
340
341	ev = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
342	if (!ev) {
343		nand_debug(NDBG_SIM,"Cannot create event");
344		return (NULL);
345	}
346
347	if (data_size > 0)
348		ev->data = malloc(sizeof(*ev), M_NANDSIM, M_NOWAIT | M_ZERO);
349	ev->type = type;
350	ev->chip = chip;
351
352	return (ev);
353}
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 *)&params->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