sync with OpenBSD -current

This commit is contained in:
purplerain 2024-05-10 01:59:48 +00:00
parent 01ab08895c
commit 492219ffd1
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
35 changed files with 666 additions and 546 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ufshci.c,v 1.9 2024/01/06 17:47:43 mglocker Exp $ */
/* $OpenBSD: ufshci.c,v 1.19 2024/05/09 08:24:09 mglocker Exp $ */
/*
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@ -61,12 +61,11 @@ struct ufshci_dmamem *ufshci_dmamem_alloc(struct ufshci_softc *, size_t);
void ufshci_dmamem_free(struct ufshci_softc *,
struct ufshci_dmamem *);
int ufshci_init(struct ufshci_softc *);
int ufshci_doorbell_get_free(struct ufshci_softc *);
int ufshci_doorbell_read(struct ufshci_softc *);
void ufshci_doorbell_write(struct ufshci_softc *, int);
int ufshci_doorbell_poll(struct ufshci_softc *, int);
void ufshci_doorbell_set(struct ufshci_softc *, int);
uint8_t ufshci_get_taskid(struct ufshci_softc *);
int ufshci_utr_cmd_nop(struct ufshci_softc *);
int ufshci_utr_cmd_nop(struct ufshci_softc *,
struct ufshci_ccb *, struct scsi_xfer *);
int ufshci_utr_cmd_lun(struct ufshci_softc *,
struct ufshci_ccb *, struct scsi_xfer *);
int ufshci_utr_cmd_inquiry(struct ufshci_softc *,
@ -127,11 +126,12 @@ ufshci_intr(void *arg)
if (status & UFSHCI_REG_IS_UTRCS) {
DPRINTF("%s: UTRCS interrupt\n", __func__);
ufshci_xfer_complete(sc);
/* Reset Interrupt Aggregation Counter and Timer. */
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN | UFSHCI_REG_UTRIACR_CTR);
sc->sc_intraggr_enabled = 0;
ufshci_xfer_complete(sc);
handled = 1;
}
@ -152,6 +152,7 @@ ufshci_attach(struct ufshci_softc *sc)
{
struct scsibus_attach_args saa;
mtx_init(&sc->sc_cmd_mtx, IPL_BIO);
mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
SIMPLEQ_INIT(&sc->sc_ccb_list);
scsi_iopool_init(&sc->sc_iopool, sc, ufshci_ccb_get, ufshci_ccb_put);
@ -169,7 +170,9 @@ ufshci_attach(struct ufshci_softc *sc)
sc->sc_hcmid = UFSHCI_READ_4(sc, UFSHCI_REG_HCMID);
sc->sc_nutmrs = UFSHCI_REG_CAP_NUTMRS(sc->sc_cap) + 1;
sc->sc_rtt = UFSHCI_REG_CAP_RTT(sc->sc_cap) + 1;
sc->sc_nutrs = UFSHCI_REG_CAP_NUTRS(sc->sc_cap) + 1;
//sc->sc_nutrs = UFSHCI_REG_CAP_NUTRS(sc->sc_cap) + 1;
/* XXX: Using more than one slot currently causes OCS errors */
sc->sc_nutrs = 1;
#if UFSHCI_DEBUG
printf("Capabilities (0x%08x):\n", sc->sc_cap);
@ -192,7 +195,12 @@ ufshci_attach(struct ufshci_softc *sc)
printf("%s: NUTRS can't be >32 (is %d)!\n",
sc->sc_dev.dv_xname, sc->sc_nutrs);
return 1;
} else if (sc->sc_nutrs == 1) {
sc->sc_iacth = sc->sc_nutrs;
} else if (sc->sc_nutrs > 1) {
sc->sc_iacth = sc->sc_nutrs - 1;
}
DPRINTF("IACTH=%d\n", sc->sc_iacth);
ufshci_init(sc);
@ -370,24 +378,6 @@ ufshci_init(struct ufshci_softc *sc)
/* 7.1.1 Host Controller Initialization: 11) */
reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRIACR);
DPRINTF("%s: UTRIACR=0x%08x\n", __func__, reg);
/*
* Only enable interrupt aggregation when interrupts are available.
* Otherwise, the interrupt aggregation counter already starts to
* count completed commands, and will keep interrupts disabled once
* reaching the threshold. We only issue the interrupt aggregation
* counter reset in the interrupt handler during runtime, so we would
* have a kind of chicken/egg problem.
*/
if (!cold) {
DPRINTF("%s: Enable interrupt aggregation\n", __func__);
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_CTR |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
sc->sc_intraggr_enabled = 1;
}
/*
* 7.1.1 Host Controller Initialization: 12)
@ -446,22 +436,6 @@ ufshci_init(struct ufshci_softc *sc)
return 0;
}
int
ufshci_doorbell_get_free(struct ufshci_softc *sc)
{
int slot;
uint32_t reg;
reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRLDBR);
for (slot = 0; slot < sc->sc_nutrs; slot++) {
if ((reg & (1 << slot)) == 0)
return slot;
}
return -1;
}
int
ufshci_doorbell_read(struct ufshci_softc *sc)
{
@ -472,6 +446,16 @@ ufshci_doorbell_read(struct ufshci_softc *sc)
return reg;
}
void
ufshci_doorbell_write(struct ufshci_softc *sc, int slot)
{
uint32_t reg;
reg = (1U << slot);
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLDBR, reg);
}
int
ufshci_doorbell_poll(struct ufshci_softc *sc, int slot)
{
@ -482,7 +466,7 @@ ufshci_doorbell_poll(struct ufshci_softc *sc, int slot)
for (i = 0; i < retry; i++) {
reg = UFSHCI_READ_4(sc, UFSHCI_REG_UTRLDBR);
if ((reg & (1 << slot)) == 0)
if ((reg & (1U << slot)) == 0)
break;
delay(10);
}
@ -494,29 +478,9 @@ ufshci_doorbell_poll(struct ufshci_softc *sc, int slot)
return 0;
}
void
ufshci_doorbell_set(struct ufshci_softc *sc, int slot)
{
uint32_t reg;
reg = (1 << slot);
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLDBR, reg);
}
uint8_t
ufshci_get_taskid(struct ufshci_softc *sc)
{
if (sc->sc_taskid == 255)
sc->sc_taskid = 0;
else
sc->sc_taskid++;
return sc->sc_taskid;
}
int
ufshci_utr_cmd_nop(struct ufshci_softc *sc)
ufshci_utr_cmd_nop(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
struct scsi_xfer *xs)
{
int slot, off, len;
uint64_t dva;
@ -524,8 +488,9 @@ ufshci_utr_cmd_nop(struct ufshci_softc *sc)
struct ufshci_ucd *ucd;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -536,20 +501,21 @@ ufshci_utr_cmd_nop(struct ufshci_softc *sc)
utrd->dw0 |= UFSHCI_UTRD_DW0_DD_NO;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */
utrd->dw0 |= UFSHCI_UTRD_DW0_I_INT;
utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2d) */
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_NOP_OUT;
ucd->cmd.hdr.flags = 0;
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -589,18 +555,14 @@ ufshci_utr_cmd_nop(struct ufshci_softc *sc)
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return 0;
}
@ -616,8 +578,9 @@ ufshci_utr_cmd_lun(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
bus_dmamap_t dmap = ccb->ccb_dmamap;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -634,14 +597,15 @@ ufshci_utr_cmd_lun(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND;
ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -698,18 +662,14 @@ ufshci_utr_cmd_lun(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return 0;
}
@ -725,8 +685,9 @@ ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
bus_dmamap_t dmap = ccb->ccb_dmamap;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -743,14 +704,15 @@ ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND;
ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -805,20 +767,14 @@ ufshci_utr_cmd_inquiry(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
}
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return slot;
}
@ -834,8 +790,9 @@ ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
bus_dmamap_t dmap = ccb->ccb_dmamap;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -852,14 +809,15 @@ ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND;
ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -918,20 +876,14 @@ ufshci_utr_cmd_capacity16(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
}
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return slot;
}
@ -947,8 +899,9 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
bus_dmamap_t dmap = ccb->ccb_dmamap;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -965,14 +918,15 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND;
ucd->cmd.hdr.flags = (1 << 6); /* Bit-5 = Write, Bit-6 = Read */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -1030,20 +984,14 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
}
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return slot;
}
@ -1059,8 +1007,9 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
bus_dmamap_t dmap = ccb->ccb_dmamap;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -1080,7 +1029,8 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
@ -1090,7 +1040,7 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
else
ucd->cmd.hdr.flags = (1 << 5); /* Bit-5 = Write */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -1102,8 +1052,6 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
ucd->cmd.expected_xfer_len = htobe32(xs->datalen);
memcpy(ucd->cmd.cdb, &xs->cmd, sizeof(ucd->cmd.cdb));
if (dir == SCSI_DATA_OUT)
ucd->cmd.cdb[1] = (1 << 3); /* FUA: Force Unit Access */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2g) */
/* Already done with above memset */
@ -1145,20 +1093,14 @@ ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
}
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return slot;
}
@ -1173,8 +1115,9 @@ ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
struct ufshci_ucd *ucd;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 1) */
slot = ufshci_doorbell_get_free(sc);
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd) + (sizeof(*utrd) * slot);
slot = ccb->ccb_slot;
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += slot;
memset(utrd, 0, sizeof(*utrd));
DPRINTF("%s: slot=%d\n", __func__, slot);
@ -1191,14 +1134,15 @@ ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw2 = UFSHCI_UTRD_DW2_OCS_IOV;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2e) */
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += slot;
memset(ucd, 0, sizeof(*ucd));
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2f) */
ucd->cmd.hdr.tc = UPIU_TC_I2T_COMMAND;
ucd->cmd.hdr.flags = 0; /* No data transfer */
ucd->cmd.hdr.lun = 0;
ucd->cmd.hdr.taskid = ufshci_get_taskid(sc);
ucd->cmd.hdr.taskid = 0;
ucd->cmd.hdr.cmd_set_type = 0; /* SCSI command */
ucd->cmd.hdr.query = 0;
ucd->cmd.hdr.response = 0;
@ -1248,20 +1192,14 @@ ufshci_utr_cmd_sync(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
return -1;
}
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 10) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 11) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 12) */
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 13) */
if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
}
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * slot, sizeof(*utrd), BUS_DMASYNC_PREWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * slot, sizeof(*ucd), BUS_DMASYNC_PREWRITE);
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
ufshci_doorbell_set(sc, slot);
ccb->ccb_status = CCB_STATUS_INPROGRESS;
ufshci_doorbell_write(sc, slot);
return slot;
}
@ -1273,23 +1211,45 @@ ufshci_xfer_complete(struct ufshci_softc *sc)
uint32_t reg;
int i;
reg = ufshci_doorbell_read(sc);
mtx_enter(&sc->sc_cmd_mtx);
/* Wait for all commands to complete. */
while ((reg = ufshci_doorbell_read(sc))) {
DPRINTF("%s: doorbell reg=0x%x\n", __func__, reg);
if (reg == 0)
break;
}
for (i = 0; i < sc->sc_nutrs; i++) {
ccb = &sc->sc_ccbs[i];
if (ccb->ccb_slot == -1)
/* CCB isn't used. */
/* Skip unused CCBs. */
if (ccb->ccb_status != CCB_STATUS_INPROGRESS)
continue;
if (reg & (1 << ccb->ccb_slot))
/* Transfer is still in progress. */
continue;
/* Transfer has completed. */
if (ccb->ccb_done == NULL)
panic("ccb_done not defined");
ccb->ccb_done(sc, ccb);
panic("ccb done wasn't defined");
/* 7.2.3: Clear completion notification 3b) */
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRLCNR, (1U << i));
/* 7.2.3: Mark software slot for re-use 3c) */
ccb->ccb_status = CCB_STATUS_READY2FREE;
DPRINTF("slot %d completed\n", i);
}
mtx_leave(&sc->sc_cmd_mtx);
/*
* Complete the CCB, which will re-schedule new transfers if any are
* pending.
*/
for (i = 0; i < sc->sc_nutrs; i++) {
ccb = &sc->sc_ccbs[i];
/* 7.2.3: Process the transfer by higher OS layer 3a) */
if (ccb->ccb_status == CCB_STATUS_READY2FREE)
ccb->ccb_done(sc, ccb);
}
return 0;
@ -1323,7 +1283,7 @@ ufshci_ccb_alloc(struct ufshci_softc *sc, int nccbs)
goto free_maps;
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_slot = i;
SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_list, ccb, ccb_entry);
}
@ -1387,15 +1347,17 @@ ufshci_scsi_cmd(struct scsi_xfer *xs)
struct scsi_link *link = xs->sc_link;
struct ufshci_softc *sc = link->bus->sb_adapter_softc;
mtx_enter(&sc->sc_cmd_mtx);
DPRINTF("%s: cmd=0x%x\n", __func__, xs->cmd.opcode);
if (!cold && !sc->sc_intraggr_enabled) {
DPRINTF("%s: Enable interrupt aggregation\n", __func__);
/* Schedule interrupt aggregation. */
if (ISSET(xs->flags, SCSI_POLL) == 0 && sc->sc_intraggr_enabled == 0) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
UFSHCI_REG_UTRIACR_CTR |
UFSHCI_REG_UTRIACR_IACTH(UFSHCI_INTR_AGGR_COUNT) |
UFSHCI_REG_UTRIACR_IACTH(sc->sc_iacth) |
UFSHCI_REG_UTRIACR_IATOVAL(UFSHCI_INTR_AGGR_TIMEOUT));
sc->sc_intraggr_enabled = 1;
}
@ -1406,45 +1368,52 @@ ufshci_scsi_cmd(struct scsi_xfer *xs)
case READ_10:
case READ_12:
case READ_16:
DPRINTF("io read\n");
ufshci_scsi_io(xs, SCSI_DATA_IN);
return;
break;
case WRITE_COMMAND:
case WRITE_10:
case WRITE_12:
case WRITE_16:
DPRINTF("io write\n");
ufshci_scsi_io(xs, SCSI_DATA_OUT);
return;
break;
case SYNCHRONIZE_CACHE:
DPRINTF("sync\n");
ufshci_scsi_sync(xs);
return;
break;
case INQUIRY:
DPRINTF("inquiry\n");
ufshci_scsi_inquiry(xs);
return;
break;
case READ_CAPACITY_16:
DPRINTF("capacity16\n");
ufshci_scsi_capacity16(xs);
return;
break;
case READ_CAPACITY:
DPRINTF("capacity\n");
ufshci_scsi_capacity(xs);
return;
break;
case TEST_UNIT_READY:
case PREVENT_ALLOW:
case START_STOP:
xs->error = XS_NOERROR;
scsi_done(xs);
return;
break;
default:
DPRINTF("%s: unhandled scsi command 0x%02x\n",
__func__, xs->cmd.opcode);
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);
break;
}
xs->error = XS_DRIVER_STUFFUP;
scsi_done(xs);
mtx_leave(&sc->sc_cmd_mtx);
}
void
@ -1498,8 +1467,8 @@ ufshci_scsi_inquiry(struct scsi_xfer *xs)
ccb->ccb_done = ufshci_scsi_io_done;
/* Response length should be UPIU_SCSI_RSP_INQUIRY_SIZE. */
ccb->ccb_slot = ufshci_utr_cmd_inquiry(sc, ccb, xs);
if (ccb->ccb_slot == -1)
error = ufshci_utr_cmd_inquiry(sc, ccb, xs);
if (error == -1)
goto error2;
if (ISSET(xs->flags, SCSI_POLL)) {
@ -1515,7 +1484,6 @@ ufshci_scsi_inquiry(struct scsi_xfer *xs)
error2:
bus_dmamap_unload(sc->sc_dmat, dmap);
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_done = NULL;
error1:
xs->error = XS_DRIVER_STUFFUP;
@ -1553,8 +1521,8 @@ ufshci_scsi_capacity16(struct scsi_xfer *xs)
ccb->ccb_done = ufshci_scsi_io_done;
/* Response length should be UPIU_SCSI_RSP_CAPACITY16_SIZE. */
ccb->ccb_slot = ufshci_utr_cmd_capacity16(sc, ccb, xs);
if (ccb->ccb_slot == -1)
error = ufshci_utr_cmd_capacity16(sc, ccb, xs);
if (error == -1)
goto error2;
if (ISSET(xs->flags, SCSI_POLL)) {
@ -1570,7 +1538,6 @@ ufshci_scsi_capacity16(struct scsi_xfer *xs)
error2:
bus_dmamap_unload(sc->sc_dmat, dmap);
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_done = NULL;
error1:
xs->error = XS_DRIVER_STUFFUP;
@ -1608,8 +1575,8 @@ ufshci_scsi_capacity(struct scsi_xfer *xs)
ccb->ccb_done = ufshci_scsi_io_done;
/* Response length should be UPIU_SCSI_RSP_CAPACITY_SIZE */
ccb->ccb_slot = ufshci_utr_cmd_capacity(sc, ccb, xs);
if (ccb->ccb_slot == -1)
error = ufshci_utr_cmd_capacity(sc, ccb, xs);
if (error == -1)
goto error2;
if (ISSET(xs->flags, SCSI_POLL)) {
@ -1625,7 +1592,6 @@ ufshci_scsi_capacity(struct scsi_xfer *xs)
error2:
bus_dmamap_unload(sc->sc_dmat, dmap);
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_done = NULL;
error1:
xs->error = XS_DRIVER_STUFFUP;
@ -1640,6 +1606,7 @@ ufshci_scsi_sync(struct scsi_xfer *xs)
struct ufshci_ccb *ccb = xs->io;
uint64_t lba;
uint32_t blocks;
int error;
/* lba = 0, blocks = 0: Synchronize all logical blocks. */
lba = 0; blocks = 0;
@ -1651,9 +1618,9 @@ ufshci_scsi_sync(struct scsi_xfer *xs)
ccb->ccb_cookie = xs;
ccb->ccb_done = ufshci_scsi_done;
ccb->ccb_slot = ufshci_utr_cmd_sync(sc, ccb, xs, (uint32_t)lba,
error = ufshci_utr_cmd_sync(sc, ccb, xs, (uint32_t)lba,
(uint16_t)blocks);
if (ccb->ccb_slot == -1)
if (error == -1)
goto error;
if (ISSET(xs->flags, SCSI_POLL)) {
@ -1668,7 +1635,6 @@ ufshci_scsi_sync(struct scsi_xfer *xs)
error:
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_done = NULL;
xs->error = XS_DRIVER_STUFFUP;
@ -1708,11 +1674,10 @@ ufshci_scsi_io(struct scsi_xfer *xs, int dir)
ccb->ccb_done = ufshci_scsi_io_done;
if (dir == SCSI_DATA_IN)
ccb->ccb_slot = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_IN);
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_IN);
else
ccb->ccb_slot = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_OUT);
if (ccb->ccb_slot == -1)
error = ufshci_utr_cmd_io(sc, ccb, xs, SCSI_DATA_OUT);
if (error == -1)
goto error2;
if (ISSET(xs->flags, SCSI_POLL)) {
@ -1728,7 +1693,6 @@ ufshci_scsi_io(struct scsi_xfer *xs, int dir)
error2:
bus_dmamap_unload(sc->sc_dmat, dmap);
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_done = NULL;
error1:
xs->error = XS_DRIVER_STUFFUP;
@ -1740,6 +1704,8 @@ ufshci_scsi_io_done(struct ufshci_softc *sc, struct ufshci_ccb *ccb)
{
struct scsi_xfer *xs = ccb->ccb_cookie;
bus_dmamap_t dmap = ccb->ccb_dmamap;
struct ufshci_ucd *ucd;
struct ufshci_utrd *utrd;
bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
ISSET(xs->flags, SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
@ -1747,11 +1713,29 @@ ufshci_scsi_io_done(struct ufshci_softc *sc, struct ufshci_ccb *ccb)
bus_dmamap_unload(sc->sc_dmat, dmap);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * ccb->ccb_slot, sizeof(*ucd),
BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * ccb->ccb_slot, sizeof(*utrd),
BUS_DMASYNC_POSTWRITE);
/* TODO: Do more checks on the Response UPIU in case of errors? */
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += ccb->ccb_slot;
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += ccb->ccb_slot;
if (utrd->dw2 != UFSHCI_UTRD_DW2_OCS_SUCCESS) {
printf("%s: error: slot=%d, ocs=0x%x, rsp-tc=0x%x\n",
__func__, ccb->ccb_slot, utrd->dw2, ucd->rsp.hdr.tc);
}
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_status = CCB_STATUS_FREE;
ccb->ccb_done = NULL;
xs->error = XS_NOERROR;
xs->error = (utrd->dw2 == UFSHCI_UTRD_DW2_OCS_SUCCESS) ?
XS_NOERROR : XS_DRIVER_STUFFUP;
xs->status = SCSI_OK;
xs->resid = 0;
scsi_done(xs);
@ -1761,12 +1745,32 @@ void
ufshci_scsi_done(struct ufshci_softc *sc, struct ufshci_ccb *ccb)
{
struct scsi_xfer *xs = ccb->ccb_cookie;
struct ufshci_ucd *ucd;
struct ufshci_utrd *utrd;
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_ucd),
sizeof(*ucd) * ccb->ccb_slot, sizeof(*ucd),
BUS_DMASYNC_POSTWRITE);
bus_dmamap_sync(sc->sc_dmat, UFSHCI_DMA_MAP(sc->sc_dmamem_utrd),
sizeof(*utrd) * ccb->ccb_slot, sizeof(*utrd),
BUS_DMASYNC_POSTWRITE);
/* TODO: Do more checks on the Response UPIU in case of errors? */
utrd = UFSHCI_DMA_KVA(sc->sc_dmamem_utrd);
utrd += ccb->ccb_slot;
ucd = UFSHCI_DMA_KVA(sc->sc_dmamem_ucd);
ucd += ccb->ccb_slot;
if (utrd->dw2 != UFSHCI_UTRD_DW2_OCS_SUCCESS) {
printf("%s: error: slot=%d, ocs=0x%x, rsp-tc=0x%x\n",
__func__, ccb->ccb_slot, utrd->dw2, ucd->rsp.hdr.tc);
}
ccb->ccb_cookie = NULL;
ccb->ccb_slot = -1;
ccb->ccb_status = CCB_STATUS_FREE;
ccb->ccb_done = NULL;
xs->error = XS_NOERROR;
xs->error = (utrd->dw2 == UFSHCI_UTRD_DW2_OCS_SUCCESS) ?
XS_NOERROR : XS_DRIVER_STUFFUP;
xs->status = SCSI_OK;
xs->resid = 0;
scsi_done(xs);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ufshcireg.h,v 1.5 2024/04/19 20:43:33 mglocker Exp $ */
/* $OpenBSD: ufshcireg.h,v 1.7 2024/05/09 08:20:22 mglocker Exp $ */
/*
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@ -21,7 +21,6 @@
*/
#define UFSHCI_UCD_PRDT_MAX_SEGS 64
#define UFSHCI_UCD_PRDT_MAX_XFER (UFSHCI_UCD_PRDT_MAX_SEGS * PAGE_SIZE)
#define UFSHCI_INTR_AGGR_COUNT 1 /* Max. allowed value = 31 */
#define UFSHCI_INTR_AGGR_TIMEOUT 0x64 /* 4ms */
#define UFSHCI_MAX_UNITS 32
@ -257,7 +256,7 @@ struct ufshci_utrd {
uint32_t dw5; /* UTP Cmd. Desc. Base Addr. Upper 32-bits (UCDBAU) */
uint32_t dw6; /* RUO, RUL */
uint32_t dw7; /* PRDTO, PRDTL */
};
} __packed;
/*
* UTP Command Descriptor, PRDT (Physical Region Description Table) Structure
@ -274,7 +273,7 @@ struct ufshci_ucd_prdt {
uint32_t dw1; /* Data base Address Upper 32-bits (DBAU) */
uint32_t dw2; /* Reserved */
uint32_t dw3; /* Data Byte Count (DBC) */
};
} __packed;
/*
* UTP Task Management Request Descriptor Structure
@ -306,7 +305,7 @@ struct ufshci_utmrd {
uint32_t dw3; /* Reserved */
uint8_t dw4_w11[32]; /* Task Management Request UPIU */
uint8_t dw12_dw19[32]; /* Task Management Response UPIU */
};
} __packed;
/*
* ****************************************************************************
@ -344,19 +343,19 @@ struct upiu_hdr {
uint8_t ehs_len;
uint8_t device_info;
uint16_t ds_len; /* Data Segment Length */
};
} __packed;
struct upiu_command {
struct upiu_hdr hdr;
uint32_t expected_xfer_len;
uint8_t cdb[16];
};
} __packed;
struct upiu_response {
struct upiu_hdr hdr;
uint32_t residual_xfer_len;
uint8_t cdb[16];
};
} __packed;
struct ufshci_ucd {
struct upiu_command cmd;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: ufshcivar.h,v 1.1 2023/02/04 23:11:59 mglocker Exp $ */
/* $OpenBSD: ufshcivar.h,v 1.4 2024/05/09 08:06:42 mglocker Exp $ */
/*
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@ -40,6 +40,10 @@ struct ufshci_ccb {
bus_dmamap_t ccb_dmamap;
void *ccb_cookie;
int ccb_slot;
#define CCB_STATUS_FREE 0
#define CCB_STATUS_INPROGRESS 1
#define CCB_STATUS_READY2FREE 2
int ccb_status;
void (*ccb_done)(struct ufshci_softc *,
struct ufshci_ccb *);
};
@ -54,6 +58,8 @@ struct ufshci_softc {
bus_dma_tag_t sc_dmat;
uint8_t sc_intraggr_enabled;
uint8_t sc_iacth;
struct mutex sc_cmd_mtx;
uint32_t sc_ver;
uint32_t sc_cap;