summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2024-01-06 13:04:04 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2024-01-06 13:04:04 +0000
commitdb10ade1673a59c14afb9dba37aad19bb56e2acb (patch)
tree9629398e7c63657d138b9d5c700541b68466f1cd
parent8a3edbe0657f6d4edb98a6f3f982a65e6bda3e29 (diff)
Merge read/write UFS commands in to one single function, since they are very
similar.
-rw-r--r--sys/dev/ic/ufshci.c152
1 files changed, 22 insertions, 130 deletions
diff --git a/sys/dev/ic/ufshci.c b/sys/dev/ic/ufshci.c
index 8724a938148..64d9c2b6a91 100644
--- a/sys/dev/ic/ufshci.c
+++ b/sys/dev/ic/ufshci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ufshci.c,v 1.6 2024/01/04 21:35:56 mglocker Exp $ */
+/* $OpenBSD: ufshci.c,v 1.7 2024/01/06 13:04:03 mglocker Exp $ */
/*
* Copyright (c) 2022 Marcus Glocker <mglocker@openbsd.org>
@@ -75,12 +75,8 @@ int ufshci_utr_cmd_capacity16(struct ufshci_softc *,
struct ufshci_ccb *, int, int);
int ufshci_utr_cmd_capacity(struct ufshci_softc *,
struct ufshci_ccb *, int, int);
-int ufshci_utr_cmd_read(struct ufshci_softc *,
- struct ufshci_ccb *, int, int,
- struct scsi_generic *);
-int ufshci_utr_cmd_write(struct ufshci_softc *,
- struct ufshci_ccb *, int, int,
- struct scsi_generic *);
+int ufshci_utr_cmd_io(struct ufshci_softc *,
+ struct ufshci_ccb *, struct scsi_xfer *, int);
int ufshci_utr_cmd_sync(struct ufshci_softc *,
struct ufshci_ccb *, int, uint32_t, uint16_t);
int ufshci_xfer_complete(struct ufshci_softc *);
@@ -1061,8 +1057,8 @@ ufshci_utr_cmd_capacity(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
}
int
-ufshci_utr_cmd_read(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
- int rsp_size, int flags, struct scsi_generic *scsi_cmd)
+ufshci_utr_cmd_io(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
+ struct scsi_xfer *xs, int dir)
{
int slot, off, len, i;
uint64_t dva;
@@ -1080,115 +1076,10 @@ ufshci_utr_cmd_read(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */
- utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I;
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */
- 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);
- 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.cmd_set_type = 0; /* SCSI command */
- ucd->cmd.hdr.query = 0;
- ucd->cmd.hdr.response = 0;
- ucd->cmd.hdr.status = 0;
- ucd->cmd.hdr.ehs_len = 0;
- ucd->cmd.hdr.device_info = 0;
- ucd->cmd.hdr.ds_len = 0;
-
- ucd->cmd.expected_xfer_len = htobe32(rsp_size);
-
- memcpy(ucd->cmd.cdb, scsi_cmd, sizeof(ucd->cmd.cdb));
- //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 */
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 3) */
- dva = UFSHCI_DMA_DVA(sc->sc_dmamem_ucd) + (sizeof(*ucd) * slot);
- DPRINTF("%s: ucd dva=%llu\n", __func__, dva);
- utrd->dw4 = (uint32_t)dva;
- utrd->dw5 = (uint32_t)(dva >> 32);
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 4) */
- off = sizeof(struct upiu_command) / 4; /* DWORD offset */
- utrd->dw6 = UFSHCI_UTRD_DW6_RUO(off);
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 5) */
- len = sizeof(struct upiu_response) / 4; /* DWORD length */
- utrd->dw6 |= UFSHCI_UTRD_DW6_RUL(len);
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 6) */
- off = (sizeof(struct upiu_command) + sizeof(struct upiu_response)) / 4;
- utrd->dw7 = UFSHCI_UTRD_DW7_PRDTO(off);
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 7) */
- utrd->dw7 |= UFSHCI_UTRD_DW7_PRDTL(dmap->dm_nsegs);
-
- /* Build PRDT data segment. */
- for (i = 0; i < dmap->dm_nsegs; i++) {
- dva = dmap->dm_segs[i].ds_addr;
- ucd->prdt[i].dw0 = (uint32_t)dva;
- ucd->prdt[i].dw1 = (uint32_t)(dva >> 32);
- ucd->prdt[i].dw2 = 0;
- ucd->prdt[i].dw3 = dmap->dm_segs[i].ds_len - 1;
- }
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 9) */
- if (UFSHCI_READ_4(sc, UFSHCI_REG_UTRLRSR) != 1) {
- printf("%s: %s: UTRLRSR not set\n",
- sc->sc_dev.dv_xname, __func__);
- 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(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));
- }
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 14) */
- ufshci_doorbell_set(sc, slot);
-
- return slot;
-}
-
-int
-ufshci_utr_cmd_write(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
- int rsp_size, int flags, struct scsi_generic *scsi_cmd)
-{
- int slot, off, len, i;
- uint64_t dva;
- struct ufshci_utrd *utrd;
- struct ufshci_ucd *ucd;
- 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);
- memset(utrd, 0, sizeof(*utrd));
- DPRINTF("%s: slot=%d\n", __func__, slot);
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2a) */
- utrd->dw0 = UFSHCI_UTRD_DW0_CT_UFS;
-
- /* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2b) */
- utrd->dw0 |= UFSHCI_UTRD_DW0_DD_I2T;
+ if (dir == SCSI_DATA_IN)
+ utrd->dw0 |= UFSHCI_UTRD_DW0_DD_T2I;
+ else
+ utrd->dw0 |= UFSHCI_UTRD_DW0_DD_I2T;
/* 7.2.1 Basic Steps when Building a UTP Transfer Request: 2c) */
utrd->dw0 |= UFSHCI_UTRD_DW0_I_REG;
@@ -1202,7 +1093,10 @@ ufshci_utr_cmd_write(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
/* 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 << 5); /* Bit-5 = Write, Bit-6 = Read */
+ if (dir == SCSI_DATA_IN)
+ ucd->cmd.hdr.flags = (1 << 6); /* Bit-6 = Read */
+ 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.cmd_set_type = 0; /* SCSI command */
@@ -1213,10 +1107,11 @@ ufshci_utr_cmd_write(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
ucd->cmd.hdr.device_info = 0;
ucd->cmd.hdr.ds_len = 0;
- ucd->cmd.expected_xfer_len = htobe32(rsp_size);
+ ucd->cmd.expected_xfer_len = htobe32(xs->datalen);
- memcpy(ucd->cmd.cdb, scsi_cmd, sizeof(ucd->cmd.cdb));
- ucd->cmd.cdb[1] = (1 << 3); /* FUA: Force Unit Access */
+ 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 */
@@ -1262,7 +1157,7 @@ ufshci_utr_cmd_write(struct ufshci_softc *sc, struct ufshci_ccb *ccb,
/* 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(flags, SCSI_POLL)) {
+ if (!ISSET(xs->flags, SCSI_POLL)) {
UFSHCI_WRITE_4(sc, UFSHCI_REG_UTRIACR,
UFSHCI_REG_UTRIACR_IAEN |
UFSHCI_REG_UTRIACR_IAPWEN |
@@ -1822,13 +1717,10 @@ ufshci_scsi_io(struct scsi_xfer *xs, int dir)
ccb->ccb_cookie = xs;
ccb->ccb_done = ufshci_scsi_io_done;
- if (dir == SCSI_DATA_IN) {
- ccb->ccb_slot = ufshci_utr_cmd_read(sc, ccb, xs->datalen,
- xs->flags, &xs->cmd);
- } else {
- ccb->ccb_slot = ufshci_utr_cmd_write(sc, ccb, xs->datalen,
- xs->flags, &xs->cmd);
- }
+ if (dir == SCSI_DATA_IN)
+ ccb->ccb_slot = 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)
goto error2;