root/dev/flash.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. flashattach
  2. flashdetach
  3. flashactivate
  4. flash_reg8_read
  5. flash_reg8_read_page
  6. flash_reg8_write
  7. flash_reg8_write_page
  8. flash_wait_ready
  9. flash_wait_complete
  10. flash_chip_enable
  11. flash_chip_disable
  12. flash_chip_reset
  13. flash_chip_identify
  14. flash_chip_erase_block
  15. flash_chip_read_block
  16. flash_chip_read_page
  17. flash_chip_read_oob
  18. flash_chip_write_block
  19. flash_chip_write_page
  20. flash_chip_verify_block
  21. flash_chip_verify_page
  22. flashopen
  23. flashclose
  24. flashstrategy
  25. flashioctl
  26. flashdump
  27. flashsize
  28. flashstart
  29. _flashstart
  30. flashdone
  31. flashgetdefaultlabel
  32. flashgetdisklabel
  33. flashminphys
  34. flashread
  35. flashwrite
  36. flashsafestrategy
  37. dumppage

    1 /*      $OpenBSD: flash.c,v 1.8 2007/06/20 18:15:46 deraadt Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2005 Uwe Stuehler <uwe@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/param.h>
   20 #include <sys/buf.h>
   21 #include <sys/conf.h>
   22 #include <sys/device.h>
   23 #include <sys/disk.h>
   24 #include <sys/disklabel.h>
   25 #include <sys/dkio.h>
   26 #include <sys/kernel.h>
   27 #include <sys/stat.h>
   28 #include <sys/systm.h>
   29 
   30 #include <dev/flashvar.h>
   31 
   32 #include <ufs/ffs/fs.h>         /* XXX */
   33 
   34 /* Samsung command set */
   35 #define SAMSUNG_CMD_PTRLO       0x00
   36 #define SAMSUNG_CMD_PTRHI       0x01
   37 #define SAMSUNG_CMD_PTROOB      0x50
   38 #define SAMSUNG_CMD_READ        0x30
   39 #define SAMSUNG_CMD_SEQIN       0x80
   40 #define SAMSUNG_CMD_WRITE       0x10
   41 #define SAMSUNG_CMD_ERASE0      0x60
   42 #define SAMSUNG_CMD_ERASE1      0xd0
   43 #define SAMSUNG_CMD_STATUS      0x70
   44 #define  STATUS_FAIL            (1<<0)
   45 #define  STATUS_READY           (1<<6)
   46 #define  STATUS_NWP             (1<<7)
   47 #define SAMSUNG_CMD_READID      0x90
   48 #define SAMSUNG_CMD_RESET       0xff
   49 
   50 int      flash_wait_ready(struct flash_softc *);
   51 int      flash_wait_complete(struct flash_softc *);
   52 
   53 /* XXX: these should go elsewhere */
   54 cdev_decl(flash);
   55 bdev_decl(flash);
   56 
   57 #define flashlock(sc) disk_lock(&(sc)->sc_dk)
   58 #define flashunlock(sc) disk_unlock(&(sc)->sc_dk)
   59 #define flashlookup(unit) \
   60         (struct flash_softc *)device_lookup(&flash_cd, (unit))
   61 
   62 void    flashminphys(struct buf *);
   63 void    flashstart(struct flash_softc *);
   64 void    _flashstart(struct flash_softc *, struct buf *);
   65 void    flashdone(void *);
   66 
   67 int     flashsafestrategy(struct flash_softc *, struct buf *);
   68 void    flashgetdefaultlabel(dev_t, struct flash_softc *,
   69     struct disklabel *);
   70 void    flashgetdisklabel(dev_t, struct flash_softc *, struct disklabel *, int);
   71 
   72 /*
   73  * Driver attachment glue
   74  */
   75 
   76 struct flashvendor {
   77         u_int8_t         vendor;
   78         const char      *name;
   79 };
   80 
   81 static const struct flashvendor flashvendors[] = {
   82         { FLASH_VENDOR_SAMSUNG, "Samsung" }
   83 };
   84 #define FLASH_NVENDORS (sizeof(flashvendors) / sizeof(flashvendors[0]))
   85 
   86 static const struct flashdev flashdevs[] = {
   87         { FLASH_DEVICE_SAMSUNG_K9F2808U0C, "K9F2808U0C 16Mx8 3.3V",
   88            512, 16, 32, 32768 },
   89         { FLASH_DEVICE_SAMSUNG_K9F1G08U0A, "K9F1G08U0A 128Mx8 3.3V",
   90           2048, 64, 64, 65536 },
   91 };
   92 #define FLASH_NDEVS (sizeof(flashdevs) / sizeof(flashdevs[0]))
   93 
   94 struct cfdriver flash_cd = {
   95         NULL, "flash", DV_DISK
   96 };
   97 
   98 struct dkdriver flashdkdriver = { flashstrategy };
   99 
  100 void
  101 flashattach(struct flash_softc *sc, struct flash_ctl_tag *tag,
  102     void *cookie)
  103 {
  104         u_int8_t vendor, device;
  105         u_int16_t id;
  106         int i;
  107 
  108         sc->sc_tag = tag;
  109         sc->sc_cookie = cookie;
  110 
  111         if (sc->sc_maxwaitready <= 0)
  112                 sc->sc_maxwaitready = 1000;      /* 1ms */
  113         if (sc->sc_maxwaitcomplete <= 0)
  114                 sc->sc_maxwaitcomplete = 200000; /* 200ms */
  115 
  116         flash_chip_enable(sc);
  117 
  118         /* Identify the flash device. */
  119         if (flash_chip_identify(sc, &vendor, &device) != 0) {
  120                 printf(": identification failed\n");
  121                 flash_chip_disable(sc);
  122                 return;
  123         }
  124         id = (vendor << 8) | device;
  125 
  126         /* Look up device characteristics, abort if not recognized. */
  127         for (i = 0; i < FLASH_NVENDORS; i++) {
  128                 if (flashvendors[i].vendor == vendor) {
  129                         printf(": %s", flashvendors[i].name);
  130                         break;
  131                 }
  132         }
  133         if (i == FLASH_NVENDORS)
  134                 printf(": vendor 0x%02x", vendor);
  135         for (i = 0; i < FLASH_NDEVS; i++) {
  136                 if (flashdevs[i].id == id) {
  137                         printf(" %s\n", flashdevs[i].longname);
  138                         break;
  139                 }
  140         }
  141         if (i == FLASH_NDEVS) {
  142                 /* Need to add this device to flashdevs first. */
  143                 printf(" device 0x%02x\n", device);
  144                 flash_chip_disable(sc);
  145                 return;
  146         }
  147         sc->sc_flashdev = &flashdevs[i];
  148 
  149         /* Check if the device really works or fail early. */
  150         if (flash_chip_reset(sc) != 0) {
  151                 printf("%s: reset failed\n", sc->sc_dev.dv_xname);
  152                 flash_chip_disable(sc);
  153                 return;
  154         }
  155 
  156         flash_chip_disable(sc);
  157 
  158         /*
  159          * Initialize and attach the disk structure.
  160          */
  161         sc->sc_dk.dk_driver = &flashdkdriver;
  162         sc->sc_dk.dk_name = sc->sc_dev.dv_xname;
  163         disk_attach(&sc->sc_dk);
  164 
  165         /* XXX establish shutdown hook to finish any commands. */
  166 }
  167 
  168 int
  169 flashdetach(struct device *self, int flags)
  170 {
  171         struct flash_softc *sc = (struct flash_softc *)self;
  172 
  173         /* Detach disk. */
  174         disk_detach(&sc->sc_dk);
  175 
  176         /* XXX more resources need to be freed here. */
  177         return 0;
  178 }
  179 
  180 int
  181 flashactivate(struct device *self, enum devact act)
  182 {
  183         /* XXX anything to be done here? */
  184         return 0;
  185 }
  186 
  187 /*
  188  * Flash controller and chip functions
  189  */
  190 
  191 u_int8_t
  192 flash_reg8_read(struct flash_softc *sc, int reg)
  193 {
  194         return sc->sc_tag->reg8_read(sc->sc_cookie, reg);
  195 }
  196 
  197 void
  198 flash_reg8_read_page(struct flash_softc *sc, caddr_t data, caddr_t oob)
  199 {
  200         int i;
  201 
  202         for (i = 0; i < sc->sc_flashdev->pagesize; i++)
  203                 data[i] = flash_reg8_read(sc, FLASH_REG_DATA);
  204 
  205         if (oob != NULL)
  206                 for (i = 0; i < sc->sc_flashdev->oobsize; i++)
  207                         oob[i] = flash_reg8_read(sc, FLASH_REG_DATA);
  208 }
  209 
  210 void
  211 flash_reg8_write(struct flash_softc *sc, int reg, u_int8_t value)
  212 {
  213         sc->sc_tag->reg8_write(sc->sc_cookie, reg, value);
  214 }
  215 
  216 void
  217 flash_reg8_write_page(struct flash_softc *sc, caddr_t data, caddr_t oob)
  218 {
  219         int i;
  220 
  221         for (i = 0; i < sc->sc_flashdev->pagesize; i++)
  222                 flash_reg8_write(sc, FLASH_REG_DATA, data[i]);
  223 
  224         if (oob != NULL)
  225                 for (i = 0; i < sc->sc_flashdev->oobsize; i++)
  226                         flash_reg8_write(sc, FLASH_REG_DATA, oob[i]);
  227 }
  228 
  229 /*
  230  * Wait for the "Ready/Busy" signal to go high, indicating that the
  231  * device is ready to accept another command.
  232  */
  233 int
  234 flash_wait_ready(struct flash_softc *sc)
  235 {
  236         int timo = sc->sc_maxwaitready;
  237         u_int8_t ready;
  238 
  239         ready = flash_reg8_read(sc, FLASH_REG_READY);
  240         while (ready == 0 && timo-- > 0) {
  241                 delay(1);
  242                 ready = flash_reg8_read(sc, FLASH_REG_READY);
  243         }
  244         return (ready == 0 ? EIO : 0);
  245 }
  246 
  247 /*
  248  * Similar to flash_wait_ready() but looks at IO 6 and IO 0 signals
  249  * besides R/B to decide whether the last operation was successful.
  250  */
  251 int
  252 flash_wait_complete(struct flash_softc *sc)
  253 {
  254         int timo = sc->sc_maxwaitcomplete;
  255         u_int8_t status;
  256 
  257         (void)flash_wait_ready(sc);
  258 
  259         flash_reg8_write(sc, FLASH_REG_CLE, 1);
  260         flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_STATUS);
  261         flash_reg8_write(sc, FLASH_REG_CLE, 0);
  262 
  263         status = flash_reg8_read(sc, FLASH_REG_DATA);
  264         while ((status & STATUS_READY) == 0 && timo-- > 0) {
  265                 if (flash_reg8_read(sc, FLASH_REG_READY))
  266                         break;
  267                 delay(1);
  268                 status = flash_reg8_read(sc, FLASH_REG_DATA);
  269         }
  270 
  271         status = flash_reg8_read(sc, FLASH_REG_DATA);
  272         return ((status & STATUS_FAIL) != 0 ? EIO : 0);
  273 }
  274 
  275 void
  276 flash_chip_enable(struct flash_softc *sc)
  277 {
  278         /* XXX aquire the lock. */
  279         flash_reg8_write(sc, FLASH_REG_CE, 1);
  280 }
  281 
  282 void
  283 flash_chip_disable(struct flash_softc *sc)
  284 {
  285         flash_reg8_write(sc, FLASH_REG_CE, 0);
  286         /* XXX release the lock. */
  287 }
  288 
  289 int
  290 flash_chip_reset(struct flash_softc *sc)
  291 {
  292         flash_reg8_write(sc, FLASH_REG_CLE, 1);
  293         flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_RESET);
  294         flash_reg8_write(sc, FLASH_REG_CLE, 0);
  295 
  296         return flash_wait_ready(sc);
  297 }
  298 
  299 int
  300 flash_chip_identify(struct flash_softc *sc, u_int8_t *vendor,
  301     u_int8_t *device)
  302 {
  303         int error;
  304 
  305         (void)flash_wait_ready(sc);
  306 
  307         flash_reg8_write(sc, FLASH_REG_CLE, 1);
  308         flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READID);
  309         flash_reg8_write(sc, FLASH_REG_CLE, 0);
  310 
  311         error = flash_wait_ready(sc);
  312         if (error == 0) {
  313                 *vendor = flash_reg8_read(sc, FLASH_REG_DATA);
  314                 *device = flash_reg8_read(sc, FLASH_REG_DATA);
  315         }
  316         return error;
  317 }
  318 
  319 int
  320 flash_chip_erase_block(struct flash_softc *sc, long blkno)
  321 {
  322         long pageno = blkno * sc->sc_flashdev->blkpages;
  323         int error;
  324 
  325         (void)flash_wait_ready(sc);
  326 
  327         /* Disable write-protection. */
  328         flash_reg8_write(sc, FLASH_REG_WP, 0);
  329 
  330         switch (sc->sc_flashdev->id) {
  331         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  332         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  333                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  334                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_ERASE0);
  335                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  336                 break;
  337         }
  338 
  339         switch (sc->sc_flashdev->id) {
  340         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  341         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  342                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  343                 flash_reg8_write(sc, FLASH_REG_ROW, pageno);
  344                 flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8);
  345                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  346                 break;
  347         }
  348 
  349         switch (sc->sc_flashdev->id) {
  350         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  351         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  352                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  353                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_ERASE1);
  354                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  355                 break;
  356         }
  357 
  358         error = flash_wait_complete(sc);
  359 
  360         /* Re-enable write-protection. */
  361         flash_reg8_write(sc, FLASH_REG_WP, 1);
  362 
  363         return error;
  364 }
  365 
  366 int
  367 flash_chip_read_block(struct flash_softc *sc, long blkno, caddr_t data)
  368 {
  369         long pageno;
  370         long blkend;
  371         int error;
  372 
  373         pageno = blkno * sc->sc_flashdev->blkpages;
  374         blkend = pageno + sc->sc_flashdev->blkpages;
  375 
  376         while (pageno < blkend) {
  377                 error = flash_chip_read_page(sc, pageno, data, NULL);
  378                 if (error != 0)
  379                         return error;
  380                 data += sc->sc_flashdev->pagesize;
  381                 pageno++;
  382         }
  383         return 0;
  384 }
  385 
  386 int
  387 flash_chip_read_page(struct flash_softc *sc, long pageno, caddr_t data,
  388     caddr_t oob)
  389 {
  390         int error;
  391 
  392         (void)flash_wait_ready(sc);
  393 
  394         switch (sc->sc_flashdev->id) {
  395         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  396         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  397                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  398                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO);
  399                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  400                 break;
  401         }
  402 
  403         switch (sc->sc_flashdev->id) {
  404         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  405                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  406                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  407                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  408                 break;
  409         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  410                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  411                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  412                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  413                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  414                 break;
  415         }
  416 
  417         switch (sc->sc_flashdev->id) {
  418         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  419         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  420                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  421                 flash_reg8_write(sc, FLASH_REG_ROW, pageno);
  422                 flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8);
  423                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  424                 break;
  425         }
  426 
  427         switch (sc->sc_flashdev->id) {
  428         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  429                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  430                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READ);
  431                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  432                 break;
  433         }
  434 
  435         if ((error = flash_wait_ready(sc)) != 0)
  436                 return error;
  437 
  438         /* Support hardware ECC calculation. */
  439         if (sc->sc_tag->regx_read_page) {
  440                 error = sc->sc_tag->regx_read_page(sc->sc_cookie, data,
  441                     oob);
  442                 if (error != 0)
  443                         return error;
  444         } else
  445                 flash_reg8_read_page(sc, data, oob);
  446 
  447         return 0;
  448 }
  449 
  450 int
  451 flash_chip_read_oob(struct flash_softc *sc, long pageno, caddr_t oob)
  452 {
  453         u_int8_t *p = (u_int8_t *)oob;
  454         int error;
  455         int i;
  456 
  457         (void)flash_wait_ready(sc);
  458 
  459         switch (sc->sc_flashdev->id) {
  460         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  461                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  462                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTROOB);
  463                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  464                 break;
  465         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  466                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  467                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO);
  468                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  469                 break;
  470         }
  471 
  472         switch (sc->sc_flashdev->id) {
  473         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  474                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  475                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  476                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  477                 break;
  478         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  479                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  480                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  481                 flash_reg8_write(sc, FLASH_REG_COL, 0x08);
  482                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  483                 break;
  484         }
  485 
  486         switch (sc->sc_flashdev->id) {
  487         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  488         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  489                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  490                 flash_reg8_write(sc, FLASH_REG_ROW, pageno);
  491                 flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8);
  492                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  493                 break;
  494         }
  495 
  496         switch (sc->sc_flashdev->id) {
  497         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  498                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  499                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_READ);
  500                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  501                 break;
  502         }
  503 
  504         if ((error = flash_wait_ready(sc)) != 0)
  505                 return error;
  506 
  507         for (i = 0; i < sc->sc_flashdev->oobsize; i++)
  508                 p[i] = flash_reg8_read(sc, FLASH_REG_DATA);
  509 
  510         return 0;
  511 }
  512 
  513 int
  514 flash_chip_write_block(struct flash_softc *sc, long blkno, caddr_t data,
  515     caddr_t oob)
  516 {
  517         long pageno;
  518         long blkend;
  519         caddr_t p;
  520         int error;
  521 
  522         pageno = blkno * sc->sc_flashdev->blkpages;
  523         blkend = pageno + sc->sc_flashdev->blkpages;
  524 
  525         p = data;
  526         while (pageno < blkend) {
  527                 error = flash_chip_write_page(sc, pageno, p, oob);
  528                 if (error != 0)
  529                         return error;
  530                 p += sc->sc_flashdev->pagesize;
  531                 pageno++;
  532         }
  533 
  534         /* Verify the newly written block. */
  535         return flash_chip_verify_block(sc, blkno, data, oob);
  536 }
  537 
  538 int
  539 flash_chip_write_page(struct flash_softc *sc, long pageno, caddr_t data,
  540     caddr_t oob)
  541 {
  542         int error;
  543 
  544         (void)flash_wait_ready(sc);
  545 
  546         /* Disable write-protection. */
  547         flash_reg8_write(sc, FLASH_REG_WP, 0);
  548 
  549         switch (sc->sc_flashdev->id) {
  550         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  551         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  552                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  553                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_PTRLO);
  554                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  555                 break;
  556         }
  557 
  558         switch (sc->sc_flashdev->id) {
  559         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  560         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  561                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  562                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_SEQIN);
  563                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  564                 break;
  565         }
  566 
  567         switch (sc->sc_flashdev->id) {
  568         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  569                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  570                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  571                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  572                 break;
  573         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  574                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  575                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  576                 flash_reg8_write(sc, FLASH_REG_COL, 0x00);
  577                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  578                 break;
  579         }
  580 
  581         switch (sc->sc_flashdev->id) {
  582         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  583         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  584                 flash_reg8_write(sc, FLASH_REG_ALE, 1);
  585                 flash_reg8_write(sc, FLASH_REG_ROW, pageno);
  586                 flash_reg8_write(sc, FLASH_REG_ROW, pageno >> 8);
  587                 flash_reg8_write(sc, FLASH_REG_ALE, 0);
  588                 break;
  589         }
  590 
  591         /* Support hardware ECC calculation. */
  592         if (sc->sc_tag->regx_write_page) {
  593                 error = sc->sc_tag->regx_write_page(sc->sc_cookie, data,
  594                     oob);
  595                 if (error != 0)
  596                         return error;
  597         } else
  598                 flash_reg8_write_page(sc, data, oob);
  599 
  600         switch (sc->sc_flashdev->id) {
  601         case FLASH_DEVICE_SAMSUNG_K9F2808U0C:
  602         case FLASH_DEVICE_SAMSUNG_K9F1G08U0A:
  603                 flash_reg8_write(sc, FLASH_REG_CLE, 1);
  604                 flash_reg8_write(sc, FLASH_REG_CMD, SAMSUNG_CMD_WRITE);
  605                 flash_reg8_write(sc, FLASH_REG_CLE, 0);
  606                 break;
  607         }
  608 
  609         /*
  610          * Wait for the write operation to complete although this can
  611          * take up to 700 us for the K9F1G08U0A flash type.
  612          */
  613         error = flash_wait_complete(sc);
  614 
  615         /* Re-enable write-protection. */
  616         flash_reg8_write(sc, FLASH_REG_WP, 1);
  617 
  618         return error;
  619 }
  620 
  621 int
  622 flash_chip_verify_block(struct flash_softc *sc, long blkno, caddr_t data,
  623     caddr_t oob)
  624 {
  625         long pageno;
  626         long blkend;
  627         int error;
  628 
  629         pageno = blkno * sc->sc_flashdev->blkpages;
  630         blkend = pageno + sc->sc_flashdev->blkpages;
  631 
  632         while (pageno < blkend) {
  633                 error = flash_chip_verify_page(sc, pageno, data, oob);
  634                 if (error != 0) {
  635                         printf("block %d page %d verify failed\n",
  636                             blkno, pageno);
  637                         return error;
  638                 }
  639                 data += sc->sc_flashdev->pagesize;
  640                 pageno++;
  641         }
  642         return 0;
  643 }
  644 
  645 int
  646 flash_chip_verify_page(struct flash_softc *sc, long pageno, caddr_t data,
  647     caddr_t oob)
  648 {
  649         static u_char rbuf[FLASH_MAXPAGESIZE];
  650         static u_char roob[FLASH_MAXOOBSIZE];
  651         int error;
  652 
  653         error = flash_chip_read_page(sc, pageno, rbuf,
  654             oob == NULL ? NULL : roob);
  655         if (error != 0)
  656                 return error;
  657 
  658         if (memcmp((const void *)&rbuf[0], (const void *)data,
  659             sc->sc_flashdev->pagesize) != 0)
  660                 return EIO;
  661 
  662         if (oob != NULL && memcmp((const void *)&roob[0],
  663             (const void *)oob, sc->sc_flashdev->oobsize) != 0)
  664                 return EIO;
  665 
  666         return 0;
  667 }
  668 
  669 /*
  670  * Block device functions
  671  */
  672 
  673 int
  674 flashopen(dev_t dev, int oflags, int devtype, struct proc *p)
  675 {
  676         struct flash_softc *sc;
  677         int error;
  678         int part;
  679 
  680         sc = flashlookup(flashunit(dev));
  681         if (sc == NULL)
  682                 return ENXIO;
  683 
  684         if ((error = flashlock(sc)) != 0) {
  685                 device_unref(&sc->sc_dev);
  686                 return error;
  687         }
  688 
  689         /*
  690          * If no partition is open load the partition info if it is
  691          * not already valid.  If partitions are already open, allow
  692          * opens only for the same kind of device.
  693          */
  694         if (sc->sc_dk.dk_openmask == 0) {
  695                 if ((sc->sc_flags & FDK_LOADED) == 0 ||
  696                     ((sc->sc_flags & FDK_SAFE) == 0) !=
  697                     (flashsafe(dev) == 0)) {
  698                         sc->sc_flags &= ~FDK_SAFE;
  699                         sc->sc_flags |= FDK_LOADED;
  700                         if (flashsafe(dev))
  701                                 sc->sc_flags |= FDK_SAFE;
  702                         flashgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0);
  703                 }
  704         } else if (((sc->sc_flags & FDK_SAFE) == 0) !=
  705             (flashsafe(dev) == 0)) {
  706                 flashunlock(sc);
  707                 device_unref(&sc->sc_dev);
  708                 return EBUSY;
  709         }
  710 
  711         /* Check that the partition exists. */
  712         part = flashpart(dev);
  713         if (part != RAW_PART &&
  714             (part >= sc->sc_dk.dk_label->d_npartitions ||
  715             sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
  716                 flashunlock(sc);
  717                 device_unref(&sc->sc_dev);
  718                 return ENXIO;
  719         }
  720 
  721         /* Prevent our unit from being deconfigured while open. */
  722         switch (devtype) {
  723         case S_IFCHR:
  724                 sc->sc_dk.dk_copenmask |= (1 << part);
  725                 break;
  726         case S_IFBLK:
  727                 sc->sc_dk.dk_bopenmask |= (1 << part);
  728                 break;
  729         }
  730         sc->sc_dk.dk_openmask =
  731             sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
  732 
  733         flashunlock(sc);
  734         device_unref(&sc->sc_dev);
  735         return 0;
  736 }
  737 
  738 int
  739 flashclose(dev_t dev, int fflag, int devtype, struct proc *p)
  740 {
  741         struct flash_softc *sc;
  742         int error;
  743         int part;
  744 
  745         sc = flashlookup(flashunit(dev));
  746         if (sc == NULL)
  747                 return ENXIO;
  748 
  749         if ((error = flashlock(sc)) != 0) {
  750                 device_unref(&sc->sc_dev);
  751                 return error;
  752         }
  753 
  754         /* Close one open partition. */
  755         part = flashpart(dev);
  756         switch (devtype) {
  757         case S_IFCHR:
  758                 sc->sc_dk.dk_copenmask &= ~(1 << part);
  759                 break;
  760         case S_IFBLK:
  761                 sc->sc_dk.dk_bopenmask &= ~(1 << part);
  762                 break;
  763         }
  764         sc->sc_dk.dk_openmask =
  765             sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;
  766 
  767         if (sc->sc_dk.dk_openmask == 0) {
  768                 /* XXX wait for I/O to complete? */
  769         }
  770 
  771         flashunlock(sc);
  772         device_unref(&sc->sc_dev);
  773         return 0;
  774 }
  775 
  776 /*
  777  * Queue the transfer of one or more flash pages.
  778  */
  779 void
  780 flashstrategy(struct buf *bp)
  781 {
  782         struct flash_softc *sc;
  783         int s;
  784 
  785         sc = flashlookup(flashunit(bp->b_dev));
  786         if (sc == NULL) {
  787                 bp->b_error = ENXIO;
  788                 goto bad;
  789         }
  790 
  791         /* Transfer only a multiple of the flash page size. */
  792         if ((bp->b_bcount % sc->sc_flashdev->pagesize) != 0) {
  793                 bp->b_error = EINVAL;
  794                 goto bad;
  795         }
  796 
  797         /* If the device has been invalidated, error out. */
  798         if ((sc->sc_flags & FDK_LOADED) == 0) {
  799                 bp->b_error = EIO;
  800                 goto bad;
  801         }
  802 
  803         /* Translate logical block numbers to physical. */
  804         if (flashsafe(bp->b_dev) && flashsafestrategy(sc, bp) <= 0)
  805                 goto done;
  806 
  807         /* Return immediately if it is a null transfer. */
  808         if (bp->b_bcount == 0)
  809                 goto done;
  810 
  811         /* Do bounds checking on partitions. */
  812         if (flashpart(bp->b_dev) != RAW_PART &&
  813             bounds_check_with_label(bp, sc->sc_dk.dk_label, 0) <= 0)
  814                 goto done;
  815 
  816         /* Queue the transfer. */
  817         s = splbio();
  818         disksort(&sc->sc_q, bp);
  819         flashstart(sc);
  820         splx(s);
  821         device_unref(&sc->sc_dev);
  822         return;
  823 
  824 bad:
  825         bp->b_flags |= B_ERROR;
  826 done:
  827         if ((bp->b_flags & B_ERROR) != 0)
  828                 bp->b_resid = bp->b_bcount;
  829         s = splbio();
  830         biodone(bp);
  831         splx(s);
  832         if (sc != NULL)
  833                 device_unref(&sc->sc_dev);
  834 }
  835 
  836 int
  837 flashioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
  838 {
  839         struct flash_softc *sc;
  840         int error = 0;
  841 
  842         sc = flashlookup(flashunit(dev));
  843         if (sc == NULL)
  844                 return ENXIO;
  845 
  846         if ((sc->sc_flags & FDK_LOADED) == 0) {
  847                 device_unref(&sc->sc_dev);
  848                 return EIO;
  849         }
  850 
  851         switch (cmd) {
  852         case DIOCGDINFO:
  853                 *(struct disklabel *)data = *sc->sc_dk.dk_label;
  854                 break;
  855         default:
  856                 error = ENOTTY;
  857                 break;
  858         }
  859 
  860         device_unref(&sc->sc_dev);
  861         return error;
  862 }
  863 
  864 int
  865 flashdump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size)
  866 {
  867         printf("flashdump\n");
  868         return ENODEV;
  869 }
  870 
  871 daddr64_t
  872 flashsize(dev_t dev)
  873 {
  874         printf("flashsize\n");
  875         return ENODEV;
  876 }
  877 
  878 void
  879 flashstart(struct flash_softc *sc)
  880 {
  881         struct buf *dp, *bp;
  882 
  883         while (1) {
  884                 /* Remove the next buffer from the queue or stop. */
  885                 dp = &sc->sc_q;
  886                 bp = dp->b_actf;
  887                 if (bp == NULL)
  888                         return;
  889                 dp->b_actf = bp->b_actf;
  890 
  891                 /* Transfer this buffer now. */
  892                 _flashstart(sc, bp);
  893         }
  894 }
  895 
  896 void
  897 _flashstart(struct flash_softc *sc, struct buf *bp)
  898 {
  899         int part;
  900         daddr64_t offset;
  901         long pgno;
  902 
  903         part = flashpart(bp->b_dev);
  904         offset = DL_GETPOFFSET(&sc->sc_dk.dk_label->d_partitions[part]) +
  905             bp->b_blkno;
  906         pgno = offset / (sc->sc_flashdev->pagesize / DEV_BSIZE);
  907 
  908         /*
  909          * If the requested page is exactly at the end of flash and it
  910          * is an "unsafe" device, return EOF, else error out.
  911          */
  912         if (!flashsafe(bp->b_dev) && pgno == sc->sc_flashdev->capacity) {
  913                 bp->b_resid = bp->b_bcount;
  914                 biodone(bp);
  915                 return;
  916         } else if (pgno >= sc->sc_flashdev->capacity) {
  917                 bp->b_error = EINVAL;
  918                 bp->b_flags |= B_ERROR;
  919                 biodone(bp);
  920                 return;
  921         }
  922 
  923         sc->sc_bp = bp;
  924 
  925         /* Instrumentation. */
  926         disk_busy(&sc->sc_dk);
  927 
  928         /* XXX this should be done asynchronously. */
  929         flash_chip_enable(sc);
  930         if ((bp->b_flags & B_READ) != 0)
  931                 bp->b_error = flash_chip_read_page(sc, pgno, bp->b_data,
  932                     NULL);
  933         else
  934                 bp->b_error = flash_chip_write_page(sc, pgno, bp->b_data,
  935                     NULL);
  936         if (bp->b_error == 0)
  937                 bp->b_resid = bp->b_bcount - sc->sc_flashdev->pagesize;
  938         flash_chip_disable(sc);
  939         flashdone(sc);
  940 }
  941 
  942 void
  943 flashdone(void *v)
  944 {
  945         struct flash_softc *sc = v;
  946         struct buf *bp = sc->sc_bp;
  947 
  948         /* Instrumentation. */
  949         disk_unbusy(&sc->sc_dk, bp->b_bcount - bp->b_resid,
  950             (bp->b_flags & B_READ) != 0);
  951 
  952         if (bp->b_error != 0)
  953                 bp->b_flags |= B_ERROR;
  954 
  955         biodone(bp);
  956         flashstart(sc);
  957 }
  958 
  959 void
  960 flashgetdefaultlabel(dev_t dev, struct flash_softc *sc,
  961     struct disklabel *lp)
  962 {
  963         size_t len;
  964 
  965         bzero(lp, sizeof(struct disklabel));
  966 
  967         lp->d_type = 0;
  968         lp->d_subtype = 0;
  969         strncpy(lp->d_typename, "NAND flash", sizeof(lp->d_typename));
  970 
  971         /* Use the product name up to the first space. */
  972         strncpy(lp->d_packname, sc->sc_flashdev->longname,
  973             sizeof(lp->d_packname));
  974         for (len = 0; len < sizeof(lp->d_packname); len++)
  975                 if (lp->d_packname[len] == ' ') {
  976                         lp->d_packname[len] = '\0';
  977                         break;
  978                 }
  979 
  980         /* Fake the disk geometry. */
  981         lp->d_ncylinders = 1;
  982         lp->d_ntracks = 16;
  983         lp->d_secsize = sc->sc_flashdev->pagesize;
  984         lp->d_nsectors = sc->sc_flashdev->capacity / lp->d_ntracks
  985             / lp->d_ncylinders;
  986         lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
  987         DL_SETDSIZE(lp, (daddr64_t)lp->d_ncylinders * lp->d_secpercyl);
  988 
  989         /* Fake hardware characteristics. */
  990         lp->d_rpm = 3600;
  991         lp->d_interleave = 1;
  992         lp->d_version = 1;
  993 
  994         /* XXX these values assume ffs. */
  995         lp->d_bbsize = BBSIZE;
  996         lp->d_sbsize = SBSIZE;
  997 
  998         /* Wrap it up. */
  999         lp->d_magic = DISKMAGIC;
 1000         lp->d_magic2 = DISKMAGIC;
 1001         lp->d_checksum = dkcksum(lp);
 1002 }
 1003 
 1004 void
 1005 flashgetdisklabel(dev_t dev, struct flash_softc *sc,
 1006     struct disklabel *lp, int spoofonly)
 1007 {
 1008         char *errstring;
 1009         dev_t labeldev;
 1010 
 1011         flashgetdefaultlabel(dev, sc, lp);
 1012 
 1013         if (sc->sc_tag->default_disklabel != NULL)
 1014                 sc->sc_tag->default_disklabel(sc->sc_cookie, dev, lp);
 1015 
 1016         /* Call the generic disklabel extraction routine. */
 1017         labeldev = flashlabeldev(dev);
 1018         errstring = readdisklabel(labeldev, flashstrategy, lp, spoofonly);
 1019         if (errstring != NULL) {
 1020                 /*printf("%s: %s\n", sc->sc_dev.dv_xname, errstring);*/
 1021         }
 1022 }
 1023 
 1024 /*
 1025  * Character device functions
 1026  */
 1027 
 1028 void
 1029 flashminphys(struct buf *bp)
 1030 {
 1031         struct flash_softc *sc;
 1032 
 1033         sc = flashlookup(flashunit(bp->b_dev));
 1034 
 1035         if (bp->b_bcount > sc->sc_flashdev->pagesize)
 1036                 bp->b_bcount = sc->sc_flashdev->pagesize;
 1037 }
 1038 
 1039 int
 1040 flashread(dev_t dev, struct uio *uio, int ioflag)
 1041 {
 1042         return physio(flashstrategy, NULL, dev, B_READ, flashminphys, uio);
 1043 }
 1044 
 1045 int
 1046 flashwrite(dev_t dev, struct uio *uio, int ioflag)
 1047 {
 1048         return physio(flashstrategy, NULL, dev, B_WRITE, flashminphys, uio);
 1049 }
 1050 
 1051 /*
 1052  * Physical access strategy "fixup" routines for transparent bad
 1053  * blocks management, wear-leveling, etc.
 1054  */
 1055 
 1056 /*
 1057  * Call the machine-specific routine if there is any or use just a
 1058  * default strategy for bad blocks management.
 1059  */
 1060 int
 1061 flashsafestrategy(struct flash_softc *sc, struct buf *bp)
 1062 {
 1063         if (sc->sc_tag->safe_strategy) {
 1064                 return sc->sc_tag->safe_strategy(sc->sc_cookie, bp);
 1065         }
 1066 
 1067         /* XXX no default bad blocks management strategy yet */
 1068         return 1;
 1069 }
 1070 
 1071 void dumppage(u_char *);
 1072 void dumppage(u_char *buf)
 1073 {
 1074         int i;
 1075         for (i = 0; i < 512; i++) {
 1076                 if ((i % 16) == 0)
 1077                         printf("%04x: ", i);
 1078                 if ((i % 16) == 8)
 1079                         printf(" ");
 1080                 printf(" %02x", buf[i]);
 1081                 if ((i % 16) == 15)
 1082                         printf("\n");
 1083         }
 1084         if ((i % 16) != 0)
 1085                 printf("\n");
 1086 }

/* [<][>][^][v][top][bottom][index][help] */