]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/isf/isf.c
Copy head (r256279) to stable/10 as part of the 10.0-RELEASE cycle.
[FreeBSD/stable/10.git] / sys / dev / isf / isf.c
1 /*-
2  * Copyright (c) 2012 Robert N. M. Watson
3  * Copyright (c) 2012 SRI International
4  * All rights reserved.
5  *
6  * This software was developed by SRI International and the University of
7  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
8  * ("CTSRD"), as part of the DARPA CRASH research programme.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/module.h>
37 #include <sys/kernel.h>
38 #include <sys/systm.h>
39
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/endian.h>
43 #include <sys/bio.h>
44 #include <sys/kthread.h>
45 #include <sys/lock.h>
46 #include <sys/malloc.h>
47 #include <sys/mutex.h>
48 #include <sys/rman.h>
49 #include <sys/taskqueue.h>
50
51 #include <machine/bus.h>
52 #include <machine/resource.h>
53
54 #include <geom/geom_disk.h>
55
56 #include <dev/isf/isf.h>
57
58 /* Read Mode */
59 #define ISF_CMD_RA      0xFF    /* Read Array mode */
60 #define ISF_CMD_RSR     0x70    /* Read Status Register mode */
61 #define ISF_CMD_RDI     0x90    /* Read Device ID/Config Reg mode */
62 #define ISF_CMD_RQ      0x98    /* Read Query mode */
63 #define ISF_CMD_CSR     0x50    /* Clear Status Register */
64
65 /* Write Mode */
66 #define ISF_CMD_WPS     0x40    /* Word Program Setup */
67 #define ISF_CMD_BPS     0xE8    /* Buffered Program Setup */
68 #define ISF_CMD_BPC     0xD0    /* Buffered Program Confirm */
69
70 /* Erase Mode */
71 #define ISF_CMD_BES     0x20    /* Block Erase Setup */
72 #define ISF_CMD_BEC     0xD0    /* Block Erase Confirm */
73
74 /* Block Locking/Unlocking */
75 #define ISF_CMD_LBS     0x60    /* Lock Block Setup */
76 #define ISF_CMD_LB      0x01    /* Lock Block */
77 #define ISF_CMD_UB      0xD0    /* Unlock Block */
78
79 /*
80  * Read Device Identifier registers.
81  *
82  * NOTE: ISF_RDIR_BLC is relative to the block base address.
83  */
84 #define ISF_REG_MC      0x00    /* Manufacture Code */
85 #define ISF_REG_ID      0x01    /* Device ID Code */
86 #define ISF_REG_BLC     0x02    /* Block Lock Configuration */
87 #define ISF_REG_RCR     0x05    /* Read Configuration Register */
88
89 /*
90  * Protection Registers
91  */
92 #define ISF_REG_L0      0x80    /* Lock Register 0 */
93 #define ISF_REG_FPP     0x81    /* 64-bit Factory Protection Register */
94 #define ISF_REG_UPP     0x85    /* 64-bit User Protection Register */
95 #define ISF_REG_L1      0x89    /* Lock Register 1 */
96 #define ISF_REG_PP1     0x8A    /* 128-bit Protection Register 1 */
97 #define ISF_REG_PP2     0x92    /* 128-bit Protection Register 2 */
98 #define ISF_REG_PP3     0x9A    /* 128-bit Protection Register 3 */
99 #define ISF_REG_PP4     0xA2    /* 128-bit Protection Register 4 */
100 #define ISF_REG_PP5     0xAA    /* 128-bit Protection Register 5 */
101 #define ISF_REG_PP6     0xB2    /* 128-bit Protection Register 6 */
102 #define ISF_REG_PP7     0xBA    /* 128-bit Protection Register 7 */
103 #define ISF_REG_PP8     0xC2    /* 128-bit Protection Register 8 */
104 #define ISF_REG_PP9     0xCA    /* 128-bit Protection Register 9 */
105 #define ISF_REG_PP10    0xD2    /* 128-bit Protection Register 10 */
106 #define ISF_REG_PP11    0xDA    /* 128-bit Protection Register 11 */
107 #define ISF_REG_PP12    0xE2    /* 128-bit Protection Register 12 */
108 #define ISF_REG_PP13    0xEA    /* 128-bit Protection Register 13 */
109 #define ISF_REG_PP14    0xF2    /* 128-bit Protection Register 14 */
110 #define ISF_REG_PP15    0xFA    /* 128-bit Protection Register 15 */
111 #define ISF_REG_PP16    0x102   /* 128-bit Protection Register 16 */
112
113 #define ISF_SR_BWS      (1 << 0)        /* BEFP Status */
114 #define ISF_SR_BLS      (1 << 1)        /* Block-Locked Status */
115 #define ISF_SR_PSS      (1 << 2)        /* Program Suspend Status */
116 #define ISF_SR_VPPS     (1 << 3)        /* Vpp Status */
117 #define ISF_SR_PS       (1 << 4)        /* Program Status */
118 #define ISF_SR_ES       (1 << 5)        /* Erase Status */
119 #define ISF_SR_ESS      (1 << 6)        /* Erase Suspend Status */
120 #define ISF_SR_DWS      (1 << 7)        /* Device Write Status */
121 #define ISF_SR_FSC_MASK (ISF_SR_VPPS | ISF_SR_PS | ISF_SR_BLS)
122
123 #define ISF_BUFFER_PROGRAM
124
125 MALLOC_DEFINE(M_ISF, "isf_data", "Intel StrateFlash driver");
126 static int      isf_debug = 0;
127
128 static struct isf_chips {
129         uint16_t         chip_id;
130         size_t           chip_size;
131         const char      *chip_desc;
132 } chip_ids[] = {
133         { 0x8817, 0x0800000, "64-Mbit Top Parameter" },
134         { 0x881A, 0x0800000, "64-Mbit Bottom Parameter" },
135         { 0x8818, 0x1000000, "128-Mbit Top Parameter" },
136         { 0x881B, 0x1000000, "128-Mbit Bottom Parameter" },
137         { 0x8919, 0x2000000, "256-Mbit Top Parameter" },
138         { 0x891C, 0x2000000, "256-Mbit Bottom Parameter" },
139         { 0x8961, 0x2000000, "512-Mbit package (half)" },
140         { 0x0000, 0x0000000, NULL }
141 };
142
143 static void     isf_task(void *arg);
144
145 /* 
146  * Device driver for the Intel StrataFlash NOR flash device.  This
147  * implementation is known to work with 256Mb instances of the device, but may
148  * also work with other 64/128/512Mb parts without much work.  Multiple
149  * device instances should be used when multiple parts are in the same
150  * physical package, due to variable block size support in the StrataFlash
151  * part.
152  */
153 devclass_t      isf_devclass;
154
155 static uint16_t
156 isf_read_reg(struct isf_softc *sc, uint16_t reg)
157 {
158
159         if (isf_debug)
160                 device_printf(sc->isf_dev, "isf_read_reg(0x%02x)\n", reg);
161         return (le16toh(bus_read_2(sc->isf_res, reg * 2)));
162 }
163
164 static uint64_t
165 isf_read_reg64(struct isf_softc *sc, uint16_t reg)
166 {
167         uint64_t val;
168         uint16_t *val16 = (uint16_t *)&val;
169
170         if (isf_debug)
171                 device_printf(sc->isf_dev, "isf_read_reg64(0x%02x)\n", reg);
172         val16[0] = bus_read_2(sc->isf_res, reg * 2);
173         val16[1] = bus_read_2(sc->isf_res, (reg+1) * 2);
174         val16[2] = bus_read_2(sc->isf_res, (reg+2) * 2);
175         val16[3] = bus_read_2(sc->isf_res, (reg+3) * 2);
176
177         return(le64toh(val));
178 }
179
180 static uint16_t
181 isf_read_off(struct isf_softc *sc, off_t off)
182 {
183
184         KASSERT(off >= 0, ("%s: negative offset\n", __func__));
185         KASSERT(off < sc->isf_disk->d_mediasize,
186             ("%s: offset out side address space 0x%08jx \n", __func__,
187             (intmax_t)off));
188
189         if (isf_debug)
190                 device_printf(sc->isf_dev, "isf_read_off(0x%08jx)\n",
191                     (intmax_t)off);
192         return (le16toh(bus_read_2(sc->isf_res, off)));
193 }
194
195 static void
196 isf_write_cmd(struct isf_softc *sc, off_t off, uint16_t cmd)
197 {
198         
199         if (isf_debug)
200                 device_printf(sc->isf_dev, "isf_write_cmd(0x%08jx, 0x%02x)\n",
201                     off, cmd);
202         bus_write_2(sc->isf_res, off, htole16(cmd));
203 }
204
205 static uint16_t
206 isf_read_status(struct isf_softc *sc, off_t off)
207 {
208         
209         isf_write_cmd(sc, off/2, ISF_CMD_RSR);
210         return isf_read_off(sc, off);
211 }
212
213 static void
214 isf_clear_status(struct isf_softc *sc)
215 {
216         
217         isf_write_cmd(sc, 0, ISF_CMD_CSR);
218 }
219
220 static int
221 isf_full_status_check(struct isf_softc *sc, off_t off)
222 {
223         int             error = 0;
224         uint16_t        status;
225         
226         status = isf_read_status(sc, off);
227         if (status & ISF_SR_VPPS) {
228                 device_printf(sc->isf_dev, "Vpp Range Error\n");
229                 error = EIO;
230         } else if (status & ISF_SR_PS) {
231                 device_printf(sc->isf_dev, "Program Error\n");
232                 error = EIO;
233         } else if (status & ISF_SR_BLS) {
234                 device_printf(sc->isf_dev, "Device Protect Error\n");
235                 error = EIO;
236         }
237         isf_clear_status(sc);
238
239         return(error);
240 }
241
242 static int
243 isf_full_erase_status_check(struct isf_softc *sc, off_t off)
244 {
245         int             error = 0;
246         uint16_t        status;
247         
248         status = isf_read_status(sc, off);
249         if (status & ISF_SR_VPPS) {
250                 device_printf(sc->isf_dev, "Vpp Range Error\n");
251                 error = EIO;
252         } else if (status & (ISF_SR_PS|ISF_SR_ES)) {
253                 device_printf(sc->isf_dev, "Command Sequence Error\n");
254                 error = EIO;
255         } else if (status & ISF_SR_ES) {
256                 device_printf(sc->isf_dev, "Block Erase Error\n");
257                 error = EIO;
258         } else if (status & ISF_SR_BLS) {
259                 device_printf(sc->isf_dev, "Block Locked Error\n");
260                 error = EIO;
261         }
262         isf_clear_status(sc);
263
264         return(error);
265 }
266
267 static void
268 isf_unlock_block(struct isf_softc *sc, off_t off)
269 {
270
271         isf_write_cmd(sc, off, ISF_CMD_LBS);
272         isf_write_cmd(sc, off, ISF_CMD_UB);
273         isf_write_cmd(sc, off, ISF_CMD_RA);
274 }
275
276 static void
277 isf_lock_block(struct isf_softc *sc, off_t off)
278 {
279
280         isf_write_cmd(sc, off, ISF_CMD_LBS);
281         isf_write_cmd(sc, off, ISF_CMD_LB);
282         isf_write_cmd(sc, off, ISF_CMD_RA);
283 }
284
285 static void
286 isf_read(struct isf_softc *sc, off_t off, void *data, size_t len)
287 {
288
289         KASSERT((uintptr_t)data % 2 == 0,
290             ("%s: unaligned data %p", __func__, data));
291         KASSERT((len <= ISF_SECTORSIZE) && (len % 2 == 0),
292             ("%s: invalid length %ju", __func__, len));
293         KASSERT(off % ISF_SECTORSIZE == 0,
294             ("%s: invalid offset %ju\n", __func__, off));
295
296         /*
297          * It is not permitted to read blocks that are in the process of
298          * being erased, but we know they will be all 1's after the
299          * erase so just report that value if asked about a block that
300          * is being erased.
301          */
302         if (sc->isf_bstate[off / ISF_ERASE_BLOCK] == BS_ERASING)
303                 memset(data, 0xFF, len);
304         else
305                 bus_read_region_2(sc->isf_res, off, (uint16_t *)data, len / 2);
306 }
307
308 static int
309 isf_write(struct isf_softc *sc, off_t off, void *data, size_t len)
310 {
311         int              cycles, error = 0;
312         uint16_t        *dp;
313         uint16_t         status;
314         off_t            coff;
315
316         KASSERT((uintptr_t)data % 2 == 0,
317             ("%s: unaligned data %p", __func__, data));
318         KASSERT((len <= ISF_SECTORSIZE) && (len % 2 == 0),
319             ("%s: invalid length %ju", __func__, len));
320         KASSERT(off % ISF_SECTORSIZE == 0,
321             ("%s: invalid offset %ju\n", __func__, off));
322         KASSERT(!sc->isf_erasing,
323             ("%s: trying to write while erasing\n", __func__));
324         KASSERT(sc->isf_bstate[off / ISF_ERASE_BLOCK] != BS_ERASING,
325             ("%s: block being erased at %ju\n", __func__, off));
326
327         isf_unlock_block(sc, off);
328
329 #ifdef ISF_BUFFER_PROGRAM
330         for (dp = data, coff = off; dp - (uint16_t *)data < len / 2;
331             dp += 32, coff += 64) {
332                 isf_clear_status(sc);
333                 isf_write_cmd(sc, coff, ISF_CMD_BPS);
334                 cycles = 0xFFFF;
335                 while ( !(isf_read_off(sc, coff) & ISF_SR_DWS) ) {
336                         if (cycles-- == 0) {
337                                 device_printf(sc->isf_dev, "timeout waiting"
338                                     " for write to start at 0x08%jx\n",
339                                     (intmax_t)coff);
340                                 return (EIO);
341                         }
342                         isf_write_cmd(sc, coff, ISF_CMD_BPS);
343                 }
344
345                 /* When writing N blocks, send N-1 as the count */
346                 isf_write_cmd(sc, coff, 31);
347                 bus_write_region_2(sc->isf_res, coff, dp, 32);
348
349                 isf_write_cmd(sc, coff, ISF_CMD_BPC);
350
351                 status = isf_read_off(sc, coff);
352                 cycles = 0xFFFFF;
353                 while ( !(status & ISF_SR_DWS) ) {
354                         if (cycles-- == 0) {
355                                 device_printf(sc->isf_dev, "timeout waiting"
356                                     " for write to complete at 0x08%jx\n",
357                                     (intmax_t)coff);
358                                 error = EIO;
359                                 break;
360                         }
361                         status = isf_read_off(sc, coff);
362                 }
363                 isf_full_status_check(sc, off);
364
365                 isf_write_cmd(sc, coff, ISF_CMD_RA);
366         }
367 #else
368         for (dp = data, coff = off; dp - (uint16_t *)data < len / 2;
369             dp++, coff += 2) {
370                 isf_write_cmd(sc, coff, ISF_CMD_WPS);
371                 bus_write_2(sc->isf_res, coff, *dp);
372                 status = isf_read_off(sc, coff);
373                 cycles=0xFFFFF;
374                 while ( !(status & ISF_SR_DWS) ) {
375                         if (cycles-- == 0) {
376                                 device_printf(sc->isf_dev, "timeout waiting"
377                                     " for write to complete at 0x08%jx\n",
378                                     (intmax_t)coff);
379                                 error = EIO;
380                                 break;
381                         }
382                         status = isf_read_off(sc, coff);
383                 }
384
385         }
386         isf_full_status_check(sc, off);
387         isf_write_cmd(sc, coff, ISF_CMD_RA);
388 #endif
389
390         isf_lock_block(sc, off);
391
392         return error;
393 }
394
395 static void
396 isf_erase_at(struct isf_softc *sc, off_t off)
397 {
398         int             cycles;
399         uint16_t        status;
400
401         isf_unlock_block(sc, off);
402         isf_clear_status(sc);
403
404         isf_write_cmd(sc, off, ISF_CMD_BES);
405         isf_write_cmd(sc, off, ISF_CMD_BEC);
406
407         cycles=0xFFFFFF;
408         status = isf_read_off(sc, off);
409         while ( !(status & ISF_SR_DWS) ) {
410 #ifdef NOTYET
411                 ISF_SLEEP(sc, sc, hz);
412 #endif
413                 if (cycles-- == 0) {
414                         device_printf(sc->isf_dev,
415                             "Giving up on erase\n");
416                         break;
417                 }
418                 status = isf_read_off(sc, off);
419         }
420
421         isf_full_erase_status_check(sc, off);
422
423         isf_lock_block(sc, off);
424
425         isf_write_cmd(sc, off, ISF_CMD_RA);
426 }
427
428 static void
429 isf_erase_range(struct isf_softc *sc, off_t blk_off, size_t size)
430 {
431         off_t           off;
432         off_t           ms = sc->isf_disk->d_mediasize;
433
434         KASSERT(blk_off % ISF_ERASE_BLOCK == 0,
435             ("%s: invalid offset %ju\n", __func__, blk_off));
436
437         ISF_LOCK_ASSERT(sc);
438
439         for (off = blk_off; off < blk_off + size; off += ISF_ERASE_BLOCK) {
440                 sc->isf_bstate[off / ISF_ERASE_BLOCK] = BS_ERASING;
441
442                 /*
443                  * The first or last 128K is four blocks depending which
444                  * part this is.  For now, just assume both are and
445                  * erase four times.
446                  */
447                 if (off == 0 || ms - off == ISF_ERASE_BLOCK) {
448                         isf_erase_at(sc, off);
449                         isf_erase_at(sc, off + 0x08000);
450                         isf_erase_at(sc, off + 0x10000);
451                         isf_erase_at(sc, off + 0x18000);
452                 } else
453                         isf_erase_at(sc, off);
454
455                 sc->isf_bstate[off / ISF_ERASE_BLOCK] = BS_STEADY;
456         }
457 }
458
459 /*
460  * disk(9) methods.
461  */
462 static int
463 isf_disk_ioctl(struct disk *disk, u_long cmd, void *data, int fflag,
464     struct thread *td)
465 {
466         int                     error = 0;
467         struct isf_softc        *sc = disk->d_drv1;
468         struct isf_range        *ir;
469
470         switch (cmd) {
471         case ISF_ERASE:
472                 ir = data;
473                 if (ir->ir_off % ISF_ERASE_BLOCK != 0 ||
474                     ir->ir_off >= disk->d_mediasize ||
475                     ir->ir_size == 0 ||
476                     ir->ir_size % ISF_ERASE_BLOCK != 0 ||
477                     ir->ir_off + ir->ir_size > disk->d_mediasize) {
478                         error = EINVAL;
479                         break;
480                 }
481                 ISF_LOCK(sc);
482                 if (sc->isf_erasing) {
483                         ISF_UNLOCK(sc);
484                         error = EBUSY;
485                         break;
486                 }
487                 sc->isf_erasing = 1;
488                 isf_erase_range(sc, ir->ir_off, ir->ir_size);
489                 sc->isf_erasing = 0;
490                 ISF_UNLOCK(sc);
491                 break;
492         default:
493                 error = EINVAL;
494         }
495
496         return (error);
497 }
498
499 static void
500 isf_disk_strategy(struct bio *bp)
501 {
502         struct isf_softc *sc = bp->bio_disk->d_drv1;
503
504         /*
505          * We advertise a block size and maximum I/O size up the stack; catch
506          * any attempts to not follow the rules.
507          */
508         KASSERT(bp->bio_bcount == ISF_SECTORSIZE,
509             ("%s: I/O size not %d", __func__, ISF_SECTORSIZE));
510
511         ISF_LOCK(sc);
512         bioq_disksort(&sc->isf_bioq, bp);
513         ISF_WAKEUP(sc);
514         ISF_UNLOCK(sc);
515 }
516
517 static void
518 isf_task(void *arg)
519 {
520         struct isf_softc        *sc = arg;
521         struct bio              *bp;
522         int                     ss = sc->isf_disk->d_sectorsize;
523         int                     error, i;
524
525         for (;;) {
526                 ISF_LOCK(sc);
527                 do {
528                         bp = bioq_first(&sc->isf_bioq);
529                         if (bp == NULL) {
530                                 if (sc->isf_doomed)
531                                         kproc_exit(0);
532                                 else
533                                         ISF_SLEEP(sc, sc, 0);
534                         }
535                 } while (bp == NULL);
536                 bioq_remove(&sc->isf_bioq, bp);
537
538                 error = 0;
539                 switch (bp->bio_cmd) {
540                 case BIO_READ:
541                         isf_read(sc, bp->bio_pblkno * ss, bp->bio_data,
542                             bp->bio_bcount);
543                         break;
544
545                 case BIO_WRITE:
546                         /*
547                          * In principle one could suspend the in-progress
548                          * erase, process any pending writes to other
549                          * blocks and then proceed, but that seems
550                          * overly complex for the likely usage modes.
551                          */
552                         if (sc->isf_erasing) {
553                                 error = EBUSY;
554                                 break;
555                         }
556
557                         /*
558                          * Read in the block we want to write and check that
559                          * we're only setting bits to 0.  If an erase would
560                          * be required return an I/O error.
561                          */
562                         isf_read(sc, bp->bio_pblkno * ss, sc->isf_rbuf,
563                             bp->bio_bcount);
564                         for (i = 0; i < bp->bio_bcount / 2; i++)
565                                 if ((sc->isf_rbuf[i] &
566                                     ((uint16_t *)bp->bio_data)[i]) !=
567                                     ((uint16_t *)bp->bio_data)[i]) {
568                                         device_printf(sc->isf_dev, "write"
569                                             " requires erase at 0x%08jx\n",
570                                             bp->bio_pblkno * ss);
571                                         error = EIO;
572                                         break;
573                                 }
574                         if (error != 0)
575                                 break;
576
577                         error = isf_write(sc, bp->bio_pblkno * ss,
578                             bp->bio_data, bp->bio_bcount);
579                         break;
580
581                 default:
582                         panic("%s: unsupported I/O operation %d", __func__,
583                             bp->bio_cmd);
584                 }
585                 if (error == 0)
586                         biodone(bp);
587                 else
588                         biofinish(bp, NULL, error);
589                 ISF_UNLOCK(sc);
590         }
591 }
592
593 static void
594 isf_dump_info(struct isf_softc *sc)
595 {
596         int i;
597         int32_t reg;
598         
599         isf_write_cmd(sc, 0, ISF_CMD_RDI);
600         device_printf(sc->isf_dev, "manufacturer code: 0x%04x\n",
601             isf_read_reg(sc, ISF_REG_MC));
602         device_printf(sc->isf_dev, "device id code: 0x%04x\n",
603             isf_read_reg(sc, ISF_REG_ID));
604         device_printf(sc->isf_dev, "read config register: 0x%04x\n",
605             isf_read_reg(sc, ISF_REG_RCR));
606
607         device_printf(sc->isf_dev, "lock register 0: 0x%04x\n",
608             isf_read_reg(sc, ISF_REG_L0));
609         device_printf(sc->isf_dev, "lock register 1: 0x%04x\n",
610             isf_read_reg(sc, ISF_REG_L1));
611
612         device_printf(sc->isf_dev, "factory PPR: 0x%016jx\n",
613             (uintmax_t)isf_read_reg64(sc, ISF_REG_FPP));
614         device_printf(sc->isf_dev, "user PPR (64-bit): 0x%016jx\n",
615             (uintmax_t)isf_read_reg64(sc, ISF_REG_UPP));
616
617         for (reg = ISF_REG_PP1, i = 1; reg <= ISF_REG_PP16; reg += 8, i++) {
618                 /* XXX: big-endian ordering of uint64_t's */
619                 device_printf(sc->isf_dev,
620                     "user PPR [%02d]: 0x%016jx%016jx\n", i,
621                     (uintmax_t)isf_read_reg64(sc, reg+4),
622                     (uintmax_t)isf_read_reg64(sc, reg));
623         }
624
625         isf_write_cmd(sc, 0, ISF_CMD_RA);
626 }
627
628 static void
629 isf_disk_insert(struct isf_softc *sc, off_t mediasize)
630 {
631         struct disk *disk;
632
633         sc->isf_doomed = 0;
634         sc->isf_erasing = 0;
635         sc->isf_bstate = malloc(sizeof(*sc->isf_bstate) *
636             (mediasize / ISF_ERASE_BLOCK), M_ISF, M_ZERO | M_WAITOK);
637         kproc_create(&isf_task, sc, &sc->isf_proc, 0, 0, "isf");
638
639         disk = disk_alloc();
640         disk->d_drv1 = sc;
641         disk->d_name = "isf";
642         disk->d_unit = sc->isf_unit;
643         disk->d_strategy = isf_disk_strategy;
644         disk->d_ioctl = isf_disk_ioctl;
645         disk->d_sectorsize = ISF_SECTORSIZE;
646         disk->d_mediasize = mediasize;
647         disk->d_maxsize = ISF_SECTORSIZE;
648         sc->isf_disk = disk;
649
650         if (bootverbose)
651                 isf_dump_info(sc);
652
653         disk_create(disk, DISK_VERSION);
654         device_printf(sc->isf_dev, "%juM flash device\n",
655             (uintmax_t)disk->d_mediasize / (1024 * 1024));
656
657 }
658
659 static void
660 isf_disk_remove(struct isf_softc *sc)
661 {
662         struct disk *disk;
663
664         ISF_LOCK_ASSERT(sc);
665         KASSERT(sc->isf_disk != NULL, ("%s: isf_disk NULL", __func__));
666
667         sc->isf_doomed = 1;
668         ISF_WAKEUP(sc);
669         ISF_SLEEP(sc, sc->isf_proc, 0);
670
671         /*
672          * XXXRW: Is it OK to call disk_destroy() under the mutex, or should
673          * we be deferring that to the calling context once it is released?
674          */
675         disk = sc->isf_disk;
676         disk_gone(disk);
677         disk_destroy(disk);
678         sc->isf_disk = NULL;
679         free(sc->isf_bstate, M_ISF);
680         device_printf(sc->isf_dev, "flash device removed\n");
681 }
682
683 int
684 isf_attach(struct isf_softc *sc)
685 {
686         uint16_t                id;
687         u_long                  start, size;
688         struct isf_chips        *cp = chip_ids;
689
690         start = rman_get_start(sc->isf_res);
691         if (start % 2 != 0) {
692                 device_printf(sc->isf_dev,
693                     "Unsupported flash start alignment %lu\n",
694                     start);
695                 return (ENXIO);
696         }
697
698         isf_write_cmd(sc, 0, ISF_CMD_RDI);
699         id = isf_read_reg(sc, ISF_REG_ID);
700         while (cp->chip_id != id)
701                 cp++;
702         if (cp->chip_desc == NULL) {
703                 device_printf(sc->isf_dev,
704                     "Unsupported device ID 0x%04x\n", id);
705                 return (ENXIO);
706         }
707         isf_write_cmd(sc, 0, ISF_CMD_RA);
708
709         size = rman_get_size(sc->isf_res);
710         if (size != cp->chip_size) {
711                 device_printf(sc->isf_dev,
712                     "Unsupported flash size %lu\n", size);
713                 return (ENXIO);
714         }
715
716         bioq_init(&sc->isf_bioq);
717         ISF_LOCK_INIT(sc);
718         sc->isf_disk = NULL;
719         isf_disk_insert(sc, size);
720         return(0);
721 }
722
723 void
724 isf_detach(struct isf_softc *sc)
725 {
726
727         /*
728          * Simulate a disk removal if one is present to deal with any pending
729          * or queued I/O.  This will occur as a result of a device driver
730          * detach -- the Intel StrataFlash has no notion of removal itself.
731          *
732          * XXXRW: Is the locking here right?
733          */
734         ISF_LOCK(sc);
735         isf_disk_remove(sc);
736         bioq_flush(&sc->isf_bioq, NULL, ENXIO);
737         KASSERT(bioq_first(&sc->isf_bioq) == NULL,
738             ("%s: non-empty bioq", __func__));
739         ISF_UNLOCK(sc);
740         ISF_LOCK_DESTROY(sc);
741 }