[BACK]Return to flash.c CVS log [TXT][DIR] Up to [local] / sys / dev

Annotation of sys/dev/flash.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb