-/* $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>
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 *);
}
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;
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;
/* 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 */
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 */
/* 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 |
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;