1 /* $OpenBSD: ufshci.c,v 1.3 2023/04/05 17:23:30 mglocker Exp $ */ 2 3 /* 4 * Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * Universal Flash Storage Host Controller Interface (UFSHCI) 2.1 driver based 21 * on the JEDEC JESD223C.pdf and JESD220C-2_1.pdf specifications. 22 */ 23 24 #include <sys/param.h> 25 #include <sys/systm.h> 26 #include <sys/buf.h> 27 #include <sys/kernel.h> 28 #include <sys/malloc.h> 29 #include <sys/device.h> 30 #include <sys/queue.h> 31 #include <sys/mutex.h> 32 #include <sys/pool.h> 33 34 #include <sys/atomic.h> 35 36 #include <machine/bus.h> 37 38 #include <scsi/scsi_all.h> 39 #include <scsi/scsi_disk.h> 40 #include <scsi/scsiconf.h> 41 42 #include <dev/ic/ufshcivar.h> 43 #include <dev/ic/ufshcireg.h> 44 45 //#define UFSHCI_DEBUG 1 46 47 #ifdef UFSHCI_DEBUG 48 int ufshci_dbglvl = 1; 49 #define DPRINTF(x...) do { printf(x); } while (0) 50 #else 51 #define DPRINTF(x...) 52 #endif 53 54 struct cfdriver ufshci_cd = { 55 NULL, "ufshci", DV_DULL 56 }; 57 58 int ufshci_reset(struct ufshci_softc *); 59 int ufshci_uccs_poll(struct ufshci_softc *); 60 struct ufshci_dmamem *ufshci_dmamem_alloc(struct ufshci_softc *, size_t); 61 void ufshci_dmamem_free(struct ufshci_softc *, 62 struct ufshci_dmamem *); 63 int ufshci_init(struct ufshci_softc *); 64 int ufshci_doorbell_get_free(struct ufshci_softc *); 65 int ufshci_doorbell_read(struct ufshci_softc *); 66 int ufshci_doorbell_poll(struct ufshci_softc *, int); 67 void ufshci_doorbell_set(struct ufshci_softc *, int); 68 uint8_t ufshci_get_taskid(struct ufshci_softc *); 69 int ufshci_utr_cmd_nop(struct ufshci_softc *); 70 int ufshci_utr_cmd_lun(struct ufshci_softc *, 71 struct ufshci_ccb *, int); 72 int ufshci_utr_cmd_inquiry(struct ufshci_softc *, 73 struct ufshci_ccb *, int, int); 74 int ufshci_utr_cmd_capacity16(struct ufshci_softc *, 75 struct ufshci_ccb *, int, int); 76 int ufshci_utr_cmd_capacity(struct ufshci_softc *, 77 struct ufshci_ccb *, int, int); 78 int ufshci_utr_cmd_read(struct ufshci_softc *, 79 struct ufshci_ccb *, int, int, uint32_t, uint16_t); 80 int ufshci_utr_cmd_write(struct ufshci_softc *, 81 struct ufshci_ccb *, int, int, uint32_t, uint16_t); 82 int ufshci_utr_cmd_sync(struct ufshci_softc *, 83 struct ufshci_ccb *, int, uint32_t, uint16_t); 84 int ufshci_xfer_complete(struct ufshci_softc *); 85 void ufshci_hexdump(void *, int, char *, int); 86 87 /* SCSI */ 88 int ufshci_ccb_alloc(struct ufshci_softc *, int); 89 void *ufshci_ccb_get(void *); 90 void ufshci_ccb_put(void *, void *); 91 void ufshci_ccb_free(struct ufshci_softc*, int); 92 93 void ufshci_scsi_cmd(struct scsi_xfer *); 94 void ufshci_minphys(struct buf *, struct scsi_link *); 95 int ufshci_scsi_probe(struct scsi_link *); 96 void ufshci_scsi_free(struct scsi_link *); 97 98 void ufshci_scsi_inquiry(struct scsi_xfer *); 99 void ufshci_scsi_capacity16(struct scsi_xfer *); 100 void ufshci_scsi_capacity(struct scsi_xfer *); 101 void ufshci_scsi_sync(struct scsi_xfer *); 102 void ufshci_scsi_io(struct scsi_xfer *, int); 103 void ufshci_scsi_io_done(struct ufshci_softc *, 104 struct ufshci_ccb *); 105 void ufshci_scsi_done(struct ufshci_softc *, 106 struct ufshci_ccb *); 107 108 #if 0 109 const struct scsi_adapter ufshci_switch = { 110 ufshci_scsi_cmd, ufshci_minphys, ufshci_scsi_probe, ufshci_scsi_free, 111 NULL 112 }; 113 #endif 114 const struct scsi_adapter ufshci_switch = { 115 ufshci_scsi_cmd, NULL, NULL, NULL, NULL 116 }; 117 118 int 119 ufshci_intr(void *arg) 120 { 121 struct ufshci_softc *sc = arg; 122 uint32_t status; 123 int handled = 0; 124 125 status = UFSHCI_READ_4(sc, UFSHCI_REG_IS); 126 DPRINTF("%s: status=0x%08x\n", __func__, status); 127 128 if (status == 0) 129 return 0; 130 131 if (status & UFSHCI_REG_IS_UCCS) { 132 DPRINTF("%s: UCCS interrupt\n", __func__); 133 handled = 1; 134 } 135 if (status & UFSHCI_REG_IS_UTRCS) { 136 DPRINTF("%s: UTRCS interrupt\n", __func__); 137 138 ufshci_xfer_complete(sc); 139 140 /* Reset Interrupt Aggregation Counter and Timer. */ 141 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 142 UFSHCI_REG_UTRIACR_IAEN | UFSHCI_REG_UTRIACR_CTR); 143 144 handled = 1; 145 } 146 147 if (handled == 0) { 148 printf("%s: UNKNOWN interrupt, status=0x%08x\n", 149 sc->sc_dev.dv_xname, status); 150 } 151 152 /* ACK interrupt */ 153 UFSHCI_WRITE_4(sc, UFSHCI_REG_IS, status); 154 155 return 1; 156 } 157 158 /* XXX: Only for testing */ 159 void 160 ufshci_attach_hook(struct device *self) 161 { 162 struct ufshci_softc *sc = (struct ufshci_softc *)self; 163 164 ufshci_attach(sc); 165 } 166 167 int 168 ufshci_attach(struct ufshci_softc *sc) 169 { 170 struct scsibus_attach_args saa; 171 172 mtx_init(&sc->sc_ccb_mtx, IPL_BIO); 173 SIMPLEQ_INIT(&sc->sc_ccb_list); 174 scsi_iopool_init(&sc->sc_iopool, sc, ufshci_ccb_get, ufshci_ccb_put); 175 176 ufshci_reset(sc); 177 178 sc->sc_ver = UFSHCI_READ_4(sc, UFSHCI_REG_VER); 179 printf(", UFSHCI %d.%d%d\n", 180 UFSHCI_REG_VER_MAJOR(sc->sc_ver), 181 UFSHCI_REG_VER_MINOR(sc->sc_ver), 182 UFSHCI_REG_VER_SUFFIX(sc->sc_ver)); 183 184 sc->sc_cap = UFSHCI_READ_4(sc, UFSHCI_REG_CAP); 185 sc->sc_hcpid = UFSHCI_READ_4(sc, UFSHCI_REG_HCPID); 186 sc->sc_hcmid = UFSHCI_READ_4(sc, UFSHCI_REG_HCMID); 187 sc->sc_nutmrs = UFSHCI_REG_CAP_NUTMRS(sc->sc_cap) + 1; 188 sc->sc_rtt = UFSHCI_REG_CAP_RTT(sc->sc_cap) + 1; 189 sc->sc_nutrs = UFSHCI_REG_CAP_NUTRS(sc->sc_cap) + 1; 190 191 #if UFSHCI_DEBUG 192 printf("Capabilities (0x%08x):\n", sc->sc_cap); 193 printf(" CS=%d\n", sc->sc_cap & UFSHCI_REG_CAP_CS ? 1 : 0); 194 printf(" UICDMETMS=%d\n", 195 sc->sc_cap & UFSHCI_REG_CAP_UICDMETMS ? 1 : 0); 196 printf(" OODDS=%d\n", sc->sc_cap & UFSHCI_REG_CAP_OODDS ? 1 : 0); 197 printf(" 64AS=%d\n", sc->sc_cap & UFSHCI_REG_CAP_64AS ? 1 : 0); 198 printf(" AUTOH8=%d\n", sc->sc_cap & UFSHCI_REG_AUTOH8 ? 1 : 0); 199 printf(" NUTMRS=%d\n", sc->sc_nutmrs); 200 printf(" RTT=%d\n", sc->sc_rtt); 201 printf(" NUTRS=%d\n", sc->sc_nutrs); 202 printf("HCPID=0x%08x:\n", sc->sc_hcpid); 203 printf("HCMID (0x%08x):\n", sc->sc_hcmid); 204 printf(" BI=0x%04x\n", UFSHCI_REG_HCMID_BI(sc->sc_hcmid)); 205 printf(" MIC=0x%04x\n", UFSHCI_REG_HCMID_MIC(sc->sc_hcmid)); 206 #endif 207 208 if (sc->sc_nutrs > 32) { 209 printf("%s: NUTRS can't be >32 (is %d)!\n", 210 sc->sc_dev.dv_xname, sc->sc_nutrs); 211 return 1; 212 } 213 214 ufshci_init(sc); 215 216 if (ufshci_ccb_alloc(sc, sc->sc_nutrs) != 0) { 217 printf("%s: %s: Can't allocate CCBs\n", 218 sc->sc_dev.dv_xname, __func__); 219 return 1; 220 } 221 222 /* Attach to SCSI layer */ 223 saa.saa_adapter = &ufshci_switch; 224 saa.saa_adapter_softc = sc; 225 saa.saa_adapter_buswidth = 2; /* XXX: What's the right value? */ 226 saa.saa_luns = 1; /* XXX: Should we use ufshci_utr_cmd_lun() */ 227 saa.saa_adapter_target = 0; 228 saa.saa_openings = sc->sc_nutrs; 229 saa.saa_pool = &sc->sc_iopool; 230 saa.saa_quirks = saa.saa_flags = 0; 231 saa.saa_wwpn = saa.saa_wwnn = 0; 232 233 config_found(&sc->sc_dev, &saa, scsiprint); 234 235 return 0; 236 } 237 238 int 239 ufshci_reset(struct ufshci_softc *sc) 240 { 241 int i; 242 int retry = 10; 243 uint32_t hce; 244 245 /* 246 * 7.1.1 Host Controller Initialization: 2) 247 * Reset and enable host controller 248 */ 249 UFSHCI_WRITE_4(sc, UFSHCI_REG_HCE, UFSHCI_REG_HCE_HCE); 250 /* 7.1.1 Host Controller Initialization: 3) */ 251 for (i = 0; i < retry; i++) { 252 hce = UFSHCI_READ_4(sc, UFSHCI_REG_HCE); 253 if (hce == 1) 254 break; 255 delay(1); 256 } 257 if (i == retry) { 258 printf("%s: Enabling Host Controller failed!\n", 259 sc->sc_dev.dv_xname); 260 return -1; 261 } 262 263 DPRINTF("\n%s: Host Controller enabled (i=%d)\n", __func__, i); 264 265 return 0; 266 } 267 268 int 269 ufshci_uccs_poll(struct ufshci_softc *sc) 270 { 271 uint32_t status; 272 int i, retry = 25; 273 274 DPRINTF("%s\n", __func__); 275 276 for (i = 0; i < retry; i++) { 277 status = UFSHCI_READ_4(sc, UFSHCI_REG_IS); 278 if (status & UFSHCI_REG_IS_UCCS) 279 break; 280 delay(10); 281 } 282 if (i == retry) { 283 printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__); 284 return -1; 285 } 286 DPRINTF("%s: completed after %d retries\n", __func__, i); 287 288 /* ACK interrupt */ 289 UFSHCI_WRITE_4(sc, UFSHCI_REG_IS, status); 290 291 return 0; 292 } 293 294 struct ufshci_dmamem * 295 ufshci_dmamem_alloc(struct ufshci_softc *sc, size_t size) 296 { 297 struct ufshci_dmamem *udm; 298 int nsegs; 299 300 udm = malloc(sizeof(*udm), M_DEVBUF, M_WAITOK | M_ZERO); 301 if (udm == NULL) 302 return NULL; 303 304 udm->udm_size = size; 305 306 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 307 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 308 &udm->udm_map) != 0) 309 goto udmfree; 310 311 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &udm->udm_seg, 312 1, &nsegs, BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0) 313 goto destroy; 314 315 if (bus_dmamem_map(sc->sc_dmat, &udm->udm_seg, nsegs, size, 316 &udm->udm_kva, BUS_DMA_WAITOK) != 0) 317 goto free; 318 319 if (bus_dmamap_load(sc->sc_dmat, udm->udm_map, udm->udm_kva, size, 320 NULL, BUS_DMA_WAITOK) != 0) 321 goto unmap; 322 323 DPRINTF("%s: size=%lu, page_size=%d, nsegs=%d\n", 324 __func__, size, PAGE_SIZE, nsegs); 325 326 return udm; 327 328 unmap: 329 bus_dmamem_unmap(sc->sc_dmat, udm->udm_kva, size); 330 free: 331 bus_dmamem_free(sc->sc_dmat, &udm->udm_seg, 1); 332 destroy: 333 bus_dmamap_destroy(sc->sc_dmat, udm->udm_map); 334 udmfree: 335 free(udm, M_DEVBUF, sizeof(*udm)); 336 337 return NULL; 338 } 339 340 void 341 ufshci_dmamem_free(struct ufshci_softc *sc, struct ufshci_dmamem *udm) 342 { 343 bus_dmamap_unload(sc->sc_dmat, udm->udm_map); 344 bus_dmamem_unmap(sc->sc_dmat, udm->udm_kva, udm->udm_size); 345 bus_dmamem_free(sc->sc_dmat, &udm->udm_seg, 1); 346 bus_dmamap_destroy(sc->sc_dmat, udm->udm_map); 347 free(udm, M_DEVBUF, sizeof(*udm)); 348 } 349 350 int 351 ufshci_init(struct ufshci_softc *sc) 352 { 353 uint32_t reg; 354 uint64_t dva; 355 356 /* 357 * 7.1.1 Host Controller Initialization: 4) 358 * TODO: Do we need to set DME_SET? 359 */ 360 361 /* 7.1.1 Host Controller Initialization: 5) */ 362 //UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, UFSHCI_REG_IE_UCCE | 363 UFSHCI_WRITE_4(sc, UFSHCI_REG_IE, 364 UFSHCI_REG_IE_UTRCE | UFSHCI_REG_IE_UTMRCE); 365 366 /* 7.1.1 Host Controller Initialization: 6) */ 367 UFSHCI_WRITE_4(sc, UFSHCI_REG_UICCMD, 368 UFSHCI_REG_UICCMD_CMDOP_DME_LINKSTARTUP); 369 if (ufshci_uccs_poll(sc) != 0) 370 return -1; 371 372 /* 373 * 7.1.1 Host Controller Initialization: 7), 8), 9) 374 * TODO: Implement retry in case UFSHCI_REG_HCS returns 0 375 */ 376 reg = UFSHCI_READ_4(sc, UFSHCI_REG_HCS); 377 if (reg & UFSHCI_REG_HCS_DP) 378 DPRINTF("%s: Device Presence SET\n", __func__); 379 else 380 DPRINTF("%s: Device Presence NOT SET\n", __func__); 381 382 /* 383 * 7.1.1 Host Controller Initialization: 10) 384 * TODO: Enable additional interrupt on the IE register 385 */ 386 387 /* 7.1.1 Host Controller Initialization: 11) */ 388 reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRIACR); 389 DPRINTF("%s: UTRIACR=0x%08x\n", __func__, reg); 390 /* 391 * Only enable interrupt aggregation when interrupts are available. 392 * Otherwise, the interrupt aggregation counter already starts to 393 * count completed commands, and will keep interrupts disabled once 394 * reaching the threshold. We only issue the interrupt aggregation 395 * counter reset in the interrupt handler during runtime, so we would 396 * have a kind of chicken/egg problem. 397 */ 398 if (!cold) { 399 DPRINTF("%s: Enable interrupt aggregation\n", __func__); 400 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 401 UFSHCI_REG_UTRIACR_IAEN | 402 UFSHCI_REG_UTRIACR_IAPWEN | 403 UFSHCI_REG_UTRIACR_CTR | 404 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 405 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 406 sc->sc_intraggr_enabled = 1; 407 } 408 409 /* 410 * 7.1.1 Host Controller Initialization: 12) 411 * TODO: More UIC commands to issue? 412 */ 413 414 /* 7.1.1 Host Controller Initialization: 13) */ 415 sc->sc_dmamem_utmrd = ufshci_dmamem_alloc(sc, 416 sizeof(struct ufshci_utmrd) * sc->sc_nutmrs); 417 if (sc->sc_dmamem_utmrd == NULL) { 418 printf("%s: Can't allocate DMA memory for UTMRD\n", 419 sc->sc_dev.dv_xname); 420 return -1; 421 } 422 /* 7.1.1 Host Controller Initialization: 14) */ 423 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_utmrd); 424 DPRINTF("%s: utmrd dva=%llu\n", __func__, dva); 425 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTMRLBA, (uint32_t)dva); 426 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTMRLBAU, (uint32_t)(dva >> 32)); 427 428 /* 7.1.1 Host Controller Initialization: 15) */ 429 sc->sc_dmamem_utrd = ufshci_dmamem_alloc(sc, 430 sizeof(struct ufshci_utrd) * sc->sc_nutrs); 431 if (sc->sc_dmamem_utrd == NULL) { 432 printf("%s: Can't allocate DMA memory for UTRD\n", 433 sc->sc_dev.dv_xname); 434 return -1; 435 } 436 /* 7.1.1 Host Controller Initialization: 16) */ 437 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_utrd); 438 DPRINTF("%s: utrd dva=%llu\n", __func__, dva); 439 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLBA, (uint32_t)dva); 440 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLBAU, (uint32_t)(dva >> 32)); 441 442 443 /* Allocate UCDs. */ 444 sc->sc_dmamem_ucd = ufshci_dmamem_alloc(sc, 445 sizeof(struct ufshci_ucd) * sc->sc_nutrs); 446 if (sc->sc_dmamem_ucd == NULL) { 447 printf("%s: Can't allocate DMA memory for UCD\n", 448 sc->sc_dev.dv_xname); 449 return -1; 450 } 451 452 /* 7.1.1 Host Controller Initialization: 17) */ 453 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTMRLRSR, UFSHCI_REG_UTMRLRSR_START); 454 455 /* 7.1.1 Host Controller Initialization: 18) */ 456 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLRSR, UFSHCI_REG_UTRLRSR_START); 457 458 /* 7.1.1 Host Controller Initialization: 19) */ 459 /* TODO: bMaxNumOfRTT will be set as the minimum value of 460 * bDeviceRTTCap and NORTT. ??? 461 */ 462 463 return 0; 464 } 465 466 int 467 ufshci_doorbell_get_free(struct ufshci_softc *sc) 468 { 469 int slot; 470 uint32_t reg; 471 472 reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRLDBR); 473 474 for (slot = 0; slot < sc->sc_nutrs; slot++) { 475 if ((reg & (1 << slot)) == 0) 476 return slot; 477 } 478 479 return -1; 480 } 481 482 int 483 ufshci_doorbell_read(struct ufshci_softc *sc) 484 { 485 uint32_t reg; 486 487 reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRLDBR); 488 489 return reg; 490 } 491 492 int 493 ufshci_doorbell_poll(struct ufshci_softc *sc, int slot) 494 { 495 uint32_t reg; 496 int i, retry = 25; 497 498 DPRINTF("%s\n", __func__); 499 500 for (i = 0; i < retry; i++) { 501 reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRLDBR); 502 if ((reg & (1 << slot)) == 0) 503 break; 504 delay(10); 505 } 506 if (i == retry) { 507 printf("%s: %s: timeout\n", sc->sc_dev.dv_xname, __func__); 508 return -1; 509 } 510 511 return 0; 512 } 513 514 void 515 ufshci_doorbell_set(struct ufshci_softc *sc, int slot) 516 { 517 uint32_t reg; 518 519 reg = (1 << slot); 520 521 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLDBR, reg); 522 } 523 524 uint8_t 525 ufshci_get_taskid(struct ufshci_softc *sc) 526 { 527 if (sc->sc_taskid == 255) 528 sc->sc_taskid = 0; 529 else 530 sc->sc_taskid++; 531 532 return sc->sc_taskid; 533 } 534 535 int 536 ufshci_utr_cmd_nop(struct ufshci_softc *sc) 537 { 538 int slot, off, len; 539 uint64_t dva; 540 struct ufshci_utrd *utrd; 541 struct ufshci_ucd *ucd; 542 543 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 544 slot = ufshci_doorbell_get_free(sc); 545 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 546 memset(utrd, 0, sizeof(*utrd)); 547 DPRINTF("%s: slot=%d\n", __func__, slot); 548 549 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 550 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 551 552 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 553 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_NO; 554 555 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 556 utrd->dw0 |= UFSHCI_UTRD_DW0_I_INT; 557 558 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 559 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 560 561 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 562 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 563 memset(ucd, 0, sizeof(*ucd)); 564 565 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 566 ucd->cmd.hdr.tc = UPIU_TC_I2T_NOP_OUT; 567 ucd->cmd.hdr.flags = 0; 568 ucd->cmd.hdr.lun = 0; 569 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 570 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 571 ucd->cmd.hdr.query = 0; 572 ucd->cmd.hdr.response = 0; 573 ucd->cmd.hdr.status = 0; 574 ucd->cmd.hdr.ehs_len = 0; 575 ucd->cmd.hdr.device_info = 0; 576 ucd->cmd.hdr.ds_len = 0; 577 578 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 579 /* Already done with above memset */ 580 581 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 582 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd); 583 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 584 utrd->dw4 = (uint32_t)dva; 585 utrd->dw5 = (uint32_t)(dva >> 32); 586 587 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 588 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 589 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 590 591 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 592 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 593 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 594 595 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 596 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 597 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 598 599 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 600 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(0); /* No data xfer */ 601 602 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 603 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 604 printf("%s: %s: UTRLRSR not set\n", 605 sc->sc_dev.dv_xname, __func__); 606 return -1; 607 } 608 609 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 610 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 611 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 612 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 613 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 614 UFSHCI_REG_UTRIACR_IAEN | 615 UFSHCI_REG_UTRIACR_IAPWEN | 616 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 617 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 618 619 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 620 ufshci_doorbell_set(sc, slot); 621 622 return 0; 623 } 624 625 int 626 ufshci_utr_cmd_lun(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 627 int rsp_size) 628 { 629 int slot, off, len, i; 630 uint64_t dva; 631 struct ufshci_utrd *utrd; 632 struct ufshci_ucd *ucd; 633 bus_dmamap_t dmap = ccb->ccb_dmamap; 634 635 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 636 slot = ufshci_doorbell_get_free(sc); 637 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 638 memset(utrd, 0, sizeof(*utrd)); 639 DPRINTF("%s: slot=%d\n", __func__, slot); 640 641 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 642 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 643 644 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 645 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I; 646 647 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 648 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 649 650 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 651 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 652 653 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 654 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 655 memset(ucd, 0, sizeof(*ucd)); 656 657 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 658 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 659 ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */ 660 ucd->cmd.hdr.lun = 0; 661 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 662 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 663 ucd->cmd.hdr.query = 0; 664 ucd->cmd.hdr.response = 0; 665 ucd->cmd.hdr.status = 0; 666 ucd->cmd.hdr.ehs_len = 0; 667 ucd->cmd.hdr.device_info = 0; 668 ucd->cmd.hdr.ds_len = 0; 669 670 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 671 672 ucd->cmd.cdb[0] = REPORT_LUNS; 673 ucd->cmd.cdb[6] = 0; 674 ucd->cmd.cdb[7] = 0; 675 ucd->cmd.cdb[8] = 0; 676 ucd->cmd.cdb[9] = rsp_size; 677 678 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 679 /* Already done with above memset */ 680 681 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 682 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd); 683 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 684 utrd->dw4 = (uint32_t)dva; 685 utrd->dw5 = (uint32_t)(dva >> 32); 686 687 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 688 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 689 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 690 691 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 692 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 693 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 694 695 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 696 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 697 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 698 699 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 700 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 701 702 /* Build PRDT data segment. */ 703 for (i = 0; i < dmap->dm_nsegs; i++) { 704 dva = dmap->dm_segs[i].ds_addr; 705 ucd->prdt[i].dw0 = (uint32_t)dva; 706 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 707 ucd->prdt[i].dw2 = 0; 708 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 709 } 710 711 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 712 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 713 printf("%s: %s: UTRLRSR not set\n", 714 sc->sc_dev.dv_xname, __func__); 715 return -1; 716 } 717 718 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 719 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 720 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 721 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 722 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 723 UFSHCI_REG_UTRIACR_IAEN | 724 UFSHCI_REG_UTRIACR_IAPWEN | 725 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 726 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 727 728 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 729 ufshci_doorbell_set(sc, slot); 730 731 return 0; 732 } 733 734 int 735 ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 736 int rsp_size, int flags) 737 { 738 int slot, off, len, i; 739 uint64_t dva; 740 struct ufshci_utrd *utrd; 741 struct ufshci_ucd *ucd; 742 bus_dmamap_t dmap = ccb->ccb_dmamap; 743 744 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 745 slot = ufshci_doorbell_get_free(sc); 746 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 747 memset(utrd, 0, sizeof(*utrd)); 748 DPRINTF("%s: slot=%d\n", __func__, slot); 749 750 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 751 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 752 753 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 754 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I; 755 756 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 757 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 758 759 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 760 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 761 762 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 763 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 764 memset(ucd, 0, sizeof(*ucd)); 765 766 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 767 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 768 ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */ 769 ucd->cmd.hdr.lun = 0; 770 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 771 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 772 ucd->cmd.hdr.query = 0; 773 ucd->cmd.hdr.response = 0; 774 ucd->cmd.hdr.status = 0; 775 ucd->cmd.hdr.ehs_len = 0; 776 ucd->cmd.hdr.device_info = 0; 777 ucd->cmd.hdr.ds_len = 0; 778 779 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 780 781 ucd->cmd.cdb[0] = INQUIRY; /* 0x12 */ 782 ucd->cmd.cdb[3] = 0; 783 ucd->cmd.cdb[4] = rsp_size; 784 785 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 786 /* Already done with above memset */ 787 788 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 789 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 790 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 791 utrd->dw4 = (uint32_t)dva; 792 utrd->dw5 = (uint32_t)(dva >> 32); 793 794 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 795 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 796 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 797 798 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 799 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 800 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 801 802 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 803 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 804 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 805 806 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 807 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 808 809 /* Build PRDT data segment. */ 810 for (i = 0; i < dmap->dm_nsegs; i++) { 811 dva = dmap->dm_segs[i].ds_addr; 812 ucd->prdt[i].dw0 = (uint32_t)dva; 813 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 814 ucd->prdt[i].dw2 = 0; 815 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 816 } 817 818 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 819 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 820 printf("%s: %s: UTRLRSR not set\n", 821 sc->sc_dev.dv_xname, __func__); 822 return -1; 823 } 824 825 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 826 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 827 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 828 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 829 if (!ISSET(flags, SCSI_POLL)) { 830 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 831 UFSHCI_REG_UTRIACR_IAEN | 832 UFSHCI_REG_UTRIACR_IAPWEN | 833 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 834 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 835 } 836 837 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 838 ufshci_doorbell_set(sc, slot); 839 840 return slot; 841 } 842 843 int 844 ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 845 int rsp_size, int flags) 846 { 847 int slot, off, len, i; 848 uint64_t dva; 849 struct ufshci_utrd *utrd; 850 struct ufshci_ucd *ucd; 851 bus_dmamap_t dmap = ccb->ccb_dmamap; 852 853 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 854 slot = ufshci_doorbell_get_free(sc); 855 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 856 memset(utrd, 0, sizeof(*utrd)); 857 DPRINTF("%s: slot=%d\n", __func__, slot); 858 859 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 860 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 861 862 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 863 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I; 864 865 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 866 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 867 868 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 869 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 870 871 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 872 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 873 memset(ucd, 0, sizeof(*ucd)); 874 875 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 876 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 877 ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */ 878 ucd->cmd.hdr.lun = 0; 879 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 880 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 881 ucd->cmd.hdr.query = 0; 882 ucd->cmd.hdr.response = 0; 883 ucd->cmd.hdr.status = 0; 884 ucd->cmd.hdr.ehs_len = 0; 885 ucd->cmd.hdr.device_info = 0; 886 ucd->cmd.hdr.ds_len = 0; 887 888 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 889 890 ucd->cmd.cdb[0] = READ_CAPACITY_16; /* 0x9e */ 891 ucd->cmd.cdb[1] = 0x10; /* Service Action */ 892 /* Logical Block Address = 0 for UFS */ 893 ucd->cmd.cdb[10] = 0; 894 ucd->cmd.cdb[11] = 0; 895 ucd->cmd.cdb[12] = 0; 896 ucd->cmd.cdb[13] = rsp_size; 897 898 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 899 /* Already done with above memset */ 900 901 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 902 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 903 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 904 utrd->dw4 = (uint32_t)dva; 905 utrd->dw5 = (uint32_t)(dva >> 32); 906 907 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 908 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 909 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 910 911 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 912 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 913 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 914 915 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 916 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 917 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 918 919 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 920 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 921 922 /* Build PRDT data segment. */ 923 for (i = 0; i < dmap->dm_nsegs; i++) { 924 dva = dmap->dm_segs[i].ds_addr; 925 ucd->prdt[i].dw0 = (uint32_t)dva; 926 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 927 ucd->prdt[i].dw2 = 0; 928 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 929 } 930 931 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 932 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 933 printf("%s: %s: UTRLRSR not set\n", 934 sc->sc_dev.dv_xname, __func__); 935 return -1; 936 } 937 938 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 939 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 940 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 941 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 942 if (!ISSET(flags, SCSI_POLL)) { 943 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 944 UFSHCI_REG_UTRIACR_IAEN | 945 UFSHCI_REG_UTRIACR_IAPWEN | 946 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 947 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 948 } 949 950 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 951 ufshci_doorbell_set(sc, slot); 952 953 return slot; 954 } 955 956 int 957 ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 958 int rsp_size, int flags) 959 { 960 int slot, off, len, i; 961 uint64_t dva; 962 struct ufshci_utrd *utrd; 963 struct ufshci_ucd *ucd; 964 bus_dmamap_t dmap = ccb->ccb_dmamap; 965 966 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 967 slot = ufshci_doorbell_get_free(sc); 968 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 969 memset(utrd, 0, sizeof(*utrd)); 970 DPRINTF("%s: slot=%d\n", __func__, slot); 971 972 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 973 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 974 975 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 976 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I; 977 978 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 979 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 980 981 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 982 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 983 984 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 985 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 986 memset(ucd, 0, sizeof(*ucd)); 987 988 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 989 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 990 ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */ 991 ucd->cmd.hdr.lun = 0; 992 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 993 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 994 ucd->cmd.hdr.query = 0; 995 ucd->cmd.hdr.response = 0; 996 ucd->cmd.hdr.status = 0; 997 ucd->cmd.hdr.ehs_len = 0; 998 ucd->cmd.hdr.device_info = 0; 999 ucd->cmd.hdr.ds_len = 0; 1000 1001 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 1002 1003 ucd->cmd.cdb[0] = READ_CAPACITY; /* 0x25 */ 1004 /* Logical Block Address = 0 for UFS */ 1005 ucd->cmd.cdb[2] = 0; 1006 ucd->cmd.cdb[3] = 0; 1007 ucd->cmd.cdb[4] = 0; 1008 ucd->cmd.cdb[5] = 0; 1009 1010 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 1011 /* Already done with above memset */ 1012 1013 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 1014 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1015 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 1016 utrd->dw4 = (uint32_t)dva; 1017 utrd->dw5 = (uint32_t)(dva >> 32); 1018 1019 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 1020 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 1021 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 1022 1023 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 1024 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 1025 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 1026 1027 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 1028 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 1029 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 1030 1031 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 1032 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 1033 1034 /* Build PRDT data segment. */ 1035 for (i = 0; i < dmap->dm_nsegs; i++) { 1036 dva = dmap->dm_segs[i].ds_addr; 1037 ucd->prdt[i].dw0 = (uint32_t)dva; 1038 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 1039 ucd->prdt[i].dw2 = 0; 1040 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 1041 } 1042 1043 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 1044 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 1045 printf("%s: %s: UTRLRSR not set\n", 1046 sc->sc_dev.dv_xname, __func__); 1047 return -1; 1048 } 1049 1050 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 1051 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 1052 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 1053 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 1054 if (!ISSET(flags, SCSI_POLL)) { 1055 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 1056 UFSHCI_REG_UTRIACR_IAEN | 1057 UFSHCI_REG_UTRIACR_IAPWEN | 1058 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 1059 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 1060 } 1061 1062 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 1063 ufshci_doorbell_set(sc, slot); 1064 1065 return slot; 1066 } 1067 1068 int 1069 ufshci_utr_cmd_read(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 1070 int rsp_size, int flags, uint32_t lba, uint16_t blocks) 1071 { 1072 int slot, off, len, i; 1073 uint64_t dva; 1074 struct ufshci_utrd *utrd; 1075 struct ufshci_ucd *ucd; 1076 bus_dmamap_t dmap = ccb->ccb_dmamap; 1077 1078 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 1079 slot = ufshci_doorbell_get_free(sc); 1080 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 1081 memset(utrd, 0, sizeof(*utrd)); 1082 DPRINTF("%s: slot=%d\n", __func__, slot); 1083 1084 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 1085 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 1086 1087 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 1088 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I; 1089 1090 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 1091 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 1092 1093 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 1094 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 1095 1096 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 1097 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1098 memset(ucd, 0, sizeof(*ucd)); 1099 1100 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 1101 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 1102 ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */ 1103 ucd->cmd.hdr.lun = 0; 1104 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 1105 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 1106 ucd->cmd.hdr.query = 0; 1107 ucd->cmd.hdr.response = 0; 1108 ucd->cmd.hdr.status = 0; 1109 ucd->cmd.hdr.ehs_len = 0; 1110 ucd->cmd.hdr.device_info = 0; 1111 ucd->cmd.hdr.ds_len = 0; 1112 1113 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 1114 1115 ucd->cmd.cdb[0] = READ_10; /* 0x28 */ 1116 //ucd->cmd.cdb[1] = (1 << 3); /* FUA: Force Unit Access */ 1117 ucd->cmd.cdb[2] = (lba >> 24) & 0xff; 1118 ucd->cmd.cdb[3] = (lba >> 16) & 0xff; 1119 ucd->cmd.cdb[4] = (lba >> 8) & 0xff; 1120 ucd->cmd.cdb[5] = (lba >> 0) & 0xff; 1121 ucd->cmd.cdb[7] = (blocks >> 8) & 0xff; 1122 ucd->cmd.cdb[8] = (blocks >> 0) & 0xff; 1123 1124 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 1125 /* Already done with above memset */ 1126 1127 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 1128 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1129 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 1130 utrd->dw4 = (uint32_t)dva; 1131 utrd->dw5 = (uint32_t)(dva >> 32); 1132 1133 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 1134 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 1135 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 1136 1137 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 1138 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 1139 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 1140 1141 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 1142 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 1143 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 1144 1145 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 1146 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 1147 1148 /* Build PRDT data segment. */ 1149 for (i = 0; i < dmap->dm_nsegs; i++) { 1150 dva = dmap->dm_segs[i].ds_addr; 1151 ucd->prdt[i].dw0 = (uint32_t)dva; 1152 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 1153 ucd->prdt[i].dw2 = 0; 1154 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 1155 } 1156 1157 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 1158 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 1159 printf("%s: %s: UTRLRSR not set\n", 1160 sc->sc_dev.dv_xname, __func__); 1161 return -1; 1162 } 1163 1164 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 1165 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 1166 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 1167 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 1168 if (!ISSET(flags, SCSI_POLL)) { 1169 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 1170 UFSHCI_REG_UTRIACR_IAEN | 1171 UFSHCI_REG_UTRIACR_IAPWEN | 1172 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 1173 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 1174 } 1175 1176 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 1177 ufshci_doorbell_set(sc, slot); 1178 1179 return slot; 1180 } 1181 1182 int 1183 ufshci_utr_cmd_write(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 1184 int rsp_size, int flags, uint32_t lba, uint16_t blocks) 1185 { 1186 int slot, off, len, i; 1187 uint64_t dva; 1188 struct ufshci_utrd *utrd; 1189 struct ufshci_ucd *ucd; 1190 bus_dmamap_t dmap = ccb->ccb_dmamap; 1191 1192 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 1193 slot = ufshci_doorbell_get_free(sc); 1194 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 1195 memset(utrd, 0, sizeof(*utrd)); 1196 DPRINTF("%s: slot=%d\n", __func__, slot); 1197 1198 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 1199 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 1200 1201 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 1202 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_I2T; 1203 1204 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 1205 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 1206 1207 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 1208 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 1209 1210 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 1211 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1212 memset(ucd, 0, sizeof(*ucd)); 1213 1214 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 1215 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 1216 ucd->cmd.hdr.flags = (1 << 5); /* Bit-5 = Write, Bit-6 = Read */ 1217 ucd->cmd.hdr.lun = 0; 1218 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 1219 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 1220 ucd->cmd.hdr.query = 0; 1221 ucd->cmd.hdr.response = 0; 1222 ucd->cmd.hdr.status = 0; 1223 ucd->cmd.hdr.ehs_len = 0; 1224 ucd->cmd.hdr.device_info = 0; 1225 ucd->cmd.hdr.ds_len = 0; 1226 1227 ucd->cmd.expected_xfer_len = htobe32(rsp_size); 1228 1229 ucd->cmd.cdb[0] = WRITE_10; /* 0x2a */ 1230 ucd->cmd.cdb[1] = (1 << 3); /* FUA: Force Unit Access */ 1231 ucd->cmd.cdb[2] = (lba >> 24) & 0xff; 1232 ucd->cmd.cdb[3] = (lba >> 16) & 0xff; 1233 ucd->cmd.cdb[4] = (lba >> 8) & 0xff; 1234 ucd->cmd.cdb[5] = (lba >> 0) & 0xff; 1235 ucd->cmd.cdb[7] = (blocks >> 8) & 0xff; 1236 ucd->cmd.cdb[8] = (blocks >> 0) & 0xff; 1237 1238 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 1239 /* Already done with above memset */ 1240 1241 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 1242 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1243 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 1244 utrd->dw4 = (uint32_t)dva; 1245 utrd->dw5 = (uint32_t)(dva >> 32); 1246 1247 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 1248 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 1249 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 1250 1251 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 1252 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 1253 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 1254 1255 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 1256 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 1257 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 1258 1259 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 1260 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs); 1261 1262 /* Build PRDT data segment. */ 1263 for (i = 0; i < dmap->dm_nsegs; i++) { 1264 dva = dmap->dm_segs[i].ds_addr; 1265 ucd->prdt[i].dw0 = (uint32_t)dva; 1266 ucd->prdt[i].dw1 = (uint32_t)(dva >> 32); 1267 ucd->prdt[i].dw2 = 0; 1268 ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1; 1269 } 1270 1271 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 1272 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 1273 printf("%s: %s: UTRLRSR not set\n", 1274 sc->sc_dev.dv_xname, __func__); 1275 return -1; 1276 } 1277 1278 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 1279 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 1280 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 1281 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 1282 if (!ISSET(flags, SCSI_POLL)) { 1283 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 1284 UFSHCI_REG_UTRIACR_IAEN | 1285 UFSHCI_REG_UTRIACR_IAPWEN | 1286 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 1287 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_COUNT)); 1288 } 1289 1290 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 1291 ufshci_doorbell_set(sc, slot); 1292 1293 return slot; 1294 } 1295 1296 int 1297 ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb, 1298 int flags, uint32_t lba, uint16_t blocks) 1299 { 1300 int slot, off, len; 1301 uint64_t dva; 1302 struct ufshci_utrd *utrd; 1303 struct ufshci_ucd *ucd; 1304 1305 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */ 1306 slot = ufshci_doorbell_get_free(sc); 1307 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 1308 memset(utrd, 0, sizeof(*utrd)); 1309 DPRINTF("%s: slot=%d\n", __func__, slot); 1310 1311 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */ 1312 utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS; 1313 1314 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */ 1315 utrd->dw0 |= UFSHCI_UTRD_DW0_DD_I2T; 1316 1317 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */ 1318 utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG; 1319 1320 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */ 1321 utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV; 1322 1323 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */ 1324 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1325 memset(ucd, 0, sizeof(*ucd)); 1326 1327 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */ 1328 ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND; 1329 ucd->cmd.hdr.flags = 0; /* No data transfer */ 1330 ucd->cmd.hdr.lun = 0; 1331 ucd->cmd.hdr.taskid = ufshci_get_taskid(sc); 1332 ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */ 1333 ucd->cmd.hdr.query = 0; 1334 ucd->cmd.hdr.response = 0; 1335 ucd->cmd.hdr.status = 0; 1336 ucd->cmd.hdr.ehs_len = 0; 1337 ucd->cmd.hdr.device_info = 0; 1338 ucd->cmd.hdr.ds_len = 0; 1339 1340 ucd->cmd.expected_xfer_len = htobe32(0); /* No data transfer */ 1341 1342 ucd->cmd.cdb[0] = SYNCHRONIZE_CACHE; /* 0x35 */ 1343 ucd->cmd.cdb[2] = (lba >> 24) & 0xff; 1344 ucd->cmd.cdb[3] = (lba >> 16) & 0xff; 1345 ucd->cmd.cdb[4] = (lba >> 8) & 0xff; 1346 ucd->cmd.cdb[5] = (lba >> 0) & 0xff; 1347 ucd->cmd.cdb[7] = (blocks >> 8) & 0xff; 1348 ucd->cmd.cdb[8] = (blocks >> 0) & 0xff; 1349 1350 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */ 1351 /* Already done with above memset */ 1352 1353 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */ 1354 dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1355 DPRINTF("%s: ucd dva=%llu\n", __func__, dva); 1356 utrd->dw4 = (uint32_t)dva; 1357 utrd->dw5 = (uint32_t)(dva >> 32); 1358 1359 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */ 1360 off = sizeof(struct upiu_command) / 4; /* DWORD offset */ 1361 utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off); 1362 1363 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */ 1364 len = sizeof(struct upiu_response) / 4; /* DWORD length */ 1365 utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len); 1366 1367 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */ 1368 off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4; 1369 utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off); 1370 1371 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */ 1372 utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(0); /* No data xfer */ 1373 1374 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */ 1375 if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) { 1376 printf("%s: %s: UTRLRSR not set\n", 1377 sc->sc_dev.dv_xname, __func__); 1378 return -1; 1379 } 1380 1381 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */ 1382 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */ 1383 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */ 1384 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */ 1385 if (!ISSET(flags, SCSI_POLL)) { 1386 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 1387 UFSHCI_REG_UTRIACR_IAEN | 1388 UFSHCI_REG_UTRIACR_IAPWEN | 1389 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 1390 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 1391 } 1392 1393 /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */ 1394 ufshci_doorbell_set(sc, slot); 1395 1396 return slot; 1397 } 1398 1399 int 1400 ufshci_xfer_complete(struct ufshci_softc *sc) 1401 { 1402 struct ufshci_ccb *ccb; 1403 uint32_t reg; 1404 int i; 1405 1406 reg = ufshci_doorbell_read(sc); 1407 1408 for (i = 0; i < sc->sc_nutrs; i++) { 1409 ccb = &sc->sc_ccbs[i]; 1410 1411 if (ccb->ccb_slot == -1) 1412 /* CCB isn't used. */ 1413 continue; 1414 1415 if (reg & (1 << ccb->ccb_slot)) 1416 /* Transfer is still in progress. */ 1417 continue; 1418 1419 /* Transfer has completed. */ 1420 if (ccb->ccb_done == NULL) 1421 panic("ccb_done not defined"); 1422 ccb->ccb_done(sc, ccb); 1423 } 1424 1425 return 0; 1426 } 1427 1428 #ifdef UFSHCI_DEBUG 1429 void 1430 ufshci_hexdump(void *buf, int len, char *title, int dbglvl) 1431 { 1432 u_char b[16]; 1433 int i, j, l; 1434 1435 if (dbglvl > ufshci_dbglvl) 1436 return; 1437 1438 printf("hexdump for %s (size=%d bytes)\n", title, len); 1439 1440 for (i = 0; i < len; i += l) { 1441 printf("%4i:", i); 1442 l = min(sizeof(b), len - i); 1443 bcopy(buf + i, b, l); 1444 1445 for (j = 0; j < sizeof(b); j++) { 1446 if (j % 2 == 0) 1447 printf(" "); 1448 if (j % 8 == 0) 1449 printf(" "); 1450 if (j < l) 1451 printf("%02x", (int)b[j]); 1452 else 1453 printf(" "); 1454 } 1455 printf(" |"); 1456 for (j = 0; j < l; j++) { 1457 if (b[j] >= 0x20 && b[j] <= 0x7e) 1458 printf("%c", b[j]); 1459 else 1460 printf("."); 1461 } 1462 printf("|\n"); 1463 } 1464 } 1465 #else 1466 void 1467 ufshci_hexdump(void *buf, int len, char *title, int dbglvl) 1468 { 1469 1470 } 1471 #endif 1472 1473 /* SCSI */ 1474 1475 int 1476 ufshci_ccb_alloc(struct ufshci_softc *sc, int nccbs) 1477 { 1478 struct ufshci_ccb *ccb; 1479 int i; 1480 1481 DPRINTF("%s: nccbs=%d, dma_size=%d, dma_nsegs=%d, " 1482 "dma_segmaxsize=%d\n", 1483 __func__, nccbs, UFSHCI_UCD_PRDT_MAX_XFER, UFSHCI_UCD_PRDT_MAX_SEGS, 1484 UFSHCI_UCD_PRDT_MAX_XFER); 1485 1486 sc->sc_ccbs = mallocarray(nccbs, sizeof(*ccb), M_DEVBUF, 1487 M_WAITOK | M_CANFAIL); 1488 if (sc->sc_ccbs == NULL) 1489 return 1; 1490 1491 for (i = 0; i < nccbs; i++) { 1492 ccb = &sc->sc_ccbs[i]; 1493 1494 if (bus_dmamap_create(sc->sc_dmat, UFSHCI_UCD_PRDT_MAX_XFER, 1495 UFSHCI_UCD_PRDT_MAX_SEGS, UFSHCI_UCD_PRDT_MAX_XFER, 0, 1496 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | BUS_DMA_64BIT, 1497 &ccb->ccb_dmamap) != 0) 1498 goto free_maps; 1499 1500 ccb->ccb_cookie = NULL; 1501 ccb->ccb_slot = -1; 1502 1503 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_list, ccb, ccb_entry); 1504 } 1505 1506 return 0; 1507 1508 free_maps: 1509 ufshci_ccb_free(sc, nccbs); 1510 return 1; 1511 } 1512 1513 void * 1514 ufshci_ccb_get(void *cookie) 1515 { 1516 struct ufshci_softc *sc = cookie; 1517 struct ufshci_ccb *ccb; 1518 1519 DPRINTF("%s\n", __func__); 1520 1521 mtx_enter(&sc->sc_ccb_mtx); 1522 ccb = SIMPLEQ_FIRST(&sc->sc_ccb_list); 1523 if (ccb != NULL) 1524 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_list, ccb_entry); 1525 mtx_leave(&sc->sc_ccb_mtx); 1526 1527 return ccb; 1528 } 1529 1530 void 1531 ufshci_ccb_put(void *cookie, void *io) 1532 { 1533 struct ufshci_softc *sc = cookie; 1534 struct ufshci_ccb *ccb = io; 1535 1536 DPRINTF("%s\n", __func__); 1537 1538 mtx_enter(&sc->sc_ccb_mtx); 1539 SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_list, ccb, ccb_entry); 1540 mtx_leave(&sc->sc_ccb_mtx); 1541 } 1542 1543 void 1544 ufshci_ccb_free(struct ufshci_softc *sc, int nccbs) 1545 { 1546 struct ufshci_ccb *ccb; 1547 1548 DPRINTF("%s\n", __func__); 1549 1550 while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_list)) != NULL) { 1551 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_list, ccb_entry); 1552 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 1553 } 1554 1555 ufshci_dmamem_free(sc, sc->sc_dmamem_utrd); 1556 free(sc->sc_ccbs, M_DEVBUF, nccbs * sizeof(*ccb)); 1557 } 1558 1559 void 1560 ufshci_scsi_cmd(struct scsi_xfer *xs) 1561 { 1562 struct scsi_link *link = xs->sc_link; 1563 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1564 1565 DPRINTF("%s: cmd=0x%x\n", __func__, xs->cmd.opcode); 1566 1567 if (!cold && !sc->sc_intraggr_enabled) { 1568 DPRINTF("%s: Enable interrupt aggregation\n", __func__); 1569 UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR, 1570 UFSHCI_REG_UTRIACR_IAEN | 1571 UFSHCI_REG_UTRIACR_IAPWEN | 1572 UFSHCI_REG_UTRIACR_CTR | 1573 UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) | 1574 UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT)); 1575 sc->sc_intraggr_enabled = 1; 1576 } 1577 1578 switch (xs->cmd.opcode) { 1579 1580 case READ_COMMAND: 1581 case READ_10: 1582 case READ_12: 1583 case READ_16: 1584 ufshci_scsi_io(xs, SCSI_DATA_IN); 1585 return; 1586 1587 case WRITE_COMMAND: 1588 case WRITE_10: 1589 case WRITE_12: 1590 case WRITE_16: 1591 ufshci_scsi_io(xs, SCSI_DATA_OUT); 1592 return; 1593 1594 case SYNCHRONIZE_CACHE: 1595 ufshci_scsi_sync(xs); 1596 return; 1597 1598 case INQUIRY: 1599 ufshci_scsi_inquiry(xs); 1600 return; 1601 1602 case READ_CAPACITY_16: 1603 ufshci_scsi_capacity16(xs); 1604 return; 1605 case READ_CAPACITY: 1606 ufshci_scsi_capacity(xs); 1607 return; 1608 1609 case TEST_UNIT_READY: 1610 case PREVENT_ALLOW: 1611 case START_STOP: 1612 xs->error = XS_NOERROR; 1613 scsi_done(xs); 1614 return; 1615 default: 1616 DPRINTF("%s: unhandled scsi command 0x%02x\n", 1617 __func__, xs->cmd.opcode); 1618 break; 1619 } 1620 1621 xs->error = XS_DRIVER_STUFFUP; 1622 scsi_done(xs); 1623 } 1624 1625 void 1626 ufshci_minphys(struct buf *bp, struct scsi_link *link) 1627 { 1628 DPRINTF("%s\n", __func__); 1629 } 1630 1631 int 1632 ufshci_scsi_probe(struct scsi_link *link) 1633 { 1634 DPRINTF("%s\n", __func__); 1635 1636 return 0; 1637 } 1638 1639 void 1640 ufshci_scsi_free(struct scsi_link *link) 1641 { 1642 DPRINTF("%s\n", __func__); 1643 } 1644 1645 void 1646 ufshci_scsi_inquiry(struct scsi_xfer *xs) 1647 { 1648 struct scsi_link *link = xs->sc_link; 1649 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1650 struct ufshci_ccb *ccb = xs->io; 1651 bus_dmamap_t dmap = ccb->ccb_dmamap; 1652 int error; 1653 1654 DPRINTF("%s: INQUIRY (%s)\n", 1655 __func__, ISSET(xs->flags, SCSI_POLL) ? "poll" : "no poll"); 1656 1657 if (xs->datalen > UPIU_SCSI_RSP_INQUIRY_SIZE) { 1658 DPRINTF("%s: request len too large\n", __func__); 1659 goto error1; 1660 } 1661 1662 error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 1663 ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1664 if (error != 0) { 1665 printf("%s: bus_dmamap_load error=%d\n", __func__, error); 1666 goto error1; 1667 } 1668 1669 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1670 BUS_DMASYNC_PREREAD); 1671 1672 ccb->ccb_cookie = xs; 1673 ccb->ccb_done = ufshci_scsi_io_done; 1674 1675 /* Response length should be UPIU_SCSI_RSP_INQUIRY_SIZE. */ 1676 ccb->ccb_slot = ufshci_utr_cmd_inquiry(sc, ccb, xs->datalen, xs->flags); 1677 if (ccb->ccb_slot == -1) 1678 goto error2; 1679 1680 if (ISSET(xs->flags, SCSI_POLL)) { 1681 if (ufshci_doorbell_poll(sc, ccb->ccb_slot) == 0) { 1682 ccb->ccb_done(sc, ccb); 1683 return; 1684 } 1685 goto error2; 1686 } 1687 1688 return; 1689 1690 error2: 1691 bus_dmamap_unload(sc->sc_dmat, dmap); 1692 ccb->ccb_cookie = NULL; 1693 ccb->ccb_slot = -1; 1694 ccb->ccb_done = NULL; 1695 error1: 1696 xs->error = XS_DRIVER_STUFFUP; 1697 scsi_done(xs); 1698 } 1699 1700 void 1701 ufshci_scsi_capacity16(struct scsi_xfer *xs) 1702 { 1703 struct scsi_link *link = xs->sc_link; 1704 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1705 struct ufshci_ccb *ccb = xs->io; 1706 bus_dmamap_t dmap = ccb->ccb_dmamap; 1707 int error; 1708 1709 DPRINTF("%s: CAPACITY16 (%s)\n", 1710 __func__, ISSET(xs->flags, SCSI_POLL) ? "poll" : "no poll"); 1711 1712 if (xs->datalen > UPIU_SCSI_RSP_CAPACITY16_SIZE) { 1713 DPRINTF("%s: request len too large\n", __func__); 1714 goto error1; 1715 } 1716 1717 error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 1718 ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1719 if (error != 0) { 1720 printf("%s: bus_dmamap_load error=%d\n", __func__, error); 1721 goto error1; 1722 } 1723 1724 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1725 BUS_DMASYNC_PREREAD); 1726 1727 ccb->ccb_cookie = xs; 1728 ccb->ccb_done = ufshci_scsi_io_done; 1729 1730 /* Response length should be UPIU_SCSI_RSP_CAPACITY16_SIZE. */ 1731 ccb->ccb_slot = ufshci_utr_cmd_capacity16(sc, ccb, xs->datalen, 1732 xs->flags); 1733 if (ccb->ccb_slot == -1) 1734 goto error2; 1735 1736 if (ISSET(xs->flags, SCSI_POLL)) { 1737 if (ufshci_doorbell_poll(sc, ccb->ccb_slot) == 0) { 1738 ccb->ccb_done(sc, ccb); 1739 return; 1740 } 1741 goto error2; 1742 } 1743 1744 return; 1745 1746 error2: 1747 bus_dmamap_unload(sc->sc_dmat, dmap); 1748 ccb->ccb_cookie = NULL; 1749 ccb->ccb_slot = -1; 1750 ccb->ccb_done = NULL; 1751 error1: 1752 xs->error = XS_DRIVER_STUFFUP; 1753 scsi_done(xs); 1754 } 1755 1756 void 1757 ufshci_scsi_capacity(struct scsi_xfer *xs) 1758 { 1759 struct scsi_link *link = xs->sc_link; 1760 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1761 struct ufshci_ccb *ccb = xs->io; 1762 bus_dmamap_t dmap = ccb->ccb_dmamap; 1763 int error; 1764 1765 DPRINTF("%s: CAPACITY (%s)\n", 1766 __func__, ISSET(xs->flags, SCSI_POLL) ? "poll" : "no poll"); 1767 1768 if (xs->datalen > UPIU_SCSI_RSP_CAPACITY_SIZE) { 1769 DPRINTF("%s: request len too large\n", __func__); 1770 goto error1; 1771 } 1772 1773 error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 1774 ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1775 if (error != 0) { 1776 printf("%s: bus_dmamap_load error=%d\n", __func__, error); 1777 goto error1; 1778 } 1779 1780 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1781 BUS_DMASYNC_PREREAD); 1782 1783 ccb->ccb_cookie = xs; 1784 ccb->ccb_done = ufshci_scsi_io_done; 1785 1786 /* Response length should be UPIU_SCSI_RSP_CAPACITY_SIZE */ 1787 ccb->ccb_slot = ufshci_utr_cmd_capacity(sc, ccb, xs->datalen, 1788 xs->flags); 1789 if (ccb->ccb_slot == -1) 1790 goto error2; 1791 1792 if (ISSET(xs->flags, SCSI_POLL)) { 1793 if (ufshci_doorbell_poll(sc, ccb->ccb_slot) == 0) { 1794 ccb->ccb_done(sc, ccb); 1795 return; 1796 } 1797 goto error2; 1798 } 1799 1800 return; 1801 1802 error2: 1803 bus_dmamap_unload(sc->sc_dmat, dmap); 1804 ccb->ccb_cookie = NULL; 1805 ccb->ccb_slot = -1; 1806 ccb->ccb_done = NULL; 1807 error1: 1808 xs->error = XS_DRIVER_STUFFUP; 1809 scsi_done(xs); 1810 } 1811 1812 void 1813 ufshci_scsi_sync(struct scsi_xfer *xs) 1814 { 1815 struct scsi_link *link = xs->sc_link; 1816 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1817 struct ufshci_ccb *ccb = xs->io; 1818 uint64_t lba; 1819 uint32_t blocks; 1820 1821 /* lba = 0, blocks = 0: Synchronize all logical blocks. */ 1822 lba = 0; blocks = 0; 1823 1824 DPRINTF("%s: SYNC, lba=%llu, blocks=%u (%s)\n", 1825 __func__, lba, blocks, 1826 ISSET(xs->flags, SCSI_POLL) ? "poll" : "no poll"); 1827 1828 ccb->ccb_cookie = xs; 1829 ccb->ccb_done = ufshci_scsi_done; 1830 1831 ccb->ccb_slot = ufshci_utr_cmd_sync(sc, ccb, xs->flags, (uint32_t)lba, 1832 (uint16_t)blocks); 1833 if (ccb->ccb_slot == -1) 1834 goto error; 1835 1836 if (ISSET(xs->flags, SCSI_POLL)) { 1837 if (ufshci_doorbell_poll(sc, ccb->ccb_slot) == 0) { 1838 ccb->ccb_done(sc, ccb); 1839 return; 1840 } 1841 goto error; 1842 } 1843 1844 return; 1845 1846 error: 1847 ccb->ccb_cookie = NULL; 1848 ccb->ccb_slot = -1; 1849 ccb->ccb_done = NULL; 1850 1851 xs->error = XS_DRIVER_STUFFUP; 1852 scsi_done(xs); 1853 } 1854 1855 void 1856 ufshci_scsi_io(struct scsi_xfer *xs, int dir) 1857 { 1858 struct scsi_link *link = xs->sc_link; 1859 struct ufshci_softc *sc = link->bus->sb_adapter_softc; 1860 struct ufshci_ccb *ccb = xs->io; 1861 bus_dmamap_t dmap = ccb->ccb_dmamap; 1862 uint64_t lba; 1863 uint32_t blocks; 1864 int error; 1865 1866 if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) != dir) 1867 goto error1; 1868 1869 scsi_cmd_rw_decode(&xs->cmd, &lba, &blocks); 1870 1871 DPRINTF("%s: %s, lba=%llu, blocks=%u, datalen=%d (%s)\n", 1872 __func__, 1873 ISSET(xs->flags, SCSI_DATA_IN) ? "READ" : "WRITE", 1874 lba, blocks, xs->datalen, 1875 ISSET(xs->flags, SCSI_POLL) ? "poll" : "no poll"); 1876 1877 error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 1878 ISSET(xs->flags, SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1879 if (error != 0) { 1880 printf("%s: bus_dmamap_load error=%d\n", __func__, error); 1881 goto error1; 1882 } 1883 1884 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1885 ISSET(xs->flags, SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : 1886 BUS_DMASYNC_PREWRITE); 1887 1888 ccb->ccb_cookie = xs; 1889 ccb->ccb_done = ufshci_scsi_io_done; 1890 1891 if (dir == SCSI_DATA_IN) { 1892 ccb->ccb_slot = ufshci_utr_cmd_read(sc, ccb, xs->datalen, 1893 xs->flags, (uint32_t)lba, (uint16_t)blocks); 1894 } else { 1895 ccb->ccb_slot = ufshci_utr_cmd_write(sc, ccb, xs->datalen, 1896 xs->flags, (uint32_t)lba, (uint16_t)blocks); 1897 } 1898 1899 if (ccb->ccb_slot == -1) 1900 goto error2; 1901 1902 if (ISSET(xs->flags, SCSI_POLL)) { 1903 if (ufshci_doorbell_poll(sc, ccb->ccb_slot) == 0) { 1904 ccb->ccb_done(sc, ccb); 1905 return; 1906 } 1907 goto error2; 1908 } 1909 1910 return; 1911 1912 error2: 1913 bus_dmamap_unload(sc->sc_dmat, dmap); 1914 ccb->ccb_cookie = NULL; 1915 ccb->ccb_slot = -1; 1916 ccb->ccb_done = NULL; 1917 error1: 1918 xs->error = XS_DRIVER_STUFFUP; 1919 scsi_done(xs); 1920 } 1921 1922 void 1923 ufshci_scsi_io_done(struct ufshci_softc *sc, struct ufshci_ccb *ccb) 1924 { 1925 struct scsi_xfer *xs = ccb->ccb_cookie; 1926 bus_dmamap_t dmap = ccb->ccb_dmamap; 1927 #if 0 1928 struct ufshci_utrd *utrd; 1929 struct ufshci_ucd *ucd; 1930 int slot = ccb->ccb_slot; 1931 #endif 1932 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1933 ISSET(xs->flags, SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1934 BUS_DMASYNC_POSTWRITE); 1935 #if 0 1936 ufshci_hexdump(xs->data, xs->datalen, "xs->data", 1); 1937 1938 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 1939 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1940 1941 printf("ucd rsp tc=0x%02x\n", ucd->rsp.hdr.tc); 1942 printf("ucd rsp flags=0x%02x\n", ucd->rsp.hdr.flags); 1943 printf("ucd rsp lun=%d\n", ucd->rsp.hdr.lun); 1944 printf("ucd rsp taskid=%d\n", ucd->rsp.hdr.taskid); 1945 printf("ucd rsp cmd_set_type=0x%02x\n", ucd->rsp.hdr.cmd_set_type); 1946 printf("ucd rsp query=0x%02x\n", ucd->rsp.hdr.query); 1947 printf("ucd rsp response=0x%02x\n", ucd->rsp.hdr.response); 1948 printf("ucd rsp status=0x%02x\n", ucd->rsp.hdr.status); 1949 printf("ucd rsp ehs_len=%d\n", ucd->rsp.hdr.ehs_len); 1950 printf("ucd rsp device_info=0x%02x\n", ucd->rsp.hdr.device_info); 1951 printf("ucd rsp ds_len=%d\n", ucd->rsp.hdr.ds_len); 1952 printf("ucd rsp rxl=%d\n", be32toh(ucd->rsp.residual_xfer_len)); 1953 #endif 1954 bus_dmamap_unload(sc->sc_dmat, dmap); 1955 1956 ccb->ccb_cookie = NULL; 1957 ccb->ccb_slot = -1; 1958 ccb->ccb_done = NULL; 1959 1960 xs->error = XS_NOERROR; 1961 xs->status = SCSI_OK; 1962 xs->resid = 0; 1963 scsi_done(xs); 1964 } 1965 1966 void 1967 ufshci_scsi_done(struct ufshci_softc *sc, struct ufshci_ccb *ccb) 1968 { 1969 struct scsi_xfer *xs = ccb->ccb_cookie; 1970 #if 0 1971 struct ufshci_utrd *utrd; 1972 struct ufshci_ucd *ucd; 1973 int slot = ccb->ccb_slot; 1974 1975 ufshci_hexdump(xs->data, xs->datalen, "xs->data", 1); 1976 1977 utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot); 1978 ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot); 1979 1980 printf("ucd rsp tc=0x%02x\n", ucd->rsp.hdr.tc); 1981 printf("ucd rsp flags=0x%02x\n", ucd->rsp.hdr.flags); 1982 printf("ucd rsp lun=%d\n", ucd->rsp.hdr.lun); 1983 printf("ucd rsp taskid=%d\n", ucd->rsp.hdr.taskid); 1984 printf("ucd rsp cmd_set_type=0x%02x\n", ucd->rsp.hdr.cmd_set_type); 1985 printf("ucd rsp query=0x%02x\n", ucd->rsp.hdr.query); 1986 printf("ucd rsp response=0x%02x\n", ucd->rsp.hdr.response); 1987 printf("ucd rsp status=0x%02x\n", ucd->rsp.hdr.status); 1988 printf("ucd rsp ehs_len=%d\n", ucd->rsp.hdr.ehs_len); 1989 printf("ucd rsp device_info=0x%02x\n", ucd->rsp.hdr.device_info); 1990 printf("ucd rsp ds_len=%d\n", ucd->rsp.hdr.ds_len); 1991 printf("ucd rsp rxl=%d\n", be32toh(ucd->rsp.residual_xfer_len)); 1992 #endif 1993 ccb->ccb_cookie = NULL; 1994 ccb->ccb_slot = -1; 1995 ccb->ccb_done = NULL; 1996 1997 xs->error = XS_NOERROR; 1998 xs->status = SCSI_OK; 1999 xs->resid = 0; 2000 scsi_done(xs); 2001 } 2002