Line data Source code
1 : /* $OpenBSD: if_tht.c,v 1.140 2017/01/22 10:17:38 dlg Exp $ */
2 :
3 : /*
4 : * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
5 : *
6 : * Permission to use, copy, modify, and distribute this software for any
7 : * purpose with or without fee is hereby granted, provided that the above
8 : * copyright notice and this permission notice appear in all copies.
9 : *
10 : * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 : * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 : */
18 :
19 : /*
20 : * Driver for the Tehuti TN30xx multi port 10Gb Ethernet chipsets,
21 : * see http://www.tehutinetworks.net/.
22 : *
23 : * This driver was made possible because Tehuti networks provided
24 : * hardware and documentation. Thanks!
25 : */
26 :
27 : #include "bpfilter.h"
28 :
29 : #include <sys/param.h>
30 : #include <sys/systm.h>
31 : #include <sys/sockio.h>
32 : #include <sys/mbuf.h>
33 : #include <sys/kernel.h>
34 : #include <sys/socket.h>
35 : #include <sys/malloc.h>
36 : #include <sys/device.h>
37 : #include <sys/timeout.h>
38 : #include <sys/queue.h>
39 : #include <sys/rwlock.h>
40 : #include <sys/time.h>
41 :
42 : #include <machine/bus.h>
43 :
44 : #include <dev/pci/pcireg.h>
45 : #include <dev/pci/pcivar.h>
46 : #include <dev/pci/pcidevs.h>
47 :
48 : #include <net/if.h>
49 : #include <net/if_media.h>
50 :
51 : #if NBPFILTER > 0
52 : #include <net/bpf.h>
53 : #endif
54 :
55 : #include <netinet/in.h>
56 : #include <netinet/if_ether.h>
57 :
58 : #ifdef THT_DEBUG
59 : #define THT_D_FIFO (1<<0)
60 : #define THT_D_TX (1<<1)
61 : #define THT_D_RX (1<<2)
62 : #define THT_D_INTR (1<<3)
63 :
64 : int thtdebug = THT_D_TX | THT_D_RX | THT_D_INTR;
65 :
66 : #define DPRINTF(l, f...) do { if (thtdebug & (l)) printf(f); } while (0)
67 : #else
68 : #define DPRINTF(l, f...)
69 : #endif
70 :
71 : /* registers */
72 :
73 : #define THT_PCI_BAR 0x10
74 :
75 : #define _Q(_q) ((_q) * 4)
76 :
77 : /* General Configuration */
78 : #define THT_REG_END_SEL 0x5448 /* PCI Endian Select */
79 : #define THT_REG_CLKPLL 0x5000
80 : #define THT_REG_CLKPLL_PLLLK (1<<9) /* PLL is locked */
81 : #define THT_REG_CLKPLL_RSTEND (1<<8) /* Reset ended */
82 : #define THT_REG_CLKPLL_TXF_DIS (1<<3) /* TX Free disabled */
83 : #define THT_REG_CLKPLL_VNT_STOP (1<<2) /* VENETO Stop */
84 : #define THT_REG_CLKPLL_PLLRST (1<<1) /* PLL Reset */
85 : #define THT_REG_CLKPLL_SFTRST (1<<0) /* Software Reset */
86 : /* Descriptors and FIFO Registers */
87 : #define THT_REG_TXT_CFG0(_q) (0x4040 + _Q(_q)) /* CFG0 TX Task queues */
88 : #define THT_REG_RXF_CFG0(_q) (0x4050 + _Q(_q)) /* CFG0 RX Free queues */
89 : #define THT_REG_RXD_CFG0(_q) (0x4060 + _Q(_q)) /* CFG0 RX DSC queues */
90 : #define THT_REG_TXF_CFG0(_q) (0x4070 + _Q(_q)) /* CFG0 TX Free queues */
91 : #define THT_REG_TXT_CFG1(_q) (0x4000 + _Q(_q)) /* CFG1 TX Task queues */
92 : #define THT_REG_RXF_CFG1(_q) (0x4010 + _Q(_q)) /* CFG1 RX Free queues */
93 : #define THT_REG_RXD_CFG1(_q) (0x4020 + _Q(_q)) /* CFG1 RX DSC queues */
94 : #define THT_REG_TXF_CFG1(_q) (0x4030 + _Q(_q)) /* CFG1 TX Free queues */
95 : #define THT_REG_TXT_RPTR(_q) (0x40c0 + _Q(_q)) /* TX Task read ptr */
96 : #define THT_REG_RXF_RPTR(_q) (0x40d0 + _Q(_q)) /* RX Free read ptr */
97 : #define THT_REG_RXD_RPTR(_q) (0x40e0 + _Q(_q)) /* RX DSC read ptr */
98 : #define THT_REG_TXF_RPTR(_q) (0x40f0 + _Q(_q)) /* TX Free read ptr */
99 : #define THT_REG_TXT_WPTR(_q) (0x4080 + _Q(_q)) /* TX Task write ptr */
100 : #define THT_REG_RXF_WPTR(_q) (0x4090 + _Q(_q)) /* RX Free write ptr */
101 : #define THT_REG_RXD_WPTR(_q) (0x40a0 + _Q(_q)) /* RX DSC write ptr */
102 : #define THT_REG_TXF_WPTR(_q) (0x40b0 + _Q(_q)) /* TX Free write ptr */
103 : #define THT_REG_HTB_ADDR 0x4100 /* HTB Addressing Mechanism enable */
104 : #define THT_REG_HTB_ADDR_HI 0x4110 /* High HTB Address */
105 : #define THT_REG_HTB_ST_TMR 0x3290 /* HTB Timer */
106 : #define THT_REG_RDINTCM(_q) (0x5120 + _Q(_q)) /* RX DSC Intr Coalescing */
107 : #define THT_REG_RDINTCM_PKT_TH(_c) ((_c)<<20) /* pkt count threshold */
108 : #define THT_REG_RDINTCM_RXF_TH(_c) ((_c)<<16) /* rxf intr req thresh */
109 : #define THT_REG_RDINTCM_COAL_RC (1<<15) /* coalescing timer recharge */
110 : #define THT_REG_RDINTCM_COAL(_c) (_c) /* coalescing timer */
111 : #define THT_REG_TDINTCM(_q) (0x5130 + _Q(_q)) /* TX DSC Intr Coalescing */
112 : #define THT_REG_TDINTCM_PKT_TH(_c) ((_c)<<20) /* pkt count threshold */
113 : #define THT_REG_TDINTCM_COAL_RC (1<<15) /* coalescing timer recharge */
114 : #define THT_REG_TDINTCM_COAL(_c) (_c) /* coalescing timer */
115 : /* 10G Ethernet MAC */
116 : #define THT_REG_10G_REV 0x6000 /* Revision */
117 : #define THT_REG_10G_SCR 0x6004 /* Scratch */
118 : #define THT_REG_10G_CTL 0x6008 /* Control/Status */
119 : #define THT_REG_10G_CTL_CMD_FRAME_EN (1<<13) /* cmd frame enable */
120 : #define THT_REG_10G_CTL_SW_RESET (1<<12) /* sw reset */
121 : #define THT_REG_10G_CTL_STATS_AUTO_CLR (1<<11) /* auto clear statistics */
122 : #define THT_REG_10G_CTL_LOOPBACK (1<<10) /* enable loopback */
123 : #define THT_REG_10G_CTL_TX_ADDR_INS (1<<9) /* set mac on tx */
124 : #define THT_REG_10G_CTL_PAUSE_IGNORE (1<<8) /* ignore pause */
125 : #define THT_REG_10G_CTL_PAUSE_FWD (1<<7) /* forward pause */
126 : #define THT_REG_10G_CTL_CRC_FWD (1<<6) /* crc forward */
127 : #define THT_REG_10G_CTL_PAD (1<<5) /* frame padding */
128 : #define THT_REG_10G_CTL_PROMISC (1<<4) /* promiscuous mode */
129 : #define THT_REG_10G_CTL_WAN_MODE (1<<3) /* WAN mode */
130 : #define THT_REG_10G_CTL_RX_EN (1<<1) /* RX enable */
131 : #define THT_REG_10G_CTL_TX_EN (1<<0) /* TX enable */
132 : #define THT_REG_10G_FRM_LEN 0x6014 /* Frame Length */
133 : #define THT_REG_10G_PAUSE 0x6018 /* Pause Quanta */
134 : #define THT_REG_10G_RX_SEC 0x601c /* RX Section */
135 : #define THT_REG_10G_TX_SEC 0x6020 /* TX Section */
136 : #define THT_REG_10G_SEC_AVAIL(_t) (_t) /* section available thresh*/
137 : #define THT_REG_10G_SEC_EMPTY(_t) ((_t)<<16) /* section empty avail */
138 : #define THT_REG_10G_RFIFO_AEF 0x6024 /* RX FIFO Almost Empty/Full */
139 : #define THT_REG_10G_TFIFO_AEF 0x6028 /* TX FIFO Almost Empty/Full */
140 : #define THT_REG_10G_FIFO_AE(_t) (_t) /* almost empty */
141 : #define THT_REG_10G_FIFO_AF(_t) ((_t)<<16) /* almost full */
142 : #define THT_REG_10G_SM_STAT 0x6030 /* MDIO Status */
143 : #define THT_REG_10G_SM_CMD 0x6034 /* MDIO Command */
144 : #define THT_REG_10G_SM_DAT 0x6038 /* MDIO Data */
145 : #define THT_REG_10G_SM_ADD 0x603c /* MDIO Address */
146 : #define THT_REG_10G_STAT 0x6040 /* Status */
147 : /* Statistic Counters */
148 : /* XXX todo */
149 : /* Status Registers */
150 : #define THT_REG_MAC_LNK_STAT 0x0200 /* Link Status */
151 : #define THT_REG_MAC_LNK_STAT_DIS (1<<4) /* Mac Stats read disable */
152 : #define THT_REG_MAC_LNK_STAT_LINK (1<<2) /* Link State */
153 : #define THT_REG_MAC_LNK_STAT_REM_FAULT (1<<1) /* Remote Fault */
154 : #define THT_REG_MAC_LNK_STAT_LOC_FAULT (1<<0) /* Local Fault */
155 : /* Interrupt Registers */
156 : #define THT_REG_ISR 0x5100 /* Interrupt Status */
157 : #define THT_REG_ISR_LINKCHG(_p) (1<<(27+(_p))) /* link changed */
158 : #define THT_REG_ISR_GPIO (1<<26) /* GPIO */
159 : #define THT_REG_ISR_RFRSH (1<<25) /* DDR Refresh */
160 : #define THT_REG_ISR_SWI (1<<23) /* software interrupt */
161 : #define THT_REG_ISR_RXF(_q) (1<<(19+(_q))) /* rx free fifo */
162 : #define THT_REG_ISR_TXF(_q) (1<<(15+(_q))) /* tx free fifo */
163 : #define THT_REG_ISR_RXD(_q) (1<<(11+(_q))) /* rx desc fifo */
164 : #define THT_REG_ISR_TMR(_t) (1<<(6+(_t))) /* timer */
165 : #define THT_REG_ISR_VNT (1<<5) /* optistrata */
166 : #define THT_REG_ISR_RxFL (1<<4) /* RX Full */
167 : #define THT_REG_ISR_TR (1<<2) /* table read */
168 : #define THT_REG_ISR_PCIE_LNK_INT (1<<1) /* pcie link fail */
169 : #define THT_REG_ISR_GPLE_CLR (1<<0) /* pcie timeout */
170 : #define THT_FMT_ISR "\020" "\035LINKCHG1" "\034LINKCHG0" \
171 : "\033GPIO" "\032RFRSH" "\030SWI" \
172 : "\027RXF3" "\026RXF2" "\025RXF1" \
173 : "\024RXF0" "\023TXF3" "\022TXF2" \
174 : "\021TXF1" "\020TXF0" "\017RXD3" \
175 : "\016RXD2" "\015RXD1" "\014RXD0" \
176 : "\012TMR3" "\011TMR2" "\010TMR1" \
177 : "\007TMR0" "\006VNT" "\005RxFL" \
178 : "\003TR" "\002PCI_LNK_INT" \
179 : "\001GPLE_CLR"
180 : #define THT_REG_ISR_GTI 0x5080 /* GTI Interrupt Status */
181 : #define THT_REG_IMR 0x5110 /* Interrupt Mask */
182 : #define THT_REG_IMR_LINKCHG(_p) (1<<(27+(_p))) /* link changed */
183 : #define THT_REG_IMR_GPIO (1<<26) /* GPIO */
184 : #define THT_REG_IMR_RFRSH (1<<25) /* DDR Refresh */
185 : #define THT_REG_IMR_SWI (1<<23) /* software interrupt */
186 : #define THT_REG_IMR_RXF(_q) (1<<(19+(_q))) /* rx free fifo */
187 : #define THT_REG_IMR_TXF(_q) (1<<(15+(_q))) /* tx free fifo */
188 : #define THT_REG_IMR_RXD(_q) (1<<(11+(_q))) /* rx desc fifo */
189 : #define THT_REG_IMR_TMR(_t) (1<<(6+(_t))) /* timer */
190 : #define THT_REG_IMR_VNT (1<<5) /* optistrata */
191 : #define THT_REG_IMR_RxFL (1<<4) /* RX Full */
192 : #define THT_REG_IMR_TR (1<<2) /* table read */
193 : #define THT_REG_IMR_PCIE_LNK_INT (1<<1) /* pcie link fail */
194 : #define THT_REG_IMR_GPLE_CLR (1<<0) /* pcie timeout */
195 : #define THT_REG_IMR_GTI 0x5090 /* GTI Interrupt Mask */
196 : #define THT_REG_ISR_MSK 0x5140 /* ISR Masked */
197 : /* Global Counters */
198 : /* XXX todo */
199 : /* DDR2 SDRAM Controller Registers */
200 : /* XXX TBD */
201 : /* EEPROM Registers */
202 : /* XXX todo */
203 : /* Init arbitration and status registers */
204 : #define THT_REG_INIT_SEMAPHORE 0x5170 /* Init Semaphore */
205 : #define THT_REG_INIT_STATUS 0x5180 /* Init Status */
206 : /* PCI Credits Registers */
207 : /* XXX todo */
208 : /* TX Arbitration Registers */
209 : #define THT_REG_TXTSK_PR(_q) (0x41b0 + _Q(_q)) /* TX Queue Priority */
210 : /* RX Part Registers */
211 : #define THT_REG_RX_FLT 0x1240 /* RX Filter Configuration */
212 : #define THT_REG_RX_FLT_ATXER (1<<15) /* accept with xfer err */
213 : #define THT_REG_RX_FLT_ATRM (1<<14) /* accept with term err */
214 : #define THT_REG_RX_FLT_AFTSQ (1<<13) /* accept with fault seq */
215 : #define THT_REG_RX_FLT_OSEN (1<<12) /* enable pkts */
216 : #define THT_REG_RX_FLT_APHER (1<<11) /* accept with phy err */
217 : #define THT_REG_RX_FLT_TXFC (1<<10) /* TX flow control */
218 : #define THT_REG_RX_FLT_FDA (1<<8) /* filter direct address */
219 : #define THT_REG_RX_FLT_AOF (1<<7) /* accept overflow frame */
220 : #define THT_REG_RX_FLT_ACF (1<<6) /* accept control frame */
221 : #define THT_REG_RX_FLT_ARUNT (1<<5) /* accept runt */
222 : #define THT_REG_RX_FLT_ACRC (1<<4) /* accept crc error */
223 : #define THT_REG_RX_FLT_AM (1<<3) /* accept multicast */
224 : #define THT_REG_RX_FLT_AB (1<<2) /* accept broadcast */
225 : #define THT_REG_RX_FLT_PRM_MASK 0x3 /* promiscuous mode */
226 : #define THT_REG_RX_FLT_PRM_NORMAL 0x0 /* normal mode */
227 : #define THT_REG_RX_FLT_PRM_ALL 0x1 /* pass all incoming frames */
228 : #define THT_REG_RX_MAX_FRAME 0x12c0 /* Max Frame Size */
229 : #define THT_REG_RX_UNC_MAC0 0x1250 /* MAC Address low word */
230 : #define THT_REG_RX_UNC_MAC1 0x1260 /* MAC Address mid word */
231 : #define THT_REG_RX_UNC_MAC2 0x1270 /* MAC Address high word */
232 : #define THT_REG_RX_MAC_MCST0(_m) (0x1a80 + (_m)*8)
233 : #define THT_REG_RX_MAC_MCST1(_m) (0x1a84 + (_m)*8)
234 : #define THT_REG_RX_MAC_MCST_CNT 15
235 : #define THT_REG_RX_MCST_HASH 0x1a00 /* imperfect multicast filter hash */
236 : #define THT_REG_RX_MCST_HASH_SIZE (256 / NBBY)
237 : /* OptiStrata Debug Registers */
238 : #define THT_REG_VPC 0x2300 /* Program Counter */
239 : #define THT_REG_VLI 0x2310 /* Last Interrupt */
240 : #define THT_REG_VIC 0x2320 /* Interrupts Count */
241 : #define THT_REG_VTMR 0x2330 /* Timer */
242 : #define THT_REG_VGLB 0x2340 /* Global */
243 : /* SW Reset Registers */
244 : #define THT_REG_RST_PRT 0x7000 /* Reset Port */
245 : #define THT_REG_RST_PRT_ACTIVE 0x1 /* port reset is active */
246 : #define THT_REG_DIS_PRT 0x7010 /* Disable Port */
247 : #define THT_REG_RST_QU_0 0x7020 /* Reset Queue 0 */
248 : #define THT_REG_RST_QU_1 0x7028 /* Reset Queue 1 */
249 : #define THT_REG_DIS_QU_0 0x7030 /* Disable Queue 0 */
250 : #define THT_REG_DIS_QU_1 0x7038 /* Disable Queue 1 */
251 :
252 : #define THT_PORT_SIZE 0x8000
253 : #define THT_PORT_REGION(_p) ((_p) * THT_PORT_SIZE)
254 : #define THT_NQUEUES 4
255 :
256 : #define THT_FIFO_ALIGN 4096
257 : #define THT_FIFO_SIZE_4k 0x0
258 : #define THT_FIFO_SIZE_8k 0x1
259 : #define THT_FIFO_SIZE_16k 0x2
260 : #define THT_FIFO_SIZE_32k 0x3
261 : #define THT_FIFO_SIZE(_r) (4096 * (1<<(_r)))
262 : #define THT_FIFO_GAP 8 /* keep 8 bytes between ptrs */
263 : #define THT_FIFO_PTR_MASK 0x00007ff8 /* rptr/wptr mask */
264 :
265 : #define THT_FIFO_DESC_LEN 208 /* a descriptor cant be bigger than this */
266 :
267 : #define THT_IMR_DOWN(_p) (THT_REG_IMR_LINKCHG(_p))
268 : #define THT_IMR_UP(_p) (THT_REG_IMR_LINKCHG(_p) | \
269 : THT_REG_IMR_RXF(0) | THT_REG_IMR_TXF(0) | \
270 : THT_REG_IMR_RXD(0))
271 :
272 : /* hardware structures (we're using the 64 bit variants) */
273 :
274 : /* physical buffer descriptor */
275 : struct tht_pbd {
276 : u_int32_t addr_lo;
277 : u_int32_t addr_hi;
278 : u_int32_t len;
279 : } __packed;
280 : #define THT_PBD_PKTLEN (64 * 1024)
281 :
282 : /* rx free fifo */
283 : struct tht_rx_free {
284 : u_int16_t bc; /* buffer count (0:4) */
285 : u_int16_t type;
286 :
287 : u_int64_t uid;
288 :
289 : /* followed by a pdb list */
290 : } __packed;
291 : #define THT_RXF_TYPE 1
292 : #define THT_RXF_1ST_PDB_LEN 128
293 : #define THT_RXF_SGL_LEN ((THT_FIFO_DESC_LEN - \
294 : sizeof(struct tht_rx_free)) / \
295 : sizeof(struct tht_pbd))
296 : #define THT_RXF_PKT_NUM 128
297 :
298 : /* rx descriptor */
299 : struct tht_rx_desc {
300 : u_int32_t flags;
301 : #define THT_RXD_FLAGS_BC(_f) ((_f) & 0x1f) /* buffer count */
302 : #define THT_RXD_FLAGS_RXFQ(_f) (((_f)>>8) & 0x3) /* rxf queue id */
303 : #define THT_RXD_FLAGS_TO (1<<15)
304 : #define THT_RXD_FLAGS_TYPE(_f) (((_f)>>16) & 0xf) /* desc type */
305 : #define THT_RXD_FLAGS_OVF (1<<21) /* overflow error */
306 : #define THT_RXD_FLAGS_RUNT (1<<22) /* runt error */
307 : #define THT_RXD_FLAGS_CRC (1<<23) /* crc error */
308 : #define THT_RXD_FLAGS_UDPCS (1<<24) /* udp checksum error */
309 : #define THT_RXD_FLAGS_TCPCS (1<<25) /* tcp checksum error */
310 : #define THT_RXD_FLAGS_IPCS (1<<26) /* ip checksum error */
311 : #define THT_RXD_FLAGS_PKT_ID 0x70000000
312 : #define THT_RXD_FLAGS_PKT_ID_NONIP 0x00000000
313 : #define THT_RXD_FLAGS_PKT_ID_TCP4 0x10000000
314 : #define THT_RXD_FLAGS_PKT_ID_UDP4 0x20000000
315 : #define THT_RXD_FLAGS_PKT_ID_IPV4 0x30000000
316 : #define THT_RXD_FLAGS_PKT_ID_TCP6 0x50000000
317 : #define THT_RXD_FLAGS_PKT_ID_UDP6 0x60000000
318 : #define THT_RXD_FLAGS_PKT_ID_IPV6 0x70000000
319 : #define THT_RXD_FLAGS_VTAG (1<<31)
320 : u_int16_t len;
321 : u_int16_t vlan;
322 : #define THT_RXD_VLAN_ID(_v) ((_v) & 0xfff)
323 : #define THT_RXD_VLAN_CFI (1<<12)
324 : #define THT_RXD_VLAN_PRI(_v) ((_v) & 0x7) >> 13)
325 :
326 : u_int64_t uid;
327 : } __packed;
328 : #define THT_RXD_TYPE 2
329 :
330 : /* rx decriptor type 3: data chain instruction */
331 : struct tht_rx_desc_dc {
332 : /* preceded by tht_rx_desc */
333 :
334 : u_int16_t cd_offset;
335 : u_int16_t flags;
336 :
337 : u_int8_t data[4];
338 : } __packed;
339 : #define THT_RXD_TYPE_DC 3
340 :
341 : /* rx descriptor type 4: rss (recv side scaling) information */
342 : struct tht_rx_desc_rss {
343 : /* preceded by tht_rx_desc */
344 :
345 : u_int8_t rss_hft;
346 : u_int8_t rss_type;
347 : u_int8_t rss_tcpu;
348 : u_int8_t reserved;
349 :
350 : u_int32_t rss_hash;
351 : } __packed;
352 : #define THT_RXD_TYPE_RSS 4
353 :
354 : /* tx task fifo */
355 : struct tht_tx_task {
356 : u_int32_t flags;
357 : #define THT_TXT_FLAGS_BC(_f) (_f) /* buffer count */
358 : #define THT_TXT_FLAGS_UDPCS (1<<5) /* udp checksum */
359 : #define THT_TXT_FLAGS_TCPCS (1<<6) /* tcp checksum */
360 : #define THT_TXT_FLAGS_IPCS (1<<7) /* ip checksum */
361 : #define THT_TXT_FLAGS_VTAG (1<<8) /* insert vlan tag */
362 : #define THT_TXT_FLAGS_LGSND (1<<9) /* tcp large send enabled */
363 : #define THT_TXT_FLAGS_FRAG (1<<10) /* ip fragmentation enabled */
364 : #define THT_TXT_FLAGS_CFI (1<<12) /* canonical format indicator */
365 : #define THT_TXT_FLAGS_PRIO(_f) ((_f)<<13) /* vlan priority */
366 : #define THT_TXT_FLAGS_VLAN(_f) ((_f)<<20) /* vlan id */
367 : u_int16_t mss_mtu;
368 : u_int16_t len;
369 :
370 : u_int64_t uid;
371 :
372 : /* followed by a pbd list */
373 : } __packed;
374 : #define THT_TXT_TYPE (3<<16)
375 : #define THT_TXT_SGL_LEN ((THT_FIFO_DESC_LEN - \
376 : sizeof(struct tht_tx_task)) / \
377 : sizeof(struct tht_pbd))
378 : #define THT_TXT_PKT_NUM 128
379 :
380 : /* tx free fifo */
381 : struct tht_tx_free {
382 : u_int32_t status;
383 :
384 : u_int64_t uid;
385 :
386 : u_int32_t pad;
387 : } __packed;
388 :
389 : /* pci controller autoconf glue */
390 :
391 : struct thtc_softc {
392 : struct device sc_dev;
393 :
394 : bus_dma_tag_t sc_dmat;
395 :
396 : bus_space_tag_t sc_memt;
397 : bus_space_handle_t sc_memh;
398 : bus_size_t sc_mems;
399 : void *sc_ih;
400 : };
401 :
402 : int thtc_match(struct device *, void *, void *);
403 : void thtc_attach(struct device *, struct device *, void *);
404 : int thtc_print(void *, const char *);
405 :
406 : struct cfattach thtc_ca = {
407 : sizeof(struct thtc_softc), thtc_match, thtc_attach
408 : };
409 :
410 : struct cfdriver thtc_cd = {
411 : NULL, "thtc", DV_DULL
412 : };
413 :
414 : /* glue between the controller and the port */
415 :
416 : struct tht_attach_args {
417 : int taa_port;
418 :
419 : struct pci_attach_args *taa_pa;
420 : };
421 :
422 : /* tht itself */
423 :
424 : struct tht_dmamem {
425 : bus_dmamap_t tdm_map;
426 : bus_dma_segment_t tdm_seg;
427 : size_t tdm_size;
428 : caddr_t tdm_kva;
429 : };
430 : #define THT_DMA_MAP(_tdm) ((_tdm)->tdm_map)
431 : #define THT_DMA_DVA(_tdm) ((_tdm)->tdm_map->dm_segs[0].ds_addr)
432 : #define THT_DMA_KVA(_tdm) ((void *)(_tdm)->tdm_kva)
433 :
434 : struct tht_fifo_desc {
435 : bus_size_t tfd_cfg0;
436 : bus_size_t tfd_cfg1;
437 : bus_size_t tfd_rptr;
438 : bus_size_t tfd_wptr;
439 : u_int32_t tfd_size;
440 : int tfd_write;
441 : };
442 : #define THT_FIFO_PRE_SYNC(_d) ((_d)->tfd_write ? \
443 : BUS_DMASYNC_PREWRITE : \
444 : BUS_DMASYNC_PREREAD)
445 : #define THT_FIFO_POST_SYNC(_d) ((_d)->tfd_write ? \
446 : BUS_DMASYNC_POSTWRITE : \
447 : BUS_DMASYNC_POSTREAD)
448 :
449 : struct tht_fifo {
450 : struct tht_fifo_desc *tf_desc;
451 : struct tht_dmamem *tf_mem;
452 : int tf_len;
453 : int tf_rptr;
454 : int tf_wptr;
455 : int tf_ready;
456 : };
457 :
458 : struct tht_pkt {
459 : u_int64_t tp_id;
460 :
461 : bus_dmamap_t tp_dmap;
462 : struct mbuf *tp_m;
463 :
464 : TAILQ_ENTRY(tht_pkt) tp_link;
465 : };
466 :
467 : struct tht_pkt_list {
468 : struct tht_pkt *tpl_pkts;
469 : TAILQ_HEAD(, tht_pkt) tpl_free;
470 : TAILQ_HEAD(, tht_pkt) tpl_used;
471 : };
472 :
473 : struct tht_softc {
474 : struct device sc_dev;
475 : struct thtc_softc *sc_thtc;
476 : int sc_port;
477 :
478 : bus_space_handle_t sc_memh;
479 :
480 : struct arpcom sc_ac;
481 : struct ifmedia sc_media;
482 : struct timeval sc_mediacheck;
483 :
484 : u_int16_t sc_lladdr[3];
485 :
486 : struct tht_pkt_list sc_tx_list;
487 : struct tht_pkt_list sc_rx_list;
488 :
489 : struct tht_fifo sc_txt;
490 : struct tht_fifo sc_rxf;
491 : struct tht_fifo sc_rxd;
492 : struct tht_fifo sc_txf;
493 :
494 : u_int32_t sc_imr;
495 :
496 : struct rwlock sc_lock;
497 : };
498 :
499 : int tht_match(struct device *, void *, void *);
500 : void tht_attach(struct device *, struct device *, void *);
501 : void tht_mountroot(struct device *);
502 : int tht_intr(void *);
503 :
504 : struct cfattach tht_ca = {
505 : sizeof(struct tht_softc), tht_match, tht_attach
506 : };
507 :
508 : struct cfdriver tht_cd = {
509 : NULL, "tht", DV_IFNET
510 : };
511 :
512 : /* pkts */
513 : int tht_pkt_alloc(struct tht_softc *,
514 : struct tht_pkt_list *, int, int);
515 : void tht_pkt_free(struct tht_softc *,
516 : struct tht_pkt_list *);
517 : void tht_pkt_put(struct tht_pkt_list *, struct tht_pkt *);
518 : struct tht_pkt *tht_pkt_get(struct tht_pkt_list *);
519 : struct tht_pkt *tht_pkt_used(struct tht_pkt_list *);
520 :
521 : /* fifos */
522 :
523 : struct tht_fifo_desc tht_txt_desc = {
524 : THT_REG_TXT_CFG0(0),
525 : THT_REG_TXT_CFG1(0),
526 : THT_REG_TXT_RPTR(0),
527 : THT_REG_TXT_WPTR(0),
528 : THT_FIFO_SIZE_16k,
529 : 1
530 : };
531 :
532 : struct tht_fifo_desc tht_rxf_desc = {
533 : THT_REG_RXF_CFG0(0),
534 : THT_REG_RXF_CFG1(0),
535 : THT_REG_RXF_RPTR(0),
536 : THT_REG_RXF_WPTR(0),
537 : THT_FIFO_SIZE_16k,
538 : 1
539 : };
540 :
541 : struct tht_fifo_desc tht_rxd_desc = {
542 : THT_REG_RXD_CFG0(0),
543 : THT_REG_RXD_CFG1(0),
544 : THT_REG_RXD_RPTR(0),
545 : THT_REG_RXD_WPTR(0),
546 : THT_FIFO_SIZE_16k,
547 : 0
548 : };
549 :
550 : struct tht_fifo_desc tht_txf_desc = {
551 : THT_REG_TXF_CFG0(0),
552 : THT_REG_TXF_CFG1(0),
553 : THT_REG_TXF_RPTR(0),
554 : THT_REG_TXF_WPTR(0),
555 : THT_FIFO_SIZE_4k,
556 : 0
557 : };
558 :
559 : int tht_fifo_alloc(struct tht_softc *, struct tht_fifo *,
560 : struct tht_fifo_desc *);
561 : void tht_fifo_free(struct tht_softc *, struct tht_fifo *);
562 :
563 : size_t tht_fifo_readable(struct tht_softc *,
564 : struct tht_fifo *);
565 : size_t tht_fifo_writable(struct tht_softc *,
566 : struct tht_fifo *);
567 : void tht_fifo_pre(struct tht_softc *,
568 : struct tht_fifo *);
569 : void tht_fifo_read(struct tht_softc *, struct tht_fifo *,
570 : void *, size_t);
571 : void tht_fifo_write(struct tht_softc *, struct tht_fifo *,
572 : void *, size_t);
573 : void tht_fifo_write_dmap(struct tht_softc *,
574 : struct tht_fifo *, bus_dmamap_t);
575 : void tht_fifo_write_pad(struct tht_softc *,
576 : struct tht_fifo *, int);
577 : void tht_fifo_post(struct tht_softc *,
578 : struct tht_fifo *);
579 :
580 : /* port operations */
581 : void tht_lladdr_read(struct tht_softc *);
582 : void tht_lladdr_write(struct tht_softc *);
583 : int tht_sw_reset(struct tht_softc *);
584 : int tht_fw_load(struct tht_softc *);
585 : void tht_fw_tick(void *arg);
586 : void tht_link_state(struct tht_softc *);
587 :
588 : /* interface operations */
589 : int tht_ioctl(struct ifnet *, u_long, caddr_t);
590 : void tht_watchdog(struct ifnet *);
591 : void tht_start(struct ifnet *);
592 : int tht_load_pkt(struct tht_softc *, struct tht_pkt *,
593 : struct mbuf *);
594 : void tht_txf(struct tht_softc *sc);
595 :
596 : void tht_rxf_fill(struct tht_softc *, int);
597 : void tht_rxf_drain(struct tht_softc *);
598 : void tht_rxd(struct tht_softc *);
599 :
600 : void tht_up(struct tht_softc *);
601 : void tht_iff(struct tht_softc *);
602 : void tht_down(struct tht_softc *);
603 :
604 : /* ifmedia operations */
605 : int tht_media_change(struct ifnet *);
606 : void tht_media_status(struct ifnet *, struct ifmediareq *);
607 :
608 : /* wrapper around dma memory */
609 : struct tht_dmamem *tht_dmamem_alloc(struct tht_softc *, bus_size_t,
610 : bus_size_t);
611 : void tht_dmamem_free(struct tht_softc *,
612 : struct tht_dmamem *);
613 :
614 : /* bus space operations */
615 : u_int32_t tht_read(struct tht_softc *, bus_size_t);
616 : void tht_write(struct tht_softc *, bus_size_t, u_int32_t);
617 : void tht_write_region(struct tht_softc *, bus_size_t,
618 : void *, size_t);
619 : int tht_wait_eq(struct tht_softc *, bus_size_t, u_int32_t,
620 : u_int32_t, int);
621 : int tht_wait_ne(struct tht_softc *, bus_size_t, u_int32_t,
622 : u_int32_t, int);
623 :
624 : #define tht_set(_s, _r, _b) tht_write((_s), (_r), \
625 : tht_read((_s), (_r)) | (_b))
626 : #define tht_clr(_s, _r, _b) tht_write((_s), (_r), \
627 : tht_read((_s), (_r)) & ~(_b))
628 : #define tht_wait_set(_s, _r, _b, _t) tht_wait_eq((_s), (_r), \
629 : (_b), (_b), (_t))
630 :
631 :
632 : /* misc */
633 : #define DEVNAME(_sc) ((_sc)->sc_dev.dv_xname)
634 : #define LWORDS(_b) (((_b) + 7) >> 3)
635 :
636 :
637 : struct thtc_device {
638 : pci_vendor_id_t td_vendor;
639 : pci_vendor_id_t td_product;
640 : u_int td_nports;
641 : };
642 :
643 : const struct thtc_device *thtc_lookup(struct pci_attach_args *);
644 :
645 : static const struct thtc_device thtc_devices[] = {
646 : { PCI_VENDOR_TEHUTI, PCI_PRODUCT_TEHUTI_TN3009, 1 },
647 : { PCI_VENDOR_TEHUTI, PCI_PRODUCT_TEHUTI_TN3010, 1 },
648 : { PCI_VENDOR_TEHUTI, PCI_PRODUCT_TEHUTI_TN3014, 2 }
649 : };
650 :
651 : const struct thtc_device *
652 0 : thtc_lookup(struct pci_attach_args *pa)
653 : {
654 : int i;
655 : const struct thtc_device *td;
656 :
657 0 : for (i = 0; i < nitems(thtc_devices); i++) {
658 0 : td = &thtc_devices[i];
659 0 : if (td->td_vendor == PCI_VENDOR(pa->pa_id) &&
660 0 : td->td_product == PCI_PRODUCT(pa->pa_id))
661 0 : return (td);
662 : }
663 :
664 0 : return (NULL);
665 0 : }
666 :
667 : int
668 0 : thtc_match(struct device *parent, void *match, void *aux)
669 : {
670 0 : struct pci_attach_args *pa = aux;
671 :
672 0 : if (thtc_lookup(pa) != NULL)
673 0 : return (1);
674 :
675 0 : return (0);
676 0 : }
677 :
678 : void
679 0 : thtc_attach(struct device *parent, struct device *self, void *aux)
680 : {
681 0 : struct thtc_softc *sc = (struct thtc_softc *)self;
682 0 : struct pci_attach_args *pa = aux;
683 : pcireg_t memtype;
684 : const struct thtc_device *td;
685 0 : struct tht_attach_args taa;
686 0 : pci_intr_handle_t ih;
687 : int i;
688 :
689 0 : bzero(&taa, sizeof(taa));
690 0 : td = thtc_lookup(pa);
691 :
692 0 : sc->sc_dmat = pa->pa_dmat;
693 :
694 0 : memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, THT_PCI_BAR);
695 0 : if (pci_mapreg_map(pa, THT_PCI_BAR, memtype, 0, &sc->sc_memt,
696 0 : &sc->sc_memh, NULL, &sc->sc_mems, 0) != 0) {
697 0 : printf(": unable to map host registers\n");
698 0 : return;
699 : }
700 :
701 0 : if (pci_intr_map(pa, &ih) != 0) {
702 0 : printf(": unable to map interrupt\n");
703 : goto unmap;
704 : }
705 :
706 0 : sc->sc_ih = pci_intr_establish(pa->pa_pc, ih,
707 0 : IPL_NET, tht_intr, sc, DEVNAME(sc));
708 0 : if (sc->sc_ih == NULL) {
709 0 : printf(": unable to establish interrupt\n");
710 0 : return;
711 : }
712 0 : printf(": %s\n", pci_intr_string(pa->pa_pc, ih));
713 :
714 0 : taa.taa_pa = pa;
715 0 : for (i = 0; i < td->td_nports; i++) {
716 0 : taa.taa_port = i;
717 :
718 0 : config_found(self, &taa, thtc_print);
719 : }
720 :
721 0 : return;
722 :
723 : unmap:
724 0 : bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
725 0 : sc->sc_mems = 0;
726 0 : }
727 :
728 : int
729 0 : thtc_print(void *aux, const char *pnp)
730 : {
731 0 : struct tht_attach_args *taa = aux;
732 :
733 0 : if (pnp != NULL)
734 0 : printf("\"%s\" at %s", tht_cd.cd_name, pnp);
735 :
736 0 : printf(" port %d", taa->taa_port);
737 :
738 0 : return (UNCONF);
739 : }
740 :
741 : int
742 0 : tht_match(struct device *parent, void *match, void *aux)
743 : {
744 0 : return (1);
745 : }
746 :
747 : void
748 0 : tht_attach(struct device *parent, struct device *self, void *aux)
749 : {
750 0 : struct thtc_softc *csc = (struct thtc_softc *)parent;
751 0 : struct tht_softc *sc = (struct tht_softc *)self;
752 0 : struct tht_attach_args *taa = aux;
753 : struct ifnet *ifp;
754 :
755 0 : sc->sc_thtc = csc;
756 0 : sc->sc_port = taa->taa_port;
757 0 : sc->sc_imr = THT_IMR_DOWN(sc->sc_port);
758 0 : rw_init(&sc->sc_lock, "thtioc");
759 :
760 0 : if (bus_space_subregion(csc->sc_memt, csc->sc_memh,
761 0 : THT_PORT_REGION(sc->sc_port), THT_PORT_SIZE,
762 0 : &sc->sc_memh) != 0) {
763 0 : printf(": unable to map port registers\n");
764 0 : return;
765 : }
766 :
767 0 : if (tht_sw_reset(sc) != 0) {
768 0 : printf(": unable to reset port\n");
769 : /* bus_space(9) says we dont have to free subregions */
770 0 : return;
771 : }
772 :
773 0 : tht_lladdr_read(sc);
774 0 : bcopy(sc->sc_lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
775 :
776 0 : ifp = &sc->sc_ac.ac_if;
777 0 : ifp->if_softc = sc;
778 0 : ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
779 0 : ifp->if_capabilities = IFCAP_VLAN_MTU;
780 0 : ifp->if_ioctl = tht_ioctl;
781 0 : ifp->if_start = tht_start;
782 0 : ifp->if_watchdog = tht_watchdog;
783 0 : ifp->if_hardmtu = MCLBYTES - ETHER_HDR_LEN - ETHER_CRC_LEN; /* XXX */
784 0 : strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
785 0 : IFQ_SET_MAXLEN(&ifp->if_snd, 400);
786 :
787 0 : ifmedia_init(&sc->sc_media, 0, tht_media_change, tht_media_status);
788 0 : ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL);
789 0 : ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
790 :
791 0 : if_attach(ifp);
792 0 : ether_ifattach(ifp);
793 :
794 0 : printf(": address %s\n", ether_sprintf(sc->sc_ac.ac_enaddr));
795 :
796 0 : config_mountroot(self, tht_mountroot);
797 0 : }
798 :
799 : void
800 0 : tht_mountroot(struct device *self)
801 : {
802 0 : struct tht_softc *sc = (struct tht_softc *)self;
803 :
804 0 : if (tht_fifo_alloc(sc, &sc->sc_txt, &tht_txt_desc) != 0)
805 0 : return;
806 :
807 0 : if (tht_fw_load(sc) != 0)
808 0 : printf("%s: firmware load failed\n", DEVNAME(sc));
809 :
810 0 : tht_sw_reset(sc);
811 :
812 0 : tht_fifo_free(sc, &sc->sc_txt);
813 :
814 0 : tht_link_state(sc);
815 0 : tht_write(sc, THT_REG_IMR, sc->sc_imr);
816 0 : }
817 :
818 : int
819 0 : tht_intr(void *arg)
820 : {
821 0 : struct thtc_softc *thtc = arg;
822 : struct tht_softc *sc = arg;
823 : struct device *d;
824 : struct ifnet *ifp;
825 : u_int32_t isr;
826 : int rv = 0;
827 :
828 0 : for (d = TAILQ_NEXT(&thtc->sc_dev, dv_list); d != NULL;
829 0 : d = TAILQ_NEXT(d, dv_list)) {
830 0 : sc = (struct tht_softc *)d;
831 :
832 0 : isr = tht_read(sc, THT_REG_ISR);
833 0 : if (isr == 0x0) {
834 0 : tht_write(sc, THT_REG_IMR, sc->sc_imr);
835 0 : continue;
836 : }
837 : rv = 1;
838 :
839 : DPRINTF(THT_D_INTR, "%s: isr: 0x%b\n", DEVNAME(sc), isr, THT_FMT_ISR);
840 :
841 0 : if (ISSET(isr, THT_REG_ISR_LINKCHG(0) | THT_REG_ISR_LINKCHG(1)))
842 0 : tht_link_state(sc);
843 :
844 0 : ifp = &sc->sc_ac.ac_if;
845 0 : if (ifp->if_flags & IFF_RUNNING) {
846 0 : if (ISSET(isr, THT_REG_ISR_RXD(0)))
847 0 : tht_rxd(sc);
848 :
849 0 : if (ISSET(isr, THT_REG_ISR_RXF(0)))
850 0 : tht_rxf_fill(sc, 0);
851 :
852 0 : if (ISSET(isr, THT_REG_ISR_TXF(0)))
853 0 : tht_txf(sc);
854 :
855 0 : tht_start(ifp);
856 0 : }
857 0 : tht_write(sc, THT_REG_IMR, sc->sc_imr);
858 0 : }
859 0 : return (rv);
860 : }
861 :
862 : int
863 0 : tht_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
864 : {
865 0 : struct tht_softc *sc = ifp->if_softc;
866 0 : struct ifreq *ifr = (struct ifreq *)addr;
867 : int s, error = 0;
868 :
869 0 : rw_enter_write(&sc->sc_lock);
870 0 : s = splnet();
871 :
872 0 : switch (cmd) {
873 : case SIOCSIFADDR:
874 0 : ifp->if_flags |= IFF_UP;
875 : /* FALLTHROUGH */
876 :
877 : case SIOCSIFFLAGS:
878 0 : if (ifp->if_flags & IFF_UP) {
879 0 : if (ifp->if_flags & IFF_RUNNING)
880 0 : error = ENETRESET;
881 : else
882 0 : tht_up(sc);
883 : } else {
884 0 : if (ifp->if_flags & IFF_RUNNING)
885 0 : tht_down(sc);
886 : }
887 : break;
888 :
889 : case SIOCGIFMEDIA:
890 : case SIOCSIFMEDIA:
891 0 : error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
892 0 : break;
893 :
894 : default:
895 0 : error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
896 0 : }
897 :
898 0 : if (error == ENETRESET) {
899 0 : if (ifp->if_flags & IFF_RUNNING)
900 0 : tht_iff(sc);
901 : error = 0;
902 0 : }
903 :
904 0 : splx(s);
905 0 : rw_exit_write(&sc->sc_lock);
906 :
907 0 : return (error);
908 : }
909 :
910 : void
911 0 : tht_up(struct tht_softc *sc)
912 : {
913 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
914 :
915 0 : if (ISSET(ifp->if_flags, IFF_RUNNING)) {
916 0 : return;
917 : }
918 :
919 0 : if (tht_pkt_alloc(sc, &sc->sc_tx_list, THT_TXT_PKT_NUM,
920 0 : THT_TXT_SGL_LEN) != 0)
921 0 : return;
922 0 : if (tht_pkt_alloc(sc, &sc->sc_rx_list, THT_RXF_PKT_NUM,
923 0 : THT_RXF_SGL_LEN) != 0)
924 : goto free_tx_list;
925 :
926 0 : if (tht_fifo_alloc(sc, &sc->sc_txt, &tht_txt_desc) != 0)
927 : goto free_rx_list;
928 0 : if (tht_fifo_alloc(sc, &sc->sc_rxf, &tht_rxf_desc) != 0)
929 : goto free_txt;
930 0 : if (tht_fifo_alloc(sc, &sc->sc_rxd, &tht_rxd_desc) != 0)
931 : goto free_rxf;
932 0 : if (tht_fifo_alloc(sc, &sc->sc_txf, &tht_txf_desc) != 0)
933 : goto free_rxd;
934 :
935 0 : tht_write(sc, THT_REG_10G_FRM_LEN, MCLBYTES - ETHER_ALIGN);
936 0 : tht_write(sc, THT_REG_10G_PAUSE, 0x96);
937 0 : tht_write(sc, THT_REG_10G_RX_SEC, THT_REG_10G_SEC_AVAIL(0x10) |
938 : THT_REG_10G_SEC_EMPTY(0x80));
939 0 : tht_write(sc, THT_REG_10G_TX_SEC, THT_REG_10G_SEC_AVAIL(0x10) |
940 : THT_REG_10G_SEC_EMPTY(0xe0));
941 0 : tht_write(sc, THT_REG_10G_RFIFO_AEF, THT_REG_10G_FIFO_AE(0x0) |
942 : THT_REG_10G_FIFO_AF(0x0));
943 0 : tht_write(sc, THT_REG_10G_TFIFO_AEF, THT_REG_10G_FIFO_AE(0x0) |
944 : THT_REG_10G_FIFO_AF(0x0));
945 0 : tht_write(sc, THT_REG_10G_CTL, THT_REG_10G_CTL_TX_EN |
946 : THT_REG_10G_CTL_RX_EN | THT_REG_10G_CTL_PAD |
947 : THT_REG_10G_CTL_PROMISC);
948 :
949 0 : tht_write(sc, THT_REG_VGLB, 0);
950 :
951 0 : tht_write(sc, THT_REG_RX_MAX_FRAME, MCLBYTES - ETHER_ALIGN);
952 :
953 0 : tht_write(sc, THT_REG_RDINTCM(0), THT_REG_RDINTCM_PKT_TH(12) |
954 : THT_REG_RDINTCM_RXF_TH(4) | THT_REG_RDINTCM_COAL_RC |
955 : THT_REG_RDINTCM_COAL(0x20));
956 0 : tht_write(sc, THT_REG_TDINTCM(0), THT_REG_TDINTCM_PKT_TH(12) |
957 : THT_REG_TDINTCM_COAL_RC | THT_REG_TDINTCM_COAL(0x20));
958 :
959 0 : bcopy(sc->sc_ac.ac_enaddr, sc->sc_lladdr, ETHER_ADDR_LEN);
960 0 : tht_lladdr_write(sc);
961 :
962 : /* populate rxf fifo */
963 0 : tht_rxf_fill(sc, 1);
964 :
965 : /* program promiscuous mode and multicast filters */
966 0 : tht_iff(sc);
967 :
968 0 : ifp->if_flags |= IFF_RUNNING;
969 0 : ifq_clr_oactive(&ifp->if_snd);
970 :
971 : /* enable interrupts */
972 0 : sc->sc_imr = THT_IMR_UP(sc->sc_port);
973 0 : tht_write(sc, THT_REG_IMR, sc->sc_imr);
974 :
975 0 : return;
976 :
977 : free_rxd:
978 0 : tht_fifo_free(sc, &sc->sc_rxd);
979 : free_rxf:
980 0 : tht_fifo_free(sc, &sc->sc_rxf);
981 : free_txt:
982 0 : tht_fifo_free(sc, &sc->sc_txt);
983 :
984 0 : tht_sw_reset(sc);
985 :
986 : free_rx_list:
987 0 : tht_pkt_free(sc, &sc->sc_rx_list);
988 : free_tx_list:
989 0 : tht_pkt_free(sc, &sc->sc_tx_list);
990 0 : }
991 :
992 : void
993 0 : tht_iff(struct tht_softc *sc)
994 : {
995 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
996 : struct ether_multi *enm;
997 : struct ether_multistep step;
998 : u_int32_t rxf;
999 0 : u_int8_t imf[THT_REG_RX_MCST_HASH_SIZE];
1000 : u_int8_t hash;
1001 : int i;
1002 :
1003 0 : ifp->if_flags &= ~IFF_ALLMULTI;
1004 :
1005 : rxf = THT_REG_RX_FLT_OSEN | THT_REG_RX_FLT_AM | THT_REG_RX_FLT_AB;
1006 0 : for (i = 0; i < THT_REG_RX_MAC_MCST_CNT; i++) {
1007 0 : tht_write(sc, THT_REG_RX_MAC_MCST0(i), 0);
1008 0 : tht_write(sc, THT_REG_RX_MAC_MCST1(i), 0);
1009 : }
1010 0 : memset(imf, 0x00, sizeof(imf));
1011 :
1012 0 : if (ifp->if_flags & IFF_PROMISC) {
1013 0 : ifp->if_flags |= IFF_ALLMULTI;
1014 : rxf |= THT_REG_RX_FLT_PRM_ALL;
1015 0 : } else if (sc->sc_ac.ac_multirangecnt > 0) {
1016 0 : ifp->if_flags |= IFF_ALLMULTI;
1017 0 : memset(imf, 0xff, sizeof(imf));
1018 0 : } else {
1019 0 : ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
1020 :
1021 : #if 0
1022 : /* fill the perfect multicast filters */
1023 : for (i = 0; i < THT_REG_RX_MAC_MCST_CNT; i++) {
1024 : if (enm == NULL)
1025 : break;
1026 :
1027 : tht_write(sc, THT_REG_RX_MAC_MCST0(i),
1028 : (enm->enm_addrlo[0] << 0) |
1029 : (enm->enm_addrlo[1] << 8) |
1030 : (enm->enm_addrlo[2] << 16) |
1031 : (enm->enm_addrlo[3] << 24));
1032 : tht_write(sc, THT_REG_RX_MAC_MCST1(i),
1033 : (enm->enm_addrlo[4] << 0) |
1034 : (enm->enm_addrlo[5] << 8));
1035 :
1036 : ETHER_NEXT_MULTI(step, enm);
1037 : }
1038 : #endif
1039 :
1040 : /* fill the imperfect multicast filter with whats left */
1041 0 : while (enm != NULL) {
1042 : hash = 0x00;
1043 0 : for (i = 0; i < ETHER_ADDR_LEN; i++)
1044 0 : hash ^= enm->enm_addrlo[i];
1045 0 : setbit(imf, hash);
1046 :
1047 0 : ETHER_NEXT_MULTI(step, enm);
1048 : }
1049 : }
1050 :
1051 0 : tht_write_region(sc, THT_REG_RX_MCST_HASH, imf, sizeof(imf));
1052 0 : tht_write(sc, THT_REG_RX_FLT, rxf);
1053 0 : }
1054 :
1055 : void
1056 0 : tht_down(struct tht_softc *sc)
1057 : {
1058 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
1059 :
1060 0 : if (!ISSET(ifp->if_flags, IFF_RUNNING)) {
1061 0 : return;
1062 : }
1063 :
1064 0 : ifp->if_flags &= ~(IFF_RUNNING | IFF_ALLMULTI);
1065 0 : ifq_clr_oactive(&ifp->if_snd);
1066 :
1067 0 : while (tht_fifo_writable(sc, &sc->sc_txt) < sc->sc_txt.tf_len &&
1068 0 : tht_fifo_readable(sc, &sc->sc_txf) > 0)
1069 0 : tsleep(sc, 0, "thtdown", hz);
1070 :
1071 0 : sc->sc_imr = THT_IMR_DOWN(sc->sc_port);
1072 0 : tht_write(sc, THT_REG_IMR, sc->sc_imr);
1073 :
1074 0 : tht_sw_reset(sc);
1075 :
1076 0 : tht_fifo_free(sc, &sc->sc_txf);
1077 0 : tht_fifo_free(sc, &sc->sc_rxd);
1078 0 : tht_fifo_free(sc, &sc->sc_rxf);
1079 0 : tht_fifo_free(sc, &sc->sc_txt);
1080 :
1081 : /* free mbufs that were on the rxf fifo */
1082 0 : tht_rxf_drain(sc);
1083 :
1084 0 : tht_pkt_free(sc, &sc->sc_rx_list);
1085 0 : tht_pkt_free(sc, &sc->sc_tx_list);
1086 0 : }
1087 :
1088 : void
1089 0 : tht_start(struct ifnet *ifp)
1090 : {
1091 0 : struct tht_softc *sc = ifp->if_softc;
1092 : struct tht_pkt *pkt;
1093 0 : struct tht_tx_task txt;
1094 : u_int32_t flags;
1095 : struct mbuf *m;
1096 : int bc;
1097 :
1098 0 : if (!(ifp->if_flags & IFF_RUNNING))
1099 0 : return;
1100 0 : if (ifq_is_oactive(&ifp->if_snd))
1101 0 : return;
1102 0 : if (IFQ_IS_EMPTY(&ifp->if_snd))
1103 0 : return;
1104 :
1105 0 : if (tht_fifo_writable(sc, &sc->sc_txt) <= THT_FIFO_DESC_LEN)
1106 0 : return;
1107 :
1108 0 : bzero(&txt, sizeof(txt));
1109 :
1110 0 : tht_fifo_pre(sc, &sc->sc_txt);
1111 :
1112 0 : do {
1113 0 : m = ifq_deq_begin(&ifp->if_snd);
1114 0 : if (m == NULL)
1115 : break;
1116 :
1117 0 : pkt = tht_pkt_get(&sc->sc_tx_list);
1118 0 : if (pkt == NULL) {
1119 0 : ifq_deq_rollback(&ifp->if_snd, m);
1120 0 : ifq_set_oactive(&ifp->if_snd);
1121 0 : break;
1122 : }
1123 :
1124 0 : ifq_deq_commit(&ifp->if_snd, m);
1125 0 : if (tht_load_pkt(sc, pkt, m) != 0) {
1126 0 : m_freem(m);
1127 0 : tht_pkt_put(&sc->sc_tx_list, pkt);
1128 0 : ifp->if_oerrors++;
1129 0 : break;
1130 : }
1131 : /* thou shalt not use m after this point, only pkt->tp_m */
1132 :
1133 : #if NBPFILTER > 0
1134 0 : if (ifp->if_bpf)
1135 0 : bpf_mtap(ifp->if_bpf, pkt->tp_m, BPF_DIRECTION_OUT);
1136 : #endif
1137 :
1138 0 : bc = sizeof(txt) +
1139 0 : sizeof(struct tht_pbd) * pkt->tp_dmap->dm_nsegs;
1140 :
1141 0 : flags = THT_TXT_TYPE | LWORDS(bc);
1142 0 : txt.flags = htole32(flags);
1143 0 : txt.len = htole16(pkt->tp_m->m_pkthdr.len);
1144 0 : txt.uid = pkt->tp_id;
1145 :
1146 : DPRINTF(THT_D_TX, "%s: txt uid 0x%llx flags 0x%08x len %d\n",
1147 : DEVNAME(sc), pkt->tp_id, flags, pkt->tp_m->m_pkthdr.len);
1148 :
1149 0 : tht_fifo_write(sc, &sc->sc_txt, &txt, sizeof(txt));
1150 0 : tht_fifo_write_dmap(sc, &sc->sc_txt, pkt->tp_dmap);
1151 0 : tht_fifo_write_pad(sc, &sc->sc_txt, bc);
1152 :
1153 0 : bus_dmamap_sync(sc->sc_thtc->sc_dmat, pkt->tp_dmap, 0,
1154 : pkt->tp_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
1155 :
1156 0 : } while (sc->sc_txt.tf_ready > THT_FIFO_DESC_LEN);
1157 :
1158 0 : tht_fifo_post(sc, &sc->sc_txt);
1159 0 : }
1160 :
1161 : int
1162 0 : tht_load_pkt(struct tht_softc *sc, struct tht_pkt *pkt, struct mbuf *m)
1163 : {
1164 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1165 0 : bus_dmamap_t dmap = pkt->tp_dmap;
1166 : struct mbuf *m0 = NULL;
1167 :
1168 0 : switch(bus_dmamap_load_mbuf(dmat, dmap, m, BUS_DMA_NOWAIT)) {
1169 : case 0:
1170 0 : pkt->tp_m = m;
1171 0 : break;
1172 :
1173 : case EFBIG: /* mbuf chain is too fragmented */
1174 0 : MGETHDR(m0, M_DONTWAIT, MT_DATA);
1175 0 : if (m0 == NULL)
1176 0 : return (ENOBUFS);
1177 0 : if (m->m_pkthdr.len > MHLEN) {
1178 0 : MCLGET(m0, M_DONTWAIT);
1179 0 : if (!(m0->m_flags & M_EXT)) {
1180 0 : m_freem(m0);
1181 0 : return (ENOBUFS);
1182 : }
1183 : }
1184 0 : m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
1185 0 : m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
1186 0 : if (bus_dmamap_load_mbuf(dmat, dmap, m0, BUS_DMA_NOWAIT)) {
1187 0 : m_freem(m0);
1188 0 : return (ENOBUFS);
1189 : }
1190 :
1191 0 : m_freem(m);
1192 0 : pkt->tp_m = m0;
1193 0 : break;
1194 :
1195 : default:
1196 0 : return (ENOBUFS);
1197 : }
1198 :
1199 0 : return (0);
1200 0 : }
1201 :
1202 : void
1203 0 : tht_txf(struct tht_softc *sc)
1204 : {
1205 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
1206 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1207 : bus_dmamap_t dmap;
1208 0 : struct tht_tx_free txf;
1209 : struct tht_pkt *pkt;
1210 :
1211 0 : if (tht_fifo_readable(sc, &sc->sc_txf) < sizeof(txf))
1212 0 : return;
1213 :
1214 0 : tht_fifo_pre(sc, &sc->sc_txf);
1215 :
1216 0 : do {
1217 0 : tht_fifo_read(sc, &sc->sc_txf, &txf, sizeof(txf));
1218 :
1219 : DPRINTF(THT_D_TX, "%s: txf uid 0x%llx\n", DEVNAME(sc), txf.uid);
1220 :
1221 0 : pkt = &sc->sc_tx_list.tpl_pkts[txf.uid];
1222 0 : dmap = pkt->tp_dmap;
1223 :
1224 0 : bus_dmamap_sync(dmat, dmap, 0, dmap->dm_mapsize,
1225 : BUS_DMASYNC_POSTWRITE);
1226 0 : bus_dmamap_unload(dmat, dmap);
1227 :
1228 0 : m_freem(pkt->tp_m);
1229 :
1230 0 : tht_pkt_put(&sc->sc_tx_list, pkt);
1231 :
1232 0 : } while (sc->sc_txf.tf_ready >= sizeof(txf));
1233 :
1234 0 : ifq_clr_oactive(&ifp->if_snd);
1235 :
1236 0 : tht_fifo_post(sc, &sc->sc_txf);
1237 0 : }
1238 :
1239 : void
1240 0 : tht_rxf_fill(struct tht_softc *sc, int wait)
1241 : {
1242 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1243 : bus_dmamap_t dmap;
1244 0 : struct tht_rx_free rxf;
1245 : struct tht_pkt *pkt;
1246 : struct mbuf *m;
1247 : int bc;
1248 :
1249 0 : if (tht_fifo_writable(sc, &sc->sc_rxf) <= THT_FIFO_DESC_LEN)
1250 0 : return;
1251 :
1252 0 : tht_fifo_pre(sc, &sc->sc_rxf);
1253 :
1254 0 : for (;;) {
1255 0 : if ((pkt = tht_pkt_get(&sc->sc_rx_list)) == NULL)
1256 : goto done;
1257 :
1258 0 : MGETHDR(m, wait ? M_WAIT : M_DONTWAIT, MT_DATA);
1259 0 : if (m == NULL)
1260 : goto put_pkt;
1261 :
1262 0 : MCLGET(m, wait ? M_WAIT : M_DONTWAIT);
1263 0 : if (!ISSET(m->m_flags, M_EXT))
1264 : goto free_m;
1265 :
1266 0 : m->m_data += ETHER_ALIGN;
1267 0 : m->m_len = m->m_pkthdr.len = MCLBYTES - ETHER_ALIGN;
1268 :
1269 0 : dmap = pkt->tp_dmap;
1270 0 : if (bus_dmamap_load_mbuf(dmat, dmap, m,
1271 0 : wait ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0)
1272 : goto free_m;
1273 :
1274 0 : pkt->tp_m = m;
1275 :
1276 0 : bc = sizeof(rxf) + sizeof(struct tht_pbd) * dmap->dm_nsegs;
1277 :
1278 0 : rxf.bc = htole16(LWORDS(bc));
1279 0 : rxf.type = htole16(THT_RXF_TYPE);
1280 0 : rxf.uid = pkt->tp_id;
1281 :
1282 0 : tht_fifo_write(sc, &sc->sc_rxf, &rxf, sizeof(rxf));
1283 0 : tht_fifo_write_dmap(sc, &sc->sc_rxf, dmap);
1284 0 : tht_fifo_write_pad(sc, &sc->sc_rxf, bc);
1285 :
1286 0 : bus_dmamap_sync(dmat, dmap, 0, dmap->dm_mapsize,
1287 : BUS_DMASYNC_PREREAD);
1288 :
1289 0 : if (sc->sc_rxf.tf_ready <= THT_FIFO_DESC_LEN)
1290 : goto done;
1291 : }
1292 :
1293 : free_m:
1294 0 : m_freem(m);
1295 : put_pkt:
1296 0 : tht_pkt_put(&sc->sc_rx_list, pkt);
1297 : done:
1298 0 : tht_fifo_post(sc, &sc->sc_rxf);
1299 0 : }
1300 :
1301 : void
1302 0 : tht_rxf_drain(struct tht_softc *sc)
1303 : {
1304 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1305 : bus_dmamap_t dmap;
1306 : struct tht_pkt *pkt;
1307 :
1308 0 : while ((pkt = tht_pkt_used(&sc->sc_rx_list)) != NULL) {
1309 0 : dmap = pkt->tp_dmap;
1310 :
1311 0 : bus_dmamap_sync(dmat, dmap, 0, dmap->dm_mapsize,
1312 : BUS_DMASYNC_POSTREAD);
1313 0 : bus_dmamap_unload(dmat, dmap);
1314 :
1315 0 : m_freem(pkt->tp_m);
1316 :
1317 0 : tht_pkt_put(&sc->sc_rx_list, pkt);
1318 : }
1319 0 : }
1320 :
1321 : void
1322 0 : tht_rxd(struct tht_softc *sc)
1323 : {
1324 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
1325 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1326 : bus_dmamap_t dmap;
1327 0 : struct tht_rx_desc rxd;
1328 : struct tht_pkt *pkt;
1329 : struct mbuf *m;
1330 0 : struct mbuf_list ml = MBUF_LIST_INITIALIZER();
1331 : int bc;
1332 : u_int32_t flags;
1333 :
1334 0 : if (tht_fifo_readable(sc, &sc->sc_rxd) < sizeof(rxd))
1335 0 : return;
1336 :
1337 0 : tht_fifo_pre(sc, &sc->sc_rxd);
1338 :
1339 0 : do {
1340 0 : tht_fifo_read(sc, &sc->sc_rxd, &rxd, sizeof(rxd));
1341 :
1342 0 : flags = letoh32(rxd.flags);
1343 0 : bc = THT_RXD_FLAGS_BC(flags) * 8;
1344 0 : bc -= sizeof(rxd);
1345 0 : pkt = &sc->sc_rx_list.tpl_pkts[rxd.uid];
1346 :
1347 0 : dmap = pkt->tp_dmap;
1348 :
1349 0 : bus_dmamap_sync(dmat, dmap, 0, dmap->dm_mapsize,
1350 : BUS_DMASYNC_POSTREAD);
1351 0 : bus_dmamap_unload(dmat, dmap);
1352 :
1353 0 : m = pkt->tp_m;
1354 0 : m->m_pkthdr.len = m->m_len = letoh16(rxd.len);
1355 :
1356 : /* XXX process type 3 rx descriptors */
1357 :
1358 0 : ml_enqueue(&ml, m);
1359 :
1360 0 : tht_pkt_put(&sc->sc_rx_list, pkt);
1361 :
1362 0 : while (bc > 0) {
1363 : static u_int32_t pad;
1364 :
1365 0 : tht_fifo_read(sc, &sc->sc_rxd, &pad, sizeof(pad));
1366 0 : bc -= sizeof(pad);
1367 : }
1368 0 : } while (sc->sc_rxd.tf_ready >= sizeof(rxd));
1369 :
1370 0 : tht_fifo_post(sc, &sc->sc_rxd);
1371 :
1372 0 : if_input(ifp, &ml);
1373 :
1374 : /* put more pkts on the fifo */
1375 0 : tht_rxf_fill(sc, 0);
1376 0 : }
1377 :
1378 : void
1379 0 : tht_watchdog(struct ifnet *ifp)
1380 : {
1381 : /* do nothing */
1382 0 : }
1383 :
1384 : int
1385 0 : tht_media_change(struct ifnet *ifp)
1386 : {
1387 : /* ignore */
1388 0 : return (0);
1389 : }
1390 :
1391 : void
1392 0 : tht_media_status(struct ifnet *ifp, struct ifmediareq *imr)
1393 : {
1394 0 : struct tht_softc *sc = ifp->if_softc;
1395 :
1396 0 : imr->ifm_active = IFM_ETHER | IFM_AUTO;
1397 0 : imr->ifm_status = IFM_AVALID;
1398 :
1399 0 : tht_link_state(sc);
1400 :
1401 0 : if (LINK_STATE_IS_UP(ifp->if_link_state))
1402 0 : imr->ifm_status |= IFM_ACTIVE;
1403 0 : }
1404 :
1405 : int
1406 0 : tht_fifo_alloc(struct tht_softc *sc, struct tht_fifo *tf,
1407 : struct tht_fifo_desc *tfd)
1408 : {
1409 : u_int64_t dva;
1410 :
1411 0 : tf->tf_len = THT_FIFO_SIZE(tfd->tfd_size);
1412 0 : tf->tf_mem = tht_dmamem_alloc(sc, tf->tf_len, THT_FIFO_ALIGN);
1413 0 : if (tf->tf_mem == NULL)
1414 0 : return (1);
1415 :
1416 0 : tf->tf_desc = tfd;
1417 0 : tf->tf_rptr = tf->tf_wptr = 0;
1418 :
1419 0 : bus_dmamap_sync(sc->sc_thtc->sc_dmat, THT_DMA_MAP(tf->tf_mem),
1420 : 0, tf->tf_len, THT_FIFO_PRE_SYNC(tfd));
1421 :
1422 0 : dva = THT_DMA_DVA(tf->tf_mem);
1423 0 : tht_write(sc, tfd->tfd_cfg0, (u_int32_t)dva | tfd->tfd_size);
1424 0 : tht_write(sc, tfd->tfd_cfg1, (u_int32_t)(dva >> 32));
1425 :
1426 0 : return (0);
1427 0 : }
1428 :
1429 : void
1430 0 : tht_fifo_free(struct tht_softc *sc, struct tht_fifo *tf)
1431 : {
1432 0 : bus_dmamap_sync(sc->sc_thtc->sc_dmat, THT_DMA_MAP(tf->tf_mem),
1433 : 0, tf->tf_len, THT_FIFO_POST_SYNC(tf->tf_desc));
1434 0 : tht_dmamem_free(sc, tf->tf_mem);
1435 0 : }
1436 :
1437 : size_t
1438 0 : tht_fifo_readable(struct tht_softc *sc, struct tht_fifo *tf)
1439 : {
1440 0 : tf->tf_wptr = tht_read(sc, tf->tf_desc->tfd_wptr);
1441 0 : tf->tf_wptr &= THT_FIFO_PTR_MASK;
1442 0 : tf->tf_ready = tf->tf_wptr - tf->tf_rptr;
1443 0 : if (tf->tf_ready < 0)
1444 0 : tf->tf_ready += tf->tf_len;
1445 :
1446 : DPRINTF(THT_D_FIFO, "%s: fifo rdable wptr: %d rptr: %d ready: %d\n",
1447 : DEVNAME(sc), tf->tf_wptr, tf->tf_rptr, tf->tf_ready);
1448 :
1449 0 : return (tf->tf_ready);
1450 : }
1451 :
1452 : size_t
1453 0 : tht_fifo_writable(struct tht_softc *sc, struct tht_fifo *tf)
1454 : {
1455 0 : tf->tf_rptr = tht_read(sc, tf->tf_desc->tfd_rptr);
1456 0 : tf->tf_rptr &= THT_FIFO_PTR_MASK;
1457 0 : tf->tf_ready = tf->tf_rptr - tf->tf_wptr;
1458 0 : if (tf->tf_ready <= 0)
1459 0 : tf->tf_ready += tf->tf_len;
1460 :
1461 : DPRINTF(THT_D_FIFO, "%s: fifo wrable wptr: %d rptr: %d ready: %d\n",
1462 : DEVNAME(sc), tf->tf_wptr, tf->tf_rptr, tf->tf_ready);
1463 :
1464 0 : return (tf->tf_ready);
1465 : }
1466 :
1467 : void
1468 0 : tht_fifo_pre(struct tht_softc *sc, struct tht_fifo *tf)
1469 : {
1470 0 : bus_dmamap_sync(sc->sc_thtc->sc_dmat, THT_DMA_MAP(tf->tf_mem),
1471 : 0, tf->tf_len, THT_FIFO_POST_SYNC(tf->tf_desc));
1472 0 : }
1473 :
1474 : void
1475 0 : tht_fifo_read(struct tht_softc *sc, struct tht_fifo *tf,
1476 : void *buf, size_t buflen)
1477 : {
1478 0 : u_int8_t *fifo = THT_DMA_KVA(tf->tf_mem);
1479 : u_int8_t *desc = buf;
1480 : size_t len;
1481 :
1482 0 : tf->tf_ready -= buflen;
1483 :
1484 0 : len = tf->tf_len - tf->tf_rptr;
1485 :
1486 0 : if (len < buflen) {
1487 0 : memcpy(desc, fifo + tf->tf_rptr, len);
1488 :
1489 0 : buflen -= len;
1490 0 : desc += len;
1491 :
1492 0 : tf->tf_rptr = 0;
1493 0 : }
1494 :
1495 0 : memcpy(desc, fifo + tf->tf_rptr, buflen);
1496 0 : tf->tf_rptr += buflen;
1497 :
1498 : DPRINTF(THT_D_FIFO, "%s: fifo rd wptr: %d rptr: %d ready: %d\n",
1499 : DEVNAME(sc), tf->tf_wptr, tf->tf_rptr, tf->tf_ready);
1500 0 : }
1501 :
1502 : void
1503 0 : tht_fifo_write(struct tht_softc *sc, struct tht_fifo *tf,
1504 : void *buf, size_t buflen)
1505 : {
1506 0 : u_int8_t *fifo = THT_DMA_KVA(tf->tf_mem);
1507 : u_int8_t *desc = buf;
1508 : size_t len;
1509 :
1510 0 : tf->tf_ready -= buflen;
1511 :
1512 0 : len = tf->tf_len - tf->tf_wptr;
1513 :
1514 0 : if (len < buflen) {
1515 0 : memcpy(fifo + tf->tf_wptr, desc, len);
1516 :
1517 0 : buflen -= len;
1518 0 : desc += len;
1519 :
1520 0 : tf->tf_wptr = 0;
1521 0 : }
1522 :
1523 0 : memcpy(fifo + tf->tf_wptr, desc, buflen);
1524 0 : tf->tf_wptr += buflen;
1525 0 : tf->tf_wptr %= tf->tf_len;
1526 :
1527 : DPRINTF(THT_D_FIFO, "%s: fifo wr wptr: %d rptr: %d ready: %d\n",
1528 : DEVNAME(sc), tf->tf_wptr, tf->tf_rptr, tf->tf_ready);
1529 0 : }
1530 :
1531 : void
1532 0 : tht_fifo_write_dmap(struct tht_softc *sc, struct tht_fifo *tf,
1533 : bus_dmamap_t dmap)
1534 : {
1535 0 : struct tht_pbd pbd;
1536 : u_int64_t dva;
1537 : int i;
1538 :
1539 0 : for (i = 0; i < dmap->dm_nsegs; i++) {
1540 0 : dva = dmap->dm_segs[i].ds_addr;
1541 :
1542 0 : pbd.addr_lo = htole32(dva);
1543 0 : pbd.addr_hi = htole32(dva >> 32);
1544 0 : pbd.len = htole32(dmap->dm_segs[i].ds_len);
1545 :
1546 0 : tht_fifo_write(sc, tf, &pbd, sizeof(pbd));
1547 : }
1548 0 : }
1549 :
1550 : void
1551 0 : tht_fifo_write_pad(struct tht_softc *sc, struct tht_fifo *tf, int bc)
1552 : {
1553 : const static u_int32_t pad = 0x0;
1554 :
1555 : /* this assumes you'll only ever be writing multiples of 4 bytes */
1556 0 : if (bc % 8)
1557 0 : tht_fifo_write(sc, tf, (void *)&pad, sizeof(pad));
1558 0 : }
1559 :
1560 : void
1561 0 : tht_fifo_post(struct tht_softc *sc, struct tht_fifo *tf)
1562 : {
1563 0 : bus_dmamap_sync(sc->sc_thtc->sc_dmat, THT_DMA_MAP(tf->tf_mem),
1564 : 0, tf->tf_len, THT_FIFO_PRE_SYNC(tf->tf_desc));
1565 0 : if (tf->tf_desc->tfd_write)
1566 0 : tht_write(sc, tf->tf_desc->tfd_wptr, tf->tf_wptr);
1567 : else
1568 0 : tht_write(sc, tf->tf_desc->tfd_rptr, tf->tf_rptr);
1569 :
1570 : DPRINTF(THT_D_FIFO, "%s: fifo post wptr: %d rptr: %d\n", DEVNAME(sc),
1571 : tf->tf_wptr, tf->tf_rptr);
1572 0 : }
1573 :
1574 : const static bus_size_t tht_mac_regs[3] = {
1575 : THT_REG_RX_UNC_MAC2, THT_REG_RX_UNC_MAC1, THT_REG_RX_UNC_MAC0
1576 : };
1577 :
1578 : void
1579 0 : tht_lladdr_read(struct tht_softc *sc)
1580 : {
1581 : int i;
1582 :
1583 0 : for (i = 0; i < nitems(tht_mac_regs); i++)
1584 0 : sc->sc_lladdr[i] = betoh16(tht_read(sc, tht_mac_regs[i]));
1585 0 : }
1586 :
1587 : void
1588 0 : tht_lladdr_write(struct tht_softc *sc)
1589 : {
1590 : int i;
1591 :
1592 0 : for (i = 0; i < nitems(tht_mac_regs); i++)
1593 0 : tht_write(sc, tht_mac_regs[i], htobe16(sc->sc_lladdr[i]));
1594 0 : }
1595 :
1596 : #define tht_swrst_set(_s, _r) tht_write((_s), (_r), 0x1)
1597 : #define tht_swrst_clr(_s, _r) tht_write((_s), (_r), 0x0)
1598 : int
1599 0 : tht_sw_reset(struct tht_softc *sc)
1600 : {
1601 : int i;
1602 :
1603 : /* this follows SW Reset process in 8.8 of the doco */
1604 :
1605 : /* 1. disable rx */
1606 0 : tht_clr(sc, THT_REG_RX_FLT, THT_REG_RX_FLT_OSEN);
1607 :
1608 : /* 2. initiate port disable */
1609 0 : tht_swrst_set(sc, THT_REG_DIS_PRT);
1610 :
1611 : /* 3. initiate queue disable */
1612 0 : tht_swrst_set(sc, THT_REG_DIS_QU_0);
1613 0 : tht_swrst_set(sc, THT_REG_DIS_QU_1);
1614 :
1615 : /* 4. wait for successful finish of previous tasks */
1616 0 : if (!tht_wait_set(sc, THT_REG_RST_PRT, THT_REG_RST_PRT_ACTIVE, 1000))
1617 0 : return (1);
1618 :
1619 : /* 5. Reset interrupt registers */
1620 0 : tht_write(sc, THT_REG_IMR, 0x0); /* 5.a */
1621 0 : tht_read(sc, THT_REG_ISR); /* 5.b */
1622 0 : for (i = 0; i < THT_NQUEUES; i++) {
1623 0 : tht_write(sc, THT_REG_RDINTCM(i), 0x0); /* 5.c/5.d */
1624 0 : tht_write(sc, THT_REG_TDINTCM(i), 0x0); /* 5.e */
1625 : }
1626 :
1627 : /* 6. initiate queue reset */
1628 0 : tht_swrst_set(sc, THT_REG_RST_QU_0);
1629 0 : tht_swrst_set(sc, THT_REG_RST_QU_1);
1630 :
1631 : /* 7. initiate port reset */
1632 0 : tht_swrst_set(sc, THT_REG_RST_PRT);
1633 :
1634 : /* 8. clear txt/rxf/rxd/txf read and write ptrs */
1635 0 : for (i = 0; i < THT_NQUEUES; i++) {
1636 0 : tht_write(sc, THT_REG_TXT_RPTR(i), 0);
1637 0 : tht_write(sc, THT_REG_RXF_RPTR(i), 0);
1638 0 : tht_write(sc, THT_REG_RXD_RPTR(i), 0);
1639 0 : tht_write(sc, THT_REG_TXF_RPTR(i), 0);
1640 :
1641 0 : tht_write(sc, THT_REG_TXT_WPTR(i), 0);
1642 0 : tht_write(sc, THT_REG_RXF_WPTR(i), 0);
1643 0 : tht_write(sc, THT_REG_RXD_WPTR(i), 0);
1644 0 : tht_write(sc, THT_REG_TXF_WPTR(i), 0);
1645 : }
1646 :
1647 : /* 9. unset port disable */
1648 0 : tht_swrst_clr(sc, THT_REG_DIS_PRT);
1649 :
1650 : /* 10. unset queue disable */
1651 0 : tht_swrst_clr(sc, THT_REG_DIS_QU_0);
1652 0 : tht_swrst_clr(sc, THT_REG_DIS_QU_1);
1653 :
1654 : /* 11. unset queue reset */
1655 0 : tht_swrst_clr(sc, THT_REG_RST_QU_0);
1656 0 : tht_swrst_clr(sc, THT_REG_RST_QU_1);
1657 :
1658 : /* 12. unset port reset */
1659 0 : tht_swrst_clr(sc, THT_REG_RST_PRT);
1660 :
1661 : /* 13. enable rx */
1662 0 : tht_set(sc, THT_REG_RX_FLT, THT_REG_RX_FLT_OSEN);
1663 :
1664 0 : return (0);
1665 0 : }
1666 :
1667 : int
1668 0 : tht_fw_load(struct tht_softc *sc)
1669 : {
1670 0 : struct timeout ticker;
1671 0 : volatile int ok = 1;
1672 0 : u_int8_t *fw, *buf;
1673 0 : size_t fwlen, wrlen;
1674 : int error = 1;
1675 :
1676 0 : if (loadfirmware("tht", &fw, &fwlen) != 0)
1677 0 : return (1);
1678 :
1679 0 : if ((fwlen % 8) != 0)
1680 : goto err;
1681 :
1682 0 : buf = fw;
1683 0 : while (fwlen > 0) {
1684 0 : while (tht_fifo_writable(sc, &sc->sc_txt) <= THT_FIFO_GAP) {
1685 0 : if (tsleep(sc, PCATCH, "thtfw", 1) == EINTR)
1686 : goto err;
1687 : }
1688 :
1689 0 : wrlen = MIN(sc->sc_txt.tf_ready - THT_FIFO_GAP, fwlen);
1690 0 : tht_fifo_pre(sc, &sc->sc_txt);
1691 0 : tht_fifo_write(sc, &sc->sc_txt, buf, wrlen);
1692 0 : tht_fifo_post(sc, &sc->sc_txt);
1693 :
1694 0 : fwlen -= wrlen;
1695 0 : buf += wrlen;
1696 : }
1697 :
1698 0 : timeout_set(&ticker, tht_fw_tick, (void *)&ok);
1699 0 : timeout_add_sec(&ticker, 2);
1700 0 : while (ok) {
1701 0 : if (tht_read(sc, THT_REG_INIT_STATUS) != 0) {
1702 : error = 0;
1703 0 : break;
1704 : }
1705 :
1706 0 : if (tsleep(sc, PCATCH, "thtinit", 1) == EINTR)
1707 : goto err;
1708 : }
1709 0 : timeout_del(&ticker);
1710 :
1711 0 : tht_write(sc, THT_REG_INIT_SEMAPHORE, 0x1);
1712 :
1713 : err:
1714 0 : free(fw, M_DEVBUF, fwlen);
1715 0 : return (error);
1716 0 : }
1717 :
1718 : void
1719 0 : tht_fw_tick(void *arg)
1720 : {
1721 0 : volatile int *ok = arg;
1722 :
1723 0 : *ok = 0;
1724 0 : }
1725 :
1726 : void
1727 0 : tht_link_state(struct tht_softc *sc)
1728 : {
1729 : static const struct timeval interval = { 0, 10000 };
1730 0 : struct ifnet *ifp = &sc->sc_ac.ac_if;
1731 : int link_state = LINK_STATE_DOWN;
1732 :
1733 0 : if (!ratecheck(&sc->sc_mediacheck, &interval))
1734 0 : return;
1735 :
1736 0 : if (tht_read(sc, THT_REG_MAC_LNK_STAT) & THT_REG_MAC_LNK_STAT_LINK)
1737 0 : link_state = LINK_STATE_FULL_DUPLEX;
1738 :
1739 0 : if (ifp->if_link_state != link_state) {
1740 0 : ifp->if_link_state = link_state;
1741 0 : if_link_state_change(ifp);
1742 0 : }
1743 :
1744 0 : if (LINK_STATE_IS_UP(ifp->if_link_state))
1745 0 : ifp->if_baudrate = IF_Gbps(10);
1746 : else
1747 0 : ifp->if_baudrate = 0;
1748 0 : }
1749 :
1750 : u_int32_t
1751 0 : tht_read(struct tht_softc *sc, bus_size_t r)
1752 : {
1753 0 : bus_space_barrier(sc->sc_thtc->sc_memt, sc->sc_memh, r, 4,
1754 : BUS_SPACE_BARRIER_READ);
1755 0 : return (bus_space_read_4(sc->sc_thtc->sc_memt, sc->sc_memh, r));
1756 : }
1757 :
1758 : void
1759 0 : tht_write(struct tht_softc *sc, bus_size_t r, u_int32_t v)
1760 : {
1761 0 : bus_space_write_4(sc->sc_thtc->sc_memt, sc->sc_memh, r, v);
1762 0 : bus_space_barrier(sc->sc_thtc->sc_memt, sc->sc_memh, r, 4,
1763 : BUS_SPACE_BARRIER_WRITE);
1764 0 : }
1765 :
1766 : void
1767 0 : tht_write_region(struct tht_softc *sc, bus_size_t r, void *buf, size_t len)
1768 : {
1769 0 : bus_space_write_raw_region_4(sc->sc_thtc->sc_memt, sc->sc_memh, r,
1770 : buf, len);
1771 0 : bus_space_barrier(sc->sc_thtc->sc_memt, sc->sc_memh, r, len,
1772 : BUS_SPACE_BARRIER_WRITE);
1773 0 : }
1774 :
1775 : int
1776 0 : tht_wait_eq(struct tht_softc *sc, bus_size_t r, u_int32_t m, u_int32_t v,
1777 : int timeout)
1778 : {
1779 0 : while ((tht_read(sc, r) & m) != v) {
1780 0 : if (timeout == 0)
1781 0 : return (0);
1782 :
1783 0 : delay(1000);
1784 0 : timeout--;
1785 : }
1786 :
1787 0 : return (1);
1788 0 : }
1789 :
1790 : int
1791 0 : tht_wait_ne(struct tht_softc *sc, bus_size_t r, u_int32_t m, u_int32_t v,
1792 : int timeout)
1793 : {
1794 0 : while ((tht_read(sc, r) & m) == v) {
1795 0 : if (timeout == 0)
1796 0 : return (0);
1797 :
1798 0 : delay(1000);
1799 0 : timeout--;
1800 : }
1801 :
1802 0 : return (1);
1803 0 : }
1804 :
1805 : struct tht_dmamem *
1806 0 : tht_dmamem_alloc(struct tht_softc *sc, bus_size_t size, bus_size_t align)
1807 : {
1808 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1809 : struct tht_dmamem *tdm;
1810 0 : int nsegs;
1811 :
1812 0 : tdm = malloc(sizeof(struct tht_dmamem), M_DEVBUF, M_WAITOK | M_ZERO);
1813 0 : tdm->tdm_size = size;
1814 :
1815 0 : if (bus_dmamap_create(dmat, size, 1, size, 0,
1816 0 : BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &tdm->tdm_map) != 0)
1817 : goto tdmfree;
1818 :
1819 0 : if (bus_dmamem_alloc(dmat, size, align, 0, &tdm->tdm_seg, 1, &nsegs,
1820 0 : BUS_DMA_WAITOK | BUS_DMA_ZERO) != 0)
1821 : goto destroy;
1822 :
1823 0 : if (bus_dmamem_map(dmat, &tdm->tdm_seg, nsegs, size, &tdm->tdm_kva,
1824 0 : BUS_DMA_WAITOK) != 0)
1825 : goto free;
1826 :
1827 0 : if (bus_dmamap_load(dmat, tdm->tdm_map, tdm->tdm_kva, size,
1828 0 : NULL, BUS_DMA_WAITOK) != 0)
1829 : goto unmap;
1830 :
1831 0 : return (tdm);
1832 :
1833 : unmap:
1834 0 : bus_dmamem_unmap(dmat, tdm->tdm_kva, size);
1835 : free:
1836 0 : bus_dmamem_free(dmat, &tdm->tdm_seg, 1);
1837 : destroy:
1838 0 : bus_dmamap_destroy(dmat, tdm->tdm_map);
1839 : tdmfree:
1840 0 : free(tdm, M_DEVBUF, 0);
1841 :
1842 0 : return (NULL);
1843 0 : }
1844 :
1845 : void
1846 0 : tht_dmamem_free(struct tht_softc *sc, struct tht_dmamem *tdm)
1847 : {
1848 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1849 :
1850 0 : bus_dmamap_unload(dmat, tdm->tdm_map);
1851 0 : bus_dmamem_unmap(dmat, tdm->tdm_kva, tdm->tdm_size);
1852 0 : bus_dmamem_free(dmat, &tdm->tdm_seg, 1);
1853 0 : bus_dmamap_destroy(dmat, tdm->tdm_map);
1854 0 : free(tdm, M_DEVBUF, 0);
1855 0 : }
1856 :
1857 : int
1858 0 : tht_pkt_alloc(struct tht_softc *sc, struct tht_pkt_list *tpl, int npkts,
1859 : int nsegs)
1860 : {
1861 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1862 : struct tht_pkt *pkt;
1863 : int i;
1864 :
1865 0 : tpl->tpl_pkts = mallocarray(npkts, sizeof(struct tht_pkt),
1866 : M_DEVBUF, M_WAITOK | M_ZERO);
1867 :
1868 0 : TAILQ_INIT(&tpl->tpl_free);
1869 0 : TAILQ_INIT(&tpl->tpl_used);
1870 0 : for (i = 0; i < npkts; i++) {
1871 0 : pkt = &tpl->tpl_pkts[i];
1872 :
1873 0 : pkt->tp_id = i;
1874 0 : if (bus_dmamap_create(dmat, THT_PBD_PKTLEN, nsegs,
1875 : THT_PBD_PKTLEN, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
1876 0 : &pkt->tp_dmap) != 0) {
1877 0 : tht_pkt_free(sc, tpl);
1878 0 : return (1);
1879 : }
1880 :
1881 0 : TAILQ_INSERT_TAIL(&tpl->tpl_free, pkt, tp_link);
1882 : }
1883 :
1884 0 : return (0);
1885 0 : }
1886 :
1887 : void
1888 0 : tht_pkt_free(struct tht_softc *sc, struct tht_pkt_list *tpl)
1889 : {
1890 0 : bus_dma_tag_t dmat = sc->sc_thtc->sc_dmat;
1891 : struct tht_pkt *pkt;
1892 :
1893 0 : while ((pkt = tht_pkt_get(tpl)) != NULL)
1894 0 : bus_dmamap_destroy(dmat, pkt->tp_dmap);
1895 0 : free(tpl->tpl_pkts, M_DEVBUF, 0);
1896 0 : tpl->tpl_pkts = NULL;
1897 0 : }
1898 :
1899 : void
1900 0 : tht_pkt_put(struct tht_pkt_list *tpl, struct tht_pkt *pkt)
1901 : {
1902 0 : TAILQ_REMOVE(&tpl->tpl_used, pkt, tp_link);
1903 0 : TAILQ_INSERT_TAIL(&tpl->tpl_free, pkt, tp_link);
1904 0 : }
1905 :
1906 : struct tht_pkt *
1907 0 : tht_pkt_get(struct tht_pkt_list *tpl)
1908 : {
1909 : struct tht_pkt *pkt;
1910 :
1911 0 : pkt = TAILQ_FIRST(&tpl->tpl_free);
1912 0 : if (pkt != NULL) {
1913 0 : TAILQ_REMOVE(&tpl->tpl_free, pkt, tp_link);
1914 0 : TAILQ_INSERT_TAIL(&tpl->tpl_used, pkt, tp_link);
1915 :
1916 0 : }
1917 :
1918 0 : return (pkt);
1919 : }
1920 :
1921 : struct tht_pkt *
1922 0 : tht_pkt_used(struct tht_pkt_list *tpl)
1923 : {
1924 0 : return (TAILQ_FIRST(&tpl->tpl_used));
1925 : }
|