2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2009-2012 Semihalf
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 /* Simulated NAND controller driver */
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/module.h>
41 #include <sys/malloc.h>
43 #include <dev/nand/nand.h>
44 #include <dev/nand/nandsim.h>
45 #include <dev/nand/nandsim_chip.h>
46 #include <dev/nand/nandsim_log.h>
47 #include <dev/nand/nandsim_swap.h>
50 struct sim_ctrl_conf ctrls[MAX_SIM_DEV];
52 static struct cdev *nandsim_dev;
53 static d_ioctl_t nandsim_ioctl;
55 static void nandsim_init_sim_param(struct sim_param *);
56 static int nandsim_create_ctrl(struct sim_ctrl *);
57 static int nandsim_destroy_ctrl(int);
58 static int nandsim_ctrl_status(struct sim_ctrl *);
59 static int nandsim_create_chip(struct sim_chip *);
60 static int nandsim_destroy_chip(struct sim_ctrl_chip *);
61 static int nandsim_chip_status(struct sim_chip *);
62 static int nandsim_start_ctrl(int);
63 static int nandsim_stop_ctrl(int);
64 static int nandsim_inject_error(struct sim_error *);
65 static int nandsim_get_block_state(struct sim_block_state *);
66 static int nandsim_set_block_state(struct sim_block_state *);
67 static int nandsim_modify(struct sim_mod *);
68 static int nandsim_dump(struct sim_dump *);
69 static int nandsim_restore(struct sim_dump *);
70 static int nandsim_freeze(struct sim_ctrl_chip *);
71 static void nandsim_print_log(struct sim_log *);
72 static struct nandsim_chip *get_nandsim_chip(uint8_t, uint8_t);
74 static struct cdevsw nandsim_cdevsw = {
75 .d_version = D_VERSION,
76 .d_flags = D_NEEDGIANT,
77 .d_ioctl = nandsim_ioctl,
82 nandsim_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
83 int flags, struct thread *td)
88 case NANDSIM_SIM_PARAM:
89 nandsim_init_sim_param((struct sim_param *)data);
91 case NANDSIM_CREATE_CTRL:
92 ret = nandsim_create_ctrl((struct sim_ctrl *)data);
94 case NANDSIM_DESTROY_CTRL:
95 ret = nandsim_destroy_ctrl(*(int *)data);
97 case NANDSIM_STATUS_CTRL:
98 ret = nandsim_ctrl_status((struct sim_ctrl *)data);
100 case NANDSIM_CREATE_CHIP:
101 ret = nandsim_create_chip((struct sim_chip *)data);
103 case NANDSIM_DESTROY_CHIP:
104 ret = nandsim_destroy_chip((struct sim_ctrl_chip *)data);
106 case NANDSIM_STATUS_CHIP:
107 ret = nandsim_chip_status((struct sim_chip *)data);
110 ret = nandsim_modify((struct sim_mod *)data);
112 case NANDSIM_START_CTRL:
113 ret = nandsim_start_ctrl(*(int *)data);
115 case NANDSIM_STOP_CTRL:
116 ret = nandsim_stop_ctrl(*(int *)data);
118 case NANDSIM_INJECT_ERROR:
119 ret = nandsim_inject_error((struct sim_error *)data);
121 case NANDSIM_SET_BLOCK_STATE:
122 ret = nandsim_set_block_state((struct sim_block_state *)data);
124 case NANDSIM_GET_BLOCK_STATE:
125 ret = nandsim_get_block_state((struct sim_block_state *)data);
127 case NANDSIM_PRINT_LOG:
128 nandsim_print_log((struct sim_log *)data);
131 ret = nandsim_dump((struct sim_dump *)data);
133 case NANDSIM_RESTORE:
134 ret = nandsim_restore((struct sim_dump *)data);
137 ret = nandsim_freeze((struct sim_ctrl_chip *)data);
148 nandsim_init_sim_param(struct sim_param *param)
154 nand_debug(NDBG_SIM,"log level:%d output %d", param->log_level,
156 nandsim_log_level = param->log_level;
157 nandsim_log_output = param->log_output;
161 nandsim_create_ctrl(struct sim_ctrl *ctrl)
163 struct sim_ctrl_conf *sim_ctrl;
165 nand_debug(NDBG_SIM,"create controller num:%d cs:%d",ctrl->num,
168 if (ctrl->num >= MAX_SIM_DEV) {
172 sim_ctrl = &ctrls[ctrl->num];
173 if(sim_ctrl->created)
176 sim_ctrl->num = ctrl->num;
177 sim_ctrl->num_cs = ctrl->num_cs;
178 sim_ctrl->ecc = ctrl->ecc;
179 memcpy(sim_ctrl->ecc_layout, ctrl->ecc_layout,
180 MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
181 strlcpy(sim_ctrl->filename, ctrl->filename,
183 sim_ctrl->created = 1;
189 nandsim_destroy_ctrl(int ctrl_num)
192 nand_debug(NDBG_SIM,"destroy controller num:%d", ctrl_num);
194 if (ctrl_num >= MAX_SIM_DEV) {
198 if (!ctrls[ctrl_num].created) {
202 if (ctrls[ctrl_num].running) {
206 memset(&ctrls[ctrl_num], 0, sizeof(ctrls[ctrl_num]));
212 nandsim_ctrl_status(struct sim_ctrl *ctrl)
215 nand_debug(NDBG_SIM,"status controller num:%d cs:%d",ctrl->num,
218 if (ctrl->num >= MAX_SIM_DEV) {
222 ctrl->num_cs = ctrls[ctrl->num].num_cs;
223 ctrl->ecc = ctrls[ctrl->num].ecc;
224 memcpy(ctrl->ecc_layout, ctrls[ctrl->num].ecc_layout,
225 MAX_ECC_BYTES * sizeof(ctrl->ecc_layout[0]));
226 strlcpy(ctrl->filename, ctrls[ctrl->num].filename,
228 ctrl->running = ctrls[ctrl->num].running;
229 ctrl->created = ctrls[ctrl->num].created;
235 nandsim_create_chip(struct sim_chip *chip)
237 struct sim_chip *sim_chip;
239 nand_debug(NDBG_SIM,"create chip num:%d at ctrl:%d", chip->num,
242 if (chip->ctrl_num >= MAX_SIM_DEV ||
243 chip->num >= MAX_CTRL_CS) {
247 if (ctrls[chip->ctrl_num].chips[chip->num]) {
251 sim_chip = malloc(sizeof(*sim_chip), M_NANDSIM,
253 if (sim_chip == NULL) {
257 memcpy(sim_chip, chip, sizeof(*sim_chip));
258 ctrls[chip->ctrl_num].chips[chip->num] = sim_chip;
259 sim_chip->created = 1;
265 nandsim_destroy_chip(struct sim_ctrl_chip *chip)
267 struct sim_ctrl_conf *ctrl_conf;
269 nand_debug(NDBG_SIM,"destroy chip num:%d at ctrl:%d", chip->chip_num,
272 if (chip->ctrl_num >= MAX_SIM_DEV ||
273 chip->chip_num >= MAX_CTRL_CS)
276 ctrl_conf = &ctrls[chip->ctrl_num];
278 if (!ctrl_conf->created || !ctrl_conf->chips[chip->chip_num])
281 if (ctrl_conf->running)
284 free(ctrl_conf->chips[chip->chip_num], M_NANDSIM);
285 ctrl_conf->chips[chip->chip_num] = NULL;
291 nandsim_chip_status(struct sim_chip *chip)
293 struct sim_ctrl_conf *ctrl_conf;
295 nand_debug(NDBG_SIM,"status for chip num:%d at ctrl:%d", chip->num,
298 if (chip->ctrl_num >= MAX_SIM_DEV &&
299 chip->num >= MAX_CTRL_CS)
302 ctrl_conf = &ctrls[chip->ctrl_num];
303 if (!ctrl_conf->chips[chip->num])
306 memcpy(chip, ctrl_conf->chips[chip->num], sizeof(*chip));
312 nandsim_start_ctrl(int num)
314 device_t nexus, ndev;
315 devclass_t nexus_devclass;
318 nand_debug(NDBG_SIM,"start ctlr num:%d", num);
320 if (num >= MAX_SIM_DEV)
323 if (!ctrls[num].created)
326 if (ctrls[num].running)
329 /* We will add our device as a child of the nexus0 device */
330 if (!(nexus_devclass = devclass_find("nexus")) ||
331 !(nexus = devclass_get_device(nexus_devclass, 0)))
335 * Create a newbus device representing this frontend instance
337 * XXX powerpc nexus doesn't implement bus_add_child, so child
338 * must be added by device_add_child().
340 #if defined(__powerpc__)
341 ndev = device_add_child(nexus, "nandsim", num);
343 ndev = BUS_ADD_CHILD(nexus, 0, "nandsim", num);
349 ret = device_probe_and_attach(ndev);
353 ctrls[num].sim_ctrl_dev = ndev;
354 ctrls[num].running = 1;
361 nandsim_stop_ctrl(int num)
364 devclass_t nexus_devclass;
367 nand_debug(NDBG_SIM,"stop controller num:%d", num);
369 if (num >= MAX_SIM_DEV) {
373 if (!ctrls[num].created || !ctrls[num].running) {
377 /* We will add our device as a child of the nexus0 device */
378 if (!(nexus_devclass = devclass_find("nexus")) ||
379 !(nexus = devclass_get_device(nexus_devclass, 0))) {
384 if (ctrls[num].sim_ctrl_dev) {
385 ret = device_delete_child(nexus, ctrls[num].sim_ctrl_dev);
386 ctrls[num].sim_ctrl_dev = NULL;
390 ctrls[num].running = 0;
395 static struct nandsim_chip *
396 get_nandsim_chip(uint8_t ctrl_num, uint8_t chip_num)
398 struct nandsim_softc *sc;
400 if (!ctrls[ctrl_num].sim_ctrl_dev)
403 sc = device_get_softc(ctrls[ctrl_num].sim_ctrl_dev);
404 return (sc->chips[chip_num]);
408 nandsim_print_log(struct sim_log *sim_log)
410 struct nandsim_softc *sc;
413 if (!ctrls[sim_log->ctrl_num].sim_ctrl_dev)
416 sc = device_get_softc(ctrls[sim_log->ctrl_num].sim_ctrl_dev);
418 len1 = strlen(&sc->log_buff[sc->log_idx + 1]);
419 if (len1 >= sim_log->len)
421 copyout(&sc->log_buff[sc->log_idx + 1], sim_log->log, len1);
422 len2 = strlen(sc->log_buff);
423 if (len2 >= (sim_log->len - len1))
424 len2 = (sim_log->len - len1);
425 copyout(sc->log_buff, &sim_log->log[len1], len2);
426 sim_log->len = len1 + len2;
431 nandsim_inject_error(struct sim_error *error)
433 struct nandsim_chip *chip;
434 struct block_space *bs;
435 struct onfi_params *param;
436 int page, page_size, block, offset;
438 nand_debug(NDBG_SIM,"inject error for chip %d at ctrl %d\n",
439 error->chip_num, error->ctrl_num);
441 if (error->ctrl_num >= MAX_SIM_DEV ||
442 error->chip_num >= MAX_CTRL_CS)
445 if (!ctrls[error->ctrl_num].created || !ctrls[error->ctrl_num].running)
448 chip = get_nandsim_chip(error->ctrl_num, error->chip_num);
449 param = &chip->params;
450 page_size = param->bytes_per_page + param->spare_bytes_per_page;
451 block = error->page_num / param->pages_per_block;
452 page = error->page_num % param->pages_per_block;
454 bs = get_bs(chip->swap, block, 1);
458 offset = (page * page_size) + error->column;
459 memset(&bs->blk_ptr[offset], error->pattern, error->len);
465 nandsim_set_block_state(struct sim_block_state *bs)
467 struct onfi_params *params;
468 struct nandsim_chip *chip;
471 nand_debug(NDBG_SIM,"set block state for %d:%d block %d\n",
472 bs->chip_num, bs->ctrl_num, bs->block_num);
474 if (bs->ctrl_num >= MAX_SIM_DEV ||
475 bs->chip_num >= MAX_CTRL_CS)
478 chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
479 params = &chip->params;
480 blocks = params->luns * params->blocks_per_lun;
482 if (bs->block_num > blocks)
485 chip->blk_state[bs->block_num].is_bad = bs->state;
487 if (bs->wearout >= 0)
488 chip->blk_state[bs->block_num].wear_lev = bs->wearout;
494 nandsim_get_block_state(struct sim_block_state *bs)
496 struct onfi_params *params;
497 struct nandsim_chip *chip;
500 if (bs->ctrl_num >= MAX_SIM_DEV ||
501 bs->chip_num >= MAX_CTRL_CS)
504 nand_debug(NDBG_SIM,"get block state for %d:%d block %d\n",
505 bs->chip_num, bs->ctrl_num, bs->block_num);
507 chip = get_nandsim_chip(bs->ctrl_num, bs->chip_num);
508 params = &chip->params;
509 blocks = params->luns * params->blocks_per_lun;
511 if (bs->block_num > blocks)
514 bs->state = chip->blk_state[bs->block_num].is_bad;
515 bs->wearout = chip->blk_state[bs->block_num].wear_lev;
521 nandsim_dump(struct sim_dump *dump)
523 struct nandsim_chip *chip;
524 struct block_space *bs;
527 nand_debug(NDBG_SIM,"dump chip %d %d\n", dump->ctrl_num, dump->chip_num);
529 if (dump->ctrl_num >= MAX_SIM_DEV ||
530 dump->chip_num >= MAX_CTRL_CS)
533 chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
534 blk_size = chip->cg.block_size +
535 (chip->cg.oob_size * chip->cg.pgs_per_blk);
537 bs = get_bs(chip->swap, dump->block_num, 0);
541 if (dump->len > blk_size)
542 dump->len = blk_size;
544 copyout(bs->blk_ptr, dump->data, dump->len);
550 nandsim_restore(struct sim_dump *dump)
552 struct nandsim_chip *chip;
553 struct block_space *bs;
556 nand_debug(NDBG_SIM,"restore chip %d %d\n", dump->ctrl_num,
559 if (dump->ctrl_num >= MAX_SIM_DEV ||
560 dump->chip_num >= MAX_CTRL_CS)
563 chip = get_nandsim_chip(dump->ctrl_num, dump->chip_num);
564 blk_size = chip->cg.block_size +
565 (chip->cg.oob_size * chip->cg.pgs_per_blk);
567 bs = get_bs(chip->swap, dump->block_num, 1);
571 if (dump->len > blk_size)
572 dump->len = blk_size;
575 copyin(dump->data, bs->blk_ptr, dump->len);
581 nandsim_freeze(struct sim_ctrl_chip *ctrl_chip)
583 struct nandsim_chip *chip;
585 if (ctrl_chip->ctrl_num >= MAX_SIM_DEV ||
586 ctrl_chip->chip_num >= MAX_CTRL_CS)
589 chip = get_nandsim_chip(ctrl_chip->ctrl_num, ctrl_chip->chip_num);
590 nandsim_chip_freeze(chip);
596 nandsim_modify(struct sim_mod *mod)
598 struct sim_chip *sim_conf = NULL;
599 struct nandsim_chip *sim_chip = NULL;
601 nand_debug(NDBG_SIM,"modify ctlr %d chip %d", mod->ctrl_num,
604 if (mod->field != SIM_MOD_LOG_LEVEL) {
605 if (mod->ctrl_num >= MAX_SIM_DEV ||
606 mod->chip_num >= MAX_CTRL_CS)
609 sim_conf = ctrls[mod->ctrl_num].chips[mod->chip_num];
610 sim_chip = get_nandsim_chip(mod->ctrl_num, mod->chip_num);
613 switch (mod->field) {
614 case SIM_MOD_LOG_LEVEL:
615 nandsim_log_level = mod->new_value;
617 case SIM_MOD_ERASE_TIME:
618 sim_conf->erase_time = sim_chip->erase_delay = mod->new_value;
620 case SIM_MOD_PROG_TIME:
621 sim_conf->prog_time = sim_chip->prog_delay = mod->new_value;
623 case SIM_MOD_READ_TIME:
624 sim_conf->read_time = sim_chip->read_delay = mod->new_value;
626 case SIM_MOD_ERROR_RATIO:
627 sim_conf->error_ratio = mod->new_value;
628 sim_chip->error_ratio = mod->new_value;
637 nandsim_modevent(module_t mod __unused, int type, void *data __unused)
639 struct sim_ctrl_chip chip_ctrl;
644 nandsim_dev = make_dev(&nandsim_cdevsw, 0,
645 UID_ROOT, GID_WHEEL, 0600, "nandsim.ioctl");
648 for (i = 0; i < MAX_SIM_DEV; i++) {
649 nandsim_stop_ctrl(i);
650 chip_ctrl.ctrl_num = i;
651 for (j = 0; j < MAX_CTRL_CS; j++) {
652 chip_ctrl.chip_num = j;
653 nandsim_destroy_chip(&chip_ctrl);
655 nandsim_destroy_ctrl(i);
657 destroy_dev(nandsim_dev);
667 DEV_MODULE(nandsim, nandsim_modevent, NULL);
668 MODULE_VERSION(nandsim, 1);
669 MODULE_DEPEND(nandsim, nand, 1, 1, 1);
670 MODULE_DEPEND(nandsim, alq, 1, 1, 1);