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