diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/sb1250-mac.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/sb1250-mac.c')
-rw-r--r-- | drivers/net/sb1250-mac.c | 2920 |
1 files changed, 2920 insertions, 0 deletions
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c new file mode 100644 index 000000000000..fd2e7c374906 --- /dev/null +++ b/drivers/net/sb1250-mac.c | |||
@@ -0,0 +1,2920 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001,2002,2003 Broadcom Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
17 | * | ||
18 | * | ||
19 | * This driver is designed for the Broadcom SiByte SOC built-in | ||
20 | * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp. | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/timer.h> | ||
26 | #include <linux/errno.h> | ||
27 | #include <linux/ioport.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/netdevice.h> | ||
31 | #include <linux/etherdevice.h> | ||
32 | #include <linux/skbuff.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/config.h> | ||
35 | #include <linux/bitops.h> | ||
36 | #include <asm/processor.h> /* Processor type for cache alignment. */ | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/cache.h> | ||
39 | |||
40 | /* This is only here until the firmware is ready. In that case, | ||
41 | the firmware leaves the ethernet address in the register for us. */ | ||
42 | #ifdef CONFIG_SIBYTE_STANDALONE | ||
43 | #define SBMAC_ETH0_HWADDR "40:00:00:00:01:00" | ||
44 | #define SBMAC_ETH1_HWADDR "40:00:00:00:01:01" | ||
45 | #define SBMAC_ETH2_HWADDR "40:00:00:00:01:02" | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* These identify the driver base version and may not be removed. */ | ||
50 | #if 0 | ||
51 | static char version1[] __devinitdata = | ||
52 | "sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n"; | ||
53 | #endif | ||
54 | |||
55 | |||
56 | /* Operational parameters that usually are not changed. */ | ||
57 | |||
58 | #define CONFIG_SBMAC_COALESCE | ||
59 | |||
60 | #define MAX_UNITS 3 /* More are supported, limit only on options */ | ||
61 | |||
62 | /* Time in jiffies before concluding the transmitter is hung. */ | ||
63 | #define TX_TIMEOUT (2*HZ) | ||
64 | |||
65 | |||
66 | MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)"); | ||
67 | MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver"); | ||
68 | |||
69 | /* A few user-configurable values which may be modified when a driver | ||
70 | module is loaded. */ | ||
71 | |||
72 | /* 1 normal messages, 0 quiet .. 7 verbose. */ | ||
73 | static int debug = 1; | ||
74 | module_param(debug, int, S_IRUGO); | ||
75 | MODULE_PARM_DESC(debug, "Debug messages"); | ||
76 | |||
77 | /* mii status msgs */ | ||
78 | static int noisy_mii = 1; | ||
79 | module_param(noisy_mii, int, S_IRUGO); | ||
80 | MODULE_PARM_DESC(noisy_mii, "MII status messages"); | ||
81 | |||
82 | /* Used to pass the media type, etc. | ||
83 | Both 'options[]' and 'full_duplex[]' should exist for driver | ||
84 | interoperability. | ||
85 | The media type is usually passed in 'options[]'. | ||
86 | */ | ||
87 | #ifdef MODULE | ||
88 | static int options[MAX_UNITS] = {-1, -1, -1}; | ||
89 | module_param_array(options, int, NULL, S_IRUGO); | ||
90 | MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS)); | ||
91 | |||
92 | static int full_duplex[MAX_UNITS] = {-1, -1, -1}; | ||
93 | module_param_array(full_duplex, int, NULL, S_IRUGO); | ||
94 | MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS)); | ||
95 | #endif | ||
96 | |||
97 | #ifdef CONFIG_SBMAC_COALESCE | ||
98 | static int int_pktcnt = 0; | ||
99 | module_param(int_pktcnt, int, S_IRUGO); | ||
100 | MODULE_PARM_DESC(int_pktcnt, "Packet count"); | ||
101 | |||
102 | static int int_timeout = 0; | ||
103 | module_param(int_timeout, int, S_IRUGO); | ||
104 | MODULE_PARM_DESC(int_timeout, "Timeout value"); | ||
105 | #endif | ||
106 | |||
107 | #include <asm/sibyte/sb1250.h> | ||
108 | #include <asm/sibyte/sb1250_defs.h> | ||
109 | #include <asm/sibyte/sb1250_regs.h> | ||
110 | #include <asm/sibyte/sb1250_mac.h> | ||
111 | #include <asm/sibyte/sb1250_dma.h> | ||
112 | #include <asm/sibyte/sb1250_int.h> | ||
113 | #include <asm/sibyte/sb1250_scd.h> | ||
114 | |||
115 | |||
116 | /********************************************************************** | ||
117 | * Simple types | ||
118 | ********************************************************************* */ | ||
119 | |||
120 | |||
121 | typedef unsigned long sbmac_port_t; | ||
122 | |||
123 | typedef enum { sbmac_speed_auto, sbmac_speed_10, | ||
124 | sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t; | ||
125 | |||
126 | typedef enum { sbmac_duplex_auto, sbmac_duplex_half, | ||
127 | sbmac_duplex_full } sbmac_duplex_t; | ||
128 | |||
129 | typedef enum { sbmac_fc_auto, sbmac_fc_disabled, sbmac_fc_frame, | ||
130 | sbmac_fc_collision, sbmac_fc_carrier } sbmac_fc_t; | ||
131 | |||
132 | typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on, | ||
133 | sbmac_state_broken } sbmac_state_t; | ||
134 | |||
135 | |||
136 | /********************************************************************** | ||
137 | * Macros | ||
138 | ********************************************************************* */ | ||
139 | |||
140 | |||
141 | #define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \ | ||
142 | (d)->sbdma_dscrtable : (d)->f+1) | ||
143 | |||
144 | |||
145 | #define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES) | ||
146 | |||
147 | #define SBMAC_READCSR(t) __raw_readq((unsigned long)t) | ||
148 | #define SBMAC_WRITECSR(t,v) __raw_writeq(v, (unsigned long)t) | ||
149 | |||
150 | |||
151 | #define SBMAC_MAX_TXDESCR 32 | ||
152 | #define SBMAC_MAX_RXDESCR 32 | ||
153 | |||
154 | #define ETHER_ALIGN 2 | ||
155 | #define ETHER_ADDR_LEN 6 | ||
156 | #define ENET_PACKET_SIZE 1518 | ||
157 | /*#define ENET_PACKET_SIZE 9216 */ | ||
158 | |||
159 | /********************************************************************** | ||
160 | * DMA Descriptor structure | ||
161 | ********************************************************************* */ | ||
162 | |||
163 | typedef struct sbdmadscr_s { | ||
164 | uint64_t dscr_a; | ||
165 | uint64_t dscr_b; | ||
166 | } sbdmadscr_t; | ||
167 | |||
168 | typedef unsigned long paddr_t; | ||
169 | |||
170 | /********************************************************************** | ||
171 | * DMA Controller structure | ||
172 | ********************************************************************* */ | ||
173 | |||
174 | typedef struct sbmacdma_s { | ||
175 | |||
176 | /* | ||
177 | * This stuff is used to identify the channel and the registers | ||
178 | * associated with it. | ||
179 | */ | ||
180 | |||
181 | struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */ | ||
182 | int sbdma_channel; /* channel number */ | ||
183 | int sbdma_txdir; /* direction (1=transmit) */ | ||
184 | int sbdma_maxdescr; /* total # of descriptors in ring */ | ||
185 | #ifdef CONFIG_SBMAC_COALESCE | ||
186 | int sbdma_int_pktcnt; /* # descriptors rx/tx before interrupt*/ | ||
187 | int sbdma_int_timeout; /* # usec rx/tx interrupt */ | ||
188 | #endif | ||
189 | |||
190 | sbmac_port_t sbdma_config0; /* DMA config register 0 */ | ||
191 | sbmac_port_t sbdma_config1; /* DMA config register 1 */ | ||
192 | sbmac_port_t sbdma_dscrbase; /* Descriptor base address */ | ||
193 | sbmac_port_t sbdma_dscrcnt; /* Descriptor count register */ | ||
194 | sbmac_port_t sbdma_curdscr; /* current descriptor address */ | ||
195 | |||
196 | /* | ||
197 | * This stuff is for maintenance of the ring | ||
198 | */ | ||
199 | |||
200 | sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */ | ||
201 | sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */ | ||
202 | |||
203 | struct sk_buff **sbdma_ctxtable; /* context table, one per descr */ | ||
204 | |||
205 | paddr_t sbdma_dscrtable_phys; /* and also the phys addr */ | ||
206 | sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */ | ||
207 | sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */ | ||
208 | } sbmacdma_t; | ||
209 | |||
210 | |||
211 | /********************************************************************** | ||
212 | * Ethernet softc structure | ||
213 | ********************************************************************* */ | ||
214 | |||
215 | struct sbmac_softc { | ||
216 | |||
217 | /* | ||
218 | * Linux-specific things | ||
219 | */ | ||
220 | |||
221 | struct net_device *sbm_dev; /* pointer to linux device */ | ||
222 | spinlock_t sbm_lock; /* spin lock */ | ||
223 | struct timer_list sbm_timer; /* for monitoring MII */ | ||
224 | struct net_device_stats sbm_stats; | ||
225 | int sbm_devflags; /* current device flags */ | ||
226 | |||
227 | int sbm_phy_oldbmsr; | ||
228 | int sbm_phy_oldanlpar; | ||
229 | int sbm_phy_oldk1stsr; | ||
230 | int sbm_phy_oldlinkstat; | ||
231 | int sbm_buffersize; | ||
232 | |||
233 | unsigned char sbm_phys[2]; | ||
234 | |||
235 | /* | ||
236 | * Controller-specific things | ||
237 | */ | ||
238 | |||
239 | unsigned long sbm_base; /* MAC's base address */ | ||
240 | sbmac_state_t sbm_state; /* current state */ | ||
241 | |||
242 | sbmac_port_t sbm_macenable; /* MAC Enable Register */ | ||
243 | sbmac_port_t sbm_maccfg; /* MAC Configuration Register */ | ||
244 | sbmac_port_t sbm_fifocfg; /* FIFO configuration register */ | ||
245 | sbmac_port_t sbm_framecfg; /* Frame configuration register */ | ||
246 | sbmac_port_t sbm_rxfilter; /* receive filter register */ | ||
247 | sbmac_port_t sbm_isr; /* Interrupt status register */ | ||
248 | sbmac_port_t sbm_imr; /* Interrupt mask register */ | ||
249 | sbmac_port_t sbm_mdio; /* MDIO register */ | ||
250 | |||
251 | sbmac_speed_t sbm_speed; /* current speed */ | ||
252 | sbmac_duplex_t sbm_duplex; /* current duplex */ | ||
253 | sbmac_fc_t sbm_fc; /* current flow control setting */ | ||
254 | |||
255 | unsigned char sbm_hwaddr[ETHER_ADDR_LEN]; | ||
256 | |||
257 | sbmacdma_t sbm_txdma; /* for now, only use channel 0 */ | ||
258 | sbmacdma_t sbm_rxdma; | ||
259 | int rx_hw_checksum; | ||
260 | int sbe_idx; | ||
261 | }; | ||
262 | |||
263 | |||
264 | /********************************************************************** | ||
265 | * Externs | ||
266 | ********************************************************************* */ | ||
267 | |||
268 | /********************************************************************** | ||
269 | * Prototypes | ||
270 | ********************************************************************* */ | ||
271 | |||
272 | static void sbdma_initctx(sbmacdma_t *d, | ||
273 | struct sbmac_softc *s, | ||
274 | int chan, | ||
275 | int txrx, | ||
276 | int maxdescr); | ||
277 | static void sbdma_channel_start(sbmacdma_t *d, int rxtx); | ||
278 | static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m); | ||
279 | static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m); | ||
280 | static void sbdma_emptyring(sbmacdma_t *d); | ||
281 | static void sbdma_fillring(sbmacdma_t *d); | ||
282 | static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d); | ||
283 | static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d); | ||
284 | static int sbmac_initctx(struct sbmac_softc *s); | ||
285 | static void sbmac_channel_start(struct sbmac_softc *s); | ||
286 | static void sbmac_channel_stop(struct sbmac_softc *s); | ||
287 | static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t); | ||
288 | static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff); | ||
289 | static uint64_t sbmac_addr2reg(unsigned char *ptr); | ||
290 | static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs); | ||
291 | static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev); | ||
292 | static void sbmac_setmulti(struct sbmac_softc *sc); | ||
293 | static int sbmac_init(struct net_device *dev, int idx); | ||
294 | static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed); | ||
295 | static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc); | ||
296 | |||
297 | static int sbmac_open(struct net_device *dev); | ||
298 | static void sbmac_timer(unsigned long data); | ||
299 | static void sbmac_tx_timeout (struct net_device *dev); | ||
300 | static struct net_device_stats *sbmac_get_stats(struct net_device *dev); | ||
301 | static void sbmac_set_rx_mode(struct net_device *dev); | ||
302 | static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | ||
303 | static int sbmac_close(struct net_device *dev); | ||
304 | static int sbmac_mii_poll(struct sbmac_softc *s,int noisy); | ||
305 | |||
306 | static void sbmac_mii_sync(struct sbmac_softc *s); | ||
307 | static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt); | ||
308 | static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx); | ||
309 | static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx, | ||
310 | unsigned int regval); | ||
311 | |||
312 | |||
313 | /********************************************************************** | ||
314 | * Globals | ||
315 | ********************************************************************* */ | ||
316 | |||
317 | static uint64_t sbmac_orig_hwaddr[MAX_UNITS]; | ||
318 | |||
319 | |||
320 | /********************************************************************** | ||
321 | * MDIO constants | ||
322 | ********************************************************************* */ | ||
323 | |||
324 | #define MII_COMMAND_START 0x01 | ||
325 | #define MII_COMMAND_READ 0x02 | ||
326 | #define MII_COMMAND_WRITE 0x01 | ||
327 | #define MII_COMMAND_ACK 0x02 | ||
328 | |||
329 | #define BMCR_RESET 0x8000 | ||
330 | #define BMCR_LOOPBACK 0x4000 | ||
331 | #define BMCR_SPEED0 0x2000 | ||
332 | #define BMCR_ANENABLE 0x1000 | ||
333 | #define BMCR_POWERDOWN 0x0800 | ||
334 | #define BMCR_ISOLATE 0x0400 | ||
335 | #define BMCR_RESTARTAN 0x0200 | ||
336 | #define BMCR_DUPLEX 0x0100 | ||
337 | #define BMCR_COLTEST 0x0080 | ||
338 | #define BMCR_SPEED1 0x0040 | ||
339 | #define BMCR_SPEED1000 BMCR_SPEED1 | ||
340 | #define BMCR_SPEED100 BMCR_SPEED0 | ||
341 | #define BMCR_SPEED10 0 | ||
342 | |||
343 | #define BMSR_100BT4 0x8000 | ||
344 | #define BMSR_100BT_FDX 0x4000 | ||
345 | #define BMSR_100BT_HDX 0x2000 | ||
346 | #define BMSR_10BT_FDX 0x1000 | ||
347 | #define BMSR_10BT_HDX 0x0800 | ||
348 | #define BMSR_100BT2_FDX 0x0400 | ||
349 | #define BMSR_100BT2_HDX 0x0200 | ||
350 | #define BMSR_1000BT_XSR 0x0100 | ||
351 | #define BMSR_PRESUP 0x0040 | ||
352 | #define BMSR_ANCOMPLT 0x0020 | ||
353 | #define BMSR_REMFAULT 0x0010 | ||
354 | #define BMSR_AUTONEG 0x0008 | ||
355 | #define BMSR_LINKSTAT 0x0004 | ||
356 | #define BMSR_JABDETECT 0x0002 | ||
357 | #define BMSR_EXTCAPAB 0x0001 | ||
358 | |||
359 | #define PHYIDR1 0x2000 | ||
360 | #define PHYIDR2 0x5C60 | ||
361 | |||
362 | #define ANAR_NP 0x8000 | ||
363 | #define ANAR_RF 0x2000 | ||
364 | #define ANAR_ASYPAUSE 0x0800 | ||
365 | #define ANAR_PAUSE 0x0400 | ||
366 | #define ANAR_T4 0x0200 | ||
367 | #define ANAR_TXFD 0x0100 | ||
368 | #define ANAR_TXHD 0x0080 | ||
369 | #define ANAR_10FD 0x0040 | ||
370 | #define ANAR_10HD 0x0020 | ||
371 | #define ANAR_PSB 0x0001 | ||
372 | |||
373 | #define ANLPAR_NP 0x8000 | ||
374 | #define ANLPAR_ACK 0x4000 | ||
375 | #define ANLPAR_RF 0x2000 | ||
376 | #define ANLPAR_ASYPAUSE 0x0800 | ||
377 | #define ANLPAR_PAUSE 0x0400 | ||
378 | #define ANLPAR_T4 0x0200 | ||
379 | #define ANLPAR_TXFD 0x0100 | ||
380 | #define ANLPAR_TXHD 0x0080 | ||
381 | #define ANLPAR_10FD 0x0040 | ||
382 | #define ANLPAR_10HD 0x0020 | ||
383 | #define ANLPAR_PSB 0x0001 /* 802.3 */ | ||
384 | |||
385 | #define ANER_PDF 0x0010 | ||
386 | #define ANER_LPNPABLE 0x0008 | ||
387 | #define ANER_NPABLE 0x0004 | ||
388 | #define ANER_PAGERX 0x0002 | ||
389 | #define ANER_LPANABLE 0x0001 | ||
390 | |||
391 | #define ANNPTR_NP 0x8000 | ||
392 | #define ANNPTR_MP 0x2000 | ||
393 | #define ANNPTR_ACK2 0x1000 | ||
394 | #define ANNPTR_TOGTX 0x0800 | ||
395 | #define ANNPTR_CODE 0x0008 | ||
396 | |||
397 | #define ANNPRR_NP 0x8000 | ||
398 | #define ANNPRR_MP 0x2000 | ||
399 | #define ANNPRR_ACK3 0x1000 | ||
400 | #define ANNPRR_TOGTX 0x0800 | ||
401 | #define ANNPRR_CODE 0x0008 | ||
402 | |||
403 | #define K1TCR_TESTMODE 0x0000 | ||
404 | #define K1TCR_MSMCE 0x1000 | ||
405 | #define K1TCR_MSCV 0x0800 | ||
406 | #define K1TCR_RPTR 0x0400 | ||
407 | #define K1TCR_1000BT_FDX 0x200 | ||
408 | #define K1TCR_1000BT_HDX 0x100 | ||
409 | |||
410 | #define K1STSR_MSMCFLT 0x8000 | ||
411 | #define K1STSR_MSCFGRES 0x4000 | ||
412 | #define K1STSR_LRSTAT 0x2000 | ||
413 | #define K1STSR_RRSTAT 0x1000 | ||
414 | #define K1STSR_LP1KFD 0x0800 | ||
415 | #define K1STSR_LP1KHD 0x0400 | ||
416 | #define K1STSR_LPASMDIR 0x0200 | ||
417 | |||
418 | #define K1SCR_1KX_FDX 0x8000 | ||
419 | #define K1SCR_1KX_HDX 0x4000 | ||
420 | #define K1SCR_1KT_FDX 0x2000 | ||
421 | #define K1SCR_1KT_HDX 0x1000 | ||
422 | |||
423 | #define STRAP_PHY1 0x0800 | ||
424 | #define STRAP_NCMODE 0x0400 | ||
425 | #define STRAP_MANMSCFG 0x0200 | ||
426 | #define STRAP_ANENABLE 0x0100 | ||
427 | #define STRAP_MSVAL 0x0080 | ||
428 | #define STRAP_1KHDXADV 0x0010 | ||
429 | #define STRAP_1KFDXADV 0x0008 | ||
430 | #define STRAP_100ADV 0x0004 | ||
431 | #define STRAP_SPEEDSEL 0x0000 | ||
432 | #define STRAP_SPEED100 0x0001 | ||
433 | |||
434 | #define PHYSUP_SPEED1000 0x10 | ||
435 | #define PHYSUP_SPEED100 0x08 | ||
436 | #define PHYSUP_SPEED10 0x00 | ||
437 | #define PHYSUP_LINKUP 0x04 | ||
438 | #define PHYSUP_FDX 0x02 | ||
439 | |||
440 | #define MII_BMCR 0x00 /* Basic mode control register (rw) */ | ||
441 | #define MII_BMSR 0x01 /* Basic mode status register (ro) */ | ||
442 | #define MII_K1STSR 0x0A /* 1K Status Register (ro) */ | ||
443 | #define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */ | ||
444 | |||
445 | |||
446 | #define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ | ||
447 | |||
448 | #define ENABLE 1 | ||
449 | #define DISABLE 0 | ||
450 | |||
451 | /********************************************************************** | ||
452 | * SBMAC_MII_SYNC(s) | ||
453 | * | ||
454 | * Synchronize with the MII - send a pattern of bits to the MII | ||
455 | * that will guarantee that it is ready to accept a command. | ||
456 | * | ||
457 | * Input parameters: | ||
458 | * s - sbmac structure | ||
459 | * | ||
460 | * Return value: | ||
461 | * nothing | ||
462 | ********************************************************************* */ | ||
463 | |||
464 | static void sbmac_mii_sync(struct sbmac_softc *s) | ||
465 | { | ||
466 | int cnt; | ||
467 | uint64_t bits; | ||
468 | int mac_mdio_genc; | ||
469 | |||
470 | mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC; | ||
471 | |||
472 | bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT; | ||
473 | |||
474 | SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc); | ||
475 | |||
476 | for (cnt = 0; cnt < 32; cnt++) { | ||
477 | SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc); | ||
478 | SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | /********************************************************************** | ||
483 | * SBMAC_MII_SENDDATA(s,data,bitcnt) | ||
484 | * | ||
485 | * Send some bits to the MII. The bits to be sent are right- | ||
486 | * justified in the 'data' parameter. | ||
487 | * | ||
488 | * Input parameters: | ||
489 | * s - sbmac structure | ||
490 | * data - data to send | ||
491 | * bitcnt - number of bits to send | ||
492 | ********************************************************************* */ | ||
493 | |||
494 | static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitcnt) | ||
495 | { | ||
496 | int i; | ||
497 | uint64_t bits; | ||
498 | unsigned int curmask; | ||
499 | int mac_mdio_genc; | ||
500 | |||
501 | mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC; | ||
502 | |||
503 | bits = M_MAC_MDIO_DIR_OUTPUT; | ||
504 | SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc); | ||
505 | |||
506 | curmask = 1 << (bitcnt - 1); | ||
507 | |||
508 | for (i = 0; i < bitcnt; i++) { | ||
509 | if (data & curmask) | ||
510 | bits |= M_MAC_MDIO_OUT; | ||
511 | else bits &= ~M_MAC_MDIO_OUT; | ||
512 | SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc); | ||
513 | SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC | mac_mdio_genc); | ||
514 | SBMAC_WRITECSR(s->sbm_mdio,bits | mac_mdio_genc); | ||
515 | curmask >>= 1; | ||
516 | } | ||
517 | } | ||
518 | |||
519 | |||
520 | |||
521 | /********************************************************************** | ||
522 | * SBMAC_MII_READ(s,phyaddr,regidx) | ||
523 | * | ||
524 | * Read a PHY register. | ||
525 | * | ||
526 | * Input parameters: | ||
527 | * s - sbmac structure | ||
528 | * phyaddr - PHY's address | ||
529 | * regidx = index of register to read | ||
530 | * | ||
531 | * Return value: | ||
532 | * value read, or 0 if an error occurred. | ||
533 | ********************************************************************* */ | ||
534 | |||
535 | static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx) | ||
536 | { | ||
537 | int idx; | ||
538 | int error; | ||
539 | int regval; | ||
540 | int mac_mdio_genc; | ||
541 | |||
542 | /* | ||
543 | * Synchronize ourselves so that the PHY knows the next | ||
544 | * thing coming down is a command | ||
545 | */ | ||
546 | |||
547 | sbmac_mii_sync(s); | ||
548 | |||
549 | /* | ||
550 | * Send the data to the PHY. The sequence is | ||
551 | * a "start" command (2 bits) | ||
552 | * a "read" command (2 bits) | ||
553 | * the PHY addr (5 bits) | ||
554 | * the register index (5 bits) | ||
555 | */ | ||
556 | |||
557 | sbmac_mii_senddata(s,MII_COMMAND_START, 2); | ||
558 | sbmac_mii_senddata(s,MII_COMMAND_READ, 2); | ||
559 | sbmac_mii_senddata(s,phyaddr, 5); | ||
560 | sbmac_mii_senddata(s,regidx, 5); | ||
561 | |||
562 | mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC; | ||
563 | |||
564 | /* | ||
565 | * Switch the port around without a clock transition. | ||
566 | */ | ||
567 | SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); | ||
568 | |||
569 | /* | ||
570 | * Send out a clock pulse to signal we want the status | ||
571 | */ | ||
572 | |||
573 | SBMAC_WRITECSR(s->sbm_mdio, | ||
574 | M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc); | ||
575 | SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); | ||
576 | |||
577 | /* | ||
578 | * If an error occurred, the PHY will signal '1' back | ||
579 | */ | ||
580 | error = SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN; | ||
581 | |||
582 | /* | ||
583 | * Issue an 'idle' clock pulse, but keep the direction | ||
584 | * the same. | ||
585 | */ | ||
586 | SBMAC_WRITECSR(s->sbm_mdio, | ||
587 | M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc); | ||
588 | SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); | ||
589 | |||
590 | regval = 0; | ||
591 | |||
592 | for (idx = 0; idx < 16; idx++) { | ||
593 | regval <<= 1; | ||
594 | |||
595 | if (error == 0) { | ||
596 | if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) | ||
597 | regval |= 1; | ||
598 | } | ||
599 | |||
600 | SBMAC_WRITECSR(s->sbm_mdio, | ||
601 | M_MAC_MDIO_DIR_INPUT|M_MAC_MDC | mac_mdio_genc); | ||
602 | SBMAC_WRITECSR(s->sbm_mdio, | ||
603 | M_MAC_MDIO_DIR_INPUT | mac_mdio_genc); | ||
604 | } | ||
605 | |||
606 | /* Switch back to output */ | ||
607 | SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc); | ||
608 | |||
609 | if (error == 0) | ||
610 | return regval; | ||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | |||
615 | /********************************************************************** | ||
616 | * SBMAC_MII_WRITE(s,phyaddr,regidx,regval) | ||
617 | * | ||
618 | * Write a value to a PHY register. | ||
619 | * | ||
620 | * Input parameters: | ||
621 | * s - sbmac structure | ||
622 | * phyaddr - PHY to use | ||
623 | * regidx - register within the PHY | ||
624 | * regval - data to write to register | ||
625 | * | ||
626 | * Return value: | ||
627 | * nothing | ||
628 | ********************************************************************* */ | ||
629 | |||
630 | static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx, | ||
631 | unsigned int regval) | ||
632 | { | ||
633 | int mac_mdio_genc; | ||
634 | |||
635 | sbmac_mii_sync(s); | ||
636 | |||
637 | sbmac_mii_senddata(s,MII_COMMAND_START,2); | ||
638 | sbmac_mii_senddata(s,MII_COMMAND_WRITE,2); | ||
639 | sbmac_mii_senddata(s,phyaddr, 5); | ||
640 | sbmac_mii_senddata(s,regidx, 5); | ||
641 | sbmac_mii_senddata(s,MII_COMMAND_ACK,2); | ||
642 | sbmac_mii_senddata(s,regval,16); | ||
643 | |||
644 | mac_mdio_genc = SBMAC_READCSR(s->sbm_mdio) & M_MAC_GENC; | ||
645 | |||
646 | SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc); | ||
647 | } | ||
648 | |||
649 | |||
650 | |||
651 | /********************************************************************** | ||
652 | * SBDMA_INITCTX(d,s,chan,txrx,maxdescr) | ||
653 | * | ||
654 | * Initialize a DMA channel context. Since there are potentially | ||
655 | * eight DMA channels per MAC, it's nice to do this in a standard | ||
656 | * way. | ||
657 | * | ||
658 | * Input parameters: | ||
659 | * d - sbmacdma_t structure (DMA channel context) | ||
660 | * s - sbmac_softc structure (pointer to a MAC) | ||
661 | * chan - channel number (0..1 right now) | ||
662 | * txrx - Identifies DMA_TX or DMA_RX for channel direction | ||
663 | * maxdescr - number of descriptors | ||
664 | * | ||
665 | * Return value: | ||
666 | * nothing | ||
667 | ********************************************************************* */ | ||
668 | |||
669 | static void sbdma_initctx(sbmacdma_t *d, | ||
670 | struct sbmac_softc *s, | ||
671 | int chan, | ||
672 | int txrx, | ||
673 | int maxdescr) | ||
674 | { | ||
675 | /* | ||
676 | * Save away interesting stuff in the structure | ||
677 | */ | ||
678 | |||
679 | d->sbdma_eth = s; | ||
680 | d->sbdma_channel = chan; | ||
681 | d->sbdma_txdir = txrx; | ||
682 | |||
683 | #if 0 | ||
684 | /* RMON clearing */ | ||
685 | s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING; | ||
686 | #endif | ||
687 | |||
688 | SBMAC_WRITECSR(IOADDR( | ||
689 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0); | ||
690 | SBMAC_WRITECSR(IOADDR( | ||
691 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0); | ||
692 | SBMAC_WRITECSR(IOADDR( | ||
693 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0); | ||
694 | SBMAC_WRITECSR(IOADDR( | ||
695 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0); | ||
696 | SBMAC_WRITECSR(IOADDR( | ||
697 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0); | ||
698 | SBMAC_WRITECSR(IOADDR( | ||
699 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0); | ||
700 | SBMAC_WRITECSR(IOADDR( | ||
701 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0); | ||
702 | SBMAC_WRITECSR(IOADDR( | ||
703 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0); | ||
704 | SBMAC_WRITECSR(IOADDR( | ||
705 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0); | ||
706 | SBMAC_WRITECSR(IOADDR( | ||
707 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0); | ||
708 | SBMAC_WRITECSR(IOADDR( | ||
709 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0); | ||
710 | SBMAC_WRITECSR(IOADDR( | ||
711 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0); | ||
712 | SBMAC_WRITECSR(IOADDR( | ||
713 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0); | ||
714 | SBMAC_WRITECSR(IOADDR( | ||
715 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0); | ||
716 | SBMAC_WRITECSR(IOADDR( | ||
717 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0); | ||
718 | SBMAC_WRITECSR(IOADDR( | ||
719 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0); | ||
720 | SBMAC_WRITECSR(IOADDR( | ||
721 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0); | ||
722 | SBMAC_WRITECSR(IOADDR( | ||
723 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0); | ||
724 | SBMAC_WRITECSR(IOADDR( | ||
725 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0); | ||
726 | SBMAC_WRITECSR(IOADDR( | ||
727 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0); | ||
728 | SBMAC_WRITECSR(IOADDR( | ||
729 | A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0); | ||
730 | |||
731 | /* | ||
732 | * initialize register pointers | ||
733 | */ | ||
734 | |||
735 | d->sbdma_config0 = | ||
736 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0); | ||
737 | d->sbdma_config1 = | ||
738 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1); | ||
739 | d->sbdma_dscrbase = | ||
740 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE); | ||
741 | d->sbdma_dscrcnt = | ||
742 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT); | ||
743 | d->sbdma_curdscr = | ||
744 | s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR); | ||
745 | |||
746 | /* | ||
747 | * Allocate memory for the ring | ||
748 | */ | ||
749 | |||
750 | d->sbdma_maxdescr = maxdescr; | ||
751 | |||
752 | d->sbdma_dscrtable = (sbdmadscr_t *) | ||
753 | kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL); | ||
754 | |||
755 | memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t)); | ||
756 | |||
757 | d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr; | ||
758 | |||
759 | d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable); | ||
760 | |||
761 | /* | ||
762 | * And context table | ||
763 | */ | ||
764 | |||
765 | d->sbdma_ctxtable = (struct sk_buff **) | ||
766 | kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL); | ||
767 | |||
768 | memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *)); | ||
769 | |||
770 | #ifdef CONFIG_SBMAC_COALESCE | ||
771 | /* | ||
772 | * Setup Rx/Tx DMA coalescing defaults | ||
773 | */ | ||
774 | |||
775 | if ( int_pktcnt ) { | ||
776 | d->sbdma_int_pktcnt = int_pktcnt; | ||
777 | } else { | ||
778 | d->sbdma_int_pktcnt = 1; | ||
779 | } | ||
780 | |||
781 | if ( int_timeout ) { | ||
782 | d->sbdma_int_timeout = int_timeout; | ||
783 | } else { | ||
784 | d->sbdma_int_timeout = 0; | ||
785 | } | ||
786 | #endif | ||
787 | |||
788 | } | ||
789 | |||
790 | /********************************************************************** | ||
791 | * SBDMA_CHANNEL_START(d) | ||
792 | * | ||
793 | * Initialize the hardware registers for a DMA channel. | ||
794 | * | ||
795 | * Input parameters: | ||
796 | * d - DMA channel to init (context must be previously init'd | ||
797 | * rxtx - DMA_RX or DMA_TX depending on what type of channel | ||
798 | * | ||
799 | * Return value: | ||
800 | * nothing | ||
801 | ********************************************************************* */ | ||
802 | |||
803 | static void sbdma_channel_start(sbmacdma_t *d, int rxtx ) | ||
804 | { | ||
805 | /* | ||
806 | * Turn on the DMA channel | ||
807 | */ | ||
808 | |||
809 | #ifdef CONFIG_SBMAC_COALESCE | ||
810 | SBMAC_WRITECSR(d->sbdma_config1, | ||
811 | V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) | | ||
812 | 0); | ||
813 | SBMAC_WRITECSR(d->sbdma_config0, | ||
814 | M_DMA_EOP_INT_EN | | ||
815 | V_DMA_RINGSZ(d->sbdma_maxdescr) | | ||
816 | V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) | | ||
817 | 0); | ||
818 | #else | ||
819 | SBMAC_WRITECSR(d->sbdma_config1,0); | ||
820 | SBMAC_WRITECSR(d->sbdma_config0, | ||
821 | V_DMA_RINGSZ(d->sbdma_maxdescr) | | ||
822 | 0); | ||
823 | #endif | ||
824 | |||
825 | SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys); | ||
826 | |||
827 | /* | ||
828 | * Initialize ring pointers | ||
829 | */ | ||
830 | |||
831 | d->sbdma_addptr = d->sbdma_dscrtable; | ||
832 | d->sbdma_remptr = d->sbdma_dscrtable; | ||
833 | } | ||
834 | |||
835 | /********************************************************************** | ||
836 | * SBDMA_CHANNEL_STOP(d) | ||
837 | * | ||
838 | * Initialize the hardware registers for a DMA channel. | ||
839 | * | ||
840 | * Input parameters: | ||
841 | * d - DMA channel to init (context must be previously init'd | ||
842 | * | ||
843 | * Return value: | ||
844 | * nothing | ||
845 | ********************************************************************* */ | ||
846 | |||
847 | static void sbdma_channel_stop(sbmacdma_t *d) | ||
848 | { | ||
849 | /* | ||
850 | * Turn off the DMA channel | ||
851 | */ | ||
852 | |||
853 | SBMAC_WRITECSR(d->sbdma_config1,0); | ||
854 | |||
855 | SBMAC_WRITECSR(d->sbdma_dscrbase,0); | ||
856 | |||
857 | SBMAC_WRITECSR(d->sbdma_config0,0); | ||
858 | |||
859 | /* | ||
860 | * Zero ring pointers | ||
861 | */ | ||
862 | |||
863 | d->sbdma_addptr = 0; | ||
864 | d->sbdma_remptr = 0; | ||
865 | } | ||
866 | |||
867 | static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset) | ||
868 | { | ||
869 | unsigned long addr; | ||
870 | unsigned long newaddr; | ||
871 | |||
872 | addr = (unsigned long) skb->data; | ||
873 | |||
874 | newaddr = (addr + power2 - 1) & ~(power2 - 1); | ||
875 | |||
876 | skb_reserve(skb,newaddr-addr+offset); | ||
877 | } | ||
878 | |||
879 | |||
880 | /********************************************************************** | ||
881 | * SBDMA_ADD_RCVBUFFER(d,sb) | ||
882 | * | ||
883 | * Add a buffer to the specified DMA channel. For receive channels, | ||
884 | * this queues a buffer for inbound packets. | ||
885 | * | ||
886 | * Input parameters: | ||
887 | * d - DMA channel descriptor | ||
888 | * sb - sk_buff to add, or NULL if we should allocate one | ||
889 | * | ||
890 | * Return value: | ||
891 | * 0 if buffer could not be added (ring is full) | ||
892 | * 1 if buffer added successfully | ||
893 | ********************************************************************* */ | ||
894 | |||
895 | |||
896 | static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb) | ||
897 | { | ||
898 | sbdmadscr_t *dsc; | ||
899 | sbdmadscr_t *nextdsc; | ||
900 | struct sk_buff *sb_new = NULL; | ||
901 | int pktsize = ENET_PACKET_SIZE; | ||
902 | |||
903 | /* get pointer to our current place in the ring */ | ||
904 | |||
905 | dsc = d->sbdma_addptr; | ||
906 | nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); | ||
907 | |||
908 | /* | ||
909 | * figure out if the ring is full - if the next descriptor | ||
910 | * is the same as the one that we're going to remove from | ||
911 | * the ring, the ring is full | ||
912 | */ | ||
913 | |||
914 | if (nextdsc == d->sbdma_remptr) { | ||
915 | return -ENOSPC; | ||
916 | } | ||
917 | |||
918 | /* | ||
919 | * Allocate a sk_buff if we don't already have one. | ||
920 | * If we do have an sk_buff, reset it so that it's empty. | ||
921 | * | ||
922 | * Note: sk_buffs don't seem to be guaranteed to have any sort | ||
923 | * of alignment when they are allocated. Therefore, allocate enough | ||
924 | * extra space to make sure that: | ||
925 | * | ||
926 | * 1. the data does not start in the middle of a cache line. | ||
927 | * 2. The data does not end in the middle of a cache line | ||
928 | * 3. The buffer can be aligned such that the IP addresses are | ||
929 | * naturally aligned. | ||
930 | * | ||
931 | * Remember, the SOCs MAC writes whole cache lines at a time, | ||
932 | * without reading the old contents first. So, if the sk_buff's | ||
933 | * data portion starts in the middle of a cache line, the SOC | ||
934 | * DMA will trash the beginning (and ending) portions. | ||
935 | */ | ||
936 | |||
937 | if (sb == NULL) { | ||
938 | sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN); | ||
939 | if (sb_new == NULL) { | ||
940 | printk(KERN_INFO "%s: sk_buff allocation failed\n", | ||
941 | d->sbdma_eth->sbm_dev->name); | ||
942 | return -ENOBUFS; | ||
943 | } | ||
944 | |||
945 | sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN); | ||
946 | |||
947 | /* mark skbuff owned by our device */ | ||
948 | sb_new->dev = d->sbdma_eth->sbm_dev; | ||
949 | } | ||
950 | else { | ||
951 | sb_new = sb; | ||
952 | /* | ||
953 | * nothing special to reinit buffer, it's already aligned | ||
954 | * and sb->data already points to a good place. | ||
955 | */ | ||
956 | } | ||
957 | |||
958 | /* | ||
959 | * fill in the descriptor | ||
960 | */ | ||
961 | |||
962 | #ifdef CONFIG_SBMAC_COALESCE | ||
963 | /* | ||
964 | * Do not interrupt per DMA transfer. | ||
965 | */ | ||
966 | dsc->dscr_a = virt_to_phys(sb_new->tail) | | ||
967 | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | | ||
968 | 0; | ||
969 | #else | ||
970 | dsc->dscr_a = virt_to_phys(sb_new->tail) | | ||
971 | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | | ||
972 | M_DMA_DSCRA_INTERRUPT; | ||
973 | #endif | ||
974 | |||
975 | /* receiving: no options */ | ||
976 | dsc->dscr_b = 0; | ||
977 | |||
978 | /* | ||
979 | * fill in the context | ||
980 | */ | ||
981 | |||
982 | d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new; | ||
983 | |||
984 | /* | ||
985 | * point at next packet | ||
986 | */ | ||
987 | |||
988 | d->sbdma_addptr = nextdsc; | ||
989 | |||
990 | /* | ||
991 | * Give the buffer to the DMA engine. | ||
992 | */ | ||
993 | |||
994 | SBMAC_WRITECSR(d->sbdma_dscrcnt,1); | ||
995 | |||
996 | return 0; /* we did it */ | ||
997 | } | ||
998 | |||
999 | /********************************************************************** | ||
1000 | * SBDMA_ADD_TXBUFFER(d,sb) | ||
1001 | * | ||
1002 | * Add a transmit buffer to the specified DMA channel, causing a | ||
1003 | * transmit to start. | ||
1004 | * | ||
1005 | * Input parameters: | ||
1006 | * d - DMA channel descriptor | ||
1007 | * sb - sk_buff to add | ||
1008 | * | ||
1009 | * Return value: | ||
1010 | * 0 transmit queued successfully | ||
1011 | * otherwise error code | ||
1012 | ********************************************************************* */ | ||
1013 | |||
1014 | |||
1015 | static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb) | ||
1016 | { | ||
1017 | sbdmadscr_t *dsc; | ||
1018 | sbdmadscr_t *nextdsc; | ||
1019 | uint64_t phys; | ||
1020 | uint64_t ncb; | ||
1021 | int length; | ||
1022 | |||
1023 | /* get pointer to our current place in the ring */ | ||
1024 | |||
1025 | dsc = d->sbdma_addptr; | ||
1026 | nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); | ||
1027 | |||
1028 | /* | ||
1029 | * figure out if the ring is full - if the next descriptor | ||
1030 | * is the same as the one that we're going to remove from | ||
1031 | * the ring, the ring is full | ||
1032 | */ | ||
1033 | |||
1034 | if (nextdsc == d->sbdma_remptr) { | ||
1035 | return -ENOSPC; | ||
1036 | } | ||
1037 | |||
1038 | /* | ||
1039 | * Under Linux, it's not necessary to copy/coalesce buffers | ||
1040 | * like it is on NetBSD. We think they're all contiguous, | ||
1041 | * but that may not be true for GBE. | ||
1042 | */ | ||
1043 | |||
1044 | length = sb->len; | ||
1045 | |||
1046 | /* | ||
1047 | * fill in the descriptor. Note that the number of cache | ||
1048 | * blocks in the descriptor is the number of blocks | ||
1049 | * *spanned*, so we need to add in the offset (if any) | ||
1050 | * while doing the calculation. | ||
1051 | */ | ||
1052 | |||
1053 | phys = virt_to_phys(sb->data); | ||
1054 | ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1))); | ||
1055 | |||
1056 | dsc->dscr_a = phys | | ||
1057 | V_DMA_DSCRA_A_SIZE(ncb) | | ||
1058 | #ifndef CONFIG_SBMAC_COALESCE | ||
1059 | M_DMA_DSCRA_INTERRUPT | | ||
1060 | #endif | ||
1061 | M_DMA_ETHTX_SOP; | ||
1062 | |||
1063 | /* transmitting: set outbound options and length */ | ||
1064 | |||
1065 | dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | | ||
1066 | V_DMA_DSCRB_PKT_SIZE(length); | ||
1067 | |||
1068 | /* | ||
1069 | * fill in the context | ||
1070 | */ | ||
1071 | |||
1072 | d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb; | ||
1073 | |||
1074 | /* | ||
1075 | * point at next packet | ||
1076 | */ | ||
1077 | |||
1078 | d->sbdma_addptr = nextdsc; | ||
1079 | |||
1080 | /* | ||
1081 | * Give the buffer to the DMA engine. | ||
1082 | */ | ||
1083 | |||
1084 | SBMAC_WRITECSR(d->sbdma_dscrcnt,1); | ||
1085 | |||
1086 | return 0; /* we did it */ | ||
1087 | } | ||
1088 | |||
1089 | |||
1090 | |||
1091 | |||
1092 | /********************************************************************** | ||
1093 | * SBDMA_EMPTYRING(d) | ||
1094 | * | ||
1095 | * Free all allocated sk_buffs on the specified DMA channel; | ||
1096 | * | ||
1097 | * Input parameters: | ||
1098 | * d - DMA channel | ||
1099 | * | ||
1100 | * Return value: | ||
1101 | * nothing | ||
1102 | ********************************************************************* */ | ||
1103 | |||
1104 | static void sbdma_emptyring(sbmacdma_t *d) | ||
1105 | { | ||
1106 | int idx; | ||
1107 | struct sk_buff *sb; | ||
1108 | |||
1109 | for (idx = 0; idx < d->sbdma_maxdescr; idx++) { | ||
1110 | sb = d->sbdma_ctxtable[idx]; | ||
1111 | if (sb) { | ||
1112 | dev_kfree_skb(sb); | ||
1113 | d->sbdma_ctxtable[idx] = NULL; | ||
1114 | } | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | |||
1119 | /********************************************************************** | ||
1120 | * SBDMA_FILLRING(d) | ||
1121 | * | ||
1122 | * Fill the specified DMA channel (must be receive channel) | ||
1123 | * with sk_buffs | ||
1124 | * | ||
1125 | * Input parameters: | ||
1126 | * d - DMA channel | ||
1127 | * | ||
1128 | * Return value: | ||
1129 | * nothing | ||
1130 | ********************************************************************* */ | ||
1131 | |||
1132 | static void sbdma_fillring(sbmacdma_t *d) | ||
1133 | { | ||
1134 | int idx; | ||
1135 | |||
1136 | for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) { | ||
1137 | if (sbdma_add_rcvbuffer(d,NULL) != 0) | ||
1138 | break; | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | |||
1143 | /********************************************************************** | ||
1144 | * SBDMA_RX_PROCESS(sc,d) | ||
1145 | * | ||
1146 | * Process "completed" receive buffers on the specified DMA channel. | ||
1147 | * Note that this isn't really ideal for priority channels, since | ||
1148 | * it processes all of the packets on a given channel before | ||
1149 | * returning. | ||
1150 | * | ||
1151 | * Input parameters: | ||
1152 | * sc - softc structure | ||
1153 | * d - DMA channel context | ||
1154 | * | ||
1155 | * Return value: | ||
1156 | * nothing | ||
1157 | ********************************************************************* */ | ||
1158 | |||
1159 | static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d) | ||
1160 | { | ||
1161 | int curidx; | ||
1162 | int hwidx; | ||
1163 | sbdmadscr_t *dsc; | ||
1164 | struct sk_buff *sb; | ||
1165 | int len; | ||
1166 | |||
1167 | for (;;) { | ||
1168 | /* | ||
1169 | * figure out where we are (as an index) and where | ||
1170 | * the hardware is (also as an index) | ||
1171 | * | ||
1172 | * This could be done faster if (for example) the | ||
1173 | * descriptor table was page-aligned and contiguous in | ||
1174 | * both virtual and physical memory -- you could then | ||
1175 | * just compare the low-order bits of the virtual address | ||
1176 | * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) | ||
1177 | */ | ||
1178 | |||
1179 | curidx = d->sbdma_remptr - d->sbdma_dscrtable; | ||
1180 | hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - | ||
1181 | d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t)); | ||
1182 | |||
1183 | /* | ||
1184 | * If they're the same, that means we've processed all | ||
1185 | * of the descriptors up to (but not including) the one that | ||
1186 | * the hardware is working on right now. | ||
1187 | */ | ||
1188 | |||
1189 | if (curidx == hwidx) | ||
1190 | break; | ||
1191 | |||
1192 | /* | ||
1193 | * Otherwise, get the packet's sk_buff ptr back | ||
1194 | */ | ||
1195 | |||
1196 | dsc = &(d->sbdma_dscrtable[curidx]); | ||
1197 | sb = d->sbdma_ctxtable[curidx]; | ||
1198 | d->sbdma_ctxtable[curidx] = NULL; | ||
1199 | |||
1200 | len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4; | ||
1201 | |||
1202 | /* | ||
1203 | * Check packet status. If good, process it. | ||
1204 | * If not, silently drop it and put it back on the | ||
1205 | * receive ring. | ||
1206 | */ | ||
1207 | |||
1208 | if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) { | ||
1209 | |||
1210 | /* | ||
1211 | * Add a new buffer to replace the old one. If we fail | ||
1212 | * to allocate a buffer, we're going to drop this | ||
1213 | * packet and put it right back on the receive ring. | ||
1214 | */ | ||
1215 | |||
1216 | if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) { | ||
1217 | sc->sbm_stats.rx_dropped++; | ||
1218 | sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */ | ||
1219 | } else { | ||
1220 | /* | ||
1221 | * Set length into the packet | ||
1222 | */ | ||
1223 | skb_put(sb,len); | ||
1224 | |||
1225 | /* | ||
1226 | * Buffer has been replaced on the | ||
1227 | * receive ring. Pass the buffer to | ||
1228 | * the kernel | ||
1229 | */ | ||
1230 | sc->sbm_stats.rx_bytes += len; | ||
1231 | sc->sbm_stats.rx_packets++; | ||
1232 | sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); | ||
1233 | /* Check hw IPv4/TCP checksum if supported */ | ||
1234 | if (sc->rx_hw_checksum == ENABLE) { | ||
1235 | if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) && | ||
1236 | !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) { | ||
1237 | sb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1238 | /* don't need to set sb->csum */ | ||
1239 | } else { | ||
1240 | sb->ip_summed = CHECKSUM_NONE; | ||
1241 | } | ||
1242 | } | ||
1243 | |||
1244 | netif_rx(sb); | ||
1245 | } | ||
1246 | } else { | ||
1247 | /* | ||
1248 | * Packet was mangled somehow. Just drop it and | ||
1249 | * put it back on the receive ring. | ||
1250 | */ | ||
1251 | sc->sbm_stats.rx_errors++; | ||
1252 | sbdma_add_rcvbuffer(d,sb); | ||
1253 | } | ||
1254 | |||
1255 | |||
1256 | /* | ||
1257 | * .. and advance to the next buffer. | ||
1258 | */ | ||
1259 | |||
1260 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1261 | |||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | |||
1267 | /********************************************************************** | ||
1268 | * SBDMA_TX_PROCESS(sc,d) | ||
1269 | * | ||
1270 | * Process "completed" transmit buffers on the specified DMA channel. | ||
1271 | * This is normally called within the interrupt service routine. | ||
1272 | * Note that this isn't really ideal for priority channels, since | ||
1273 | * it processes all of the packets on a given channel before | ||
1274 | * returning. | ||
1275 | * | ||
1276 | * Input parameters: | ||
1277 | * sc - softc structure | ||
1278 | * d - DMA channel context | ||
1279 | * | ||
1280 | * Return value: | ||
1281 | * nothing | ||
1282 | ********************************************************************* */ | ||
1283 | |||
1284 | static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d) | ||
1285 | { | ||
1286 | int curidx; | ||
1287 | int hwidx; | ||
1288 | sbdmadscr_t *dsc; | ||
1289 | struct sk_buff *sb; | ||
1290 | unsigned long flags; | ||
1291 | |||
1292 | spin_lock_irqsave(&(sc->sbm_lock), flags); | ||
1293 | |||
1294 | for (;;) { | ||
1295 | /* | ||
1296 | * figure out where we are (as an index) and where | ||
1297 | * the hardware is (also as an index) | ||
1298 | * | ||
1299 | * This could be done faster if (for example) the | ||
1300 | * descriptor table was page-aligned and contiguous in | ||
1301 | * both virtual and physical memory -- you could then | ||
1302 | * just compare the low-order bits of the virtual address | ||
1303 | * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) | ||
1304 | */ | ||
1305 | |||
1306 | curidx = d->sbdma_remptr - d->sbdma_dscrtable; | ||
1307 | hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - | ||
1308 | d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t)); | ||
1309 | |||
1310 | /* | ||
1311 | * If they're the same, that means we've processed all | ||
1312 | * of the descriptors up to (but not including) the one that | ||
1313 | * the hardware is working on right now. | ||
1314 | */ | ||
1315 | |||
1316 | if (curidx == hwidx) | ||
1317 | break; | ||
1318 | |||
1319 | /* | ||
1320 | * Otherwise, get the packet's sk_buff ptr back | ||
1321 | */ | ||
1322 | |||
1323 | dsc = &(d->sbdma_dscrtable[curidx]); | ||
1324 | sb = d->sbdma_ctxtable[curidx]; | ||
1325 | d->sbdma_ctxtable[curidx] = NULL; | ||
1326 | |||
1327 | /* | ||
1328 | * Stats | ||
1329 | */ | ||
1330 | |||
1331 | sc->sbm_stats.tx_bytes += sb->len; | ||
1332 | sc->sbm_stats.tx_packets++; | ||
1333 | |||
1334 | /* | ||
1335 | * for transmits, we just free buffers. | ||
1336 | */ | ||
1337 | |||
1338 | dev_kfree_skb_irq(sb); | ||
1339 | |||
1340 | /* | ||
1341 | * .. and advance to the next buffer. | ||
1342 | */ | ||
1343 | |||
1344 | d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); | ||
1345 | |||
1346 | } | ||
1347 | |||
1348 | /* | ||
1349 | * Decide if we should wake up the protocol or not. | ||
1350 | * Other drivers seem to do this when we reach a low | ||
1351 | * watermark on the transmit queue. | ||
1352 | */ | ||
1353 | |||
1354 | netif_wake_queue(d->sbdma_eth->sbm_dev); | ||
1355 | |||
1356 | spin_unlock_irqrestore(&(sc->sbm_lock), flags); | ||
1357 | |||
1358 | } | ||
1359 | |||
1360 | |||
1361 | |||
1362 | /********************************************************************** | ||
1363 | * SBMAC_INITCTX(s) | ||
1364 | * | ||
1365 | * Initialize an Ethernet context structure - this is called | ||
1366 | * once per MAC on the 1250. Memory is allocated here, so don't | ||
1367 | * call it again from inside the ioctl routines that bring the | ||
1368 | * interface up/down | ||
1369 | * | ||
1370 | * Input parameters: | ||
1371 | * s - sbmac context structure | ||
1372 | * | ||
1373 | * Return value: | ||
1374 | * 0 | ||
1375 | ********************************************************************* */ | ||
1376 | |||
1377 | static int sbmac_initctx(struct sbmac_softc *s) | ||
1378 | { | ||
1379 | |||
1380 | /* | ||
1381 | * figure out the addresses of some ports | ||
1382 | */ | ||
1383 | |||
1384 | s->sbm_macenable = s->sbm_base + R_MAC_ENABLE; | ||
1385 | s->sbm_maccfg = s->sbm_base + R_MAC_CFG; | ||
1386 | s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG; | ||
1387 | s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG; | ||
1388 | s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG; | ||
1389 | s->sbm_isr = s->sbm_base + R_MAC_STATUS; | ||
1390 | s->sbm_imr = s->sbm_base + R_MAC_INT_MASK; | ||
1391 | s->sbm_mdio = s->sbm_base + R_MAC_MDIO; | ||
1392 | |||
1393 | s->sbm_phys[0] = 1; | ||
1394 | s->sbm_phys[1] = 0; | ||
1395 | |||
1396 | s->sbm_phy_oldbmsr = 0; | ||
1397 | s->sbm_phy_oldanlpar = 0; | ||
1398 | s->sbm_phy_oldk1stsr = 0; | ||
1399 | s->sbm_phy_oldlinkstat = 0; | ||
1400 | |||
1401 | /* | ||
1402 | * Initialize the DMA channels. Right now, only one per MAC is used | ||
1403 | * Note: Only do this _once_, as it allocates memory from the kernel! | ||
1404 | */ | ||
1405 | |||
1406 | sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR); | ||
1407 | sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR); | ||
1408 | |||
1409 | /* | ||
1410 | * initial state is OFF | ||
1411 | */ | ||
1412 | |||
1413 | s->sbm_state = sbmac_state_off; | ||
1414 | |||
1415 | /* | ||
1416 | * Initial speed is (XXX TEMP) 10MBit/s HDX no FC | ||
1417 | */ | ||
1418 | |||
1419 | s->sbm_speed = sbmac_speed_10; | ||
1420 | s->sbm_duplex = sbmac_duplex_half; | ||
1421 | s->sbm_fc = sbmac_fc_disabled; | ||
1422 | |||
1423 | return 0; | ||
1424 | } | ||
1425 | |||
1426 | |||
1427 | static void sbdma_uninitctx(struct sbmacdma_s *d) | ||
1428 | { | ||
1429 | if (d->sbdma_dscrtable) { | ||
1430 | kfree(d->sbdma_dscrtable); | ||
1431 | d->sbdma_dscrtable = NULL; | ||
1432 | } | ||
1433 | |||
1434 | if (d->sbdma_ctxtable) { | ||
1435 | kfree(d->sbdma_ctxtable); | ||
1436 | d->sbdma_ctxtable = NULL; | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1440 | |||
1441 | static void sbmac_uninitctx(struct sbmac_softc *sc) | ||
1442 | { | ||
1443 | sbdma_uninitctx(&(sc->sbm_txdma)); | ||
1444 | sbdma_uninitctx(&(sc->sbm_rxdma)); | ||
1445 | } | ||
1446 | |||
1447 | |||
1448 | /********************************************************************** | ||
1449 | * SBMAC_CHANNEL_START(s) | ||
1450 | * | ||
1451 | * Start packet processing on this MAC. | ||
1452 | * | ||
1453 | * Input parameters: | ||
1454 | * s - sbmac structure | ||
1455 | * | ||
1456 | * Return value: | ||
1457 | * nothing | ||
1458 | ********************************************************************* */ | ||
1459 | |||
1460 | static void sbmac_channel_start(struct sbmac_softc *s) | ||
1461 | { | ||
1462 | uint64_t reg; | ||
1463 | sbmac_port_t port; | ||
1464 | uint64_t cfg,fifo,framecfg; | ||
1465 | int idx, th_value; | ||
1466 | |||
1467 | /* | ||
1468 | * Don't do this if running | ||
1469 | */ | ||
1470 | |||
1471 | if (s->sbm_state == sbmac_state_on) | ||
1472 | return; | ||
1473 | |||
1474 | /* | ||
1475 | * Bring the controller out of reset, but leave it off. | ||
1476 | */ | ||
1477 | |||
1478 | SBMAC_WRITECSR(s->sbm_macenable,0); | ||
1479 | |||
1480 | /* | ||
1481 | * Ignore all received packets | ||
1482 | */ | ||
1483 | |||
1484 | SBMAC_WRITECSR(s->sbm_rxfilter,0); | ||
1485 | |||
1486 | /* | ||
1487 | * Calculate values for various control registers. | ||
1488 | */ | ||
1489 | |||
1490 | cfg = M_MAC_RETRY_EN | | ||
1491 | M_MAC_TX_HOLD_SOP_EN | | ||
1492 | V_MAC_TX_PAUSE_CNT_16K | | ||
1493 | M_MAC_AP_STAT_EN | | ||
1494 | M_MAC_FAST_SYNC | | ||
1495 | M_MAC_SS_EN | | ||
1496 | 0; | ||
1497 | |||
1498 | /* | ||
1499 | * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars | ||
1500 | * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above | ||
1501 | * Use a larger RD_THRSH for gigabit | ||
1502 | */ | ||
1503 | if (periph_rev >= 2) | ||
1504 | th_value = 64; | ||
1505 | else | ||
1506 | th_value = 28; | ||
1507 | |||
1508 | fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ | ||
1509 | ((s->sbm_speed == sbmac_speed_1000) | ||
1510 | ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) | | ||
1511 | V_MAC_TX_RL_THRSH(4) | | ||
1512 | V_MAC_RX_PL_THRSH(4) | | ||
1513 | V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ | ||
1514 | V_MAC_RX_PL_THRSH(4) | | ||
1515 | V_MAC_RX_RL_THRSH(8) | | ||
1516 | 0; | ||
1517 | |||
1518 | framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | | ||
1519 | V_MAC_MAX_FRAMESZ_DEFAULT | | ||
1520 | V_MAC_BACKOFF_SEL(1); | ||
1521 | |||
1522 | /* | ||
1523 | * Clear out the hash address map | ||
1524 | */ | ||
1525 | |||
1526 | port = s->sbm_base + R_MAC_HASH_BASE; | ||
1527 | for (idx = 0; idx < MAC_HASH_COUNT; idx++) { | ||
1528 | SBMAC_WRITECSR(port,0); | ||
1529 | port += sizeof(uint64_t); | ||
1530 | } | ||
1531 | |||
1532 | /* | ||
1533 | * Clear out the exact-match table | ||
1534 | */ | ||
1535 | |||
1536 | port = s->sbm_base + R_MAC_ADDR_BASE; | ||
1537 | for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { | ||
1538 | SBMAC_WRITECSR(port,0); | ||
1539 | port += sizeof(uint64_t); | ||
1540 | } | ||
1541 | |||
1542 | /* | ||
1543 | * Clear out the DMA Channel mapping table registers | ||
1544 | */ | ||
1545 | |||
1546 | port = s->sbm_base + R_MAC_CHUP0_BASE; | ||
1547 | for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { | ||
1548 | SBMAC_WRITECSR(port,0); | ||
1549 | port += sizeof(uint64_t); | ||
1550 | } | ||
1551 | |||
1552 | |||
1553 | port = s->sbm_base + R_MAC_CHLO0_BASE; | ||
1554 | for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { | ||
1555 | SBMAC_WRITECSR(port,0); | ||
1556 | port += sizeof(uint64_t); | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1560 | * Program the hardware address. It goes into the hardware-address | ||
1561 | * register as well as the first filter register. | ||
1562 | */ | ||
1563 | |||
1564 | reg = sbmac_addr2reg(s->sbm_hwaddr); | ||
1565 | |||
1566 | port = s->sbm_base + R_MAC_ADDR_BASE; | ||
1567 | SBMAC_WRITECSR(port,reg); | ||
1568 | port = s->sbm_base + R_MAC_ETHERNET_ADDR; | ||
1569 | |||
1570 | #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS | ||
1571 | /* | ||
1572 | * Pass1 SOCs do not receive packets addressed to the | ||
1573 | * destination address in the R_MAC_ETHERNET_ADDR register. | ||
1574 | * Set the value to zero. | ||
1575 | */ | ||
1576 | SBMAC_WRITECSR(port,0); | ||
1577 | #else | ||
1578 | SBMAC_WRITECSR(port,reg); | ||
1579 | #endif | ||
1580 | |||
1581 | /* | ||
1582 | * Set the receive filter for no packets, and write values | ||
1583 | * to the various config registers | ||
1584 | */ | ||
1585 | |||
1586 | SBMAC_WRITECSR(s->sbm_rxfilter,0); | ||
1587 | SBMAC_WRITECSR(s->sbm_imr,0); | ||
1588 | SBMAC_WRITECSR(s->sbm_framecfg,framecfg); | ||
1589 | SBMAC_WRITECSR(s->sbm_fifocfg,fifo); | ||
1590 | SBMAC_WRITECSR(s->sbm_maccfg,cfg); | ||
1591 | |||
1592 | /* | ||
1593 | * Initialize DMA channels (rings should be ok now) | ||
1594 | */ | ||
1595 | |||
1596 | sbdma_channel_start(&(s->sbm_rxdma), DMA_RX); | ||
1597 | sbdma_channel_start(&(s->sbm_txdma), DMA_TX); | ||
1598 | |||
1599 | /* | ||
1600 | * Configure the speed, duplex, and flow control | ||
1601 | */ | ||
1602 | |||
1603 | sbmac_set_speed(s,s->sbm_speed); | ||
1604 | sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc); | ||
1605 | |||
1606 | /* | ||
1607 | * Fill the receive ring | ||
1608 | */ | ||
1609 | |||
1610 | sbdma_fillring(&(s->sbm_rxdma)); | ||
1611 | |||
1612 | /* | ||
1613 | * Turn on the rest of the bits in the enable register | ||
1614 | */ | ||
1615 | |||
1616 | SBMAC_WRITECSR(s->sbm_macenable, | ||
1617 | M_MAC_RXDMA_EN0 | | ||
1618 | M_MAC_TXDMA_EN0 | | ||
1619 | M_MAC_RX_ENABLE | | ||
1620 | M_MAC_TX_ENABLE); | ||
1621 | |||
1622 | |||
1623 | |||
1624 | |||
1625 | #ifdef CONFIG_SBMAC_COALESCE | ||
1626 | /* | ||
1627 | * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0 | ||
1628 | */ | ||
1629 | SBMAC_WRITECSR(s->sbm_imr, | ||
1630 | ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | | ||
1631 | ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0)); | ||
1632 | #else | ||
1633 | /* | ||
1634 | * Accept any kind of interrupt on TX and RX DMA channel 0 | ||
1635 | */ | ||
1636 | SBMAC_WRITECSR(s->sbm_imr, | ||
1637 | (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | | ||
1638 | (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)); | ||
1639 | #endif | ||
1640 | |||
1641 | /* | ||
1642 | * Enable receiving unicasts and broadcasts | ||
1643 | */ | ||
1644 | |||
1645 | SBMAC_WRITECSR(s->sbm_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN); | ||
1646 | |||
1647 | /* | ||
1648 | * we're running now. | ||
1649 | */ | ||
1650 | |||
1651 | s->sbm_state = sbmac_state_on; | ||
1652 | |||
1653 | /* | ||
1654 | * Program multicast addresses | ||
1655 | */ | ||
1656 | |||
1657 | sbmac_setmulti(s); | ||
1658 | |||
1659 | /* | ||
1660 | * If channel was in promiscuous mode before, turn that on | ||
1661 | */ | ||
1662 | |||
1663 | if (s->sbm_devflags & IFF_PROMISC) { | ||
1664 | sbmac_promiscuous_mode(s,1); | ||
1665 | } | ||
1666 | |||
1667 | } | ||
1668 | |||
1669 | |||
1670 | /********************************************************************** | ||
1671 | * SBMAC_CHANNEL_STOP(s) | ||
1672 | * | ||
1673 | * Stop packet processing on this MAC. | ||
1674 | * | ||
1675 | * Input parameters: | ||
1676 | * s - sbmac structure | ||
1677 | * | ||
1678 | * Return value: | ||
1679 | * nothing | ||
1680 | ********************************************************************* */ | ||
1681 | |||
1682 | static void sbmac_channel_stop(struct sbmac_softc *s) | ||
1683 | { | ||
1684 | /* don't do this if already stopped */ | ||
1685 | |||
1686 | if (s->sbm_state == sbmac_state_off) | ||
1687 | return; | ||
1688 | |||
1689 | /* don't accept any packets, disable all interrupts */ | ||
1690 | |||
1691 | SBMAC_WRITECSR(s->sbm_rxfilter,0); | ||
1692 | SBMAC_WRITECSR(s->sbm_imr,0); | ||
1693 | |||
1694 | /* Turn off ticker */ | ||
1695 | |||
1696 | /* XXX */ | ||
1697 | |||
1698 | /* turn off receiver and transmitter */ | ||
1699 | |||
1700 | SBMAC_WRITECSR(s->sbm_macenable,0); | ||
1701 | |||
1702 | /* We're stopped now. */ | ||
1703 | |||
1704 | s->sbm_state = sbmac_state_off; | ||
1705 | |||
1706 | /* | ||
1707 | * Stop DMA channels (rings should be ok now) | ||
1708 | */ | ||
1709 | |||
1710 | sbdma_channel_stop(&(s->sbm_rxdma)); | ||
1711 | sbdma_channel_stop(&(s->sbm_txdma)); | ||
1712 | |||
1713 | /* Empty the receive and transmit rings */ | ||
1714 | |||
1715 | sbdma_emptyring(&(s->sbm_rxdma)); | ||
1716 | sbdma_emptyring(&(s->sbm_txdma)); | ||
1717 | |||
1718 | } | ||
1719 | |||
1720 | /********************************************************************** | ||
1721 | * SBMAC_SET_CHANNEL_STATE(state) | ||
1722 | * | ||
1723 | * Set the channel's state ON or OFF | ||
1724 | * | ||
1725 | * Input parameters: | ||
1726 | * state - new state | ||
1727 | * | ||
1728 | * Return value: | ||
1729 | * old state | ||
1730 | ********************************************************************* */ | ||
1731 | static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *sc, | ||
1732 | sbmac_state_t state) | ||
1733 | { | ||
1734 | sbmac_state_t oldstate = sc->sbm_state; | ||
1735 | |||
1736 | /* | ||
1737 | * If same as previous state, return | ||
1738 | */ | ||
1739 | |||
1740 | if (state == oldstate) { | ||
1741 | return oldstate; | ||
1742 | } | ||
1743 | |||
1744 | /* | ||
1745 | * If new state is ON, turn channel on | ||
1746 | */ | ||
1747 | |||
1748 | if (state == sbmac_state_on) { | ||
1749 | sbmac_channel_start(sc); | ||
1750 | } | ||
1751 | else { | ||
1752 | sbmac_channel_stop(sc); | ||
1753 | } | ||
1754 | |||
1755 | /* | ||
1756 | * Return previous state | ||
1757 | */ | ||
1758 | |||
1759 | return oldstate; | ||
1760 | } | ||
1761 | |||
1762 | |||
1763 | /********************************************************************** | ||
1764 | * SBMAC_PROMISCUOUS_MODE(sc,onoff) | ||
1765 | * | ||
1766 | * Turn on or off promiscuous mode | ||
1767 | * | ||
1768 | * Input parameters: | ||
1769 | * sc - softc | ||
1770 | * onoff - 1 to turn on, 0 to turn off | ||
1771 | * | ||
1772 | * Return value: | ||
1773 | * nothing | ||
1774 | ********************************************************************* */ | ||
1775 | |||
1776 | static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff) | ||
1777 | { | ||
1778 | uint64_t reg; | ||
1779 | |||
1780 | if (sc->sbm_state != sbmac_state_on) | ||
1781 | return; | ||
1782 | |||
1783 | if (onoff) { | ||
1784 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
1785 | reg |= M_MAC_ALLPKT_EN; | ||
1786 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
1787 | } | ||
1788 | else { | ||
1789 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
1790 | reg &= ~M_MAC_ALLPKT_EN; | ||
1791 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
1792 | } | ||
1793 | } | ||
1794 | |||
1795 | /********************************************************************** | ||
1796 | * SBMAC_SETIPHDR_OFFSET(sc,onoff) | ||
1797 | * | ||
1798 | * Set the iphdr offset as 15 assuming ethernet encapsulation | ||
1799 | * | ||
1800 | * Input parameters: | ||
1801 | * sc - softc | ||
1802 | * | ||
1803 | * Return value: | ||
1804 | * nothing | ||
1805 | ********************************************************************* */ | ||
1806 | |||
1807 | static void sbmac_set_iphdr_offset(struct sbmac_softc *sc) | ||
1808 | { | ||
1809 | uint64_t reg; | ||
1810 | |||
1811 | /* Hard code the off set to 15 for now */ | ||
1812 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
1813 | reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); | ||
1814 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
1815 | |||
1816 | /* read system identification to determine revision */ | ||
1817 | if (periph_rev >= 2) { | ||
1818 | sc->rx_hw_checksum = ENABLE; | ||
1819 | } else { | ||
1820 | sc->rx_hw_checksum = DISABLE; | ||
1821 | } | ||
1822 | } | ||
1823 | |||
1824 | |||
1825 | /********************************************************************** | ||
1826 | * SBMAC_ADDR2REG(ptr) | ||
1827 | * | ||
1828 | * Convert six bytes into the 64-bit register value that | ||
1829 | * we typically write into the SBMAC's address/mcast registers | ||
1830 | * | ||
1831 | * Input parameters: | ||
1832 | * ptr - pointer to 6 bytes | ||
1833 | * | ||
1834 | * Return value: | ||
1835 | * register value | ||
1836 | ********************************************************************* */ | ||
1837 | |||
1838 | static uint64_t sbmac_addr2reg(unsigned char *ptr) | ||
1839 | { | ||
1840 | uint64_t reg = 0; | ||
1841 | |||
1842 | ptr += 6; | ||
1843 | |||
1844 | reg |= (uint64_t) *(--ptr); | ||
1845 | reg <<= 8; | ||
1846 | reg |= (uint64_t) *(--ptr); | ||
1847 | reg <<= 8; | ||
1848 | reg |= (uint64_t) *(--ptr); | ||
1849 | reg <<= 8; | ||
1850 | reg |= (uint64_t) *(--ptr); | ||
1851 | reg <<= 8; | ||
1852 | reg |= (uint64_t) *(--ptr); | ||
1853 | reg <<= 8; | ||
1854 | reg |= (uint64_t) *(--ptr); | ||
1855 | |||
1856 | return reg; | ||
1857 | } | ||
1858 | |||
1859 | |||
1860 | /********************************************************************** | ||
1861 | * SBMAC_SET_SPEED(s,speed) | ||
1862 | * | ||
1863 | * Configure LAN speed for the specified MAC. | ||
1864 | * Warning: must be called when MAC is off! | ||
1865 | * | ||
1866 | * Input parameters: | ||
1867 | * s - sbmac structure | ||
1868 | * speed - speed to set MAC to (see sbmac_speed_t enum) | ||
1869 | * | ||
1870 | * Return value: | ||
1871 | * 1 if successful | ||
1872 | * 0 indicates invalid parameters | ||
1873 | ********************************************************************* */ | ||
1874 | |||
1875 | static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed) | ||
1876 | { | ||
1877 | uint64_t cfg; | ||
1878 | uint64_t framecfg; | ||
1879 | |||
1880 | /* | ||
1881 | * Save new current values | ||
1882 | */ | ||
1883 | |||
1884 | s->sbm_speed = speed; | ||
1885 | |||
1886 | if (s->sbm_state == sbmac_state_on) | ||
1887 | return 0; /* save for next restart */ | ||
1888 | |||
1889 | /* | ||
1890 | * Read current register values | ||
1891 | */ | ||
1892 | |||
1893 | cfg = SBMAC_READCSR(s->sbm_maccfg); | ||
1894 | framecfg = SBMAC_READCSR(s->sbm_framecfg); | ||
1895 | |||
1896 | /* | ||
1897 | * Mask out the stuff we want to change | ||
1898 | */ | ||
1899 | |||
1900 | cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); | ||
1901 | framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | | ||
1902 | M_MAC_SLOT_SIZE); | ||
1903 | |||
1904 | /* | ||
1905 | * Now add in the new bits | ||
1906 | */ | ||
1907 | |||
1908 | switch (speed) { | ||
1909 | case sbmac_speed_10: | ||
1910 | framecfg |= V_MAC_IFG_RX_10 | | ||
1911 | V_MAC_IFG_TX_10 | | ||
1912 | K_MAC_IFG_THRSH_10 | | ||
1913 | V_MAC_SLOT_SIZE_10; | ||
1914 | cfg |= V_MAC_SPEED_SEL_10MBPS; | ||
1915 | break; | ||
1916 | |||
1917 | case sbmac_speed_100: | ||
1918 | framecfg |= V_MAC_IFG_RX_100 | | ||
1919 | V_MAC_IFG_TX_100 | | ||
1920 | V_MAC_IFG_THRSH_100 | | ||
1921 | V_MAC_SLOT_SIZE_100; | ||
1922 | cfg |= V_MAC_SPEED_SEL_100MBPS ; | ||
1923 | break; | ||
1924 | |||
1925 | case sbmac_speed_1000: | ||
1926 | framecfg |= V_MAC_IFG_RX_1000 | | ||
1927 | V_MAC_IFG_TX_1000 | | ||
1928 | V_MAC_IFG_THRSH_1000 | | ||
1929 | V_MAC_SLOT_SIZE_1000; | ||
1930 | cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; | ||
1931 | break; | ||
1932 | |||
1933 | case sbmac_speed_auto: /* XXX not implemented */ | ||
1934 | /* fall through */ | ||
1935 | default: | ||
1936 | return 0; | ||
1937 | } | ||
1938 | |||
1939 | /* | ||
1940 | * Send the bits back to the hardware | ||
1941 | */ | ||
1942 | |||
1943 | SBMAC_WRITECSR(s->sbm_framecfg,framecfg); | ||
1944 | SBMAC_WRITECSR(s->sbm_maccfg,cfg); | ||
1945 | |||
1946 | return 1; | ||
1947 | } | ||
1948 | |||
1949 | /********************************************************************** | ||
1950 | * SBMAC_SET_DUPLEX(s,duplex,fc) | ||
1951 | * | ||
1952 | * Set Ethernet duplex and flow control options for this MAC | ||
1953 | * Warning: must be called when MAC is off! | ||
1954 | * | ||
1955 | * Input parameters: | ||
1956 | * s - sbmac structure | ||
1957 | * duplex - duplex setting (see sbmac_duplex_t) | ||
1958 | * fc - flow control setting (see sbmac_fc_t) | ||
1959 | * | ||
1960 | * Return value: | ||
1961 | * 1 if ok | ||
1962 | * 0 if an invalid parameter combination was specified | ||
1963 | ********************************************************************* */ | ||
1964 | |||
1965 | static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc) | ||
1966 | { | ||
1967 | uint64_t cfg; | ||
1968 | |||
1969 | /* | ||
1970 | * Save new current values | ||
1971 | */ | ||
1972 | |||
1973 | s->sbm_duplex = duplex; | ||
1974 | s->sbm_fc = fc; | ||
1975 | |||
1976 | if (s->sbm_state == sbmac_state_on) | ||
1977 | return 0; /* save for next restart */ | ||
1978 | |||
1979 | /* | ||
1980 | * Read current register values | ||
1981 | */ | ||
1982 | |||
1983 | cfg = SBMAC_READCSR(s->sbm_maccfg); | ||
1984 | |||
1985 | /* | ||
1986 | * Mask off the stuff we're about to change | ||
1987 | */ | ||
1988 | |||
1989 | cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); | ||
1990 | |||
1991 | |||
1992 | switch (duplex) { | ||
1993 | case sbmac_duplex_half: | ||
1994 | switch (fc) { | ||
1995 | case sbmac_fc_disabled: | ||
1996 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; | ||
1997 | break; | ||
1998 | |||
1999 | case sbmac_fc_collision: | ||
2000 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; | ||
2001 | break; | ||
2002 | |||
2003 | case sbmac_fc_carrier: | ||
2004 | cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; | ||
2005 | break; | ||
2006 | |||
2007 | case sbmac_fc_auto: /* XXX not implemented */ | ||
2008 | /* fall through */ | ||
2009 | case sbmac_fc_frame: /* not valid in half duplex */ | ||
2010 | default: /* invalid selection */ | ||
2011 | return 0; | ||
2012 | } | ||
2013 | break; | ||
2014 | |||
2015 | case sbmac_duplex_full: | ||
2016 | switch (fc) { | ||
2017 | case sbmac_fc_disabled: | ||
2018 | cfg |= V_MAC_FC_CMD_DISABLED; | ||
2019 | break; | ||
2020 | |||
2021 | case sbmac_fc_frame: | ||
2022 | cfg |= V_MAC_FC_CMD_ENABLED; | ||
2023 | break; | ||
2024 | |||
2025 | case sbmac_fc_collision: /* not valid in full duplex */ | ||
2026 | case sbmac_fc_carrier: /* not valid in full duplex */ | ||
2027 | case sbmac_fc_auto: /* XXX not implemented */ | ||
2028 | /* fall through */ | ||
2029 | default: | ||
2030 | return 0; | ||
2031 | } | ||
2032 | break; | ||
2033 | case sbmac_duplex_auto: | ||
2034 | /* XXX not implemented */ | ||
2035 | break; | ||
2036 | } | ||
2037 | |||
2038 | /* | ||
2039 | * Send the bits back to the hardware | ||
2040 | */ | ||
2041 | |||
2042 | SBMAC_WRITECSR(s->sbm_maccfg,cfg); | ||
2043 | |||
2044 | return 1; | ||
2045 | } | ||
2046 | |||
2047 | |||
2048 | |||
2049 | |||
2050 | /********************************************************************** | ||
2051 | * SBMAC_INTR() | ||
2052 | * | ||
2053 | * Interrupt handler for MAC interrupts | ||
2054 | * | ||
2055 | * Input parameters: | ||
2056 | * MAC structure | ||
2057 | * | ||
2058 | * Return value: | ||
2059 | * nothing | ||
2060 | ********************************************************************* */ | ||
2061 | static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs) | ||
2062 | { | ||
2063 | struct net_device *dev = (struct net_device *) dev_instance; | ||
2064 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2065 | uint64_t isr; | ||
2066 | int handled = 0; | ||
2067 | |||
2068 | for (;;) { | ||
2069 | |||
2070 | /* | ||
2071 | * Read the ISR (this clears the bits in the real | ||
2072 | * register, except for counter addr) | ||
2073 | */ | ||
2074 | |||
2075 | isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR; | ||
2076 | |||
2077 | if (isr == 0) | ||
2078 | break; | ||
2079 | |||
2080 | handled = 1; | ||
2081 | |||
2082 | /* | ||
2083 | * Transmits on channel 0 | ||
2084 | */ | ||
2085 | |||
2086 | if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) { | ||
2087 | sbdma_tx_process(sc,&(sc->sbm_txdma)); | ||
2088 | } | ||
2089 | |||
2090 | /* | ||
2091 | * Receives on channel 0 | ||
2092 | */ | ||
2093 | |||
2094 | /* | ||
2095 | * It's important to test all the bits (or at least the | ||
2096 | * EOP_SEEN bit) when deciding to do the RX process | ||
2097 | * particularly when coalescing, to make sure we | ||
2098 | * take care of the following: | ||
2099 | * | ||
2100 | * If you have some packets waiting (have been received | ||
2101 | * but no interrupt) and get a TX interrupt before | ||
2102 | * the RX timer or counter expires, reading the ISR | ||
2103 | * above will clear the timer and counter, and you | ||
2104 | * won't get another interrupt until a packet shows | ||
2105 | * up to start the timer again. Testing | ||
2106 | * EOP_SEEN here takes care of this case. | ||
2107 | * (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0) | ||
2108 | */ | ||
2109 | |||
2110 | |||
2111 | if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { | ||
2112 | sbdma_rx_process(sc,&(sc->sbm_rxdma)); | ||
2113 | } | ||
2114 | } | ||
2115 | return IRQ_RETVAL(handled); | ||
2116 | } | ||
2117 | |||
2118 | |||
2119 | /********************************************************************** | ||
2120 | * SBMAC_START_TX(skb,dev) | ||
2121 | * | ||
2122 | * Start output on the specified interface. Basically, we | ||
2123 | * queue as many buffers as we can until the ring fills up, or | ||
2124 | * we run off the end of the queue, whichever comes first. | ||
2125 | * | ||
2126 | * Input parameters: | ||
2127 | * | ||
2128 | * | ||
2129 | * Return value: | ||
2130 | * nothing | ||
2131 | ********************************************************************* */ | ||
2132 | static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) | ||
2133 | { | ||
2134 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2135 | |||
2136 | /* lock eth irq */ | ||
2137 | spin_lock_irq (&sc->sbm_lock); | ||
2138 | |||
2139 | /* | ||
2140 | * Put the buffer on the transmit ring. If we | ||
2141 | * don't have room, stop the queue. | ||
2142 | */ | ||
2143 | |||
2144 | if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { | ||
2145 | /* XXX save skb that we could not send */ | ||
2146 | netif_stop_queue(dev); | ||
2147 | spin_unlock_irq(&sc->sbm_lock); | ||
2148 | |||
2149 | return 1; | ||
2150 | } | ||
2151 | |||
2152 | dev->trans_start = jiffies; | ||
2153 | |||
2154 | spin_unlock_irq (&sc->sbm_lock); | ||
2155 | |||
2156 | return 0; | ||
2157 | } | ||
2158 | |||
2159 | /********************************************************************** | ||
2160 | * SBMAC_SETMULTI(sc) | ||
2161 | * | ||
2162 | * Reprogram the multicast table into the hardware, given | ||
2163 | * the list of multicasts associated with the interface | ||
2164 | * structure. | ||
2165 | * | ||
2166 | * Input parameters: | ||
2167 | * sc - softc | ||
2168 | * | ||
2169 | * Return value: | ||
2170 | * nothing | ||
2171 | ********************************************************************* */ | ||
2172 | |||
2173 | static void sbmac_setmulti(struct sbmac_softc *sc) | ||
2174 | { | ||
2175 | uint64_t reg; | ||
2176 | sbmac_port_t port; | ||
2177 | int idx; | ||
2178 | struct dev_mc_list *mclist; | ||
2179 | struct net_device *dev = sc->sbm_dev; | ||
2180 | |||
2181 | /* | ||
2182 | * Clear out entire multicast table. We do this by nuking | ||
2183 | * the entire hash table and all the direct matches except | ||
2184 | * the first one, which is used for our station address | ||
2185 | */ | ||
2186 | |||
2187 | for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { | ||
2188 | port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)); | ||
2189 | SBMAC_WRITECSR(port,0); | ||
2190 | } | ||
2191 | |||
2192 | for (idx = 0; idx < MAC_HASH_COUNT; idx++) { | ||
2193 | port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)); | ||
2194 | SBMAC_WRITECSR(port,0); | ||
2195 | } | ||
2196 | |||
2197 | /* | ||
2198 | * Clear the filter to say we don't want any multicasts. | ||
2199 | */ | ||
2200 | |||
2201 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
2202 | reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN); | ||
2203 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
2204 | |||
2205 | if (dev->flags & IFF_ALLMULTI) { | ||
2206 | /* | ||
2207 | * Enable ALL multicasts. Do this by inverting the | ||
2208 | * multicast enable bit. | ||
2209 | */ | ||
2210 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
2211 | reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN); | ||
2212 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
2213 | return; | ||
2214 | } | ||
2215 | |||
2216 | |||
2217 | /* | ||
2218 | * Progam new multicast entries. For now, only use the | ||
2219 | * perfect filter. In the future we'll need to use the | ||
2220 | * hash filter if the perfect filter overflows | ||
2221 | */ | ||
2222 | |||
2223 | /* XXX only using perfect filter for now, need to use hash | ||
2224 | * XXX if the table overflows */ | ||
2225 | |||
2226 | idx = 1; /* skip station address */ | ||
2227 | mclist = dev->mc_list; | ||
2228 | while (mclist && (idx < MAC_ADDR_COUNT)) { | ||
2229 | reg = sbmac_addr2reg(mclist->dmi_addr); | ||
2230 | port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); | ||
2231 | SBMAC_WRITECSR(port,reg); | ||
2232 | idx++; | ||
2233 | mclist = mclist->next; | ||
2234 | } | ||
2235 | |||
2236 | /* | ||
2237 | * Enable the "accept multicast bits" if we programmed at least one | ||
2238 | * multicast. | ||
2239 | */ | ||
2240 | |||
2241 | if (idx > 1) { | ||
2242 | reg = SBMAC_READCSR(sc->sbm_rxfilter); | ||
2243 | reg |= M_MAC_MCAST_EN; | ||
2244 | SBMAC_WRITECSR(sc->sbm_rxfilter,reg); | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | |||
2249 | |||
2250 | #if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) | ||
2251 | /********************************************************************** | ||
2252 | * SBMAC_PARSE_XDIGIT(str) | ||
2253 | * | ||
2254 | * Parse a hex digit, returning its value | ||
2255 | * | ||
2256 | * Input parameters: | ||
2257 | * str - character | ||
2258 | * | ||
2259 | * Return value: | ||
2260 | * hex value, or -1 if invalid | ||
2261 | ********************************************************************* */ | ||
2262 | |||
2263 | static int sbmac_parse_xdigit(char str) | ||
2264 | { | ||
2265 | int digit; | ||
2266 | |||
2267 | if ((str >= '0') && (str <= '9')) | ||
2268 | digit = str - '0'; | ||
2269 | else if ((str >= 'a') && (str <= 'f')) | ||
2270 | digit = str - 'a' + 10; | ||
2271 | else if ((str >= 'A') && (str <= 'F')) | ||
2272 | digit = str - 'A' + 10; | ||
2273 | else | ||
2274 | return -1; | ||
2275 | |||
2276 | return digit; | ||
2277 | } | ||
2278 | |||
2279 | /********************************************************************** | ||
2280 | * SBMAC_PARSE_HWADDR(str,hwaddr) | ||
2281 | * | ||
2282 | * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte | ||
2283 | * Ethernet address. | ||
2284 | * | ||
2285 | * Input parameters: | ||
2286 | * str - string | ||
2287 | * hwaddr - pointer to hardware address | ||
2288 | * | ||
2289 | * Return value: | ||
2290 | * 0 if ok, else -1 | ||
2291 | ********************************************************************* */ | ||
2292 | |||
2293 | static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr) | ||
2294 | { | ||
2295 | int digit1,digit2; | ||
2296 | int idx = 6; | ||
2297 | |||
2298 | while (*str && (idx > 0)) { | ||
2299 | digit1 = sbmac_parse_xdigit(*str); | ||
2300 | if (digit1 < 0) | ||
2301 | return -1; | ||
2302 | str++; | ||
2303 | if (!*str) | ||
2304 | return -1; | ||
2305 | |||
2306 | if ((*str == ':') || (*str == '-')) { | ||
2307 | digit2 = digit1; | ||
2308 | digit1 = 0; | ||
2309 | } | ||
2310 | else { | ||
2311 | digit2 = sbmac_parse_xdigit(*str); | ||
2312 | if (digit2 < 0) | ||
2313 | return -1; | ||
2314 | str++; | ||
2315 | } | ||
2316 | |||
2317 | *hwaddr++ = (digit1 << 4) | digit2; | ||
2318 | idx--; | ||
2319 | |||
2320 | if (*str == '-') | ||
2321 | str++; | ||
2322 | if (*str == ':') | ||
2323 | str++; | ||
2324 | } | ||
2325 | return 0; | ||
2326 | } | ||
2327 | #endif | ||
2328 | |||
2329 | static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) | ||
2330 | { | ||
2331 | if (new_mtu > ENET_PACKET_SIZE) | ||
2332 | return -EINVAL; | ||
2333 | _dev->mtu = new_mtu; | ||
2334 | printk(KERN_INFO "changing the mtu to %d\n", new_mtu); | ||
2335 | return 0; | ||
2336 | } | ||
2337 | |||
2338 | /********************************************************************** | ||
2339 | * SBMAC_INIT(dev) | ||
2340 | * | ||
2341 | * Attach routine - init hardware and hook ourselves into linux | ||
2342 | * | ||
2343 | * Input parameters: | ||
2344 | * dev - net_device structure | ||
2345 | * | ||
2346 | * Return value: | ||
2347 | * status | ||
2348 | ********************************************************************* */ | ||
2349 | |||
2350 | static int sbmac_init(struct net_device *dev, int idx) | ||
2351 | { | ||
2352 | struct sbmac_softc *sc; | ||
2353 | unsigned char *eaddr; | ||
2354 | uint64_t ea_reg; | ||
2355 | int i; | ||
2356 | int err; | ||
2357 | |||
2358 | sc = netdev_priv(dev); | ||
2359 | |||
2360 | /* Determine controller base address */ | ||
2361 | |||
2362 | sc->sbm_base = IOADDR(dev->base_addr); | ||
2363 | sc->sbm_dev = dev; | ||
2364 | sc->sbe_idx = idx; | ||
2365 | |||
2366 | eaddr = sc->sbm_hwaddr; | ||
2367 | |||
2368 | /* | ||
2369 | * Read the ethernet address. The firwmare left this programmed | ||
2370 | * for us in the ethernet address register for each mac. | ||
2371 | */ | ||
2372 | |||
2373 | ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR); | ||
2374 | SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0); | ||
2375 | for (i = 0; i < 6; i++) { | ||
2376 | eaddr[i] = (uint8_t) (ea_reg & 0xFF); | ||
2377 | ea_reg >>= 8; | ||
2378 | } | ||
2379 | |||
2380 | for (i = 0; i < 6; i++) { | ||
2381 | dev->dev_addr[i] = eaddr[i]; | ||
2382 | } | ||
2383 | |||
2384 | |||
2385 | /* | ||
2386 | * Init packet size | ||
2387 | */ | ||
2388 | |||
2389 | sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN; | ||
2390 | |||
2391 | /* | ||
2392 | * Initialize context (get pointers to registers and stuff), then | ||
2393 | * allocate the memory for the descriptor tables. | ||
2394 | */ | ||
2395 | |||
2396 | sbmac_initctx(sc); | ||
2397 | |||
2398 | /* | ||
2399 | * Set up Linux device callins | ||
2400 | */ | ||
2401 | |||
2402 | spin_lock_init(&(sc->sbm_lock)); | ||
2403 | |||
2404 | dev->open = sbmac_open; | ||
2405 | dev->hard_start_xmit = sbmac_start_tx; | ||
2406 | dev->stop = sbmac_close; | ||
2407 | dev->get_stats = sbmac_get_stats; | ||
2408 | dev->set_multicast_list = sbmac_set_rx_mode; | ||
2409 | dev->do_ioctl = sbmac_mii_ioctl; | ||
2410 | dev->tx_timeout = sbmac_tx_timeout; | ||
2411 | dev->watchdog_timeo = TX_TIMEOUT; | ||
2412 | |||
2413 | dev->change_mtu = sb1250_change_mtu; | ||
2414 | |||
2415 | /* This is needed for PASS2 for Rx H/W checksum feature */ | ||
2416 | sbmac_set_iphdr_offset(sc); | ||
2417 | |||
2418 | err = register_netdev(dev); | ||
2419 | if (err) | ||
2420 | goto out_uninit; | ||
2421 | |||
2422 | if (periph_rev >= 2) { | ||
2423 | printk(KERN_INFO "%s: enabling TCP rcv checksum\n", | ||
2424 | sc->sbm_dev->name); | ||
2425 | } | ||
2426 | |||
2427 | /* | ||
2428 | * Display Ethernet address (this is called during the config | ||
2429 | * process so we need to finish off the config message that | ||
2430 | * was being displayed) | ||
2431 | */ | ||
2432 | printk(KERN_INFO | ||
2433 | "%s: SiByte Ethernet at 0x%08lX, address: %02X:%02X:%02X:%02X:%02X:%02X\n", | ||
2434 | dev->name, dev->base_addr, | ||
2435 | eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]); | ||
2436 | |||
2437 | |||
2438 | return 0; | ||
2439 | |||
2440 | out_uninit: | ||
2441 | sbmac_uninitctx(sc); | ||
2442 | |||
2443 | return err; | ||
2444 | } | ||
2445 | |||
2446 | |||
2447 | static int sbmac_open(struct net_device *dev) | ||
2448 | { | ||
2449 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2450 | |||
2451 | if (debug > 1) { | ||
2452 | printk(KERN_DEBUG "%s: sbmac_open() irq %d.\n", dev->name, dev->irq); | ||
2453 | } | ||
2454 | |||
2455 | /* | ||
2456 | * map/route interrupt (clear status first, in case something | ||
2457 | * weird is pending; we haven't initialized the mac registers | ||
2458 | * yet) | ||
2459 | */ | ||
2460 | |||
2461 | SBMAC_READCSR(sc->sbm_isr); | ||
2462 | if (request_irq(dev->irq, &sbmac_intr, SA_SHIRQ, dev->name, dev)) | ||
2463 | return -EBUSY; | ||
2464 | |||
2465 | /* | ||
2466 | * Configure default speed | ||
2467 | */ | ||
2468 | |||
2469 | sbmac_mii_poll(sc,noisy_mii); | ||
2470 | |||
2471 | /* | ||
2472 | * Turn on the channel | ||
2473 | */ | ||
2474 | |||
2475 | sbmac_set_channel_state(sc,sbmac_state_on); | ||
2476 | |||
2477 | /* | ||
2478 | * XXX Station address is in dev->dev_addr | ||
2479 | */ | ||
2480 | |||
2481 | if (dev->if_port == 0) | ||
2482 | dev->if_port = 0; | ||
2483 | |||
2484 | netif_start_queue(dev); | ||
2485 | |||
2486 | sbmac_set_rx_mode(dev); | ||
2487 | |||
2488 | /* Set the timer to check for link beat. */ | ||
2489 | init_timer(&sc->sbm_timer); | ||
2490 | sc->sbm_timer.expires = jiffies + 2 * HZ/100; | ||
2491 | sc->sbm_timer.data = (unsigned long)dev; | ||
2492 | sc->sbm_timer.function = &sbmac_timer; | ||
2493 | add_timer(&sc->sbm_timer); | ||
2494 | |||
2495 | return 0; | ||
2496 | } | ||
2497 | |||
2498 | |||
2499 | |||
2500 | static int sbmac_mii_poll(struct sbmac_softc *s,int noisy) | ||
2501 | { | ||
2502 | int bmsr,bmcr,k1stsr,anlpar; | ||
2503 | int chg; | ||
2504 | char buffer[100]; | ||
2505 | char *p = buffer; | ||
2506 | |||
2507 | /* Read the mode status and mode control registers. */ | ||
2508 | bmsr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMSR); | ||
2509 | bmcr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMCR); | ||
2510 | |||
2511 | /* get the link partner status */ | ||
2512 | anlpar = sbmac_mii_read(s,s->sbm_phys[0],MII_ANLPAR); | ||
2513 | |||
2514 | /* if supported, read the 1000baseT register */ | ||
2515 | if (bmsr & BMSR_1000BT_XSR) { | ||
2516 | k1stsr = sbmac_mii_read(s,s->sbm_phys[0],MII_K1STSR); | ||
2517 | } | ||
2518 | else { | ||
2519 | k1stsr = 0; | ||
2520 | } | ||
2521 | |||
2522 | chg = 0; | ||
2523 | |||
2524 | if ((bmsr & BMSR_LINKSTAT) == 0) { | ||
2525 | /* | ||
2526 | * If link status is down, clear out old info so that when | ||
2527 | * it comes back up it will force us to reconfigure speed | ||
2528 | */ | ||
2529 | s->sbm_phy_oldbmsr = 0; | ||
2530 | s->sbm_phy_oldanlpar = 0; | ||
2531 | s->sbm_phy_oldk1stsr = 0; | ||
2532 | return 0; | ||
2533 | } | ||
2534 | |||
2535 | if ((s->sbm_phy_oldbmsr != bmsr) || | ||
2536 | (s->sbm_phy_oldanlpar != anlpar) || | ||
2537 | (s->sbm_phy_oldk1stsr != k1stsr)) { | ||
2538 | if (debug > 1) { | ||
2539 | printk(KERN_DEBUG "%s: bmsr:%x/%x anlpar:%x/%x k1stsr:%x/%x\n", | ||
2540 | s->sbm_dev->name, | ||
2541 | s->sbm_phy_oldbmsr,bmsr, | ||
2542 | s->sbm_phy_oldanlpar,anlpar, | ||
2543 | s->sbm_phy_oldk1stsr,k1stsr); | ||
2544 | } | ||
2545 | s->sbm_phy_oldbmsr = bmsr; | ||
2546 | s->sbm_phy_oldanlpar = anlpar; | ||
2547 | s->sbm_phy_oldk1stsr = k1stsr; | ||
2548 | chg = 1; | ||
2549 | } | ||
2550 | |||
2551 | if (chg == 0) | ||
2552 | return 0; | ||
2553 | |||
2554 | p += sprintf(p,"Link speed: "); | ||
2555 | |||
2556 | if (k1stsr & K1STSR_LP1KFD) { | ||
2557 | s->sbm_speed = sbmac_speed_1000; | ||
2558 | s->sbm_duplex = sbmac_duplex_full; | ||
2559 | s->sbm_fc = sbmac_fc_frame; | ||
2560 | p += sprintf(p,"1000BaseT FDX"); | ||
2561 | } | ||
2562 | else if (k1stsr & K1STSR_LP1KHD) { | ||
2563 | s->sbm_speed = sbmac_speed_1000; | ||
2564 | s->sbm_duplex = sbmac_duplex_half; | ||
2565 | s->sbm_fc = sbmac_fc_disabled; | ||
2566 | p += sprintf(p,"1000BaseT HDX"); | ||
2567 | } | ||
2568 | else if (anlpar & ANLPAR_TXFD) { | ||
2569 | s->sbm_speed = sbmac_speed_100; | ||
2570 | s->sbm_duplex = sbmac_duplex_full; | ||
2571 | s->sbm_fc = (anlpar & ANLPAR_PAUSE) ? sbmac_fc_frame : sbmac_fc_disabled; | ||
2572 | p += sprintf(p,"100BaseT FDX"); | ||
2573 | } | ||
2574 | else if (anlpar & ANLPAR_TXHD) { | ||
2575 | s->sbm_speed = sbmac_speed_100; | ||
2576 | s->sbm_duplex = sbmac_duplex_half; | ||
2577 | s->sbm_fc = sbmac_fc_disabled; | ||
2578 | p += sprintf(p,"100BaseT HDX"); | ||
2579 | } | ||
2580 | else if (anlpar & ANLPAR_10FD) { | ||
2581 | s->sbm_speed = sbmac_speed_10; | ||
2582 | s->sbm_duplex = sbmac_duplex_full; | ||
2583 | s->sbm_fc = sbmac_fc_frame; | ||
2584 | p += sprintf(p,"10BaseT FDX"); | ||
2585 | } | ||
2586 | else if (anlpar & ANLPAR_10HD) { | ||
2587 | s->sbm_speed = sbmac_speed_10; | ||
2588 | s->sbm_duplex = sbmac_duplex_half; | ||
2589 | s->sbm_fc = sbmac_fc_collision; | ||
2590 | p += sprintf(p,"10BaseT HDX"); | ||
2591 | } | ||
2592 | else { | ||
2593 | p += sprintf(p,"Unknown"); | ||
2594 | } | ||
2595 | |||
2596 | if (noisy) { | ||
2597 | printk(KERN_INFO "%s: %s\n",s->sbm_dev->name,buffer); | ||
2598 | } | ||
2599 | |||
2600 | return 1; | ||
2601 | } | ||
2602 | |||
2603 | |||
2604 | static void sbmac_timer(unsigned long data) | ||
2605 | { | ||
2606 | struct net_device *dev = (struct net_device *)data; | ||
2607 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2608 | int next_tick = HZ; | ||
2609 | int mii_status; | ||
2610 | |||
2611 | spin_lock_irq (&sc->sbm_lock); | ||
2612 | |||
2613 | /* make IFF_RUNNING follow the MII status bit "Link established" */ | ||
2614 | mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR); | ||
2615 | |||
2616 | if ( (mii_status & BMSR_LINKSTAT) != (sc->sbm_phy_oldlinkstat) ) { | ||
2617 | sc->sbm_phy_oldlinkstat = mii_status & BMSR_LINKSTAT; | ||
2618 | if (mii_status & BMSR_LINKSTAT) { | ||
2619 | netif_carrier_on(dev); | ||
2620 | } | ||
2621 | else { | ||
2622 | netif_carrier_off(dev); | ||
2623 | } | ||
2624 | } | ||
2625 | |||
2626 | /* | ||
2627 | * Poll the PHY to see what speed we should be running at | ||
2628 | */ | ||
2629 | |||
2630 | if (sbmac_mii_poll(sc,noisy_mii)) { | ||
2631 | if (sc->sbm_state != sbmac_state_off) { | ||
2632 | /* | ||
2633 | * something changed, restart the channel | ||
2634 | */ | ||
2635 | if (debug > 1) { | ||
2636 | printk("%s: restarting channel because speed changed\n", | ||
2637 | sc->sbm_dev->name); | ||
2638 | } | ||
2639 | sbmac_channel_stop(sc); | ||
2640 | sbmac_channel_start(sc); | ||
2641 | } | ||
2642 | } | ||
2643 | |||
2644 | spin_unlock_irq (&sc->sbm_lock); | ||
2645 | |||
2646 | sc->sbm_timer.expires = jiffies + next_tick; | ||
2647 | add_timer(&sc->sbm_timer); | ||
2648 | } | ||
2649 | |||
2650 | |||
2651 | static void sbmac_tx_timeout (struct net_device *dev) | ||
2652 | { | ||
2653 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2654 | |||
2655 | spin_lock_irq (&sc->sbm_lock); | ||
2656 | |||
2657 | |||
2658 | dev->trans_start = jiffies; | ||
2659 | sc->sbm_stats.tx_errors++; | ||
2660 | |||
2661 | spin_unlock_irq (&sc->sbm_lock); | ||
2662 | |||
2663 | printk (KERN_WARNING "%s: Transmit timed out\n",dev->name); | ||
2664 | } | ||
2665 | |||
2666 | |||
2667 | |||
2668 | |||
2669 | static struct net_device_stats *sbmac_get_stats(struct net_device *dev) | ||
2670 | { | ||
2671 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2672 | unsigned long flags; | ||
2673 | |||
2674 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2675 | |||
2676 | /* XXX update other stats here */ | ||
2677 | |||
2678 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2679 | |||
2680 | return &sc->sbm_stats; | ||
2681 | } | ||
2682 | |||
2683 | |||
2684 | |||
2685 | static void sbmac_set_rx_mode(struct net_device *dev) | ||
2686 | { | ||
2687 | unsigned long flags; | ||
2688 | int msg_flag = 0; | ||
2689 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2690 | |||
2691 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2692 | if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) { | ||
2693 | /* | ||
2694 | * Promiscuous changed. | ||
2695 | */ | ||
2696 | |||
2697 | if (dev->flags & IFF_PROMISC) { | ||
2698 | /* Unconditionally log net taps. */ | ||
2699 | msg_flag = 1; | ||
2700 | sbmac_promiscuous_mode(sc,1); | ||
2701 | } | ||
2702 | else { | ||
2703 | msg_flag = 2; | ||
2704 | sbmac_promiscuous_mode(sc,0); | ||
2705 | } | ||
2706 | } | ||
2707 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2708 | |||
2709 | if (msg_flag) { | ||
2710 | printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", | ||
2711 | dev->name,(msg_flag==1)?"en":"dis"); | ||
2712 | } | ||
2713 | |||
2714 | /* | ||
2715 | * Program the multicasts. Do this every time. | ||
2716 | */ | ||
2717 | |||
2718 | sbmac_setmulti(sc); | ||
2719 | |||
2720 | } | ||
2721 | |||
2722 | static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | ||
2723 | { | ||
2724 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2725 | u16 *data = (u16 *)&rq->ifr_ifru; | ||
2726 | unsigned long flags; | ||
2727 | int retval; | ||
2728 | |||
2729 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2730 | retval = 0; | ||
2731 | |||
2732 | switch(cmd) { | ||
2733 | case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ | ||
2734 | data[0] = sc->sbm_phys[0] & 0x1f; | ||
2735 | /* Fall Through */ | ||
2736 | case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ | ||
2737 | data[3] = sbmac_mii_read(sc, data[0] & 0x1f, data[1] & 0x1f); | ||
2738 | break; | ||
2739 | case SIOCDEVPRIVATE+2: /* Write the specified MII register */ | ||
2740 | if (!capable(CAP_NET_ADMIN)) { | ||
2741 | retval = -EPERM; | ||
2742 | break; | ||
2743 | } | ||
2744 | if (debug > 1) { | ||
2745 | printk(KERN_DEBUG "%s: sbmac_mii_ioctl: write %02X %02X %02X\n",dev->name, | ||
2746 | data[0],data[1],data[2]); | ||
2747 | } | ||
2748 | sbmac_mii_write(sc, data[0] & 0x1f, data[1] & 0x1f, data[2]); | ||
2749 | break; | ||
2750 | default: | ||
2751 | retval = -EOPNOTSUPP; | ||
2752 | } | ||
2753 | |||
2754 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2755 | return retval; | ||
2756 | } | ||
2757 | |||
2758 | static int sbmac_close(struct net_device *dev) | ||
2759 | { | ||
2760 | struct sbmac_softc *sc = netdev_priv(dev); | ||
2761 | unsigned long flags; | ||
2762 | int irq; | ||
2763 | |||
2764 | sbmac_set_channel_state(sc,sbmac_state_off); | ||
2765 | |||
2766 | del_timer_sync(&sc->sbm_timer); | ||
2767 | |||
2768 | spin_lock_irqsave(&sc->sbm_lock, flags); | ||
2769 | |||
2770 | netif_stop_queue(dev); | ||
2771 | |||
2772 | if (debug > 1) { | ||
2773 | printk(KERN_DEBUG "%s: Shutting down ethercard\n",dev->name); | ||
2774 | } | ||
2775 | |||
2776 | spin_unlock_irqrestore(&sc->sbm_lock, flags); | ||
2777 | |||
2778 | irq = dev->irq; | ||
2779 | synchronize_irq(irq); | ||
2780 | free_irq(irq, dev); | ||
2781 | |||
2782 | sbdma_emptyring(&(sc->sbm_txdma)); | ||
2783 | sbdma_emptyring(&(sc->sbm_rxdma)); | ||
2784 | |||
2785 | return 0; | ||
2786 | } | ||
2787 | |||
2788 | |||
2789 | |||
2790 | #if defined(SBMAC_ETH0_HWADDR) || defined(SBMAC_ETH1_HWADDR) || defined(SBMAC_ETH2_HWADDR) | ||
2791 | static void | ||
2792 | sbmac_setup_hwaddr(int chan,char *addr) | ||
2793 | { | ||
2794 | uint8_t eaddr[6]; | ||
2795 | uint64_t val; | ||
2796 | sbmac_port_t port; | ||
2797 | |||
2798 | port = A_MAC_CHANNEL_BASE(chan); | ||
2799 | sbmac_parse_hwaddr(addr,eaddr); | ||
2800 | val = sbmac_addr2reg(eaddr); | ||
2801 | SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),val); | ||
2802 | val = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR)); | ||
2803 | } | ||
2804 | #endif | ||
2805 | |||
2806 | static struct net_device *dev_sbmac[MAX_UNITS]; | ||
2807 | |||
2808 | static int __init | ||
2809 | sbmac_init_module(void) | ||
2810 | { | ||
2811 | int idx; | ||
2812 | struct net_device *dev; | ||
2813 | sbmac_port_t port; | ||
2814 | int chip_max_units; | ||
2815 | |||
2816 | /* | ||
2817 | * For bringup when not using the firmware, we can pre-fill | ||
2818 | * the MAC addresses using the environment variables | ||
2819 | * specified in this file (or maybe from the config file?) | ||
2820 | */ | ||
2821 | #ifdef SBMAC_ETH0_HWADDR | ||
2822 | sbmac_setup_hwaddr(0,SBMAC_ETH0_HWADDR); | ||
2823 | #endif | ||
2824 | #ifdef SBMAC_ETH1_HWADDR | ||
2825 | sbmac_setup_hwaddr(1,SBMAC_ETH1_HWADDR); | ||
2826 | #endif | ||
2827 | #ifdef SBMAC_ETH2_HWADDR | ||
2828 | sbmac_setup_hwaddr(2,SBMAC_ETH2_HWADDR); | ||
2829 | #endif | ||
2830 | |||
2831 | /* | ||
2832 | * Walk through the Ethernet controllers and find | ||
2833 | * those who have their MAC addresses set. | ||
2834 | */ | ||
2835 | switch (soc_type) { | ||
2836 | case K_SYS_SOC_TYPE_BCM1250: | ||
2837 | case K_SYS_SOC_TYPE_BCM1250_ALT: | ||
2838 | chip_max_units = 3; | ||
2839 | break; | ||
2840 | case K_SYS_SOC_TYPE_BCM1120: | ||
2841 | case K_SYS_SOC_TYPE_BCM1125: | ||
2842 | case K_SYS_SOC_TYPE_BCM1125H: | ||
2843 | case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */ | ||
2844 | chip_max_units = 2; | ||
2845 | break; | ||
2846 | default: | ||
2847 | chip_max_units = 0; | ||
2848 | break; | ||
2849 | } | ||
2850 | if (chip_max_units > MAX_UNITS) | ||
2851 | chip_max_units = MAX_UNITS; | ||
2852 | |||
2853 | for (idx = 0; idx < chip_max_units; idx++) { | ||
2854 | |||
2855 | /* | ||
2856 | * This is the base address of the MAC. | ||
2857 | */ | ||
2858 | |||
2859 | port = A_MAC_CHANNEL_BASE(idx); | ||
2860 | |||
2861 | /* | ||
2862 | * The R_MAC_ETHERNET_ADDR register will be set to some nonzero | ||
2863 | * value for us by the firmware if we're going to use this MAC. | ||
2864 | * If we find a zero, skip this MAC. | ||
2865 | */ | ||
2866 | |||
2867 | sbmac_orig_hwaddr[idx] = SBMAC_READCSR(IOADDR(port+R_MAC_ETHERNET_ADDR)); | ||
2868 | if (sbmac_orig_hwaddr[idx] == 0) { | ||
2869 | printk(KERN_DEBUG "sbmac: not configuring MAC at " | ||
2870 | "%lx\n", port); | ||
2871 | continue; | ||
2872 | } | ||
2873 | |||
2874 | /* | ||
2875 | * Okay, cool. Initialize this MAC. | ||
2876 | */ | ||
2877 | |||
2878 | dev = alloc_etherdev(sizeof(struct sbmac_softc)); | ||
2879 | if (!dev) | ||
2880 | return -ENOMEM; /* return ENOMEM */ | ||
2881 | |||
2882 | printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port); | ||
2883 | |||
2884 | dev->irq = K_INT_MAC_0 + idx; | ||
2885 | dev->base_addr = port; | ||
2886 | dev->mem_end = 0; | ||
2887 | if (sbmac_init(dev, idx)) { | ||
2888 | port = A_MAC_CHANNEL_BASE(idx); | ||
2889 | SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR), | ||
2890 | sbmac_orig_hwaddr[idx]); | ||
2891 | free_netdev(dev); | ||
2892 | continue; | ||
2893 | } | ||
2894 | dev_sbmac[idx] = dev; | ||
2895 | } | ||
2896 | return 0; | ||
2897 | } | ||
2898 | |||
2899 | |||
2900 | static void __exit | ||
2901 | sbmac_cleanup_module(void) | ||
2902 | { | ||
2903 | struct net_device *dev; | ||
2904 | int idx; | ||
2905 | |||
2906 | for (idx = 0; idx < MAX_UNITS; idx++) { | ||
2907 | struct sbmac_softc *sc; | ||
2908 | dev = dev_sbmac[idx]; | ||
2909 | if (!dev) | ||
2910 | continue; | ||
2911 | |||
2912 | sc = netdev_priv(dev); | ||
2913 | unregister_netdev(dev); | ||
2914 | sbmac_uninitctx(sc); | ||
2915 | free_netdev(dev); | ||
2916 | } | ||
2917 | } | ||
2918 | |||
2919 | module_init(sbmac_init_module); | ||
2920 | module_exit(sbmac_cleanup_module); | ||