1 | /* $NetBSD: atwvar.h,v 1.37 2010/03/14 21:25:59 dyoung Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2003, 2004 The NetBSD Foundation, Inc. All rights reserved. |
5 | * |
6 | * This code is derived from software contributed to The NetBSD Foundation |
7 | * by David Young. |
8 | * |
9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions |
11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
19 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
20 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
21 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
22 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
28 | * POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
30 | |
31 | #ifndef _DEV_IC_ATWVAR_H_ |
32 | #define _DEV_IC_ATWVAR_H_ |
33 | |
34 | #include <sys/queue.h> |
35 | #include <sys/callout.h> |
36 | #include <sys/time.h> |
37 | |
38 | /* |
39 | * Transmit descriptor list size. This is arbitrary, but allocate |
40 | * enough descriptors for 64 pending transmissions and 16 segments |
41 | * per packet. Since a descriptor holds 2 buffer addresses, that's |
42 | * 8 descriptors per packet. This MUST work out to a power of 2. |
43 | */ |
44 | #define ATW_NTXSEGS 16 |
45 | |
46 | #define ATW_TXQUEUELEN 64 |
47 | #define ATW_NTXDESC (ATW_TXQUEUELEN * ATW_NTXSEGS) |
48 | #define ATW_NTXDESC_MASK (ATW_NTXDESC - 1) |
49 | #define ATW_NEXTTX(x) ((x + 1) & ATW_NTXDESC_MASK) |
50 | |
51 | /* |
52 | * Receive descriptor list size. We have one Rx buffer per incoming |
53 | * packet, so this logic is a little simpler. |
54 | */ |
55 | #define ATW_NRXDESC 64 |
56 | #define ATW_NRXDESC_MASK (ATW_NRXDESC - 1) |
57 | #define ATW_NEXTRX(x) ((x + 1) & ATW_NRXDESC_MASK) |
58 | |
59 | /* |
60 | * Control structures are DMA'd to the ADM8211 chip. We allocate them in |
61 | * a single clump that maps to a single DMA segment to make several things |
62 | * easier. |
63 | */ |
64 | struct atw_control_data { |
65 | /* |
66 | * The transmit descriptors. |
67 | */ |
68 | struct atw_txdesc acd_txdescs[ATW_NTXDESC]; |
69 | |
70 | /* |
71 | * The receive descriptors. |
72 | */ |
73 | struct atw_rxdesc acd_rxdescs[ATW_NRXDESC]; |
74 | }; |
75 | |
76 | #define ATW_CDOFF(x) offsetof(struct atw_control_data, x) |
77 | #define ATW_CDTXOFF(x) ATW_CDOFF(acd_txdescs[(x)]) |
78 | #define ATW_CDRXOFF(x) ATW_CDOFF(acd_rxdescs[(x)]) |
79 | /* |
80 | * Software state for transmit jobs. |
81 | */ |
82 | struct atw_txsoft { |
83 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ |
84 | bus_dmamap_t txs_dmamap; /* our DMA map */ |
85 | int txs_firstdesc; /* first descriptor in packet */ |
86 | int txs_lastdesc; /* last descriptor in packet */ |
87 | int txs_ndescs; /* number of descriptors */ |
88 | struct ieee80211_duration txs_d0; |
89 | struct ieee80211_duration txs_dn; |
90 | SIMPLEQ_ENTRY(atw_txsoft) txs_q; |
91 | }; |
92 | |
93 | SIMPLEQ_HEAD(atw_txsq, atw_txsoft); |
94 | |
95 | /* |
96 | * Software state for receive jobs. |
97 | */ |
98 | struct atw_rxsoft { |
99 | struct mbuf *rxs_mbuf; /* head of our mbuf chain */ |
100 | bus_dmamap_t rxs_dmamap; /* our DMA map */ |
101 | }; |
102 | |
103 | /* |
104 | * Table which describes the transmit threshold mode. We generally |
105 | * start at index 0. Whenever we get a transmit underrun, we increment |
106 | * our index, falling back if we encounter the NULL terminator. |
107 | */ |
108 | struct atw_txthresh_tab { |
109 | u_int32_t txth_opmode; /* OPMODE bits */ |
110 | const char *txth_name; /* name of mode */ |
111 | }; |
112 | |
113 | #define ATW_TXTHRESH_TAB_LO_RATE { \ |
114 | { ATW_NAR_TR_L64, "64 bytes" }, \ |
115 | { ATW_NAR_TR_L160, "160 bytes" }, \ |
116 | { ATW_NAR_TR_L192, "192 bytes" }, \ |
117 | { ATW_NAR_SF, "store and forward" }, \ |
118 | { 0, NULL }, \ |
119 | } |
120 | |
121 | #define ATW_TXTHRESH_TAB_HI_RATE { \ |
122 | { ATW_NAR_TR_H96, "96 bytes" }, \ |
123 | { ATW_NAR_TR_H288, "288 bytes" }, \ |
124 | { ATW_NAR_TR_H544, "544 bytes" }, \ |
125 | { ATW_NAR_SF, "store and forward" }, \ |
126 | { 0, NULL }, \ |
127 | } |
128 | |
129 | enum atw_rftype { ATW_RFTYPE_INTERSIL = 0, ATW_RFTYPE_RFMD = 1, |
130 | ATW_RFTYPE_MARVEL = 2 }; |
131 | |
132 | enum atw_bbptype { ATW_BBPTYPE_INTERSIL = 0, ATW_BBPTYPE_RFMD = 1, |
133 | ATW_BBPTYPE_MARVEL = 2, ATW_C_BBPTYPE_RFMD = 5 }; |
134 | |
135 | /* Radio capture format for ADMtek. */ |
136 | |
137 | #define ATW_RX_RADIOTAP_PRESENT \ |
138 | ((1 << IEEE80211_RADIOTAP_FLAGS) | (1 << IEEE80211_RADIOTAP_RATE) | \ |
139 | (1 << IEEE80211_RADIOTAP_CHANNEL) | \ |
140 | (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)) |
141 | |
142 | struct { |
143 | struct ieee80211_radiotap_header ; |
144 | uint8_t ; |
145 | uint8_t ; |
146 | uint16_t ; |
147 | uint16_t ; |
148 | uint8_t ; |
149 | } __packed; |
150 | |
151 | #define ATW_TX_RADIOTAP_PRESENT ((1 << IEEE80211_RADIOTAP_RATE) | \ |
152 | (1 << IEEE80211_RADIOTAP_CHANNEL)) |
153 | |
154 | struct { |
155 | struct ieee80211_radiotap_header ; |
156 | uint8_t ; |
157 | uint8_t ; |
158 | uint16_t ; |
159 | uint16_t ; |
160 | } __packed; |
161 | |
162 | enum atw_revision { |
163 | ATW_REVISION_AB = 0x11, /* ADM8211A */ |
164 | ATW_REVISION_AF = 0x15, /* ADM8211A? */ |
165 | ATW_REVISION_BA = 0x20, /* ADM8211B */ |
166 | ATW_REVISION_CA = 0x30 /* ADM8211C/CR */ |
167 | }; |
168 | |
169 | struct atw_softc { |
170 | device_t sc_dev; |
171 | device_suspensor_t sc_suspensor; |
172 | pmf_qual_t sc_qual; |
173 | |
174 | struct ethercom sc_ec; |
175 | struct ieee80211com sc_ic; |
176 | int (*sc_newstate)(struct ieee80211com *, |
177 | enum ieee80211_state, int); |
178 | void (*sc_recv_mgmt)(struct ieee80211com *, |
179 | struct mbuf *, struct ieee80211_node *, |
180 | int, int, u_int32_t); |
181 | struct ieee80211_node *(*sc_node_alloc)(struct ieee80211_node_table*); |
182 | void (*sc_node_free)(struct ieee80211_node *); |
183 | |
184 | int sc_tx_timer; |
185 | int sc_rescan_timer; |
186 | |
187 | bus_space_tag_t sc_st; /* bus space tag */ |
188 | bus_space_handle_t sc_sh; /* bus space handle */ |
189 | bus_dma_tag_t sc_dmat; /* bus dma tag */ |
190 | u_int32_t sc_cacheline; /* cache line size */ |
191 | u_int32_t sc_maxburst; /* maximum burst length */ |
192 | |
193 | const struct atw_txthresh_tab *sc_txth; |
194 | int sc_txthresh; /* current tx threshold */ |
195 | |
196 | u_int sc_cur_chan; /* current channel */ |
197 | |
198 | int sc_flags; |
199 | |
200 | u_int16_t *sc_srom; |
201 | u_int16_t sc_sromsz; |
202 | |
203 | struct bpf_if * sc_radiobpf; |
204 | |
205 | bus_dma_segment_t sc_cdseg; /* control data memory */ |
206 | int sc_cdnseg; /* number of segments */ |
207 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ |
208 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
209 | |
210 | /* |
211 | * Software state for transmit and receive descriptors. |
212 | */ |
213 | struct atw_txsoft sc_txsoft[ATW_TXQUEUELEN]; |
214 | struct atw_rxsoft sc_rxsoft[ATW_NRXDESC]; |
215 | |
216 | /* |
217 | * Control data structures. |
218 | */ |
219 | struct atw_control_data *sc_control_data; |
220 | #define sc_txdescs sc_control_data->acd_txdescs |
221 | #define sc_rxdescs sc_control_data->acd_rxdescs |
222 | #define sc_setup_desc sc_control_data->acd_setup_desc |
223 | |
224 | int sc_txfree; /* number of free Tx descriptors */ |
225 | int sc_txnext; /* next ready Tx descriptor */ |
226 | int sc_ntxsegs; /* number of transmit segs per pkt */ |
227 | |
228 | struct atw_txsq sc_txfreeq; /* free Tx descsofts */ |
229 | struct atw_txsq sc_txdirtyq; /* dirty Tx descsofts */ |
230 | |
231 | int sc_rxptr; /* next ready RX descriptor/descsoft */ |
232 | |
233 | u_int32_t sc_busmode; /* copy of ATW_PAR */ |
234 | u_int32_t sc_opmode; /* copy of ATW_NAR */ |
235 | u_int32_t sc_inten; /* copy of ATW_IER */ |
236 | u_int32_t sc_wepctl; /* copy of ATW_WEPCTL */ |
237 | |
238 | u_int32_t sc_rxint_mask; /* mask of Rx interrupts we want */ |
239 | u_int32_t sc_txint_mask; /* mask of Tx interrupts we want */ |
240 | u_int32_t sc_linkint_mask;/* link-state interrupts mask */ |
241 | |
242 | enum atw_rftype sc_rftype; |
243 | enum atw_bbptype sc_bbptype; |
244 | u_int32_t sc_synctl_rd; |
245 | u_int32_t sc_synctl_wr; |
246 | u_int32_t sc_bbpctl_rd; |
247 | u_int32_t sc_bbpctl_wr; |
248 | |
249 | void (*sc_recv_beacon)(struct ieee80211com *, struct mbuf *, |
250 | int, u_int32_t); |
251 | void (*sc_recv_prresp)(struct ieee80211com *, struct mbuf *, |
252 | int, u_int32_t); |
253 | |
254 | /* ADM8211 state variables. */ |
255 | u_int8_t sc_sram[ATW_SRAM_MAXSIZE]; |
256 | u_int sc_sramlen; |
257 | u_int8_t sc_bssid[IEEE80211_ADDR_LEN]; |
258 | uint8_t sc_rev; |
259 | uint8_t sc_rf3000_options1; |
260 | uint8_t sc_rf3000_options2; |
261 | |
262 | struct evcnt sc_misc_ev; |
263 | struct evcnt sc_workaround1_ev; |
264 | struct evcnt sc_rxamatch_ev; |
265 | struct evcnt sc_rxpkt1in_ev; |
266 | |
267 | struct evcnt sc_xmit_ev; |
268 | struct evcnt sc_tuf_ev; /* transmit underflow errors */ |
269 | struct evcnt sc_tro_ev; /* transmit overrun */ |
270 | struct evcnt sc_trt_ev; /* retry count exceeded */ |
271 | struct evcnt sc_tlt_ev; /* lifetime exceeded */ |
272 | struct evcnt sc_sofbr_ev; /* packet size mismatch */ |
273 | |
274 | struct evcnt sc_recv_ev; |
275 | struct evcnt sc_crc16e_ev; |
276 | struct evcnt sc_crc32e_ev; |
277 | struct evcnt sc_icve_ev; |
278 | struct evcnt sc_sfde_ev; |
279 | struct evcnt sc_sige_ev; |
280 | |
281 | struct callout sc_scan_ch; |
282 | union { |
283 | struct atw_rx_radiotap_header tap; |
284 | u_int8_t pad[64]; |
285 | } sc_rxtapu; |
286 | union { |
287 | struct atw_tx_radiotap_header tap; |
288 | u_int8_t pad[64]; |
289 | } sc_txtapu; |
290 | }; |
291 | |
292 | #define sc_if sc_ec.ec_if |
293 | #define sc_rxtap sc_rxtapu.tap |
294 | #define sc_txtap sc_txtapu.tap |
295 | |
296 | /* XXX this is fragile. try not to introduce any u_int32_t's. */ |
297 | struct atw_frame { |
298 | /*00*/ u_int8_t atw_dst[IEEE80211_ADDR_LEN]; |
299 | /*06*/ u_int8_t atw_rate; /* TX rate in 100Kbps */ |
300 | /*07*/ u_int8_t atw_service; /* 0 */ |
301 | /*08*/ u_int16_t atw_paylen; /* payload length */ |
302 | /*0a*/ u_int8_t atw_fc[2]; /* 802.11 Frame |
303 | * Control |
304 | */ |
305 | /* 802.11 PLCP Length for first & last fragment */ |
306 | /*0c*/ u_int16_t atw_tail_plcplen; |
307 | /*0e*/ u_int16_t atw_head_plcplen; |
308 | /* 802.11 Duration for first & last fragment */ |
309 | /*10*/ u_int16_t atw_tail_dur; |
310 | /*12*/ u_int16_t atw_head_dur; |
311 | /*14*/ u_int8_t atw_addr4[IEEE80211_ADDR_LEN]; |
312 | union { |
313 | struct { |
314 | /*1a*/ u_int16_t hdrctl; /*transmission control*/ |
315 | /*1c*/ u_int16_t fragthr;/* fragmentation threshold |
316 | * [0:11], zero [12:15]. |
317 | */ |
318 | /*1e*/ u_int8_t fragnum;/* fragment number [4:7], |
319 | * zero [0:3]. |
320 | */ |
321 | /*1f*/ u_int8_t rtylmt; /* retry limit */ |
322 | /*20*/ u_int8_t wepkey0[4];/* ??? */ |
323 | /*24*/ u_int8_t wepkey1[4];/* ??? */ |
324 | /*28*/ u_int8_t wepkey2[4];/* ??? */ |
325 | /*2c*/ u_int8_t wepkey3[4];/* ??? */ |
326 | /*30*/ u_int8_t keyid; |
327 | /*31*/ u_int8_t reserved0[7]; |
328 | } s1; |
329 | struct { |
330 | u_int8_t pad[6]; |
331 | struct ieee80211_frame ihdr; |
332 | } s2; |
333 | } u; |
334 | } __packed; |
335 | |
336 | #define atw_hdrctl u.s1.hdrctl |
337 | #define atw_fragthr u.s1.fragthr |
338 | #define atw_fragnum u.s1.fragnum |
339 | #define atw_rtylmt u.s1.rtylmt |
340 | #define atw_keyid u.s1.keyid |
341 | #define atw_ihdr u.s2.ihdr |
342 | |
343 | #define ATW_HDRCTL_SHORT_PREAMBLE __BIT(0) /* use short preamble */ |
344 | #define ATW_HDRCTL_MORE_FRAG __BIT(1) /* ??? from Linux */ |
345 | #define ATW_HDRCTL_MORE_DATA __BIT(2) /* ??? from Linux */ |
346 | #define ATW_HDRCTL_FRAG_NUM __BIT(3) /* ??? from Linux */ |
347 | #define ATW_HDRCTL_RTSCTS __BIT(4) /* send RTS */ |
348 | #define ATW_HDRCTL_WEP __BIT(5) |
349 | /* MAC adds FCS? Linux calls this "enable extended header" */ |
350 | #define ATW_HDRCTL_UNKNOWN1 __BIT(15) |
351 | #define ATW_HDRCTL_UNKNOWN2 __BIT(8) |
352 | |
353 | #define ATW_FRAGTHR_FRAGTHR_MASK __BITS(0, 11) |
354 | #define ATW_FRAGNUM_FRAGNUM_MASK __BITS(4, 7) |
355 | |
356 | /* Values for sc_flags. */ |
357 | #define ATWF_MRL 0x00000001 /* memory read line okay */ |
358 | #define ATWF_MRM 0x00000002 /* memory read multi okay */ |
359 | #define ATWF_MWI 0x00000004 /* memory write inval okay */ |
360 | #define ATWF_SHORT_PREAMBLE 0x00000008 /* short preamble enabled */ |
361 | #define ATWF_ATTACHED 0x00000010 /* attach has succeeded */ |
362 | #define ATWF_ENABLED 0x00000020 /* chip is enabled */ |
363 | #define ATWF_WEP_SRAM_VALID 0x00000040 /* SRAM matches s/w state */ |
364 | |
365 | #define ATW_CDTXADDR(sc, x) ((sc)->sc_cddma + ATW_CDTXOFF((x))) |
366 | #define ATW_CDRXADDR(sc, x) ((sc)->sc_cddma + ATW_CDRXOFF((x))) |
367 | |
368 | #define ATW_CDTXSYNC(sc, x, n, ops) \ |
369 | do { \ |
370 | int __x, __n; \ |
371 | \ |
372 | __x = (x); \ |
373 | __n = (n); \ |
374 | \ |
375 | /* If it will wrap around, sync to the end of the ring. */ \ |
376 | if ((__x + __n) > ATW_NTXDESC) { \ |
377 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
378 | ATW_CDTXOFF(__x), sizeof(struct atw_txdesc) * \ |
379 | (ATW_NTXDESC - __x), (ops)); \ |
380 | __n -= (ATW_NTXDESC - __x); \ |
381 | __x = 0; \ |
382 | } \ |
383 | \ |
384 | /* Now sync whatever is left. */ \ |
385 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
386 | ATW_CDTXOFF(__x), sizeof(struct atw_txdesc) * __n, (ops)); \ |
387 | } while (0) |
388 | |
389 | #define ATW_CDRXSYNC(sc, x, ops) \ |
390 | bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cddmamap, \ |
391 | ATW_CDRXOFF((x)), sizeof(struct atw_rxdesc), (ops)) |
392 | |
393 | /* |
394 | * Note we rely on MCLBYTES being a power of two. Because the `length' |
395 | * field is only 11 bits, we must subtract 1 from the length to avoid |
396 | * having it truncated to 0! |
397 | */ |
398 | static inline void |
399 | atw_init_rxdesc(struct atw_softc *sc, int x) |
400 | { |
401 | struct atw_rxsoft *rxs = &sc->sc_rxsoft[x]; |
402 | struct atw_rxdesc *rxd = &sc->sc_rxdescs[x]; |
403 | struct mbuf *m = rxs->rxs_mbuf; |
404 | |
405 | rxd->ar_buf1 = |
406 | htole32(rxs->rxs_dmamap->dm_segs[0].ds_addr); |
407 | rxd->ar_buf2 = /* for descriptor chaining */ |
408 | htole32(ATW_CDRXADDR((sc), ATW_NEXTRX(x))); |
409 | rxd->ar_ctlrssi = |
410 | htole32(__SHIFTIN(((m->m_ext.ext_size - 1) & ~0x3U), |
411 | ATW_RXCTL_RBS1_MASK) | |
412 | 0 /* ATW_RXCTL_RCH */ | |
413 | (x == (ATW_NRXDESC - 1) ? ATW_RXCTL_RER : 0)); |
414 | rxd->ar_stat = htole32(ATW_RXSTAT_OWN); |
415 | |
416 | ATW_CDRXSYNC((sc), x, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); |
417 | } |
418 | |
419 | /* country codes from ADM8211 SROM */ |
420 | #define ATW_COUNTRY_FCC 0 /* USA 1-11 */ |
421 | #define ATW_COUNTRY_IC 1 /* Canada 1-11 */ |
422 | #define ATW_COUNTRY_ETSI 2 /* European Union (?) 1-13 */ |
423 | #define ATW_COUNTRY_SPAIN 3 /* 10-11 */ |
424 | #define ATW_COUNTRY_FRANCE 4 /* 10-13 */ |
425 | #define ATW_COUNTRY_MKK 5 /* Japan: 14 */ |
426 | #define ATW_COUNTRY_MKK2 6 /* Japan: 1-14 */ |
427 | |
428 | /* |
429 | * register space access macros |
430 | */ |
431 | #define ATW_READ(sc, reg) \ |
432 | bus_space_read_4((sc)->sc_st, (sc)->sc_sh, (reg)) |
433 | |
434 | #define ATW_WRITE(sc, reg, val) \ |
435 | bus_space_write_4((sc)->sc_st, (sc)->sc_sh, (reg), (val)) |
436 | |
437 | #define ATW_SET(sc, reg, mask) \ |
438 | ATW_WRITE((sc), (reg), ATW_READ((sc), (reg)) | (mask)) |
439 | |
440 | #define ATW_CLR(sc, reg, mask) \ |
441 | ATW_WRITE((sc), (reg), ATW_READ((sc), (reg)) & ~(mask)) |
442 | |
443 | #define ATW_ISSET(sc, reg, mask) \ |
444 | (ATW_READ((sc), (reg)) & (mask)) |
445 | |
446 | void atw_attach(struct atw_softc *); |
447 | int atw_detach(struct atw_softc *); |
448 | int atw_activate(device_t, enum devact); |
449 | int atw_intr(void *arg); |
450 | bool atw_shutdown(device_t, int); |
451 | bool atw_suspend(device_t, const pmf_qual_t *); |
452 | |
453 | #endif /* _DEV_IC_ATWVAR_H_ */ |
454 | |