1 /*- 2 * Copyright (c) 2013 Ilya Bakulin. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __FBSDID("$FreeBSD$"); 28 29 #include <sys/param.h> 30 #include <sys/module.h> 31 #include <sys/kernel.h> 32 #include <sys/malloc.h> 33 #include <sys/systm.h> 34 #include <sys/lock.h> 35 #include <sys/mutex.h> 36 #include <sys/bus.h> 37 #include <sys/endian.h> 38 #include <sys/sysctl.h> 39 40 #include <cam/cam.h> 41 #include <cam/cam_ccb.h> 42 #include <cam/cam_debug.h> 43 #include <cam/cam_sim.h> 44 #include <cam/cam_xpt_sim.h> 45 #include <cam/scsi/scsi_all.h> 46 47 static int is_sdio_mode = 1; 48 49 struct mmcnull_softc { 50 device_t dev; 51 struct mtx sc_mtx; 52 53 struct cam_devq *devq; 54 struct cam_sim *sim; 55 struct cam_path *path; 56 57 struct callout tick; 58 union ccb *cur_ccb; 59 }; 60 61 static void mmcnull_identify(driver_t *, device_t); 62 static int mmcnull_probe(device_t); 63 static int mmcnull_attach(device_t); 64 static int mmcnull_detach(device_t); 65 static void mmcnull_action_sd(struct cam_sim *, union ccb *); 66 static void mmcnull_action_sdio(struct cam_sim *, union ccb *); 67 static void mmcnull_intr_sd(void *xsc); 68 static void mmcnull_intr_sdio(void *xsc); 69 static void mmcnull_poll(struct cam_sim *); 70 71 static void 72 mmcnull_identify(driver_t *driver, device_t parent) 73 { 74 device_t child; 75 76 if (resource_disabled("mmcnull", 0)) 77 return; 78 79 if (device_get_unit(parent) != 0) 80 return; 81 82 /* Avoid duplicates. */ 83 if (device_find_child(parent, "mmcnull", -1)) 84 return; 85 86 child = BUS_ADD_CHILD(parent, 20, "mmcnull", 0); 87 if (child == NULL) { 88 device_printf(parent, "add MMCNULL child failed\n"); 89 return; 90 } 91 } 92 93 94 static int 95 mmcnull_probe(device_t dev) 96 { 97 device_set_desc(dev, "Emulated MMC controller"); 98 return (BUS_PROBE_DEFAULT); 99 } 100 101 static int 102 mmcnull_attach(device_t dev) 103 { 104 struct mmcnull_softc *sc; 105 sim_action_func action_func; 106 107 sc = device_get_softc(dev); 108 sc->dev = dev; 109 110 mtx_init(&sc->sc_mtx, "mmcnullmtx", NULL, MTX_DEF); 111 112 if ((sc->devq = cam_simq_alloc(1)) == NULL) 113 return (ENOMEM); 114 115 if (is_sdio_mode) 116 action_func = mmcnull_action_sdio; 117 else 118 action_func = mmcnull_action_sd; 119 sc->sim = cam_sim_alloc(action_func, mmcnull_poll, "mmcnull", sc, 120 device_get_unit(dev), &sc->sc_mtx, 1, 1, 121 sc->devq); 122 123 if (sc->sim == NULL) { 124 cam_simq_free(sc->devq); 125 device_printf(dev, "cannot allocate CAM SIM\n"); 126 return (EINVAL); 127 } 128 129 mtx_lock(&sc->sc_mtx); 130 if (xpt_bus_register(sc->sim, dev, 0) != 0) { 131 device_printf(dev, 132 "cannot register SCSI pass-through bus\n"); 133 cam_sim_free(sc->sim, FALSE); 134 cam_simq_free(sc->devq); 135 mtx_unlock(&sc->sc_mtx); 136 return (EINVAL); 137 } 138 mtx_unlock(&sc->sc_mtx); 139 140 callout_init_mtx(&sc->tick, &sc->sc_mtx, 0); /* Callout to emulate interrupts */ 141 142 device_printf(dev, "attached OK\n"); 143 144 return (0); 145 } 146 147 static int 148 mmcnull_detach(device_t dev) 149 { 150 struct mmcnull_softc *sc; 151 152 sc = device_get_softc(dev); 153 154 if (sc == NULL) 155 return (EINVAL); 156 157 if (sc->sim != NULL) { 158 mtx_lock(&sc->sc_mtx); 159 xpt_bus_deregister(cam_sim_path(sc->sim)); 160 cam_sim_free(sc->sim, FALSE); 161 mtx_unlock(&sc->sc_mtx); 162 } 163 164 if (sc->devq != NULL) 165 cam_simq_free(sc->devq); 166 167 callout_drain(&sc->tick); 168 mtx_destroy(&sc->sc_mtx); 169 170 device_printf(dev, "detached OK\n"); 171 return (0); 172 } 173 174 /* 175 * The interrupt handler 176 * This implementation calls it via callout(9) 177 * with the mutex already taken 178 */ 179 static void 180 mmcnull_intr_sd(void *xsc) { 181 struct mmcnull_softc *sc; 182 union ccb *ccb; 183 struct ccb_mmcio *mmcio; 184 185 sc = (struct mmcnull_softc *) xsc; 186 mtx_assert(&sc->sc_mtx, MA_OWNED); 187 188 ccb = sc->cur_ccb; 189 mmcio = &ccb->mmcio; 190 device_printf(sc->dev, "mmcnull_intr: MMC command = %d\n", 191 mmcio->cmd.opcode); 192 193 switch (mmcio->cmd.opcode) { 194 case MMC_GO_IDLE_STATE: 195 device_printf(sc->dev, "Reset device\n"); 196 break; 197 case SD_SEND_IF_COND: 198 mmcio->cmd.resp[0] = 0x1AA; // To match mmc_xpt expectations :-) 199 break; 200 case MMC_APP_CMD: 201 mmcio->cmd.resp[0] = R1_APP_CMD; 202 break; 203 case SD_SEND_RELATIVE_ADDR: 204 case MMC_SELECT_CARD: 205 mmcio->cmd.resp[0] = 0x1 << 16; 206 break; 207 case ACMD_SD_SEND_OP_COND: 208 mmcio->cmd.resp[0] = 0xc0ff8000; 209 mmcio->cmd.resp[0] |= MMC_OCR_CARD_BUSY; 210 break; 211 case MMC_ALL_SEND_CID: 212 /* Note: this is a real CID from Wandboard int mmc */ 213 mmcio->cmd.resp[0] = 0x1b534d30; 214 mmcio->cmd.resp[1] = 0x30303030; 215 mmcio->cmd.resp[2] = 0x10842806; 216 mmcio->cmd.resp[3] = 0x5700e900; 217 break; 218 case MMC_SEND_CSD: 219 /* Note: this is a real CSD from Wandboard int mmc */ 220 mmcio->cmd.resp[0] = 0x400e0032; 221 mmcio->cmd.resp[1] = 0x5b590000; 222 mmcio->cmd.resp[2] = 0x751f7f80; 223 mmcio->cmd.resp[3] = 0x0a404000; 224 break; 225 case MMC_READ_SINGLE_BLOCK: 226 case MMC_READ_MULTIPLE_BLOCK: 227 strcpy(mmcio->cmd.data->data, "WTF?!"); 228 break; 229 default: 230 device_printf(sc->dev, "mmcnull_intr_sd: unknown command\n"); 231 mmcio->cmd.error = 1; 232 } 233 ccb->ccb_h.status = CAM_REQ_CMP; 234 235 sc->cur_ccb = NULL; 236 xpt_done(ccb); 237 } 238 239 static void 240 mmcnull_intr_sdio_newintr(void *xsc) { 241 struct mmcnull_softc *sc; 242 struct cam_path *dpath; 243 244 sc = (struct mmcnull_softc *) xsc; 245 mtx_assert(&sc->sc_mtx, MA_OWNED); 246 device_printf(sc->dev, "mmcnull_intr_sdio_newintr()\n"); 247 248 /* Our path */ 249 if (xpt_create_path(&dpath, NULL, cam_sim_path(sc->sim), 0, 0) != CAM_REQ_CMP) { 250 device_printf(sc->dev, "mmcnull_intr_sdio_newintr(): cannot create path\n"); 251 return; 252 } 253 xpt_async(AC_UNIT_ATTENTION, dpath, NULL); 254 xpt_free_path(dpath); 255 } 256 257 static void 258 mmcnull_intr_sdio(void *xsc) { 259 struct mmcnull_softc *sc; 260 union ccb *ccb; 261 struct ccb_mmcio *mmcio; 262 263 sc = (struct mmcnull_softc *) xsc; 264 mtx_assert(&sc->sc_mtx, MA_OWNED); 265 266 ccb = sc->cur_ccb; 267 mmcio = &ccb->mmcio; 268 device_printf(sc->dev, "mmcnull_intr: MMC command = %d\n", 269 mmcio->cmd.opcode); 270 271 switch (mmcio->cmd.opcode) { 272 case MMC_GO_IDLE_STATE: 273 device_printf(sc->dev, "Reset device\n"); 274 break; 275 case SD_SEND_IF_COND: 276 mmcio->cmd.resp[0] = 0x1AA; // To match mmc_xpt expectations :-) 277 break; 278 case MMC_APP_CMD: 279 mmcio->cmd.resp[0] = R1_APP_CMD; 280 break; 281 case IO_SEND_OP_COND: 282 mmcio->cmd.resp[0] = 0x12345678; 283 mmcio->cmd.resp[0] |= ~ R4_IO_MEM_PRESENT; 284 break; 285 case SD_SEND_RELATIVE_ADDR: 286 case MMC_SELECT_CARD: 287 mmcio->cmd.resp[0] = 0x1 << 16; 288 break; 289 case ACMD_SD_SEND_OP_COND: 290 /* TODO: steal valid OCR from somewhere :-) */ 291 mmcio->cmd.resp[0] = 0x123; 292 mmcio->cmd.resp[0] |= MMC_OCR_CARD_BUSY; 293 break; 294 case MMC_ALL_SEND_CID: 295 mmcio->cmd.resp[0] = 0x1234; 296 mmcio->cmd.resp[1] = 0x5678; 297 mmcio->cmd.resp[2] = 0x9ABC; 298 mmcio->cmd.resp[3] = 0xDEF0; 299 break; 300 case MMC_READ_SINGLE_BLOCK: 301 case MMC_READ_MULTIPLE_BLOCK: 302 strcpy(mmcio->cmd.data->data, "WTF?!"); 303 break; 304 case SD_IO_RW_DIRECT: 305 device_printf(sc->dev, "Scheduling interrupt generation...\n"); 306 callout_reset(&sc->tick, hz / 10, mmcnull_intr_sdio_newintr, sc); 307 break; 308 default: 309 device_printf(sc->dev, "mmcnull_intr_sdio: unknown command\n"); 310 } 311 ccb->ccb_h.status = CAM_REQ_CMP; 312 313 sc->cur_ccb = NULL; 314 xpt_done(ccb); 315 } 316 317 /* 318 * This is a MMC IO handler 319 * It extracts MMC command from CCB and sends it 320 * to the h/w 321 */ 322 static void 323 mmcnull_handle_mmcio(struct cam_sim *sim, union ccb *ccb) 324 { 325 struct mmcnull_softc *sc; 326 struct ccb_mmcio *mmcio; 327 328 sc = cam_sim_softc(sim); 329 mmcio = &ccb->mmcio; 330 ccb->ccb_h.status = CAM_REQ_INPROG; 331 sc->cur_ccb = ccb; 332 333 /* Real h/w will wait for the interrupt */ 334 if (is_sdio_mode) 335 callout_reset(&sc->tick, hz / 10, mmcnull_intr_sdio, sc); 336 else 337 callout_reset(&sc->tick, hz / 10, mmcnull_intr_sd, sc); 338 } 339 340 static void 341 mmcnull_action_sd(struct cam_sim *sim, union ccb *ccb) 342 { 343 struct mmcnull_softc *sc; 344 345 sc = cam_sim_softc(sim); 346 if (sc == NULL) { 347 ccb->ccb_h.status = CAM_SEL_TIMEOUT; 348 xpt_done(ccb); 349 return; 350 } 351 352 mtx_assert(&sc->sc_mtx, MA_OWNED); 353 354 device_printf(sc->dev, "action: func_code %0x\n", ccb->ccb_h.func_code); 355 356 switch (ccb->ccb_h.func_code) { 357 case XPT_PATH_INQ: 358 { 359 struct ccb_pathinq *cpi; 360 361 cpi = &ccb->cpi; 362 cpi->version_num = 1; 363 cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE | PI_WIDE_16; 364 cpi->target_sprt = 0; 365 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN; 366 cpi->hba_eng_cnt = 0; 367 cpi->max_target = 0; 368 cpi->max_lun = 0; 369 cpi->initiator_id = 1; 370 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 371 strncpy(cpi->hba_vid, "FreeBSD Foundation", HBA_IDLEN); 372 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 373 cpi->unit_number = cam_sim_unit(sim); 374 cpi->bus_id = cam_sim_bus(sim); 375 cpi->base_transfer_speed = 100; /* XXX WTF? */ 376 cpi->protocol = PROTO_MMCSD; 377 cpi->protocol_version = SCSI_REV_0; 378 cpi->transport = XPORT_MMCSD; 379 cpi->transport_version = 0; 380 381 cpi->ccb_h.status = CAM_REQ_CMP; 382 break; 383 } 384 case XPT_GET_TRAN_SETTINGS: 385 { 386 struct ccb_trans_settings *cts = &ccb->cts; 387 struct ccb_trans_settings_mmc *mcts; 388 mcts = &ccb->cts.proto_specific.mmc; 389 390 device_printf(sc->dev, "Got XPT_GET_TRAN_SETTINGS\n"); 391 392 cts->protocol = PROTO_MMCSD; 393 cts->protocol_version = 0; 394 cts->transport = XPORT_MMCSD; 395 cts->transport_version = 0; 396 cts->xport_specific.valid = 0; 397 mcts->host_f_max = 12000000; 398 mcts->host_f_min = 200000; 399 mcts->host_ocr = 1; /* Fix this */ 400 ccb->ccb_h.status = CAM_REQ_CMP; 401 break; 402 } 403 case XPT_SET_TRAN_SETTINGS: 404 device_printf(sc->dev, "Got XPT_SET_TRAN_SETTINGS, should update IOS...\n"); 405 ccb->ccb_h.status = CAM_REQ_CMP; 406 break; 407 case XPT_RESET_BUS: 408 device_printf(sc->dev, "Got XPT_RESET_BUS, ACK it...\n"); 409 ccb->ccb_h.status = CAM_REQ_CMP; 410 break; 411 case XPT_MMC_IO: 412 /* 413 * Here is the HW-dependent part of 414 * sending the command to the underlying h/w 415 * At some point in the future an interrupt comes. 416 * Then the request will be marked as completed. 417 */ 418 device_printf(sc->dev, "Got XPT_MMC_IO\n"); 419 mmcnull_handle_mmcio(sim, ccb); 420 return; 421 break; 422 case XPT_RESET_DEV: 423 /* This is sent by `camcontrol reset`*/ 424 device_printf(sc->dev, "Got XPT_RESET_DEV\n"); 425 ccb->ccb_h.status = CAM_REQ_CMP; 426 break; 427 default: 428 device_printf(sc->dev, "Func code %d is unknown\n", ccb->ccb_h.func_code); 429 ccb->ccb_h.status = CAM_REQ_INVALID; 430 break; 431 } 432 xpt_done(ccb); 433 return; 434 } 435 436 static void 437 mmcnull_action_sdio(struct cam_sim *sim, union ccb *ccb) { 438 mmcnull_action_sd(sim, ccb); 439 } 440 441 static void 442 mmcnull_poll(struct cam_sim *sim) 443 { 444 return; 445 } 446 447 448 static device_method_t mmcnull_methods[] = { 449 /* Device interface */ 450 DEVMETHOD(device_identify, mmcnull_identify), 451 DEVMETHOD(device_probe, mmcnull_probe), 452 DEVMETHOD(device_attach, mmcnull_attach), 453 DEVMETHOD(device_detach, mmcnull_detach), 454 DEVMETHOD_END 455 }; 456 457 static driver_t mmcnull_driver = { 458 "mmcnull", mmcnull_methods, sizeof(struct mmcnull_softc) 459 }; 460 461 static devclass_t mmcnull_devclass; 462 463 DRIVER_MODULE(mmcnull, isa, mmcnull_driver, mmcnull_devclass, 0, 0); 464