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