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
SQ_CDTXSYNC(struct sq_softc * sc,int __x,int __n,int ops)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
SQ_INIT_RXDESC(struct sq_softc * sc,unsigned int x)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