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