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