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, struct bio *bp) 297 { 298 299 switch (bp->bio_cmd) { 300 case BIO_READ: 301 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno * 302 ALTERA_SDCARD_SECTORSIZE); 303 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_READ_BLOCK); 304 break; 305 306 case BIO_WRITE: 307 altera_sdcard_write_rxtx_buffer(sc, bp->bio_data, 308 bp->bio_bcount); 309 altera_sdcard_write_cmd_arg(sc, bp->bio_pblkno * 310 ALTERA_SDCARD_SECTORSIZE); 311 altera_sdcard_write_cmd(sc, ALTERA_SDCARD_CMD_WRITE_BLOCK); 312 break; 313 314 default: 315 panic("%s: unsupported I/O operation %d", __func__, 316 bp->bio_cmd); 317 } 318 } 319 320 void 321 altera_sdcard_io_start(struct altera_sdcard_softc *sc, struct bio *bp) 322 { 323 324 ALTERA_SDCARD_LOCK_ASSERT(sc); 325 KASSERT(sc->as_currentbio == NULL, 326 ("%s: bio already started", __func__)); 327 328 /* 329 * We advertise a block size and maximum I/O size up the stack of the 330 * SD Card IP Core sector size. Catch any attempts to not follow the 331 * rules. 332 */ 333 KASSERT(bp->bio_bcount == ALTERA_SDCARD_SECTORSIZE, 334 ("%s: I/O size not %d", __func__, ALTERA_SDCARD_SECTORSIZE)); 335 altera_sdcard_io_start_internal(sc, bp); 336 sc->as_currentbio = bp; 337 sc->as_retriesleft = ALTERA_SDCARD_RETRY_LIMIT; 338 } 339 340 /* 341 * Handle completed I/O. ASR is passed in to avoid reading it more than once. 342 * Return 1 if the I/O is actually complete (success, or retry limit 343 * exceeded), or 0 if not. 344 */ 345 int 346 altera_sdcard_io_complete(struct altera_sdcard_softc *sc, uint16_t asr) 347 { 348 struct bio *bp; 349 uint16_t rr1, mask; 350 int error; 351 352 ALTERA_SDCARD_LOCK_ASSERT(sc); 353 KASSERT(!(asr & ALTERA_SDCARD_ASR_CMDINPROGRESS), 354 ("%s: still in progress", __func__)); 355 KASSERT(asr & ALTERA_SDCARD_ASR_CARDPRESENT, 356 ("%s: card removed", __func__)); 357 358 bp = sc->as_currentbio; 359 360 /*- 361 * Handle I/O retries if an error is returned by the device. Various 362 * quirks handled in the process: 363 * 364 * 1. ALTERA_SDCARD_ASR_CMDDATAERROR is ignored for BIO_WRITE. 365 * 2. ALTERA_SDCARD_RR1_COMMANDCRCFAILED is optionally ignored for 366 * BIO_READ. 367 */ 368 error = 0; 369 rr1 = altera_sdcard_read_rr1(sc); 370 switch (bp->bio_cmd) { 371 case BIO_READ: 372 mask = ALTERA_SDCARD_RR1_ERRORMASK; 373 if (altera_sdcard_ignore_crc_errors) 374 mask &= ~ALTERA_SDCARD_RR1_COMMANDCRCFAILED; 375 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT) 376 error = EIO; 377 else if ((asr & ALTERA_SDCARD_ASR_CMDDATAERROR) && 378 (rr1 & mask)) 379 error = EIO; 380 else 381 error = 0; 382 break; 383 384 case BIO_WRITE: 385 if (asr & ALTERA_SDCARD_ASR_CMDTIMEOUT) 386 error = EIO; 387 else 388 error = 0; 389 break; 390 391 default: 392 break; 393 } 394 if (error) { 395 sc->as_retriesleft--; 396 if (sc->as_retriesleft == 0 || bootverbose) 397 device_printf(sc->as_dev, "%s: %s operation block %ju " 398 "length %ju failed; asr 0x%08x (rr1: 0x%04x)%s\n", 399 __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" : 400 (bp->bio_cmd == BIO_WRITE ? "BIO_WRITE" : 401 "unknown"), 402 bp->bio_pblkno, bp->bio_bcount, asr, rr1, 403 sc->as_retriesleft != 0 ? " retrying" : ""); 404 /* 405 * This attempt experienced an error; possibly retry. 406 */ 407 if (sc->as_retriesleft != 0) { 408 sc->as_flags |= ALTERA_SDCARD_FLAG_IOERROR; 409 altera_sdcard_io_start_internal(sc, bp); 410 return (0); 411 } 412 sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR; 413 } else { 414 /* 415 * Successful I/O completion path. 416 */ 417 if (sc->as_flags & ALTERA_SDCARD_FLAG_IOERROR) { 418 device_printf(sc->as_dev, "%s: %s operation block %ju" 419 " length %ju succeeded after %d retries\n", 420 __func__, bp->bio_cmd == BIO_READ ? "BIO_READ" : 421 (bp->bio_cmd == BIO_WRITE ? "write" : "unknown"), 422 bp->bio_pblkno, bp->bio_bcount, 423 ALTERA_SDCARD_RETRY_LIMIT - sc->as_retriesleft); 424 sc->as_flags &= ~ALTERA_SDCARD_FLAG_IOERROR; 425 } 426 switch (bp->bio_cmd) { 427 case BIO_READ: 428 altera_sdcard_read_rxtx_buffer(sc, bp->bio_data, 429 bp->bio_bcount); 430 break; 431 432 case BIO_WRITE: 433 break; 434 435 default: 436 panic("%s: unsupported I/O operation %d", __func__, 437 bp->bio_cmd); 438 } 439 bp->bio_resid = 0; 440 error = 0; 441 } 442 biofinish(bp, NULL, error); 443 sc->as_currentbio = NULL; 444 return (1); 445 } 446