1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright © 2026 Dmitry Salychev 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 30 #include <sys/param.h> 31 #include <sys/errno.h> 32 33 #include <vm/vm.h> 34 #include <vm/pmap.h> 35 36 #include <machine/vmparam.h> 37 38 #include "dpaa2_types.h" 39 #include "dpaa2_frame.h" 40 #include "dpaa2_buf.h" 41 #include "dpaa2_swp.h" 42 43 /** 44 * @brief Build a DPAA2 frame descriptor. 45 */ 46 int 47 dpaa2_fd_build(device_t dev, const uint16_t tx_data_off, struct dpaa2_buf *buf, 48 bus_dma_segment_t *segs, const int nsegs, struct dpaa2_fd *fd) 49 { 50 struct dpaa2_buf *sgt = buf->sgt; 51 struct dpaa2_sg_entry *sge; 52 struct dpaa2_swa *swa; 53 int i, error; 54 55 if (buf == NULL || segs == NULL || nsegs == 0 || fd == NULL) 56 return (EINVAL); 57 58 KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); 59 KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); 60 KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); 61 KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); 62 63 memset(fd, 0, sizeof(*fd)); 64 65 /* Populate and map S/G table */ 66 if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { 67 sge = (struct dpaa2_sg_entry *)sgt->vaddr + tx_data_off; 68 for (i = 0; i < nsegs; i++) { 69 sge[i].addr = (uint64_t)segs[i].ds_addr; 70 sge[i].len = (uint32_t)segs[i].ds_len; 71 sge[i].offset_fmt = 0u; 72 } 73 sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ 74 75 KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, 76 sgt->paddr)); 77 78 error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, 79 DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, 80 BUS_DMA_NOWAIT); 81 if (__predict_false(error != 0)) { 82 device_printf(dev, "%s: bus_dmamap_load() failed: " 83 "error=%d\n", __func__, error); 84 return (error); 85 } 86 87 buf->paddr = sgt->paddr; 88 buf->vaddr = sgt->vaddr; 89 } else { 90 return (EINVAL); 91 } 92 93 swa = (struct dpaa2_swa *)sgt->vaddr; 94 swa->magic = DPAA2_MAGIC; 95 swa->buf = buf; 96 97 fd->addr = buf->paddr; 98 fd->data_length = (uint32_t)buf->m->m_pkthdr.len; 99 fd->bpid_ivp_bmt = 0; 100 fd->offset_fmt_sl = 0x2000u | tx_data_off; 101 fd->ctrl = (0x4u & DPAA2_FD_PTAC_MASK) << DPAA2_FD_PTAC_SHIFT; 102 103 return (0); 104 } 105 106 int 107 dpaa2_fd_err(struct dpaa2_fd *fd) 108 { 109 return ((fd->ctrl >> DPAA2_FD_ERR_SHIFT) & DPAA2_FD_ERR_MASK); 110 } 111 112 uint32_t 113 dpaa2_fd_data_len(struct dpaa2_fd *fd) 114 { 115 if (dpaa2_fd_short_len(fd)) { 116 return (fd->data_length & DPAA2_FD_LEN_MASK); 117 } 118 return (fd->data_length); 119 } 120 121 int 122 dpaa2_fd_format(struct dpaa2_fd *fd) 123 { 124 return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> 125 DPAA2_FD_FMT_SHIFT) & DPAA2_FD_FMT_MASK)); 126 } 127 128 bool 129 dpaa2_fd_short_len(struct dpaa2_fd *fd) 130 { 131 return (((fd->offset_fmt_sl >> DPAA2_FD_SL_SHIFT) 132 & DPAA2_FD_SL_MASK) == 1); 133 } 134 135 int 136 dpaa2_fd_offset(struct dpaa2_fd *fd) 137 { 138 return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK); 139 } 140 141 int 142 dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa) 143 { 144 int rc; 145 146 if (fd == NULL || swa == NULL) 147 return (EINVAL); 148 149 if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_MASK) >= 0x4u) { 150 *swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr); 151 rc = 0; 152 } else { 153 *swa = NULL; 154 rc = ENOENT; 155 } 156 157 return (rc); 158 } 159 160 int 161 dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa) 162 { 163 /* TODO: To be implemented next. */ 164 return (ENOENT); 165 } 166