1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * Memory target support for SDcard. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/note.h> 31 #include <sys/conf.h> 32 #include <sys/blkdev.h> 33 #include <sys/ddi.h> 34 #include <sys/sunddi.h> 35 #include <sys/sdcard/sda.h> 36 #include <sys/sdcard/sda_impl.h> 37 38 static int sda_mem_errno(sda_err_t); 39 static int sda_mem_rw(sda_slot_t *, bd_xfer_t *, uint8_t, uint16_t); 40 static void sda_mem_done(sda_cmd_t *); 41 static void sda_mem_getstring(uint32_t *, char *, int, int); 42 43 /* 44 * To minimize complexity and reduce layering, we implement almost the 45 * entire memory card driver (sdcard) here. The memory card still 46 * needs to be a separate driver though, due to the requirement to 47 * have both SCSI HBA bus ops and SD bus ops. 48 */ 49 50 /* 51 * Everything beyond this is private. 52 */ 53 54 int 55 sda_mem_errno(sda_err_t errno) 56 { 57 /* the hot path */ 58 if (errno == SDA_EOK) { 59 return (0); 60 } 61 62 switch (errno) { 63 case SDA_ENOMEM: 64 return (ENOMEM); 65 case SDA_ETIME: 66 return (ETIMEDOUT); 67 case SDA_EWPROTECT: 68 return (EROFS); 69 case SDA_ESUSPENDED: 70 case SDA_ENODEV: 71 return (ENODEV); 72 case SDA_EFAULT: 73 case SDA_ECRC7: 74 case SDA_EPROTO: 75 case SDA_ERESET: 76 case SDA_EIO: 77 case SDA_ERESID: 78 default: 79 return (EIO); 80 } 81 } 82 83 void 84 sda_mem_done(sda_cmd_t *cmdp) 85 { 86 bd_xfer_t *xfer = sda_cmd_data(cmdp); 87 int errno = sda_cmd_errno(cmdp); 88 89 bd_xfer_done(xfer, sda_mem_errno(errno)); 90 sda_cmd_free(cmdp); 91 } 92 93 int 94 sda_mem_rw(sda_slot_t *slot, bd_xfer_t *xfer, uint8_t cmd, uint16_t flags) 95 { 96 sda_cmd_t *cmdp; 97 uint64_t nblks; 98 uint64_t blkno; 99 uint16_t rblen; 100 101 blkno = xfer->x_blkno; 102 nblks = xfer->x_nblks; 103 104 ASSERT(nblks != 0); 105 106 if ((blkno + nblks) > slot->s_nblks) { 107 return (EINVAL); 108 } 109 110 cmdp = sda_cmd_alloc(slot, cmd, blkno << slot->s_bshift, 111 R1, xfer, KM_NOSLEEP); 112 if (cmdp == NULL) { 113 return (ENOMEM); 114 } 115 116 if (slot->s_hostp->h_dma != NULL) { 117 cmdp->sc_dmah = xfer->x_dmah; 118 cmdp->sc_ndmac = xfer->x_ndmac; 119 cmdp->sc_dmac = xfer->x_dmac; 120 cmdp->sc_kvaddr = 0; 121 } else { 122 cmdp->sc_ndmac = 0; 123 cmdp->sc_kvaddr = xfer->x_kaddr; 124 } 125 126 rblen = slot->s_blksz; 127 128 /* other fields are set by sda_cmd_alloc */ 129 cmdp->sc_blksz = rblen; 130 cmdp->sc_nblks = (uint16_t)nblks; 131 cmdp->sc_flags = flags; 132 133 sda_cmd_submit(slot, cmdp, sda_mem_done); 134 return (0); 135 } 136 137 int 138 sda_mem_bd_read(void *arg, bd_xfer_t *xfer) 139 { 140 sda_slot_t *slot = arg; 141 uint8_t cmd; 142 uint16_t flags; 143 144 if (xfer->x_nblks > 1) { 145 cmd = CMD_READ_MULTI; 146 flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ | 147 SDA_CMDF_AUTO_CMD12; 148 } else { 149 cmd = CMD_READ_SINGLE; 150 flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_READ; 151 } 152 153 return (sda_mem_rw(slot, xfer, cmd, flags)); 154 } 155 156 int 157 sda_mem_bd_write(void *arg, bd_xfer_t *xfer) 158 { 159 sda_slot_t *slot = arg; 160 uint8_t cmd; 161 uint16_t flags; 162 163 if ((slot->s_flags & SLOTF_WRITABLE) == 0) { 164 return (EROFS); 165 } 166 if (xfer->x_nblks > 1) { 167 cmd = CMD_WRITE_MULTI; 168 flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE | 169 SDA_CMDF_AUTO_CMD12; 170 } else { 171 cmd = CMD_WRITE_SINGLE; 172 flags = SDA_CMDF_DAT | SDA_CMDF_MEM | SDA_CMDF_WRITE; 173 } 174 175 return (sda_mem_rw(slot, xfer, cmd, flags)); 176 } 177 178 void 179 sda_mem_bd_driveinfo(void *arg, bd_drive_t *drive) 180 { 181 sda_slot_t *slot = arg; 182 183 drive->d_qsize = 4; /* we queue up internally, 4 is enough */ 184 drive->d_maxxfer = 65536; 185 drive->d_removable = B_TRUE; 186 drive->d_hotpluggable = B_FALSE; 187 drive->d_target = slot->s_slot_num; 188 } 189 190 int 191 sda_mem_bd_mediainfo(void *arg, bd_media_t *media) 192 { 193 sda_slot_t *slot = arg; 194 195 sda_slot_enter(slot); 196 if (!slot->s_ready) { 197 sda_slot_exit(slot); 198 return (ENXIO); 199 } 200 media->m_nblks = slot->s_nblks; 201 media->m_blksize = slot->s_blksz; 202 media->m_readonly = slot->s_flags & SLOTF_WRITABLE ? B_FALSE : B_TRUE; 203 sda_slot_exit(slot); 204 return (0); 205 } 206 207 uint32_t 208 sda_mem_getbits(uint32_t *resp, int hibit, int len) 209 { 210 uint32_t val = 0; 211 uint32_t bit; 212 213 for (bit = hibit; len--; bit--) { 214 val <<= 1; 215 val |= ((resp[bit / 32]) >> (bit % 32)) & 1; 216 } 217 return (val); 218 } 219 220 void 221 sda_mem_getstring(uint32_t *resp, char *s, int hibit, int len) 222 { 223 while (len--) { 224 *s++ = sda_mem_getbits(resp, hibit, 8); 225 hibit -= 8; 226 } 227 *s = 0; 228 } 229 230 uint32_t 231 sda_mem_maxclk(sda_slot_t *slot) 232 { 233 static const uint32_t mult[16] = { 234 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 235 }; 236 237 static const uint32_t units[8] = { 238 10000, 100000, 1000000, 10000000, 0, 0, 0, 0, 239 }; 240 uint8_t ts; 241 242 ts = sda_mem_getbits(slot->s_rcsd, 103, 8); 243 244 return ((units[ts & 0x7]) * (mult[(ts >> 3) & 0xf])); 245 } 246 247 int 248 sda_mem_parse_cid_csd(sda_slot_t *slot) 249 { 250 uint32_t *rcid; 251 uint32_t *rcsd; 252 int csdver; 253 uint16_t rblen; 254 uint16_t bshift; 255 uint32_t cmult; 256 uint32_t csize; 257 258 rcid = slot->s_rcid; 259 rcsd = slot->s_rcsd; 260 261 csdver = sda_mem_getbits(rcsd, 127, 2); 262 263 if (slot->s_flags & SLOTF_SDMEM) { 264 switch (csdver) { 265 case 0: 266 csize = sda_mem_getbits(rcsd, 73, 12); 267 rblen = (1 << sda_mem_getbits(rcsd, 83, 4)); 268 cmult = (4 << sda_mem_getbits(rcsd, 49, 3)); 269 bshift = 9; 270 break; 271 case 1: 272 rblen = 512; 273 csize = sda_mem_getbits(rcsd, 69, 22); 274 cmult = 1024; 275 bshift = 0; 276 break; 277 default: 278 sda_slot_err(slot, "Unknown SD CSD version (%d)", 279 csdver); 280 return (DDI_FAILURE); 281 } 282 283 slot->s_mfg = sda_mem_getbits(rcid, 127, 8); 284 sda_mem_getstring(rcid, slot->s_oem, 119, 2); 285 sda_mem_getstring(rcid, slot->s_prod, 103, 5); 286 slot->s_majver = sda_mem_getbits(rcid, 63, 4); 287 slot->s_minver = sda_mem_getbits(rcid, 59, 4); 288 slot->s_serial = sda_mem_getbits(rcid, 55, 32); 289 slot->s_year = sda_mem_getbits(rcid, 19, 8) + 2000; 290 slot->s_month = sda_mem_getbits(rcid, 11, 4); 291 292 } else if (slot->s_flags & SLOTF_MMC) { 293 if ((csdver < 1) || (csdver > 2)) { 294 sda_slot_err(slot, "Unknown MMC CSD version (%d)", 295 csdver); 296 return (DDI_FAILURE); 297 } 298 299 switch (sda_mem_getbits(rcsd, 125, 4)) { 300 case 0: /* MMC 1.0 - 1.2 */ 301 case 1: /* MMC 1.4 */ 302 slot->s_mfg = sda_mem_getbits(rcid, 127, 24); 303 slot->s_oem[0] = 0; 304 sda_mem_getstring(rcid, slot->s_prod, 103, 7); 305 slot->s_majver = sda_mem_getbits(rcid, 47, 4); 306 slot->s_minver = sda_mem_getbits(rcid, 43, 4); 307 slot->s_serial = sda_mem_getbits(rcid, 39, 24); 308 break; 309 310 case 2: /* MMC 2.0 - 2.2 */ 311 case 3: /* MMC 3.1 - 3.3 */ 312 case 4: /* MMC 4.x */ 313 slot->s_mfg = sda_mem_getbits(rcid, 127, 8); 314 sda_mem_getstring(rcid, slot->s_oem, 119, 2); 315 sda_mem_getstring(rcid, slot->s_prod, 103, 6); 316 slot->s_majver = sda_mem_getbits(rcid, 55, 4); 317 slot->s_minver = sda_mem_getbits(rcid, 51, 4); 318 slot->s_serial = sda_mem_getbits(rcid, 47, 32); 319 break; 320 321 default: 322 /* this error isn't fatal to us */ 323 sda_slot_err(slot, "Unknown MMCA version (%d)", 324 sda_mem_getbits(rcsd, 125, 4)); 325 break; 326 } 327 328 slot->s_year = sda_mem_getbits(rcid, 11, 4) + 1997; 329 slot->s_month = sda_mem_getbits(rcid, 15, 4); 330 331 csize = sda_mem_getbits(rcsd, 73, 12); 332 rblen = (1 << sda_mem_getbits(rcsd, 83, 4)); 333 cmult = (4 << sda_mem_getbits(rcsd, 49, 3)); 334 bshift = 9; 335 336 } else { 337 338 sda_slot_err(slot, "Card type unknown"); 339 return (DDI_FAILURE); 340 } 341 342 /* 343 * These fields are common to all known MMC/SDcard memory cards. 344 * 345 * The spec requires that block size 512 be supported. 346 * The media may have a different native size, but 512 347 * byte blocks will always work. This is true for SDcard, 348 * and apparently for MMC as well. 349 */ 350 rblen = max(rblen, 512); /* paranoia */ 351 slot->s_nblks = (csize + 1) * cmult * (rblen / 512); 352 slot->s_bshift = bshift; 353 slot->s_blksz = 512; 354 355 slot->s_r2w = (1 << sda_mem_getbits(rcsd, 28, 3)); 356 slot->s_ccc = sda_mem_getbits(rcsd, 95, 12); 357 slot->s_perm_wp = sda_mem_getbits(rcsd, 13, 1); 358 slot->s_temp_wp = sda_mem_getbits(rcsd, 12, 1); 359 slot->s_dsr = sda_mem_getbits(rcsd, 76, 1); 360 361 if (((slot->s_ccc & (1 << 4)) == 0) || 362 (slot->s_perm_wp != 0) || (slot->s_temp_wp != 0)) { 363 slot->s_flags &= ~SLOTF_WRITABLE; 364 } 365 366 return (DDI_SUCCESS); 367 } 368