if_casvar.h revision 1.7.2.1 1 /* $NetBSD: if_casvar.h,v 1.7.2.1 2020/02/29 20:19:10 ad Exp $ */
2 /* $OpenBSD: if_casvar.h,v 1.6 2009/06/13 12:18:58 kettenis Exp $ */
3
4 /*
5 *
6 * Copyright (C) 2007 Mark Kettenis.
7 * Copyright (C) 2001 Eduardo Horvath.
8 * All rights reserved.
9 *
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34 #ifndef _IF_CASVAR_H
35 #define _IF_CASVAR_H
36
37 #include <sys/queue.h>
38 #include <sys/callout.h>
39 #include <sys/rndsource.h>
40
41 /*
42 * Misc. definitions for Sun Cassini ethernet controllers.
43 */
44
45 /*
46 * Preferred page size. Cassini has a configurable page size, but
47 * needs at least 8k to handle jumbo frames. This happens to be the
48 * default anyway.
49 */
50 #define CAS_PAGE_SIZE 8192
51
52 /*
53 * Transmit descriptor ring size. This is arbitrary, but allocate
54 * enough descriptors for 64 pending transmissions and 16 segments
55 * per packet.
56 */
57 #define CAS_NTXSEGS 16
58
59 #define CAS_TXQUEUELEN 64
60 #define CAS_NTXDESC (CAS_TXQUEUELEN * CAS_NTXSEGS)
61 #define CAS_NTXDESC_MASK (CAS_NTXDESC - 1)
62 #define CAS_NEXTTX(x) ((x + 1) & CAS_NTXDESC_MASK)
63
64 struct cas_sxd {
65 struct mbuf *sd_mbuf;
66 bus_dmamap_t sd_map;
67 };
68
69 /*
70 * Receive descriptor ring size. We have one Rx buffer per incoming
71 * packet, so this logic is a little simpler.
72 */
73 #define CAS_NRXDESC 128
74 #define CAS_NRXDESC_MASK (CAS_NRXDESC - 1)
75
76 /*
77 * Receive completion ring size.
78 */
79 #define CAS_NRXCOMP 256
80 #define CAS_NRXCOMP_MASK (CAS_NRXCOMP - 1)
81 #define CAS_NEXTRX(x) ((x + 1) & CAS_NRXCOMP_MASK)
82
83 /*
84 * Control structures are DMA'd to the Cassini chip. We allocate them in
85 * a single clump that maps to a single DMA segment to make several things
86 * easier.
87 */
88 struct cas_control_data {
89 /*
90 * The transmit descriptors.
91 */
92 struct cas_desc ccd_txdescs[CAS_NTXDESC];
93
94 /*
95 * The receive completions.
96 */
97 struct cas_comp ccd_rxcomps[CAS_NRXCOMP];
98
99 /*
100 * The receive descriptors.
101 */
102 struct cas_desc ccd_rxdescs[CAS_NRXDESC];
103 char ccd_unused[CAS_PAGE_SIZE - CAS_NRXDESC * 16];
104 struct cas_desc ccd_rxdescs2[CAS_NRXDESC];
105 };
106
107 #define CAS_CDOFF(x) offsetof(struct cas_control_data, x)
108 #define CAS_CDTXOFF(x) CAS_CDOFF(ccd_txdescs[(x)])
109 #define CAS_CDRXOFF(x) CAS_CDOFF(ccd_rxdescs[(x)])
110 #define CAS_CDRXOFF2(x) CAS_CDOFF(ccd_rxdescs2[(x)])
111 #define CAS_CDRXCOFF(x) CAS_CDOFF(ccd_rxcomps[(x)])
112
113 /*
114 * Software state for receive jobs.
115 */
116 struct cas_rxsoft {
117 bus_dmamap_t rxs_dmamap; /* our DMA map */
118 bus_dma_segment_t rxs_dmaseg; /* our DMA segment */
119 char *rxs_kva;
120 };
121
122 enum cas_attach_stage {
123 CAS_ATT_BACKEND_2 = 0
124 , CAS_ATT_BACKEND_1
125 , CAS_ATT_FINISHED
126 , CAS_ATT_MII
127 , CAS_ATT_7
128 , CAS_ATT_6
129 , CAS_ATT_5
130 , CAS_ATT_4
131 , CAS_ATT_3
132 , CAS_ATT_2
133 , CAS_ATT_1
134 , CAS_ATT_0
135 , CAS_ATT_BACKEND_0
136 };
137
138 /*
139 * Software state per device.
140 */
141 struct cas_softc {
142 device_t sc_dev; /* generic device information */
143 struct ethercom sc_ethercom; /* ethernet common data */
144 struct mii_data sc_mii; /* MII media control */
145 #define sc_media sc_mii.mii_media/* shorthand */
146 struct callout sc_tick_ch; /* tick callout */
147
148 bus_space_tag_t sc_memt;
149 bus_space_handle_t sc_memh;
150 bus_size_t sc_size;
151
152 void *sc_ih;
153 pci_chipset_tag_t sc_pc;
154 pci_intr_handle_t sc_handle;
155
156 bus_dma_tag_t sc_dmatag; /* bus dma tag */
157 bus_dmamap_t sc_dmamap; /* bus dma handle */
158 int sc_burst; /* DVMA burst size in effect */
159 int sc_phys[2]; /* MII instance -> PHY map */
160
161 u_int sc_variant;
162 #define CAS_UNKNOWN 0 /* don't know */
163 #define CAS_CAS 1 /* Sun Cassini */
164 #if 0 /* notyet */
165 #define CAS_CASPLUS 2 /* Sun Cassini+ */
166 #endif
167 #define CAS_SATURN 3 /* National Semiconductor Saturn */
168
169 u_int sc_flags;
170 #define CAS_SERDES (1 << 4) /* use the SERDES */
171
172 int sc_mif_config; /* Selected MII reg setting */
173
174 /*
175 * Ring buffer DMA stuff.
176 */
177 bus_dma_segment_t sc_cdseg; /* control data memory */
178 int sc_cdnseg; /* number of segments */
179 bus_dmamap_t sc_cddmamap; /* control data DMA map */
180 #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr
181
182 /*
183 * Software state for transmit and receive descriptors.
184 */
185 struct cas_sxd sc_txd[CAS_NTXDESC];
186 uint32_t sc_tx_cnt, sc_tx_prod, sc_tx_cons;
187
188 struct cas_rxsoft sc_rxsoft[CAS_NRXDESC];
189 struct cas_rxsoft sc_rxsoft2[CAS_NRXDESC];
190
191 /*
192 * Control data structures.
193 */
194 struct cas_control_data *sc_control_data;
195 #define sc_txdescs sc_control_data->ccd_txdescs
196 #define sc_rxdescs sc_control_data->ccd_rxdescs
197 #define sc_rxdescs2 sc_control_data->ccd_rxdescs2
198 #define sc_rxcomps sc_control_data->ccd_rxcomps
199
200 int sc_rxptr; /* next ready RX descriptor/descsoft */
201 int sc_rxfifosize;
202 int sc_rxdptr;
203
204 int sc_rev;
205 int sc_inited;
206 int sc_debug;
207 void *sc_sh; /* shutdownhook cookie */
208
209 krndsource_t rnd_source;
210
211 struct evcnt sc_ev_intr;
212 enum cas_attach_stage sc_att_stage;
213 };
214
215 /*
216 * This maccro determines whether we have a Cassini+.
217 */
218 #define CAS_PLUS(sc) (sc->sc_rev > 0x10)
219
220 #define CAS_DMA_READ(v) le64toh(v)
221 #define CAS_DMA_WRITE(v) htole64(v)
222
223 #define CAS_CDTXADDR(sc, x) ((sc)->sc_cddma + CAS_CDTXOFF((x)))
224 #define CAS_CDRXADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXOFF((x)))
225 #define CAS_CDRXADDR2(sc, x) ((sc)->sc_cddma + CAS_CDRXOFF2((x)))
226 #define CAS_CDRXCADDR(sc, x) ((sc)->sc_cddma + CAS_CDRXCOFF((x)))
227
228 #define CAS_CDTXSYNC(sc, x, n, ops) \
229 do { \
230 int __x, __n; \
231 \
232 __x = (x); \
233 __n = (n); \
234 \
235 /* If it will wrap around, sync to the end of the ring. */ \
236 if ((__x + __n) > CAS_NTXDESC) { \
237 bus_dmamap_sync((sc)->sc_dmatag, (sc)->sc_cddmamap, \
238 CAS_CDTXOFF(__x), sizeof(struct cas_desc) * \
239 (CAS_NTXDESC - __x), (ops)); \
240 __n -= (CAS_NTXDESC - __x); \
241 __x = 0; \
242 } \
243 \
244 /* Now sync whatever is left. */ \
245 bus_dmamap_sync((sc)->sc_dmatag, (sc)->sc_cddmamap, \
246 CAS_CDTXOFF(__x), sizeof(struct cas_desc) * __n, (ops)); \
247 } while (0)
248
249 #define CAS_CDRXSYNC(sc, x, ops) \
250 bus_dmamap_sync((sc)->sc_dmatag, (sc)->sc_cddmamap, \
251 CAS_CDRXOFF((x)), sizeof(struct cas_desc), (ops))
252
253 #define CAS_CDRXCSYNC(sc, x, ops) \
254 bus_dmamap_sync((sc)->sc_dmatag, (sc)->sc_cddmamap, \
255 CAS_CDRXCOFF((x)), sizeof(struct cas_desc), (ops))
256
257 #define CAS_INIT_RXDESC(sc, d, s) \
258 do { \
259 struct cas_rxsoft *__rxs = &sc->sc_rxsoft[(s)]; \
260 struct cas_desc *__rxd = &sc->sc_rxdescs[(d)]; \
261 \
262 __rxd->cd_addr = \
263 CAS_DMA_WRITE(__rxs->rxs_dmamap->dm_segs[0].ds_addr); \
264 __rxd->cd_flags = \
265 CAS_DMA_WRITE((s)); \
266 CAS_CDRXSYNC((sc), (d), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
267 } while (0)
268
269 #define CAS_INTR_PCI 1
270 #define CAS_INTR_REG 2
271
272 #endif
273