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 *)&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