sync with OpenBSD -current
This commit is contained in:
parent
01ab08895c
commit
492219ffd1
35 changed files with 666 additions and 546 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue