]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/altera/sdcard/altera_sdcard_io.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / altera / sdcard / altera_sdcard_io.c
1 /*-
2  * Copyright (c) 2012 Robert N. M. Watson
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/condvar.h>
37 #include <sys/conf.h>
38 #include <sys/bio.h>
39 #include <sys/endian.h>
40 #include <sys/kernel.h>
41 #include <sys/lock.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/mutex.h>
45 #include <sys/rman.h>
46 #include <sys/systm.h>
47 #include <sys/taskqueue.h>
48
49 #include <machine/bus.h>
50 #include <machine/resource.h>
51
52 #include <geom/geom_disk.h>
53
54 #include <dev/altera/sdcard/altera_sdcard.h>
55
56 int altera_sdcard_ignore_crc_errors = 1;
57 int altera_sdcard_verify_rxtx_writes = 1;
58
59 /*
60  * Low-level I/O routines for the Altera SD Card University IP Core driver.
61  *
62  * XXXRW: Throughout, it is assumed that the IP Core handles multibyte
63  * registers as little endian, as is the case for other Altera IP cores.
64  * However, the specification makes no reference to endianness, so this
65  * assumption might not always be correct.
66  */
67 uint16_t
68 altera_sdcard_read_asr(struct altera_sdcard_softc *sc)
69 {
70
71         return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_ASR)));
72 }
73
74 static int
75 altera_sdcard_process_csd0(struct altera_sdcard_softc *sc)
76 {
77         uint64_t c_size, c_size_mult, read_bl_len;
78         uint8_t byte0, byte1, byte2;
79
80         ALTERA_SDCARD_LOCK_ASSERT(sc);
81
82         /*-
83          * Compute card capacity per SD Card interface description as follows:
84          *
85          *   Memory capacity = BLOCKNR * BLOCK_LEN
86          *
87          * Where:
88          *
89          *   BLOCKNR = (C_SIZE + 1) * MULT
90          *   MULT = 2^(C_SIZE_MULT+2)
91          *   BLOCK_LEN = 2^READ_BL_LEN
92          */
93         read_bl_len = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_READ_BL_LEN_BYTE];
94         read_bl_len &= ALTERA_SDCARD_CSD_READ_BL_LEN_MASK;
95
96         byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE0];
97         byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MASK0;
98         byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE1];
99         byte2 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_BYTE2];
100         byte2 &= ALTERA_SDCARD_CSD_C_SIZE_MASK2;
101         c_size = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_RSHIFT0) |
102             (byte1 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT1) |
103             (byte2 << ALTERA_SDCARD_CSD_C_SIZE_LSHIFT2);
104
105         byte0 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE0];
106         byte0 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK0;
107         byte1 = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_C_SIZE_MULT_BYTE1];
108         byte1 &= ALTERA_SDCARD_CSD_C_SIZE_MULT_MASK1;
109         c_size_mult = (byte0 >> ALTERA_SDCARD_CSD_C_SIZE_MULT_RSHIFT0) |
110             (byte1 << ALTERA_SDCARD_CSD_C_SIZE_MULT_LSHIFT1);
111
112         /*
113          * If we're just getting back zero's, mark the card as bad, even
114          * though it could just mean a Very Small Disk Indeed.
115          */
116         if (c_size == 0 && c_size_mult == 0 && read_bl_len == 0) {
117                 device_printf(sc->as_dev, "Ignored zero-size card\n");
118                 return (ENXIO);
119         }
120         sc->as_mediasize = (c_size + 1) * (1 << (c_size_mult + 2)) *
121             (1 << read_bl_len);
122         return (0);
123 }
124
125 int
126 altera_sdcard_read_csd(struct altera_sdcard_softc *sc)
127 {
128         uint8_t csd_structure;
129         int error;
130
131         ALTERA_SDCARD_LOCK_ASSERT(sc);
132
133         /*
134          * XXXRW: Assume for now that when the SD Card IP Core negotiates
135          * voltage/speed/etc, it must use the CSD register, and therefore
136          * populates the SD Card IP Core's cache of the register value.  This
137          * means that we can read it without issuing further SD Card commands.
138          * If this assumption proves false, we will (a) get back garbage and
139          * (b) need to add additional states in the driver state machine in
140          * order to query card properties before I/O can start.
141          *
142          * XXXRW: Treating this as an array of bytes, so no byte swapping --
143          * is that a safe assumption?
144          */
145         KASSERT(((uintptr_t)&sc->as_csd.csd_data) % 2 == 0,
146             ("%s: CSD buffer unaligned", __func__));
147         bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_CSD,
148             (uint16_t *)sc->as_csd.csd_data, sizeof(sc->as_csd) / 2);
149
150         /*
151          * Interpret the loaded CSD, extracting certain fields and copying
152          * them into the softc for easy software access.
153          *
154          * Currently, we support only CSD Version 1.0.  If we detect a newer
155          * version, suppress card detection.
156          */
157         csd_structure = sc->as_csd.csd_data[ALTERA_SDCARD_CSD_STRUCTURE_BYTE];
158         csd_structure &= ALTERA_SDCARD_CSD_STRUCTURE_MASK;
159         csd_structure >>= ALTERA_SDCARD_CSD_STRUCTURE_RSHIFT;
160         sc->as_csd_structure = csd_structure;
161
162         /*
163          * Interpret the CSD field based on its version.  Extract fields,
164          * especially mediasize.
165          *
166          * XXXRW: Desirable to support further CSD versions here.
167          */
168         switch (sc->as_csd_structure) {
169         case 0:
170                 error = altera_sdcard_process_csd0(sc);
171                 if (error)
172                         return (error);
173                 break;
174
175         default:
176                 device_printf(sc->as_dev,
177                     "Ignored disk with unsupported CSD structure (%d)\n",
178                     sc->as_csd_structure);
179                 return (ENXIO);
180         }
181         return (0);
182 }
183
184 /*
185  * XXXRW: The Altera IP Core specification indicates that RR1 is a 16-bit
186  * register, but all bits it identifies are >16 bit.  Most likely, RR1 is a
187  * 32-bit register?
188  */
189 static uint16_t
190 altera_sdcard_read_rr1(struct altera_sdcard_softc *sc)
191 {
192
193         return (le16toh(bus_read_2(sc->as_res, ALTERA_SDCARD_OFF_RR1)));
194 }
195
196 static void
197 altera_sdcard_write_cmd_arg(struct altera_sdcard_softc *sc, uint32_t cmd_arg)
198 {
199
200         bus_write_4(sc->as_res, ALTERA_SDCARD_OFF_CMD_ARG, htole32(cmd_arg));
201 }
202
203 static void
204 altera_sdcard_write_cmd(struct altera_sdcard_softc *sc, uint16_t cmd)
205 {
206
207         bus_write_2(sc->as_res, ALTERA_SDCARD_OFF_CMD, htole16(cmd));
208 }
209
210 static void
211 altera_sdcard_read_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
212     size_t len)
213 {
214
215         KASSERT((uintptr_t)data % 2 == 0,
216             ("%s: unaligned data %p", __func__, data));
217         KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
218             ("%s: invalid length %ju", __func__, len));
219
220         bus_read_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
221             (uint16_t *)data, len / 2);
222 }
223
224 static void
225 altera_sdcard_write_rxtx_buffer(struct altera_sdcard_softc *sc, void *data,
226     size_t len)
227 {
228         u_int corrections, differences, i, retry_counter;
229         uint16_t d, v;
230
231         KASSERT((uintptr_t)data % 2 == 0,
232             ("%s: unaligned data %p", __func__, data));
233         KASSERT((len <= ALTERA_SDCARD_SECTORSIZE) && (len % 2 == 0),
234             ("%s: invalid length %ju", __func__, len));
235
236         retry_counter = 0;
237         do {
238                 bus_write_region_2(sc->as_res, ALTERA_SDCARD_OFF_RXTX_BUFFER,
239                     (uint16_t *)data, len / 2);
240
241                 /*
242                  * XXXRW: Due to a possible hardware bug, the above call to
243                  * bus_write_region_2() might not succeed.  If the workaround
244                  * is enabled, verify each write and retry until it succeeds.
245                  *
246                  * XXXRW: Do we want a limit counter for retries here?
247                  */
248 recheck:
249                 corrections = 0;
250                 differences = 0;
251                 if (altera_sdcard_verify_rxtx_writes) {
252                         for (i = 0; i < ALTERA_SDCARD_SECTORSIZE; i += 2) {
253                                 v = bus_read_2(sc->as_res,
254                                     ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
255                                 d = *(uint16_t *)((uint8_t *)data + i);
256                                 if (v != d) {
257                                         if (retry_counter == 0) {
258                                                 bus_write_2(sc->as_res,
259                                                     ALTERA_SDCARD_OFF_RXTX_BUFFER + i,
260                                                     d);
261                                                 v = bus_read_2(sc->as_res,
262                                                     ALTERA_SDCARD_OFF_RXTX_BUFFER + i);
263                                                 if (v == d) {
264                                                         corrections++;
265                                                         device_printf(sc->as_dev,
266                                                             "%s: single word rewrite worked"
267                                                             " at offset %u\n", 
268                                                             __func__, i);
269                                                         continue;
270                                                 }
271                                         }
272                                         differences++;
273                                         device_printf(sc->as_dev,
274                                             "%s: retrying write -- difference"
275                                             " %u at offset %u, retry %u\n",
276                                             __func__, differences, i,
277                                             retry_counter);
278                                 }
279                         }
280                         if (differences != 0) {
281                                 retry_counter++;
282                                 if (retry_counter == 1 &&
283                                     corrections == differences)
284                                         goto recheck;
285                         }
286                 }
287         } while (differences != 0);
288         if (retry_counter)
289                 device_printf(sc->as_dev, "%s: succeeded after %u retries\n",
290                     __func__, retry_counter);
291 }
292
293 static void
294 altera_sdcard_io_start_internal(struct altera_sdcard_softc *sc, struct bio *bp)
295 {
296
297         switch (bp->bio_cmd) {
298         case BIO_READ:
299                 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
300                     ALTERA_SDCARD_SECTORSIZE);
301                 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK);
302                 break;
303
304         case BIO_WRITE:
305                 altera_sdcard_write_rxtx_buffer(sc, bp->bio_data,
306                     bp->bio_bcount);
307                 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno *
308                     ALTERA_SDCARD_SECTORSIZE);
309                 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK);
310                 break;
311
312         default:
313                 panic("%s: unsupported I/O operation %d", __func__,
314                     bp->bio_cmd);
315         }
316 }
317
318 void
319 altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp)
320 {
321
322         ALTERA_SDCARD_LOCK_ASSERT(sc);
323         KASSERT(sc->as_currentbio == NULL,
324             ("%s: bio already started", __func__));
325
326         /*
327          * We advertise a block size and maximum I/O size up the stack of the
328          * SD Card IP Core sector size.  Catch any attempts to not follow the
329          * rules.
330          */
331         KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE,
332             ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE));
333         altera_sdcard_io_start_internal(sc, bp);
334         sc->as_currentbio = bp;
335         sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT;
336 }
337
338 /*
339  * Handle completed I/O.  ASR is passed in to avoid reading it more than once.
340  * Return 1 if the I/O is actually complete (success, or retry limit
341  * exceeded), or 0 if not.
342  */
343 int
344 altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr)
345 {
346         struct bio *bp;
347         uint16_t rr1, mask;
348         int error;
349
350         ALTERA_SDCARD_LOCK_ASSERT(sc);
351         KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS),
352             ("%s: still in progress", __func__));
353         KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT,
354             ("%s: card removed", __func__));
355
356         bp = sc->as_currentbio;
357
358         /*-
359          * Handle I/O retries if an error is returned by the device.  Various
360          * quirks handled in the process:
361          *
362          * 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE.
363          * 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for
364          *    BIO_READ.
365          */
366         error = 0;
367         rr1 = altera_sdcard_read_rr1(sc);
368         switch (bp->bio_cmd) {
369         case BIO_READ:
370                 mask = ALTERA_SDCARD_RR1_ERRORMASK;
371                 if (altera_sdcard_ignore_crc_errors)
372                         mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED;
373                 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
374                         error = EIO;
375                 else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) &&
376                     (rr1 & mask))
377                         error = EIO;
378                 else
379                         error = 0;
380                 break;
381
382         case BIO_WRITE:
383                 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT)
384                         error = EIO;
385                 else
386                         error = 0;
387                 break;
388
389         default:
390                 break;
391         }
392         if (error) {
393                 sc->as_retriesleft--;
394                 if (sc->as_retriesleft == 0 || bootverbose)
395                         device_printf(sc->as_dev, "%s: %s operation block %ju "
396                             "length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n",
397                             __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
398                             (bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" :
399                             "unknown"),
400                             bp->bio_pblkno, bp->bio_bcount, asr, rr1,
401                             sc->as_retriesleft != 0 ? " retrying" : "");
402                 /*
403                  * This attempt experienced an error; possibly retry.
404                  */
405                 if (sc->as_retriesleft != 0) {
406                         sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR;
407                         altera_sdcard_io_start_internal(sc, bp);
408                         return (0);
409                 }
410                 sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
411         } else {
412                 /*
413                  * Successful I/O completion path.
414                  */
415                 if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) {
416                         device_printf(sc->as_dev, "%s: %s operation block %ju"
417                             " length %ju succeeded after %d retries\n",
418                             __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" :
419                             (bp->bio_cmd == BIO_WRITE ? "write" : "unknown"),
420                             bp->bio_pblkno, bp->bio_bcount,
421                             ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft);
422                         sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR;
423                 }
424                 switch (bp->bio_cmd) {
425                 case BIO_READ:
426                         altera_sdcard_read_rxtx_buffer(sc, bp->bio_data,
427                             bp->bio_bcount);
428                         break;
429
430                 case BIO_WRITE:
431                         break;
432
433                 default:
434                         panic("%s: unsupported I/O operation %d", __func__,
435                             bp->bio_cmd);
436                 }
437                 bp->bio_resid = 0;
438                 error = 0;
439         }
440         biofinish(bp, NULL, error);
441         sc->as_currentbio = NULL;
442         return (1);
443 }