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/11/sys/dev/nand/nand_geom.c 312858 2017-01-27 03:44:50Z kan $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/conf.h>
33#include <sys/bus.h>
34#include <sys/malloc.h>
35#include <sys/uio.h>
36#include <sys/bio.h>
37#include <geom/geom.h>
38#include <geom/geom_disk.h>
39
40#include <dev/nand/nand.h>
41#include <dev/nand/nandbus.h>
42#include <dev/nand/nand_dev.h>
43#include "nand_if.h"
44#include "nandbus_if.h"
45
46#define	BIO_NAND_STD	((void *)1)
47#define	BIO_NAND_RAW	((void *)2)
48
49static disk_ioctl_t nand_ioctl;
50static disk_getattr_t nand_getattr;
51static disk_strategy_t nand_strategy;
52static disk_strategy_t nand_strategy_raw;
53
54static int
55nand_read(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
56{
57
58	nand_debug(NDBG_GEOM, "Read from chip %d [%p] at %d", chip->num, chip,
59	    offset);
60
61	return (nand_read_pages(chip, offset, buf, len));
62}
63
64static int
65nand_write(struct nand_chip *chip, uint32_t offset, void* buf, uint32_t len)
66{
67
68	nand_debug(NDBG_GEOM, "Write to chip %d [%p] at %d", chip->num, chip,
69	    offset);
70
71	return (nand_prog_pages(chip, offset, buf, len));
72}
73
74static int
75nand_read_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
76{
77	nand_debug(NDBG_GEOM, "Raw read from chip %d [%p] at %d", chip->num,
78	    chip, offset);
79
80	return (nand_read_pages_raw(chip, offset, buf, len));
81}
82
83static int
84nand_write_raw(struct nand_chip *chip, uint32_t offset, void *buf, uint32_t len)
85{
86
87	nand_debug(NDBG_GEOM, "Raw write to chip %d [%p] at %d", chip->num,
88	    chip, offset);
89
90	return (nand_prog_pages_raw(chip, offset, buf, len));
91}
92
93static void
94nand_strategy(struct bio *bp)
95{
96	struct nand_chip *chip;
97
98	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
99
100	bp->bio_driver1 = BIO_NAND_STD;
101
102	nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
103	    bp->bio_cmd == BIO_READ ? "READ" :
104	    (bp->bio_cmd == BIO_WRITE ? "WRITE" :
105	    (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
106	    chip->num, chip);
107
108	mtx_lock(&chip->qlock);
109	bioq_insert_tail(&chip->bioq, bp);
110	mtx_unlock(&chip->qlock);
111	taskqueue_enqueue(chip->tq, &chip->iotask);
112}
113
114static void
115nand_strategy_raw(struct bio *bp)
116{
117	struct nand_chip *chip;
118
119	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
120
121	/* Inform taskqueue that it's a raw access */
122	bp->bio_driver1 = BIO_NAND_RAW;
123
124	nand_debug(NDBG_GEOM, "Strategy %s on chip %d [%p]",
125	    bp->bio_cmd == BIO_READ ? "READ" :
126	    (bp->bio_cmd == BIO_WRITE ? "WRITE" :
127	    (bp->bio_cmd == BIO_DELETE ? "DELETE" : "UNKNOWN")),
128	    chip->num, chip);
129
130	mtx_lock(&chip->qlock);
131	bioq_insert_tail(&chip->bioq, bp);
132	mtx_unlock(&chip->qlock);
133	taskqueue_enqueue(chip->tq, &chip->iotask);
134}
135
136static int
137nand_oob_access(struct nand_chip *chip, uint32_t page, uint32_t offset,
138    uint32_t len, uint8_t *data, uint8_t write)
139{
140	struct chip_geom *cg;
141	int ret = 0;
142
143	cg = &chip->chip_geom;
144
145	if (!write)
146		ret = nand_read_oob(chip, page, data, cg->oob_size);
147	else
148		ret = nand_prog_oob(chip, page, data, cg->oob_size);
149
150	return (ret);
151}
152
153static int
154nand_getattr(struct bio *bp)
155{
156	struct nand_chip *chip;
157	struct chip_geom *cg;
158	device_t dev;
159	int val;
160
161	if (bp->bio_disk == NULL || bp->bio_disk->d_drv1 == NULL)
162		return (ENXIO);
163
164	chip = (struct nand_chip *)bp->bio_disk->d_drv1;
165	cg = &(chip->chip_geom);
166
167	dev = device_get_parent(chip->dev);
168	dev = device_get_parent(dev);
169
170	if (strcmp(bp->bio_attribute, "NAND::device") == 0) {
171		if (bp->bio_length != sizeof(dev))
172			return (EFAULT);
173		bcopy(&dev, bp->bio_data, sizeof(dev));
174	} else {
175		if (strcmp(bp->bio_attribute, "NAND::oobsize") == 0)
176			val = cg->oob_size;
177		else if (strcmp(bp->bio_attribute, "NAND::pagesize") == 0)
178			val = cg->page_size;
179		else if (strcmp(bp->bio_attribute, "NAND::blocksize") == 0)
180			val = cg->block_size;
181		else
182			return (-1);
183		if (bp->bio_length != sizeof(val))
184			return (EFAULT);
185		bcopy(&val, bp->bio_data, sizeof(val));
186	}
187	bp->bio_completed = bp->bio_length;
188	return (0);
189}
190
191static int
192nand_ioctl(struct disk *ndisk, u_long cmd, void *data, int fflag,
193    struct thread *td)
194{
195	struct nand_chip *chip;
196	struct chip_geom  *cg;
197	struct nand_oob_rw *oob_rw = NULL;
198	struct nand_raw_rw *raw_rw = NULL;
199	device_t nandbus;
200	size_t bufsize = 0, len = 0;
201	size_t raw_size;
202	off_t off;
203	uint8_t *buf = NULL;
204	int ret = 0;
205	uint8_t status;
206
207	chip = (struct nand_chip *)ndisk->d_drv1;
208	cg = &chip->chip_geom;
209	nandbus = device_get_parent(chip->dev);
210
211	if ((cmd == NAND_IO_RAW_READ) || (cmd == NAND_IO_RAW_PROG)) {
212		raw_rw = (struct nand_raw_rw *)data;
213		raw_size =  cg->pgs_per_blk * (cg->page_size + cg->oob_size);
214
215		/* Check if len is not bigger than chip size */
216		if (raw_rw->len > raw_size)
217			return (EFBIG);
218
219		/*
220		 * Do not ask for too much memory, in case of large transfers
221		 * read/write in 16-pages chunks
222		 */
223		bufsize = 16 * (cg->page_size + cg->oob_size);
224		if (raw_rw->len < bufsize)
225			bufsize = raw_rw->len;
226
227		buf = malloc(bufsize, M_NAND, M_WAITOK);
228		len = raw_rw->len;
229		off = 0;
230	}
231
232	switch (cmd) {
233	case NAND_IO_ERASE:
234		ret = nand_erase_blocks(chip, ((off_t *)data)[0],
235		    ((off_t *)data)[1]);
236		break;
237
238	case NAND_IO_OOB_READ:
239		oob_rw = (struct nand_oob_rw *)data;
240		ret = nand_oob_access(chip, oob_rw->page, 0,
241		    oob_rw->len, oob_rw->data, 0);
242		break;
243
244	case NAND_IO_OOB_PROG:
245		oob_rw = (struct nand_oob_rw *)data;
246		ret = nand_oob_access(chip, oob_rw->page, 0,
247		    oob_rw->len, oob_rw->data, 1);
248		break;
249
250	case NAND_IO_GET_STATUS:
251		NANDBUS_LOCK(nandbus);
252		ret = NANDBUS_GET_STATUS(nandbus, &status);
253		if (ret == 0)
254			*(uint8_t *)data = status;
255		NANDBUS_UNLOCK(nandbus);
256		break;
257
258	case NAND_IO_RAW_PROG:
259		while (len > 0) {
260			if (len < bufsize)
261				bufsize = len;
262
263			ret = copyin(raw_rw->data + off, buf, bufsize);
264			if (ret)
265				break;
266			ret = nand_prog_pages_raw(chip, raw_rw->off + off, buf,
267			    bufsize);
268			if (ret)
269				break;
270			len -= bufsize;
271			off += bufsize;
272		}
273		break;
274
275	case NAND_IO_RAW_READ:
276		while (len > 0) {
277			if (len < bufsize)
278				bufsize = len;
279
280			ret = nand_read_pages_raw(chip, raw_rw->off + off, buf,
281			    bufsize);
282			if (ret)
283				break;
284
285			ret = copyout(buf, raw_rw->data + off, bufsize);
286			if (ret)
287				break;
288			len -= bufsize;
289			off += bufsize;
290		}
291		break;
292
293	case NAND_IO_GET_CHIP_PARAM:
294		nand_get_chip_param(chip, (struct chip_param_io *)data);
295		break;
296
297	default:
298		printf("Unknown nand_ioctl request \n");
299		ret = EIO;
300	}
301
302	if (buf)
303		free(buf, M_NAND);
304
305	return (ret);
306}
307
308static void
309nand_io_proc(void *arg, int pending)
310{
311	struct nand_chip *chip = arg;
312	struct bio *bp;
313	int err = 0;
314
315	for (;;) {
316		mtx_lock(&chip->qlock);
317		bp = bioq_takefirst(&chip->bioq);
318		mtx_unlock(&chip->qlock);
319		if (bp == NULL)
320			break;
321
322		if (bp->bio_driver1 == BIO_NAND_STD) {
323			if (bp->bio_cmd == BIO_READ) {
324				err = nand_read(chip,
325				    bp->bio_offset & 0xffffffff,
326				    bp->bio_data, bp->bio_bcount);
327			} else if (bp->bio_cmd == BIO_WRITE) {
328				err = nand_write(chip,
329				    bp->bio_offset & 0xffffffff,
330				    bp->bio_data, bp->bio_bcount);
331			}
332		} else if (bp->bio_driver1 == BIO_NAND_RAW) {
333			if (bp->bio_cmd == BIO_READ) {
334				err = nand_read_raw(chip,
335				    bp->bio_offset & 0xffffffff,
336				    bp->bio_data, bp->bio_bcount);
337			} else if (bp->bio_cmd == BIO_WRITE) {
338				err = nand_write_raw(chip,
339				    bp->bio_offset & 0xffffffff,
340				    bp->bio_data, bp->bio_bcount);
341			}
342		} else
343			panic("Unknown access type in bio->bio_driver1\n");
344
345		if (bp->bio_cmd == BIO_DELETE) {
346			nand_debug(NDBG_GEOM, "Delete on chip%d offset %lld "
347			    "length %ld\n", chip->num, bp->bio_offset,
348			    bp->bio_bcount);
349			err = nand_erase_blocks(chip,
350			    bp->bio_offset & 0xffffffff,
351			    bp->bio_bcount);
352		}
353
354		if (err == 0 || err == ECC_CORRECTABLE)
355			bp->bio_resid = 0;
356		else {
357			nand_debug(NDBG_GEOM,"nand_[read|write|erase_blocks] "
358			    "error: %d\n", err);
359
360			bp->bio_error = EIO;
361			bp->bio_flags |= BIO_ERROR;
362			bp->bio_resid = bp->bio_bcount;
363		}
364		biodone(bp);
365	}
366}
367
368int
369create_geom_disk(struct nand_chip *chip)
370{
371	struct disk *ndisk, *rdisk;
372
373	/* Create the disk device */
374	ndisk = disk_alloc();
375	ndisk->d_strategy = nand_strategy;
376	ndisk->d_ioctl = nand_ioctl;
377	ndisk->d_getattr = nand_getattr;
378	ndisk->d_name = "gnand";
379	ndisk->d_drv1 = chip;
380	ndisk->d_maxsize = chip->chip_geom.block_size;
381	ndisk->d_sectorsize = chip->chip_geom.page_size;
382	ndisk->d_mediasize = chip->chip_geom.chip_size;
383	ndisk->d_unit = chip->num +
384	    10 * device_get_unit(device_get_parent(chip->dev));
385
386	/*
387	 * When using BBT, make two last blocks of device unavailable
388	 * to user (because those are used to store BBT table).
389	 */
390	if (chip->bbt != NULL)
391		ndisk->d_mediasize -= (2 * chip->chip_geom.block_size);
392
393	ndisk->d_flags = DISKFLAG_CANDELETE;
394
395	snprintf(ndisk->d_ident, sizeof(ndisk->d_ident),
396	    "nand: Man:0x%02x Dev:0x%02x", chip->id.man_id, chip->id.dev_id);
397	ndisk->d_rotation_rate = DISK_RR_NON_ROTATING;
398
399	disk_create(ndisk, DISK_VERSION);
400
401	/* Create the RAW disk device */
402	rdisk = disk_alloc();
403	rdisk->d_strategy = nand_strategy_raw;
404	rdisk->d_ioctl = nand_ioctl;
405	rdisk->d_getattr = nand_getattr;
406	rdisk->d_name = "gnand.raw";
407	rdisk->d_drv1 = chip;
408	rdisk->d_maxsize = chip->chip_geom.block_size;
409	rdisk->d_sectorsize = chip->chip_geom.page_size;
410	rdisk->d_mediasize = chip->chip_geom.chip_size;
411	rdisk->d_unit = chip->num +
412	    10 * device_get_unit(device_get_parent(chip->dev));
413
414	rdisk->d_flags = DISKFLAG_CANDELETE;
415
416	snprintf(rdisk->d_ident, sizeof(rdisk->d_ident),
417	    "nand_raw: Man:0x%02x Dev:0x%02x", chip->id.man_id,
418	    chip->id.dev_id);
419	rdisk->d_rotation_rate = DISK_RR_NON_ROTATING;
420
421	disk_create(rdisk, DISK_VERSION);
422
423	chip->ndisk = ndisk;
424	chip->rdisk = rdisk;
425
426	mtx_init(&chip->qlock, "NAND I/O lock", NULL, MTX_DEF);
427	bioq_init(&chip->bioq);
428
429	TASK_INIT(&chip->iotask, 0, nand_io_proc, chip);
430	chip->tq = taskqueue_create("nand_taskq", M_WAITOK,
431	    taskqueue_thread_enqueue, &chip->tq);
432	taskqueue_start_threads(&chip->tq, 1, PI_DISK, "nand taskq");
433
434	if (bootverbose)
435		device_printf(chip->dev, "Created gnand%d for chip [0x%0x, "
436		    "0x%0x]\n", ndisk->d_unit, chip->id.man_id,
437		    chip->id.dev_id);
438
439	return (0);
440}
441
442void
443destroy_geom_disk(struct nand_chip *chip)
444{
445	struct bio *bp;
446
447	taskqueue_free(chip->tq);
448	disk_destroy(chip->ndisk);
449	disk_destroy(chip->rdisk);
450
451	mtx_lock(&chip->qlock);
452	for (;;) {
453		bp = bioq_takefirst(&chip->bioq);
454		if (bp == NULL)
455			break;
456		bp->bio_error = EIO;
457		bp->bio_flags |= BIO_ERROR;
458		bp->bio_resid = bp->bio_bcount;
459
460		biodone(bp);
461	}
462	mtx_unlock(&chip->qlock);
463
464	mtx_destroy(&chip->qlock);
465}
466