xref: /openbsd-src/sys/dev/ic/ufshci.c (revision fc405d53b73a2d73393cb97f684863d17b583e38)
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