1 /* $NetBSD: sqvar.h,v 1.15 2015/04/13 21:18:42 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Rafal K. Boni 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef _ARCH_SGIMIPS_HPC_SQVAR_H_ 31 #define _ARCH_SGIMIPS_HPC_SQVAR_H_ 32 33 #include <sys/queue.h> 34 #include <sys/callout.h> 35 36 #include <sys/rndsource.h> 37 38 #include <sgimips/hpc/hpcvar.h> 39 #include <sgimips/hpc/hpcreg.h> 40 41 /* Note, these must be powers of two for the magic NEXT/PREV macros to work */ 42 #define SQ_NRXDESC 64 43 #define SQ_NTXDESC 64 44 45 #define SQ_NRXDESC_MASK (SQ_NRXDESC - 1) 46 #define SQ_NEXTRX(x) ((x + 1) & SQ_NRXDESC_MASK) 47 #define SQ_PREVRX(x) ((x - 1) & SQ_NRXDESC_MASK) 48 49 #define SQ_NTXDESC_MASK (SQ_NTXDESC - 1) 50 #define SQ_NEXTTX(x) ((x + 1) & SQ_NTXDESC_MASK) 51 #define SQ_PREVTX(x) ((x - 1) & SQ_NTXDESC_MASK) 52 53 /* 54 * We pack all DMA control structures into one container so we can alloc just 55 * one chunk of DMA-safe memory and pack them into it. Otherwise, we'd have to 56 * allocate a page for each descriptor, since the bus_dmamem_alloc() interface 57 * does not allow us to allocate smaller chunks. 58 */ 59 struct sq_control { 60 /* Receive descriptors */ 61 struct hpc_dma_desc rx_desc[SQ_NRXDESC]; 62 63 /* Transmit descriptors */ 64 struct hpc_dma_desc tx_desc[SQ_NTXDESC]; 65 }; 66 67 #define SQ_CDOFF(x) offsetof(struct sq_control, x) 68 #define SQ_CDTXOFF(x) SQ_CDOFF(tx_desc[(x)]) 69 #define SQ_CDRXOFF(x) SQ_CDOFF(rx_desc[(x)]) 70 71 #define SQ_TYPE_8003 0 72 #define SQ_TYPE_80C03 1 73 74 /* Trace Actions */ 75 #define SQ_RESET 1 76 #define SQ_ADD_TO_DMA 2 77 #define SQ_START_DMA 3 78 #define SQ_DONE_DMA 4 79 #define SQ_RESTART_DMA 5 80 #define SQ_TXINTR_ENTER 6 81 #define SQ_TXINTR_EXIT 7 82 #define SQ_TXINTR_BUSY 8 83 #define SQ_IOCTL 9 84 #define SQ_ENQUEUE 10 85 86 struct sq_action_trace { 87 int action; 88 int line; 89 int bufno; 90 int status; 91 int freebuf; 92 }; 93 94 #define SQ_TRACEBUF_SIZE 100 95 96 #define SQ_TRACE(act, sc, buf, stat) do { \ 97 (sc)->sq_trace[(sc)->sq_trace_idx].action = (act); \ 98 (sc)->sq_trace[(sc)->sq_trace_idx].line = __LINE__; \ 99 (sc)->sq_trace[(sc)->sq_trace_idx].bufno = (buf); \ 100 (sc)->sq_trace[(sc)->sq_trace_idx].status = (stat); \ 101 (sc)->sq_trace[(sc)->sq_trace_idx].freebuf = (sc)->sc_nfreetx; \ 102 if (++(sc)->sq_trace_idx == SQ_TRACEBUF_SIZE) \ 103 (sc)->sq_trace_idx = 0; \ 104 } while (/* CONSTCOND */0) 105 106 struct sq_softc { 107 device_t sc_dev; 108 109 /* HPC registers */ 110 bus_space_tag_t sc_hpct; 111 bus_space_handle_t sc_hpch; 112 113 114 /* HPC external ethernet registers: aka Seeq 8003 registers */ 115 bus_space_tag_t sc_regt; 116 bus_space_handle_t sc_regh; 117 118 bus_dma_tag_t sc_dmat; 119 120 struct ethercom sc_ethercom; 121 uint8_t sc_enaddr[ETHER_ADDR_LEN]; 122 123 int sc_type; 124 125 struct sq_control* sc_control; 126 #define sc_rxdesc sc_control->rx_desc 127 #define sc_txdesc sc_control->tx_desc 128 129 /* DMA structures for control data (DMA RX/TX descriptors) */ 130 int sc_ncdseg; 131 bus_dma_segment_t sc_cdseg; 132 bus_dmamap_t sc_cdmap; 133 #define sc_cddma sc_cdmap->dm_segs[0].ds_addr 134 135 int sc_nextrx; 136 137 /* DMA structures for RX packet data */ 138 bus_dma_segment_t sc_rxseg[SQ_NRXDESC]; 139 bus_dmamap_t sc_rxmap[SQ_NRXDESC]; 140 struct mbuf* sc_rxmbuf[SQ_NRXDESC]; 141 142 int sc_nexttx; 143 int sc_prevtx; 144 int sc_nfreetx; 145 146 /* DMA structures for TX packet data */ 147 bus_dma_segment_t sc_txseg[SQ_NTXDESC]; 148 bus_dmamap_t sc_txmap[SQ_NTXDESC]; 149 struct mbuf* sc_txmbuf[SQ_NTXDESC]; 150 151 uint8_t sc_rxcmd; /* prototype rxcmd */ 152 153 struct evcnt sq_intrcnt; /* count interrupts */ 154 155 krndsource_t rnd_source; /* random source */ 156 struct hpc_values *hpc_regs; /* HPC register definitions */ 157 158 int sq_trace_idx; 159 struct sq_action_trace sq_trace[SQ_TRACEBUF_SIZE]; 160 }; 161 162 #define SQ_CDTXADDR(sc, x) ((sc)->sc_cddma + SQ_CDTXOFF((x))) 163 #define SQ_CDRXADDR(sc, x) ((sc)->sc_cddma + SQ_CDRXOFF((x))) 164 165 static inline void 166 SQ_CDTXSYNC(struct sq_softc *sc, int __x, int __n, int ops) 167 { 168 /* If it will wrap around, sync to the end of the ring. */ 169 if ((__x + __n) > SQ_NTXDESC) { 170 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, 171 SQ_CDTXOFF(__x), sizeof(struct hpc_dma_desc) * 172 (SQ_NTXDESC - __x), (ops)); 173 __n -= (SQ_NTXDESC - __x); 174 __x = 0; 175 } 176 177 /* Now sync whatever is left. */ 178 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, 179 SQ_CDTXOFF(__x), sizeof(struct hpc_dma_desc) * __n, (ops)); 180 } 181 182 #define SQ_CDRXSYNC(sc, x, ops) \ 183 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, \ 184 SQ_CDRXOFF((x)), sizeof(struct hpc_dma_desc), (ops)) 185 186 static inline void 187 SQ_INIT_RXDESC(struct sq_softc *sc, unsigned int x) 188 { 189 struct hpc_dma_desc* __rxd = &(sc)->sc_rxdesc[(x)]; 190 struct mbuf *__m = (sc)->sc_rxmbuf[(x)]; 191 192 __m->m_data = __m->m_ext.ext_buf; 193 if (sc->hpc_regs->revision == 3) { 194 __rxd->hpc3_hdd_bufptr = 195 (sc)->sc_rxmap[(x)]->dm_segs[0].ds_addr; 196 __rxd->hpc3_hdd_ctl = __m->m_ext.ext_size | HPC3_HDD_CTL_OWN | 197 HPC3_HDD_CTL_INTR | HPC3_HDD_CTL_EOPACKET | 198 ((x) == (SQ_NRXDESC - 1) ? HPC3_HDD_CTL_EOCHAIN : 0); 199 } else { 200 __rxd->hpc1_hdd_bufptr = 201 (sc)->sc_rxmap[(x)]->dm_segs[0].ds_addr | 202 ((x) == (SQ_NRXDESC - 1) ? HPC1_HDD_CTL_EOCHAIN : 0); 203 __rxd->hpc1_hdd_ctl = __m->m_ext.ext_size | HPC1_HDD_CTL_OWN | 204 HPC1_HDD_CTL_INTR | HPC1_HDD_CTL_EOPACKET; 205 } 206 __rxd->hdd_descptr = SQ_CDRXADDR((sc), SQ_NEXTRX((x))); 207 SQ_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 208 } 209 210 #endif /* _ARCH_SGIMIPS_HPC_SQVAR_H_ */ 211