1 /* $NetBSD: sqvar.h,v 1.12 2011/01/25 13:12:39 tsutsui 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 "rnd.h" 34 35 #include <sys/queue.h> 36 #include <sys/callout.h> 37 38 #if NRND > 0 39 #include <sys/rnd.h> 40 #endif 41 42 #include <sgimips/hpc/hpcvar.h> 43 #include <sgimips/hpc/hpcreg.h> 44 45 /* Note, these must be powers of two for the magic NEXT/PREV macros to work */ 46 #define SQ_NRXDESC 64 47 #define SQ_NTXDESC 64 48 49 #define SQ_NRXDESC_MASK (SQ_NRXDESC - 1) 50 #define SQ_NEXTRX(x) ((x + 1) & SQ_NRXDESC_MASK) 51 #define SQ_PREVRX(x) ((x - 1) & SQ_NRXDESC_MASK) 52 53 #define SQ_NTXDESC_MASK (SQ_NTXDESC - 1) 54 #define SQ_NEXTTX(x) ((x + 1) & SQ_NTXDESC_MASK) 55 #define SQ_PREVTX(x) ((x - 1) & SQ_NTXDESC_MASK) 56 57 /* 58 * We pack all DMA control structures into one container so we can alloc just 59 * one chunk of DMA-safe memory and pack them into it. Otherwise, we'd have to 60 * allocate a page for each descriptor, since the bus_dmamem_alloc() interface 61 * does not allow us to allocate smaller chunks. 62 */ 63 struct sq_control { 64 /* Receive descriptors */ 65 struct hpc_dma_desc rx_desc[SQ_NRXDESC]; 66 67 /* Transmit descriptors */ 68 struct hpc_dma_desc tx_desc[SQ_NTXDESC]; 69 }; 70 71 #define SQ_CDOFF(x) offsetof(struct sq_control, x) 72 #define SQ_CDTXOFF(x) SQ_CDOFF(tx_desc[(x)]) 73 #define SQ_CDRXOFF(x) SQ_CDOFF(rx_desc[(x)]) 74 75 #define SQ_TYPE_8003 0 76 #define SQ_TYPE_80C03 1 77 78 /* Trace Actions */ 79 #define SQ_RESET 1 80 #define SQ_ADD_TO_DMA 2 81 #define SQ_START_DMA 3 82 #define SQ_DONE_DMA 4 83 #define SQ_RESTART_DMA 5 84 #define SQ_TXINTR_ENTER 6 85 #define SQ_TXINTR_EXIT 7 86 #define SQ_TXINTR_BUSY 8 87 #define SQ_IOCTL 9 88 #define SQ_ENQUEUE 10 89 90 struct sq_action_trace { 91 int action; 92 int line; 93 int bufno; 94 int status; 95 int freebuf; 96 }; 97 98 #define SQ_TRACEBUF_SIZE 100 99 100 #define SQ_TRACE(act, sc, buf, stat) do { \ 101 (sc)->sq_trace[(sc)->sq_trace_idx].action = (act); \ 102 (sc)->sq_trace[(sc)->sq_trace_idx].line = __LINE__; \ 103 (sc)->sq_trace[(sc)->sq_trace_idx].bufno = (buf); \ 104 (sc)->sq_trace[(sc)->sq_trace_idx].status = (stat); \ 105 (sc)->sq_trace[(sc)->sq_trace_idx].freebuf = (sc)->sc_nfreetx; \ 106 if (++(sc)->sq_trace_idx == SQ_TRACEBUF_SIZE) \ 107 (sc)->sq_trace_idx = 0; \ 108 } while (/* CONSTCOND */0) 109 110 struct sq_softc { 111 device_t sc_dev; 112 113 /* HPC registers */ 114 bus_space_tag_t sc_hpct; 115 bus_space_handle_t sc_hpch; 116 117 118 /* HPC external ethernet registers: aka Seeq 8003 registers */ 119 bus_space_tag_t sc_regt; 120 bus_space_handle_t sc_regh; 121 122 bus_dma_tag_t sc_dmat; 123 124 struct ethercom sc_ethercom; 125 uint8_t sc_enaddr[ETHER_ADDR_LEN]; 126 127 int sc_type; 128 129 struct sq_control* sc_control; 130 #define sc_rxdesc sc_control->rx_desc 131 #define sc_txdesc sc_control->tx_desc 132 133 /* DMA structures for control data (DMA RX/TX descriptors) */ 134 int sc_ncdseg; 135 bus_dma_segment_t sc_cdseg; 136 bus_dmamap_t sc_cdmap; 137 #define sc_cddma sc_cdmap->dm_segs[0].ds_addr 138 139 int sc_nextrx; 140 141 /* DMA structures for RX packet data */ 142 bus_dma_segment_t sc_rxseg[SQ_NRXDESC]; 143 bus_dmamap_t sc_rxmap[SQ_NRXDESC]; 144 struct mbuf* sc_rxmbuf[SQ_NRXDESC]; 145 146 int sc_nexttx; 147 int sc_prevtx; 148 int sc_nfreetx; 149 150 /* DMA structures for TX packet data */ 151 bus_dma_segment_t sc_txseg[SQ_NTXDESC]; 152 bus_dmamap_t sc_txmap[SQ_NTXDESC]; 153 struct mbuf* sc_txmbuf[SQ_NTXDESC]; 154 155 uint8_t sc_rxcmd; /* prototype rxcmd */ 156 157 struct evcnt sq_intrcnt; /* count interrupts */ 158 159 #if NRND > 0 160 rndsource_element_t rnd_source; /* random source */ 161 #endif 162 struct hpc_values *hpc_regs; /* HPC register definitions */ 163 164 int sq_trace_idx; 165 struct sq_action_trace sq_trace[SQ_TRACEBUF_SIZE]; 166 }; 167 168 #define SQ_CDTXADDR(sc, x) ((sc)->sc_cddma + SQ_CDTXOFF((x))) 169 #define SQ_CDRXADDR(sc, x) ((sc)->sc_cddma + SQ_CDRXOFF((x))) 170 171 static inline void 172 SQ_CDTXSYNC(struct sq_softc *sc, int __x, int __n, int ops) 173 { 174 /* If it will wrap around, sync to the end of the ring. */ 175 if ((__x + __n) > SQ_NTXDESC) { 176 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, 177 SQ_CDTXOFF(__x), sizeof(struct hpc_dma_desc) * 178 (SQ_NTXDESC - __x), (ops)); 179 __n -= (SQ_NTXDESC - __x); 180 __x = 0; 181 } 182 183 /* Now sync whatever is left. */ 184 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, 185 SQ_CDTXOFF(__x), sizeof(struct hpc_dma_desc) * __n, (ops)); 186 } 187 188 #define SQ_CDRXSYNC(sc, x, ops) \ 189 bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, \ 190 SQ_CDRXOFF((x)), sizeof(struct hpc_dma_desc), (ops)) 191 192 static inline void 193 SQ_INIT_RXDESC(struct sq_softc *sc, unsigned int x) 194 { 195 struct hpc_dma_desc* __rxd = &(sc)->sc_rxdesc[(x)]; 196 struct mbuf *__m = (sc)->sc_rxmbuf[(x)]; 197 198 __m->m_data = __m->m_ext.ext_buf; 199 if (sc->hpc_regs->revision == 3) { 200 __rxd->hpc3_hdd_bufptr = 201 (sc)->sc_rxmap[(x)]->dm_segs[0].ds_addr; 202 __rxd->hpc3_hdd_ctl = __m->m_ext.ext_size | HPC3_HDD_CTL_OWN | 203 HPC3_HDD_CTL_INTR | HPC3_HDD_CTL_EOPACKET | 204 ((x) == (SQ_NRXDESC - 1) ? HPC3_HDD_CTL_EOCHAIN : 0); 205 } else { 206 __rxd->hpc1_hdd_bufptr = 207 (sc)->sc_rxmap[(x)]->dm_segs[0].ds_addr | 208 ((x) == (SQ_NRXDESC - 1) ? HPC1_HDD_CTL_EOCHAIN : 0); 209 __rxd->hpc1_hdd_ctl = __m->m_ext.ext_size | HPC1_HDD_CTL_OWN | 210 HPC1_HDD_CTL_INTR | HPC1_HDD_CTL_EOPACKET; 211 } 212 __rxd->hdd_descptr = SQ_CDRXADDR((sc), SQ_NEXTRX((x))); 213 SQ_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 214 } 215 216 #endif /* _ARCH_SGIMIPS_HPC_SQVAR_H_ */ 217