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