Home | History | Annotate | Line # | Download | only in flash
flash.c revision 1.15.10.1
      1  1.15.10.1   thorpej /*	$NetBSD: flash.c,v 1.15.10.1 2021/04/02 22:17:44 thorpej Exp $	*/
      2        1.1     ahoka 
      3        1.1     ahoka /*-
      4        1.1     ahoka  * Copyright (c) 2011 Department of Software Engineering,
      5        1.1     ahoka  *		      University of Szeged, Hungary
      6        1.1     ahoka  * Copyright (c) 2011 Adam Hoka <ahoka (at) NetBSD.org>
      7        1.1     ahoka  * Copyright (c) 2010 David Tengeri <dtengeri (at) inf.u-szeged.hu>
      8        1.1     ahoka  * All rights reserved.
      9        1.1     ahoka  *
     10        1.1     ahoka  * This code is derived from software contributed to The NetBSD Foundation
     11        1.1     ahoka  * by the Department of Software Engineering, University of Szeged, Hungary
     12        1.1     ahoka  *
     13        1.1     ahoka  * Redistribution and use in source and binary forms, with or without
     14        1.1     ahoka  * modification, are permitted provided that the following conditions
     15        1.1     ahoka  * are met:
     16        1.1     ahoka  * 1. Redistributions of source code must retain the above copyright
     17        1.1     ahoka  *    notice, this list of conditions and the following disclaimer.
     18        1.1     ahoka  * 2. Redistributions in binary form must reproduce the above copyright
     19        1.1     ahoka  *    notice, this list of conditions and the following disclaimer in the
     20        1.1     ahoka  *    documentation and/or other materials provided with the distribution.
     21        1.1     ahoka  *
     22        1.1     ahoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23        1.1     ahoka  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24        1.1     ahoka  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25        1.1     ahoka  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26        1.1     ahoka  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     27        1.1     ahoka  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     28        1.1     ahoka  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     29        1.1     ahoka  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     30        1.1     ahoka  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31        1.1     ahoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32        1.1     ahoka  * SUCH DAMAGE.
     33        1.1     ahoka  */
     34        1.1     ahoka 
     35        1.1     ahoka /*-
     36        1.1     ahoka  * Framework for storage devices based on Flash technology
     37        1.1     ahoka  */
     38        1.1     ahoka 
     39        1.1     ahoka #include <sys/cdefs.h>
     40  1.15.10.1   thorpej __KERNEL_RCSID(0, "$NetBSD: flash.c,v 1.15.10.1 2021/04/02 22:17:44 thorpej Exp $");
     41        1.1     ahoka 
     42        1.1     ahoka #include <sys/param.h>
     43        1.1     ahoka #include <sys/types.h>
     44        1.1     ahoka #include <sys/proc.h>
     45        1.1     ahoka #include <sys/errno.h>
     46        1.1     ahoka #include <sys/ioctl.h>
     47        1.1     ahoka #include <sys/device.h>
     48        1.1     ahoka #include <sys/conf.h>
     49        1.1     ahoka #include <sys/kmem.h>
     50        1.1     ahoka #include <sys/uio.h>
     51        1.1     ahoka #include <sys/kernel.h>
     52        1.1     ahoka 
     53        1.1     ahoka #include <sys/atomic.h>
     54        1.1     ahoka #include <sys/buf.h>
     55        1.1     ahoka #include <sys/bufq.h>
     56        1.1     ahoka #include <sys/disk.h>
     57        1.1     ahoka #include <sys/disklabel.h>
     58        1.1     ahoka #include <sys/malloc.h>
     59        1.1     ahoka #include <sys/reboot.h>
     60        1.1     ahoka 
     61       1.13  riastrad #include "ioconf.h"
     62       1.13  riastrad 
     63        1.1     ahoka #include <sys/flashio.h>
     64        1.1     ahoka #include "flash.h"
     65        1.1     ahoka 
     66        1.1     ahoka #ifdef FLASH_DEBUG
     67        1.7     ahoka int flashdebug = FLASH_DEBUG;
     68        1.1     ahoka #endif
     69        1.1     ahoka 
     70        1.1     ahoka dev_type_open(flashopen);
     71        1.1     ahoka dev_type_close(flashclose);
     72        1.1     ahoka dev_type_read(flashread);
     73        1.1     ahoka dev_type_write(flashwrite);
     74        1.1     ahoka dev_type_ioctl(flashioctl);
     75        1.1     ahoka dev_type_strategy(flashstrategy);
     76        1.1     ahoka dev_type_dump(flashdump);
     77        1.1     ahoka 
     78        1.1     ahoka int flash_print(void *aux, const char *pnp);
     79        1.1     ahoka 
     80        1.1     ahoka bool flash_shutdown(device_t dev, int how);
     81        1.1     ahoka int flash_nsectors(struct buf *bp);
     82        1.1     ahoka int flash_sector(struct buf *bp);
     83        1.1     ahoka 
     84        1.1     ahoka int flash_match(device_t parent, cfdata_t match, void *aux);
     85        1.1     ahoka void flash_attach(device_t parent, device_t self, void *aux);
     86        1.1     ahoka int flash_detach(device_t device, int flags);
     87        1.1     ahoka 
     88        1.1     ahoka CFATTACH_DECL_NEW(flash, sizeof(struct flash_softc),
     89        1.1     ahoka     flash_match, flash_attach, flash_detach, NULL);
     90        1.1     ahoka 
     91        1.1     ahoka /**
     92        1.1     ahoka  * Block device's operation
     93        1.1     ahoka  */
     94        1.1     ahoka const struct bdevsw flash_bdevsw = {
     95        1.1     ahoka 	.d_open = flashopen,
     96        1.1     ahoka 	.d_close = flashclose,
     97        1.1     ahoka 	.d_strategy = flashstrategy,
     98        1.1     ahoka 	.d_ioctl = flashioctl,
     99        1.1     ahoka 	.d_dump = flashdump,
    100        1.6     ahoka 	.d_psize = nosize,
    101       1.11  dholland 	.d_discard = nodiscard,	/* XXX this driver probably wants a discard */
    102        1.1     ahoka 	.d_flag = D_DISK | D_MPSAFE
    103        1.1     ahoka };
    104        1.1     ahoka 
    105        1.1     ahoka /**
    106        1.1     ahoka  * Character device's operations
    107        1.1     ahoka  */
    108        1.1     ahoka const struct cdevsw flash_cdevsw = {
    109        1.1     ahoka 	.d_open = flashopen,
    110        1.1     ahoka 	.d_close = flashclose,
    111        1.1     ahoka 	.d_read = flashread,
    112        1.1     ahoka 	.d_write = flashwrite,
    113        1.1     ahoka 	.d_ioctl = flashioctl,
    114        1.1     ahoka 	.d_stop = nostop,
    115        1.1     ahoka 	.d_tty = notty,
    116        1.1     ahoka 	.d_poll = nopoll,
    117        1.1     ahoka 	.d_mmap = nommap,
    118        1.1     ahoka 	.d_kqfilter = nokqfilter,
    119       1.12  dholland 	.d_discard = nodiscard,
    120        1.1     ahoka 	.d_flag = D_DISK | D_MPSAFE
    121        1.1     ahoka };
    122        1.1     ahoka 
    123        1.1     ahoka /* ARGSUSED */
    124        1.1     ahoka int
    125        1.1     ahoka flash_match(device_t parent, cfdata_t match, void *aux)
    126        1.1     ahoka {
    127        1.1     ahoka 	/* pseudo device, always attaches */
    128        1.1     ahoka 	return 1;
    129        1.1     ahoka }
    130        1.1     ahoka 
    131        1.1     ahoka /* ARGSUSED */
    132        1.1     ahoka void
    133        1.1     ahoka flash_attach(device_t parent, device_t self, void *aux)
    134        1.1     ahoka {
    135        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    136        1.8     cliff 	struct flash_attach_args * const faa = aux;
    137        1.1     ahoka 	char pbuf[2][sizeof("9999 KB")];
    138        1.1     ahoka 
    139        1.1     ahoka 	sc->sc_dev = self;
    140        1.1     ahoka 	sc->sc_parent_dev = parent;
    141        1.1     ahoka 	sc->flash_if = faa->flash_if;
    142        1.7     ahoka 	sc->sc_partinfo = faa->partinfo;
    143        1.1     ahoka 	sc->hw_softc = device_private(parent);
    144        1.1     ahoka 
    145        1.7     ahoka 	format_bytes(pbuf[0], sizeof(pbuf[0]), sc->sc_partinfo.part_size);
    146        1.1     ahoka 	format_bytes(pbuf[1], sizeof(pbuf[1]), sc->flash_if->erasesize);
    147        1.1     ahoka 
    148        1.1     ahoka 	aprint_naive("\n");
    149        1.6     ahoka 
    150       1.14  jmcneill 	aprint_normal(": partition");
    151       1.14  jmcneill 	if (sc->sc_partinfo.part_name != NULL)
    152       1.14  jmcneill 		aprint_normal(" \"%s\"", sc->sc_partinfo.part_name);
    153        1.6     ahoka 
    154       1.14  jmcneill 	aprint_normal(", size %s, offset %#jx",
    155       1.14  jmcneill 		pbuf[0], (uintmax_t)sc->sc_partinfo.part_offset);
    156        1.1     ahoka 
    157        1.7     ahoka 	if (sc->sc_partinfo.part_flags & FLASH_PART_READONLY) {
    158        1.1     ahoka 		sc->sc_readonly = true;
    159        1.1     ahoka 		aprint_normal(", read only");
    160        1.1     ahoka 	} else {
    161        1.1     ahoka 		sc->sc_readonly = false;
    162        1.1     ahoka 	}
    163        1.1     ahoka 
    164        1.1     ahoka 	aprint_normal("\n");
    165        1.1     ahoka 
    166        1.7     ahoka 	if (sc->sc_partinfo.part_size == 0) {
    167        1.1     ahoka 		aprint_error_dev(self,
    168        1.1     ahoka 		    "partition size must be larger than 0\n");
    169        1.1     ahoka 		return;
    170        1.1     ahoka 	}
    171        1.6     ahoka 
    172        1.1     ahoka 	switch (sc->flash_if->type) {
    173        1.1     ahoka 	case FLASH_TYPE_NOR:
    174        1.1     ahoka 		aprint_normal_dev(sc->sc_dev,
    175        1.1     ahoka 		    "erase size %s bytes, write size %d bytes\n",
    176        1.1     ahoka 		    pbuf[1], sc->flash_if->writesize);
    177        1.1     ahoka 		break;
    178        1.1     ahoka 
    179        1.1     ahoka 	case FLASH_TYPE_NAND:
    180        1.1     ahoka 	default:
    181        1.1     ahoka 		aprint_normal_dev(sc->sc_dev,
    182        1.1     ahoka 		    "erase size %s, page size %d bytes, write size %d bytes\n",
    183        1.1     ahoka 		    pbuf[1], sc->flash_if->page_size,
    184        1.1     ahoka 		    sc->flash_if->writesize);
    185        1.1     ahoka 		break;
    186        1.1     ahoka 	}
    187        1.6     ahoka 
    188        1.1     ahoka 	if (!pmf_device_register1(sc->sc_dev, NULL, NULL, flash_shutdown))
    189        1.1     ahoka 		aprint_error_dev(sc->sc_dev,
    190        1.1     ahoka 		    "couldn't establish power handler\n");
    191        1.1     ahoka }
    192        1.1     ahoka 
    193        1.1     ahoka int
    194        1.1     ahoka flash_detach(device_t device, int flags)
    195        1.1     ahoka {
    196        1.8     cliff 	struct flash_softc * const sc = device_private(device);
    197        1.1     ahoka 
    198        1.1     ahoka 	pmf_device_deregister(sc->sc_dev);
    199        1.1     ahoka 
    200        1.1     ahoka 	/* freeing flash_if is our responsibility */
    201        1.1     ahoka 	kmem_free(sc->flash_if, sizeof(*sc->flash_if));
    202        1.6     ahoka 
    203        1.1     ahoka 	return 0;
    204        1.1     ahoka }
    205        1.1     ahoka 
    206        1.1     ahoka int
    207        1.1     ahoka flash_print(void *aux, const char *pnp)
    208        1.1     ahoka {
    209        1.1     ahoka 	struct flash_attach_args *arg;
    210        1.1     ahoka 	const char *type;
    211        1.1     ahoka 
    212        1.1     ahoka 	if (pnp != NULL) {
    213        1.1     ahoka 		arg = aux;
    214        1.1     ahoka 		switch (arg->flash_if->type) {
    215        1.1     ahoka 		case FLASH_TYPE_NOR:
    216        1.1     ahoka 			type = "NOR";
    217        1.1     ahoka 			break;
    218        1.1     ahoka 		case FLASH_TYPE_NAND:
    219        1.1     ahoka 			type = "NAND";
    220        1.1     ahoka 			break;
    221        1.1     ahoka 		default:
    222        1.1     ahoka 			panic("flash_print: unknown type %d",
    223        1.1     ahoka 			    arg->flash_if->type);
    224        1.1     ahoka 		}
    225        1.1     ahoka 		aprint_normal("%s flash at %s", type, pnp);
    226        1.1     ahoka 	}
    227        1.1     ahoka 	return UNCONF;
    228        1.1     ahoka }
    229        1.1     ahoka 
    230        1.1     ahoka device_t
    231        1.8     cliff flash_attach_mi(struct flash_interface * const flash_if, device_t device)
    232        1.1     ahoka {
    233        1.1     ahoka 	struct flash_attach_args arg;
    234        1.1     ahoka 
    235        1.1     ahoka #ifdef DIAGNOSTIC
    236        1.1     ahoka 	if (flash_if == NULL) {
    237        1.1     ahoka 		aprint_error("flash_attach_mi: NULL\n");
    238        1.1     ahoka 		return 0;
    239        1.1     ahoka 	}
    240        1.1     ahoka #endif
    241        1.1     ahoka 	arg.flash_if = flash_if;
    242        1.1     ahoka 
    243  1.15.10.1   thorpej 	return config_found(device, &arg, flash_print,
    244  1.15.10.1   thorpej 	    CFARG_IATTR, "flashbus",
    245  1.15.10.1   thorpej 	    CFARG_EOL);
    246        1.1     ahoka }
    247        1.1     ahoka 
    248        1.1     ahoka /**
    249        1.1     ahoka  * flash_open - open the character device
    250        1.1     ahoka  * Checks if there is a driver registered to the minor number of the open
    251        1.1     ahoka  * request.
    252        1.1     ahoka  */
    253        1.1     ahoka int
    254        1.8     cliff flashopen(dev_t dev, int flags, int fmt, lwp_t *l)
    255        1.1     ahoka {
    256        1.1     ahoka 	int unit = minor(dev);
    257        1.1     ahoka 	struct flash_softc *sc;
    258        1.1     ahoka 
    259        1.7     ahoka 	FLDPRINTFN(1, ("flash: opening device unit %d\n", unit));
    260        1.1     ahoka 
    261        1.1     ahoka 	if ((sc = device_lookup_private(&flash_cd, unit)) == NULL)
    262        1.1     ahoka 		return ENXIO;
    263        1.1     ahoka 
    264        1.1     ahoka 	/* TODO return eperm if want to open for writing a read only dev */
    265        1.1     ahoka 
    266        1.1     ahoka 	/* reset buffer length */
    267        1.1     ahoka //	sc->sc_cache->fc_len = 0;
    268        1.6     ahoka 
    269        1.1     ahoka 	return 0;
    270        1.1     ahoka }
    271        1.1     ahoka 
    272        1.1     ahoka /**
    273        1.1     ahoka  * flash_close - close device
    274        1.1     ahoka  * We don't have to release any resources, so just return 0.
    275        1.1     ahoka  */
    276        1.1     ahoka int
    277        1.8     cliff flashclose(dev_t dev, int flags, int fmt, lwp_t *l)
    278        1.1     ahoka {
    279        1.1     ahoka 	int unit = minor(dev);
    280        1.1     ahoka 	struct flash_softc *sc;
    281        1.1     ahoka 	int err;
    282        1.1     ahoka 
    283        1.7     ahoka 	FLDPRINTFN(1, ("flash: closing flash device unit %d\n", unit));
    284        1.1     ahoka 
    285        1.1     ahoka 	if ((sc = device_lookup_private(&flash_cd, unit)) == NULL)
    286        1.1     ahoka 		return ENXIO;
    287        1.1     ahoka 
    288        1.1     ahoka 	if (!sc->sc_readonly) {
    289        1.1     ahoka 		err = flash_sync(sc->sc_dev);
    290        1.1     ahoka 		if (err)
    291        1.1     ahoka 			return err;
    292        1.1     ahoka 	}
    293        1.6     ahoka 
    294        1.1     ahoka 	return 0;
    295        1.1     ahoka }
    296        1.1     ahoka 
    297        1.1     ahoka /**
    298        1.1     ahoka  * flash_read - read from character device
    299        1.8     cliff  * This function uses the registered driver's read function to read the
    300        1.8     cliff  * requested length to * a buffer and then moves this buffer to userspace.
    301        1.1     ahoka  */
    302        1.1     ahoka int
    303        1.8     cliff flashread(dev_t dev, struct uio * const uio, int flag)
    304        1.1     ahoka {
    305        1.1     ahoka 	return physio(flashstrategy, NULL, dev, B_READ, minphys, uio);
    306        1.1     ahoka }
    307        1.1     ahoka 
    308        1.1     ahoka /**
    309        1.1     ahoka  * flash_write - write to character device
    310        1.1     ahoka  * This function moves the data into a buffer from userspace to kernel space,
    311        1.1     ahoka  * then uses the registered driver's write function to write out the data to
    312        1.1     ahoka  * the media.
    313        1.1     ahoka  */
    314        1.1     ahoka int
    315        1.8     cliff flashwrite(dev_t dev, struct uio * const uio, int flag)
    316        1.1     ahoka {
    317        1.1     ahoka 	return physio(flashstrategy, NULL, dev, B_WRITE, minphys, uio);
    318        1.1     ahoka }
    319        1.1     ahoka 
    320        1.1     ahoka void
    321        1.8     cliff flashstrategy(struct buf * const bp)
    322        1.1     ahoka {
    323        1.1     ahoka 	struct flash_softc *sc;
    324        1.1     ahoka 	const struct flash_interface *flash_if;
    325        1.1     ahoka 	const struct flash_partition *part;
    326        1.1     ahoka 	int unit, device_blks;
    327        1.1     ahoka 
    328        1.1     ahoka 	unit = minor(bp->b_dev);
    329        1.1     ahoka 	sc = device_lookup_private(&flash_cd, unit);
    330        1.1     ahoka 	if (sc == NULL) {
    331        1.1     ahoka 		bp->b_error = ENXIO;
    332        1.1     ahoka 		goto done;
    333        1.1     ahoka 	}
    334        1.1     ahoka 
    335        1.1     ahoka 	flash_if = sc->flash_if;
    336        1.7     ahoka 	part = &sc->sc_partinfo;
    337        1.1     ahoka 
    338        1.1     ahoka 	/* divider */
    339        1.1     ahoka 	KASSERT(flash_if->writesize != 0);
    340        1.6     ahoka 
    341        1.1     ahoka 	aprint_debug_dev(sc->sc_dev, "flash_strategy()\n");
    342        1.1     ahoka 
    343        1.1     ahoka 	if (!(bp->b_flags & B_READ) && sc->sc_readonly) {
    344        1.1     ahoka 		bp->b_error = EACCES;
    345        1.1     ahoka 		goto done;
    346        1.1     ahoka 	}
    347        1.1     ahoka 
    348        1.1     ahoka 	/* check if length is not negative */
    349        1.1     ahoka 	if (bp->b_blkno < 0) {
    350        1.1     ahoka 		bp->b_error = EINVAL;
    351        1.1     ahoka 		goto done;
    352        1.1     ahoka 	}
    353        1.1     ahoka 
    354       1.15   msaitoh 	/* zero length i/o */
    355        1.1     ahoka 	if (bp->b_bcount == 0) {
    356        1.1     ahoka 		goto done;
    357        1.1     ahoka 	}
    358        1.1     ahoka 
    359        1.7     ahoka 	device_blks = sc->sc_partinfo.part_size / DEV_BSIZE;
    360        1.1     ahoka 	KASSERT(part->part_offset % DEV_BSIZE == 0);
    361        1.1     ahoka 	bp->b_rawblkno = bp->b_blkno + (part->part_offset / DEV_BSIZE);
    362        1.1     ahoka 
    363        1.1     ahoka 	if (bounds_check_with_mediasize(bp, DEV_BSIZE, device_blks) <= 0) {
    364        1.1     ahoka 		goto done;
    365        1.1     ahoka 	}
    366        1.1     ahoka 
    367        1.1     ahoka 	bp->b_resid = bp->b_bcount;
    368        1.1     ahoka 	flash_if->submit(sc->sc_parent_dev, bp);
    369        1.6     ahoka 
    370        1.1     ahoka 	return;
    371        1.1     ahoka done:
    372        1.1     ahoka 	bp->b_resid = bp->b_bcount;
    373        1.1     ahoka 	biodone(bp);
    374        1.1     ahoka }
    375        1.1     ahoka 
    376        1.1     ahoka /*
    377        1.1     ahoka  * Handle the ioctl for the device
    378        1.1     ahoka  */
    379        1.1     ahoka int
    380        1.8     cliff flashioctl(dev_t dev, u_long command, void * const data, int flags, lwp_t *l)
    381        1.1     ahoka {
    382        1.1     ahoka 	struct flash_erase_params *ep;
    383        1.1     ahoka 	struct flash_info_params *ip;
    384        1.1     ahoka 	struct flash_dump_params *dp;
    385        1.1     ahoka 	struct flash_badblock_params *bbp;
    386        1.1     ahoka 	struct flash_erase_instruction ei;
    387        1.1     ahoka 	struct flash_softc *sc;
    388        1.1     ahoka 	int unit, err;
    389        1.1     ahoka 	size_t retlen;
    390        1.3     ahoka 	flash_off_t offset;
    391        1.3     ahoka 	bool bad;
    392        1.1     ahoka 
    393        1.1     ahoka 	unit = minor(dev);
    394        1.1     ahoka 	if ((sc = device_lookup_private(&flash_cd, unit)) == NULL)
    395        1.1     ahoka 		return ENXIO;
    396        1.1     ahoka 
    397        1.1     ahoka 	err = 0;
    398        1.1     ahoka 	switch (command) {
    399        1.1     ahoka 	case FLASH_ERASE_BLOCK:
    400        1.1     ahoka 		/**
    401        1.1     ahoka 		 * Set up an erase instruction then call the registered
    402        1.1     ahoka 		 * driver's erase operation.
    403        1.1     ahoka 		 */
    404        1.1     ahoka 		ep = data;
    405        1.1     ahoka 
    406        1.1     ahoka 		if (sc->sc_readonly) {
    407        1.1     ahoka 			return EACCES;
    408        1.1     ahoka 		}
    409        1.1     ahoka 
    410        1.1     ahoka 		ei.ei_addr = ep->ep_addr;
    411        1.1     ahoka 		ei.ei_len = ep->ep_len;
    412        1.1     ahoka 		ei.ei_callback = NULL;
    413        1.6     ahoka 
    414        1.1     ahoka 		err = flash_erase(sc->sc_dev, &ei);
    415        1.1     ahoka 		if (err) {
    416        1.1     ahoka 			return err;
    417        1.1     ahoka 		}
    418        1.1     ahoka 
    419        1.1     ahoka 		break;
    420        1.1     ahoka 	case FLASH_BLOCK_ISBAD:
    421        1.1     ahoka 		/**
    422        1.1     ahoka 		 * Set up an erase instruction then call the registered
    423        1.1     ahoka 		 * driver's erase operation.
    424        1.1     ahoka 		 */
    425        1.1     ahoka 		bbp = data;
    426        1.1     ahoka 
    427        1.3     ahoka 		err = flash_block_isbad(sc->sc_dev, bbp->bbp_addr, &bad);
    428        1.3     ahoka 		if (err) {
    429        1.1     ahoka 			return err;
    430        1.1     ahoka 		}
    431        1.3     ahoka 		bbp->bbp_isbad = bad;
    432        1.1     ahoka 
    433        1.1     ahoka 		break;
    434        1.1     ahoka 	case FLASH_BLOCK_MARKBAD:
    435        1.1     ahoka 		bbp = data;
    436        1.1     ahoka 
    437        1.1     ahoka 		err = flash_block_markbad(sc->sc_dev, bbp->bbp_addr);
    438        1.1     ahoka 
    439        1.6     ahoka 		break;
    440        1.1     ahoka 	case FLASH_DUMP:
    441        1.1     ahoka 		dp = data;
    442        1.1     ahoka 		offset = dp->dp_block * sc->flash_if->erasesize;
    443        1.7     ahoka 		FLDPRINTF(("Reading from block: %jd len: %jd\n",
    444        1.1     ahoka 			(intmax_t )dp->dp_block, (intmax_t )dp->dp_len));
    445        1.1     ahoka 		err = flash_read(sc->sc_parent_dev, offset, dp->dp_len,
    446        1.1     ahoka 		    &retlen, dp->dp_buf);
    447        1.1     ahoka 		if (err)
    448        1.1     ahoka 			return err;
    449        1.1     ahoka 		if (retlen != dp->dp_len) {
    450        1.1     ahoka 			dp->dp_len = -1;
    451        1.1     ahoka 			dp->dp_buf = NULL;
    452        1.1     ahoka 		}
    453        1.1     ahoka 
    454        1.1     ahoka 		break;
    455        1.1     ahoka 	case FLASH_GET_INFO:
    456        1.1     ahoka 		ip = data;
    457        1.6     ahoka 
    458        1.1     ahoka 		ip->ip_page_size = sc->flash_if->page_size;
    459        1.1     ahoka 		ip->ip_erase_size = sc->flash_if->erasesize;
    460        1.1     ahoka 		ip->ip_flash_type = sc->flash_if->type;
    461        1.7     ahoka 		ip->ip_flash_size = sc->sc_partinfo.part_size;
    462        1.1     ahoka 		break;
    463        1.1     ahoka 	default:
    464        1.1     ahoka 		err = ENODEV;
    465        1.1     ahoka 	}
    466        1.1     ahoka 
    467        1.1     ahoka 	return err;
    468        1.1     ahoka }
    469        1.2  uebayasi 
    470        1.1     ahoka int
    471        1.1     ahoka flashdump(dev_t dev, daddr_t blkno, void *va, size_t size)
    472        1.1     ahoka {
    473        1.8     cliff 	return EACCES;
    474        1.1     ahoka }
    475        1.1     ahoka 
    476        1.1     ahoka bool
    477        1.1     ahoka flash_shutdown(device_t self, int how)
    478        1.1     ahoka {
    479        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    480        1.6     ahoka 
    481        1.1     ahoka 	if ((how & RB_NOSYNC) == 0 && !sc->sc_readonly)
    482        1.1     ahoka 		flash_sync(self);
    483        1.1     ahoka 
    484        1.1     ahoka 	return true;
    485        1.1     ahoka }
    486        1.1     ahoka 
    487        1.1     ahoka const struct flash_interface *
    488        1.1     ahoka flash_get_interface(dev_t dev)
    489        1.1     ahoka {
    490        1.1     ahoka 	struct flash_softc *sc;
    491        1.1     ahoka 	int unit;
    492        1.1     ahoka 
    493        1.1     ahoka 	unit = minor(dev);
    494        1.1     ahoka 	if ((sc = device_lookup_private(&flash_cd, unit)) == NULL)
    495        1.1     ahoka 		return NULL;
    496        1.1     ahoka 
    497        1.1     ahoka 	return sc->flash_if;
    498        1.1     ahoka }
    499        1.1     ahoka 
    500        1.1     ahoka const struct flash_softc *
    501        1.1     ahoka flash_get_softc(dev_t dev)
    502        1.1     ahoka {
    503        1.1     ahoka 	struct flash_softc *sc;
    504        1.1     ahoka 	int unit;
    505        1.1     ahoka 
    506        1.1     ahoka 	unit = minor(dev);
    507        1.1     ahoka 	sc = device_lookup_private(&flash_cd, unit);
    508        1.1     ahoka 
    509        1.1     ahoka 	return sc;
    510        1.1     ahoka }
    511        1.1     ahoka 
    512        1.1     ahoka device_t
    513        1.1     ahoka flash_get_device(dev_t dev)
    514        1.1     ahoka {
    515        1.1     ahoka 	struct flash_softc *sc;
    516        1.1     ahoka 	int unit;
    517        1.1     ahoka 
    518        1.1     ahoka 	unit = minor(dev);
    519        1.1     ahoka 	sc = device_lookup_private(&flash_cd, unit);
    520        1.1     ahoka 
    521        1.1     ahoka 	return sc->sc_dev;
    522        1.1     ahoka }
    523        1.1     ahoka 
    524        1.9     ahoka flash_size_t
    525        1.9     ahoka flash_get_size(dev_t dev)
    526        1.9     ahoka {
    527        1.9     ahoka 	const struct flash_softc *sc;
    528        1.9     ahoka 
    529        1.9     ahoka 	sc = flash_get_softc(dev);
    530        1.9     ahoka 
    531        1.9     ahoka 	return sc->sc_partinfo.part_size;
    532        1.9     ahoka }
    533        1.9     ahoka 
    534        1.1     ahoka int
    535        1.8     cliff flash_erase(device_t self, struct flash_erase_instruction * const ei)
    536        1.1     ahoka {
    537        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    538        1.1     ahoka 	KASSERT(ei != NULL);
    539        1.1     ahoka 	struct flash_erase_instruction e = *ei;
    540        1.1     ahoka 
    541        1.1     ahoka 	if (sc->sc_readonly)
    542        1.1     ahoka 		return EACCES;
    543        1.1     ahoka 
    544        1.1     ahoka 	/* adjust for flash partition */
    545        1.7     ahoka 	e.ei_addr += sc->sc_partinfo.part_offset;
    546        1.1     ahoka 
    547        1.1     ahoka 	/* bounds check for flash partition */
    548        1.7     ahoka 	if (e.ei_addr + e.ei_len > sc->sc_partinfo.part_size +
    549        1.7     ahoka 	    sc->sc_partinfo.part_offset)
    550        1.1     ahoka 		return EINVAL;
    551        1.6     ahoka 
    552        1.1     ahoka 	return sc->flash_if->erase(device_parent(self), &e);
    553        1.1     ahoka }
    554        1.1     ahoka 
    555        1.1     ahoka int
    556        1.8     cliff flash_read(device_t self, flash_off_t offset, size_t len, size_t * const retlen,
    557        1.8     cliff     uint8_t * const buf)
    558        1.1     ahoka {
    559        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    560        1.1     ahoka 
    561        1.7     ahoka 	offset += sc->sc_partinfo.part_offset;
    562        1.1     ahoka 
    563        1.7     ahoka 	if (offset + len > sc->sc_partinfo.part_size +
    564        1.7     ahoka 	    sc->sc_partinfo.part_offset)
    565        1.1     ahoka 		return EINVAL;
    566        1.1     ahoka 
    567        1.1     ahoka 	return sc->flash_if->read(device_parent(self),
    568        1.1     ahoka 	    offset, len, retlen, buf);
    569        1.1     ahoka }
    570        1.1     ahoka 
    571        1.1     ahoka int
    572        1.8     cliff flash_write(device_t self, flash_off_t offset, size_t len,
    573        1.8     cliff     size_t * const retlen, const uint8_t * const buf)
    574        1.1     ahoka {
    575        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    576        1.1     ahoka 
    577        1.1     ahoka 	if (sc->sc_readonly)
    578        1.1     ahoka 		return EACCES;
    579        1.1     ahoka 
    580        1.7     ahoka 	offset += sc->sc_partinfo.part_offset;
    581        1.1     ahoka 
    582        1.7     ahoka 	if (offset + len > sc->sc_partinfo.part_size +
    583        1.7     ahoka 	    sc->sc_partinfo.part_offset)
    584        1.1     ahoka 		return EINVAL;
    585        1.1     ahoka 
    586        1.1     ahoka 	return sc->flash_if->write(device_parent(self),
    587        1.1     ahoka 	    offset, len, retlen, buf);
    588        1.1     ahoka }
    589        1.1     ahoka 
    590        1.1     ahoka int
    591        1.3     ahoka flash_block_markbad(device_t self, flash_off_t offset)
    592        1.1     ahoka {
    593        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    594        1.1     ahoka 
    595        1.1     ahoka 	if (sc->sc_readonly)
    596        1.1     ahoka 		return EACCES;
    597        1.6     ahoka 
    598        1.7     ahoka 	offset += sc->sc_partinfo.part_offset;
    599        1.6     ahoka 
    600        1.1     ahoka 	if (offset + sc->flash_if->erasesize >=
    601        1.7     ahoka 	    sc->sc_partinfo.part_size +
    602        1.7     ahoka 	    sc->sc_partinfo.part_offset)
    603        1.1     ahoka 		return EINVAL;
    604        1.1     ahoka 
    605        1.1     ahoka 	return sc->flash_if->block_markbad(device_parent(self), offset);
    606        1.1     ahoka }
    607        1.1     ahoka 
    608        1.1     ahoka int
    609        1.8     cliff flash_block_isbad(device_t self, flash_off_t offset, bool * const bad)
    610        1.1     ahoka {
    611        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    612        1.6     ahoka 
    613        1.7     ahoka 	offset += sc->sc_partinfo.part_offset;
    614        1.1     ahoka 
    615        1.1     ahoka 	if (offset + sc->flash_if->erasesize >
    616        1.7     ahoka 	    sc->sc_partinfo.part_size +
    617        1.7     ahoka 	    sc->sc_partinfo.part_offset)
    618        1.1     ahoka 		return EINVAL;
    619        1.1     ahoka 
    620        1.3     ahoka 	return sc->flash_if->block_isbad(device_parent(self), offset, bad);
    621        1.1     ahoka }
    622        1.1     ahoka 
    623        1.1     ahoka int
    624        1.1     ahoka flash_sync(device_t self)
    625        1.1     ahoka {
    626        1.8     cliff 	struct flash_softc * const sc = device_private(self);
    627        1.6     ahoka 
    628        1.1     ahoka 	if (sc->sc_readonly)
    629        1.1     ahoka 		return EACCES;
    630        1.1     ahoka 
    631        1.1     ahoka 	/* noop now TODO: implement */
    632        1.1     ahoka 	return 0;
    633        1.1     ahoka }
    634        1.1     ahoka 
    635        1.1     ahoka MODULE(MODULE_CLASS_DRIVER, flash, NULL);
    636        1.1     ahoka 
    637        1.1     ahoka #ifdef _MODULE
    638        1.1     ahoka #include "ioconf.c"
    639        1.1     ahoka #endif
    640        1.1     ahoka 
    641        1.1     ahoka static int
    642        1.1     ahoka flash_modcmd(modcmd_t cmd, void *opaque)
    643        1.1     ahoka {
    644        1.1     ahoka 	int error = 0;
    645        1.1     ahoka #ifdef _MODULE
    646        1.1     ahoka 	int bmaj = -1, cmaj = -1;
    647        1.1     ahoka #endif
    648        1.1     ahoka 
    649        1.1     ahoka 	switch (cmd) {
    650        1.1     ahoka 	case MODULE_CMD_INIT:
    651        1.1     ahoka #ifdef _MODULE
    652        1.1     ahoka 		error = config_init_component(cfdriver_ioconf_flash,
    653        1.1     ahoka 		    cfattach_ioconf_flash, cfdata_ioconf_flash);
    654        1.1     ahoka 		if (error)
    655        1.1     ahoka 			return error;
    656        1.1     ahoka 		error = devsw_attach("flash", &flash_bdevsw, &bmaj,
    657        1.1     ahoka 		    &flash_cdevsw, &cmaj);
    658        1.1     ahoka 		if (error)
    659        1.1     ahoka 			config_fini_component(cfdriver_ioconf_flash,
    660        1.1     ahoka 			    cfattach_ioconf_flash, cfdata_ioconf_flash);
    661        1.1     ahoka #endif
    662        1.1     ahoka 		return error;
    663        1.1     ahoka 	case MODULE_CMD_FINI:
    664        1.1     ahoka #ifdef _MODULE
    665        1.1     ahoka 		devsw_detach(&flash_bdevsw, &flash_cdevsw);
    666        1.1     ahoka 		error = config_fini_component(cfdriver_ioconf_flash,
    667        1.1     ahoka 		    cfattach_ioconf_flash, cfdata_ioconf_flash);
    668        1.1     ahoka #endif
    669        1.1     ahoka 		return error;
    670        1.1     ahoka 	default:
    671        1.1     ahoka 		return ENOTTY;
    672        1.1     ahoka 	}
    673        1.1     ahoka }
    674