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