blob: 67bfd6f4336617854f1c627544a4181b226ad585 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/* de4x5.c: A DIGITAL DC21x4x DECchip and DE425/DE434/DE435/DE450/DE500
2 ethernet driver for Linux.
3
4 Copyright 1994, 1995 Digital Equipment Corporation.
5
6 Testing resources for this driver have been made available
7 in part by NASA Ames Research Center (mjacob@nas.nasa.gov).
8
9 The author may be reached at davies@maniac.ultranet.com.
10
11 This program is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
15
16 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 You should have received a copy of the GNU General Public License along
28 with this program; if not, write to the Free Software Foundation, Inc.,
29 675 Mass Ave, Cambridge, MA 02139, USA.
30
31 Originally, this driver was written for the Digital Equipment
32 Corporation series of EtherWORKS ethernet cards:
33
34 DE425 TP/COAX EISA
35 DE434 TP PCI
36 DE435 TP/COAX/AUI PCI
37 DE450 TP/COAX/AUI PCI
38 DE500 10/100 PCI Fasternet
39
40 but it will now attempt to support all cards which conform to the
41 Digital Semiconductor SROM Specification. The driver currently
42 recognises the following chips:
43
Jeff Garzikf3b197a2006-05-26 21:39:03 -040044 DC21040 (no SROM)
45 DC21041[A]
46 DC21140[A]
47 DC21142
48 DC21143
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50 So far the driver is known to work with the following cards:
51
52 KINGSTON
53 Linksys
54 ZNYX342
55 SMC8432
56 SMC9332 (w/new SROM)
57 ZNYX31[45]
Jeff Garzikf3b197a2006-05-26 21:39:03 -040058 ZNYX346 10/100 4 port (can act as a 10/100 bridge!)
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60 The driver has been tested on a relatively busy network using the DE425,
61 DE434, DE435 and DE500 cards and benchmarked with 'ttcp': it transferred
62 16M of data to a DECstation 5000/200 as follows:
63
64 TCP UDP
65 TX RX TX RX
66 DE425 1030k 997k 1170k 1128k
67 DE434 1063k 995k 1170k 1125k
68 DE435 1063k 995k 1170k 1125k
69 DE500 1063k 998k 1170k 1125k in 10Mb/s mode
70
71 All values are typical (in kBytes/sec) from a sample of 4 for each
72 measurement. Their error is +/-20k on a quiet (private) network and also
73 depend on what load the CPU has.
74
75 =========================================================================
76 This driver has been written substantially from scratch, although its
77 inheritance of style and stack interface from 'ewrk3.c' and in turn from
78 Donald Becker's 'lance.c' should be obvious. With the module autoload of
79 every usable DECchip board, I pinched Donald's 'next_module' field to
80 link my modules together.
81
82 Upto 15 EISA cards can be supported under this driver, limited primarily
83 by the available IRQ lines. I have checked different configurations of
84 multiple depca, EtherWORKS 3 cards and de4x5 cards and have not found a
85 problem yet (provided you have at least depca.c v0.38) ...
86
87 PCI support has been added to allow the driver to work with the DE434,
88 DE435, DE450 and DE500 cards. The I/O accesses are a bit of a kludge due
89 to the differences in the EISA and PCI CSR address offsets from the base
90 address.
91
92 The ability to load this driver as a loadable module has been included
93 and used extensively during the driver development (to save those long
94 reboot sequences). Loadable module support under PCI and EISA has been
95 achieved by letting the driver autoprobe as if it were compiled into the
96 kernel. Do make sure you're not sharing interrupts with anything that
97 cannot accommodate interrupt sharing!
98
99 To utilise this ability, you have to do 8 things:
100
101 0) have a copy of the loadable modules code installed on your system.
102 1) copy de4x5.c from the /linux/drivers/net directory to your favourite
103 temporary directory.
104 2) for fixed autoprobes (not recommended), edit the source code near
105 line 5594 to reflect the I/O address you're using, or assign these when
106 loading by:
107
108 insmod de4x5 io=0xghh where g = bus number
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400109 hh = device number
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111 NB: autoprobing for modules is now supported by default. You may just
112 use:
113
114 insmod de4x5
115
116 to load all available boards. For a specific board, still use
117 the 'io=?' above.
118 3) compile de4x5.c, but include -DMODULE in the command line to ensure
119 that the correct bits are compiled (see end of source code).
120 4) if you are wanting to add a new card, goto 5. Otherwise, recompile a
121 kernel with the de4x5 configuration turned off and reboot.
122 5) insmod de4x5 [io=0xghh]
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400123 6) run the net startup bits for your new eth?? interface(s) manually
124 (usually /etc/rc.inet[12] at boot time).
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 7) enjoy!
126
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400127 To unload a module, turn off the associated interface(s)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 'ifconfig eth?? down' then 'rmmod de4x5'.
129
130 Automedia detection is included so that in principal you can disconnect
131 from, e.g. TP, reconnect to BNC and things will still work (after a
132 pause whilst the driver figures out where its media went). My tests
133 using ping showed that it appears to work....
134
135 By default, the driver will now autodetect any DECchip based card.
136 Should you have a need to restrict the driver to DIGITAL only cards, you
137 can compile with a DEC_ONLY define, or if loading as a module, use the
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400138 'dec_only=1' parameter.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140 I've changed the timing routines to use the kernel timer and scheduling
141 functions so that the hangs and other assorted problems that occurred
142 while autosensing the media should be gone. A bonus for the DC21040
143 auto media sense algorithm is that it can now use one that is more in
144 line with the rest (the DC21040 chip doesn't have a hardware timer).
145 The downside is the 1 'jiffies' (10ms) resolution.
146
147 IEEE 802.3u MII interface code has been added in anticipation that some
148 products may use it in the future.
149
150 The SMC9332 card has a non-compliant SROM which needs fixing - I have
151 patched this driver to detect it because the SROM format used complies
152 to a previous DEC-STD format.
153
154 I have removed the buffer copies needed for receive on Intels. I cannot
155 remove them for Alphas since the Tulip hardware only does longword
156 aligned DMA transfers and the Alphas get alignment traps with non
157 longword aligned data copies (which makes them really slow). No comment.
158
159 I have added SROM decoding routines to make this driver work with any
160 card that supports the Digital Semiconductor SROM spec. This will help
161 all cards running the dc2114x series chips in particular. Cards using
162 the dc2104x chips should run correctly with the basic driver. I'm in
163 debt to <mjacob@feral.com> for the testing and feedback that helped get
164 this feature working. So far we have tested KINGSTON, SMC8432, SMC9332
165 (with the latest SROM complying with the SROM spec V3: their first was
166 broken), ZNYX342 and LinkSys. ZYNX314 (dual 21041 MAC) and ZNYX 315
167 (quad 21041 MAC) cards also appear to work despite their incorrectly
168 wired IRQs.
169
170 I have added a temporary fix for interrupt problems when some SCSI cards
171 share the same interrupt as the DECchip based cards. The problem occurs
172 because the SCSI card wants to grab the interrupt as a fast interrupt
173 (runs the service routine with interrupts turned off) vs. this card
174 which really needs to run the service routine with interrupts turned on.
175 This driver will now add the interrupt service routine as a fast
176 interrupt if it is bounced from the slow interrupt. THIS IS NOT A
177 RECOMMENDED WAY TO RUN THE DRIVER and has been done for a limited time
178 until people sort out their compatibility issues and the kernel
179 interrupt service code is fixed. YOU SHOULD SEPARATE OUT THE FAST
180 INTERRUPT CARDS FROM THE SLOW INTERRUPT CARDS to ensure that they do not
181 run on the same interrupt. PCMCIA/CardBus is another can of worms...
182
183 Finally, I think I have really fixed the module loading problem with
184 more than one DECchip based card. As a side effect, I don't mess with
185 the device structure any more which means that if more than 1 card in
186 2.0.x is installed (4 in 2.1.x), the user will have to edit
187 linux/drivers/net/Space.c to make room for them. Hence, module loading
188 is the preferred way to use this driver, since it doesn't have this
189 limitation.
190
191 Where SROM media detection is used and full duplex is specified in the
192 SROM, the feature is ignored unless lp->params.fdx is set at compile
193 time OR during a module load (insmod de4x5 args='eth??:fdx' [see
194 below]). This is because there is no way to automatically detect full
195 duplex links except through autonegotiation. When I include the
196 autonegotiation feature in the SROM autoconf code, this detection will
197 occur automatically for that case.
198
199 Command line arguments are now allowed, similar to passing arguments
200 through LILO. This will allow a per adapter board set up of full duplex
201 and media. The only lexical constraints are: the board name (dev->name)
202 appears in the list before its parameters. The list of parameters ends
203 either at the end of the parameter list or with another board name. The
204 following parameters are allowed:
205
206 fdx for full duplex
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400207 autosense to set the media/speed; with the following
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 sub-parameters:
209 TP, TP_NW, BNC, AUI, BNC_AUI, 100Mb, 10Mb, AUTO
210
211 Case sensitivity is important for the sub-parameters. They *must* be
212 upper case. Examples:
213
214 insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
215
216 For a compiled in driver, at or above line 548, place e.g.
217 #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
218
219 Yes, I know full duplex isn't permissible on BNC or AUI; they're just
220 examples. By default, full duplex is turned off and AUTO is the default
221 autosense setting. In reality, I expect only the full duplex option to
222 be used. Note the use of single quotes in the two examples above and the
223 lack of commas to separate items. ALSO, you must get the requested media
224 correct in relation to what the adapter SROM says it has. There's no way
225 to determine this in advance other than by trial and error and common
226 sense, e.g. call a BNC connectored port 'BNC', not '10Mb'.
227
228 Changed the bus probing. EISA used to be done first, followed by PCI.
229 Most people probably don't even know what a de425 is today and the EISA
230 probe has messed up some SCSI cards in the past, so now PCI is always
231 probed first followed by EISA if a) the architecture allows EISA and
232 either b) there have been no PCI cards detected or c) an EISA probe is
233 forced by the user. To force a probe include "force_eisa" in your
234 insmod "args" line; for built-in kernels either change the driver to do
235 this automatically or include #define DE4X5_FORCE_EISA on or before
236 line 1040 in the driver.
237
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400238 TO DO:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 ------
240
241 Revision History
242 ----------------
243
244 Version Date Description
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400245
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 0.1 17-Nov-94 Initial writing. ALPHA code release.
247 0.2 13-Jan-95 Added PCI support for DE435's.
248 0.21 19-Jan-95 Added auto media detection.
249 0.22 10-Feb-95 Fix interrupt handler call <chris@cosy.sbg.ac.at>.
250 Fix recognition bug reported by <bkm@star.rl.ac.uk>.
251 Add request/release_region code.
252 Add loadable modules support for PCI.
253 Clean up loadable modules support.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400254 0.23 28-Feb-95 Added DC21041 and DC21140 support.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 Fix missed frame counter value and initialisation.
256 Fixed EISA probe.
257 0.24 11-Apr-95 Change delay routine to use <linux/udelay>.
258 Change TX_BUFFS_AVAIL macro.
259 Change media autodetection to allow manual setting.
260 Completed DE500 (DC21140) support.
261 0.241 18-Apr-95 Interim release without DE500 Autosense Algorithm.
262 0.242 10-May-95 Minor changes.
263 0.30 12-Jun-95 Timer fix for DC21140.
264 Portability changes.
265 Add ALPHA changes from <jestabro@ant.tay1.dec.com>.
266 Add DE500 semi automatic autosense.
267 Add Link Fail interrupt TP failure detection.
268 Add timer based link change detection.
269 Plugged a memory leak in de4x5_queue_pkt().
270 0.31 13-Jun-95 Fixed PCI stuff for 1.3.1.
271 0.32 26-Jun-95 Added verify_area() calls in de4x5_ioctl() from a
272 suggestion by <heiko@colossus.escape.de>.
273 0.33 8-Aug-95 Add shared interrupt support (not released yet).
274 0.331 21-Aug-95 Fix de4x5_open() with fast CPUs.
275 Fix de4x5_interrupt().
276 Fix dc21140_autoconf() mess.
277 No shared interrupt support.
278 0.332 11-Sep-95 Added MII management interface routines.
279 0.40 5-Mar-96 Fix setup frame timeout <maartenb@hpkuipc.cern.ch>.
280 Add kernel timer code (h/w is too flaky).
281 Add MII based PHY autosense.
282 Add new multicasting code.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400283 Add new autosense algorithms for media/mode
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 selection using kernel scheduling/timing.
285 Re-formatted.
286 Made changes suggested by <jeff@router.patch.net>:
287 Change driver to detect all DECchip based cards
288 with DEC_ONLY restriction a special case.
289 Changed driver to autoprobe as a module. No irq
290 checking is done now - assume BIOS is good!
291 Added SMC9332 detection <manabe@Roy.dsl.tutics.ac.jp>
292 0.41 21-Mar-96 Don't check for get_hw_addr checksum unless DEC card
293 only <niles@axp745gsfc.nasa.gov>
294 Fix for multiple PCI cards reported by <jos@xos.nl>
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700295 Duh, put the IRQF_SHARED flag into request_interrupt().
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 Fix SMC ethernet address in enet_det[].
297 Print chip name instead of "UNKNOWN" during boot.
298 0.42 26-Apr-96 Fix MII write TA bit error.
299 Fix bug in dc21040 and dc21041 autosense code.
300 Remove buffer copies on receive for Intels.
301 Change sk_buff handling during media disconnects to
302 eliminate DUP packets.
303 Add dynamic TX thresholding.
304 Change all chips to use perfect multicast filtering.
305 Fix alloc_device() bug <jari@markkus2.fimr.fi>
306 0.43 21-Jun-96 Fix unconnected media TX retry bug.
307 Add Accton to the list of broken cards.
308 Fix TX under-run bug for non DC21140 chips.
309 Fix boot command probe bug in alloc_device() as
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400310 reported by <koen.gadeyne@barco.com> and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 <orava@nether.tky.hut.fi>.
312 Add cache locks to prevent a race condition as
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400313 reported by <csd@microplex.com> and
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 <baba@beckman.uiuc.edu>.
315 Upgraded alloc_device() code.
316 0.431 28-Jun-96 Fix potential bug in queue_pkt() from discussion
317 with <csd@microplex.com>
318 0.44 13-Aug-96 Fix RX overflow bug in 2114[023] chips.
319 Fix EISA probe bugs reported by <os2@kpi.kharkov.ua>
320 and <michael@compurex.com>.
321 0.441 9-Sep-96 Change dc21041_autoconf() to probe quiet BNC media
322 with a loopback packet.
323 0.442 9-Sep-96 Include AUI in dc21041 media printout. Bug reported
324 by <bhat@mundook.cs.mu.OZ.AU>
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400325 0.45 8-Dec-96 Include endian functions for PPC use, from work
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 by <cort@cs.nmt.edu> and <g.thomas@opengroup.org>.
327 0.451 28-Dec-96 Added fix to allow autoprobe for modules after
328 suggestion from <mjacob@feral.com>.
329 0.5 30-Jan-97 Added SROM decoding functions.
330 Updated debug flags.
331 Fix sleep/wakeup calls for PCI cards, bug reported
332 by <cross@gweep.lkg.dec.com>.
333 Added multi-MAC, one SROM feature from discussion
334 with <mjacob@feral.com>.
335 Added full module autoprobe capability.
336 Added attempt to use an SMC9332 with broken SROM.
337 Added fix for ZYNX multi-mac cards that didn't
338 get their IRQs wired correctly.
339 0.51 13-Feb-97 Added endian fixes for the SROM accesses from
340 <paubert@iram.es>
341 Fix init_connection() to remove extra device reset.
342 Fix MAC/PHY reset ordering in dc21140m_autoconf().
343 Fix initialisation problem with lp->timeout in
344 typeX_infoblock() from <paubert@iram.es>.
345 Fix MII PHY reset problem from work done by
346 <paubert@iram.es>.
347 0.52 26-Apr-97 Some changes may not credit the right people -
348 a disk crash meant I lost some mail.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400349 Change RX interrupt routine to drop rather than
350 defer packets to avoid hang reported by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 <g.thomas@opengroup.org>.
352 Fix srom_exec() to return for COMPACT and type 1
353 infoblocks.
354 Added DC21142 and DC21143 functions.
355 Added byte counters from <phil@tazenda.demon.co.uk>
Thomas Gleixner1fb9df52006-07-01 19:29:39 -0700356 Added IRQF_DISABLED temporary fix from
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 <mjacob@feral.com>.
358 0.53 12-Nov-97 Fix the *_probe() to include 'eth??' name during
359 module load: bug reported by
360 <Piete.Brooks@cl.cam.ac.uk>
361 Fix multi-MAC, one SROM, to work with 2114x chips:
362 bug reported by <cmetz@inner.net>.
363 Make above search independent of BIOS device scan
364 direction.
365 Completed DC2114[23] autosense functions.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400366 0.531 21-Dec-97 Fix DE500-XA 100Mb/s bug reported by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 <robin@intercore.com
368 Fix type1_infoblock() bug introduced in 0.53, from
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400369 problem reports by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 <parmee@postecss.ncrfran.france.ncr.com> and
371 <jo@ice.dillingen.baynet.de>.
372 Added argument list to set up each board from either
373 a module's command line or a compiled in #define.
374 Added generic MII PHY functionality to deal with
375 newer PHY chips.
376 Fix the mess in 2.1.67.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400377 0.532 5-Jan-98 Fix bug in mii_get_phy() reported by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 <redhat@cococo.net>.
379 Fix bug in pci_probe() for 64 bit systems reported
380 by <belliott@accessone.com>.
381 0.533 9-Jan-98 Fix more 64 bit bugs reported by <jal@cs.brown.edu>.
382 0.534 24-Jan-98 Fix last (?) endian bug from <geert@linux-m68k.org>
383 0.535 21-Feb-98 Fix Ethernet Address PROM reset bug for DC21040.
384 0.536 21-Mar-98 Change pci_probe() to use the pci_dev structure.
385 **Incompatible with 2.0.x from here.**
386 0.540 5-Jul-98 Atomicize assertion of dev->interrupt for SMP
387 from <lma@varesearch.com>
388 Add TP, AUI and BNC cases to 21140m_autoconf() for
389 case where a 21140 under SROM control uses, e.g. AUI
390 from problem report by <delchini@lpnp09.in2p3.fr>
391 Add MII parallel detection to 2114x_autoconf() for
392 case where no autonegotiation partner exists from
393 problem report by <mlapsley@ndirect.co.uk>.
394 Add ability to force connection type directly even
395 when using SROM control from problem report by
396 <earl@exis.net>.
397 Updated the PCI interface to conform with the latest
398 version. I hope nothing is broken...
399 Add TX done interrupt modification from suggestion
400 by <Austin.Donnelly@cl.cam.ac.uk>.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400401 Fix is_anc_capable() bug reported by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 <Austin.Donnelly@cl.cam.ac.uk>.
403 Fix type[13]_infoblock() bug: during MII search, PHY
404 lp->rst not run because lp->ibn not initialised -
405 from report & fix by <paubert@iram.es>.
406 Fix probe bug with EISA & PCI cards present from
407 report by <eirik@netcom.com>.
408 0.541 24-Aug-98 Fix compiler problems associated with i386-string
409 ops from multiple bug reports and temporary fix
410 from <paubert@iram.es>.
411 Fix pci_probe() to correctly emulate the old
412 pcibios_find_class() function.
413 Add an_exception() for old ZYNX346 and fix compile
414 warning on PPC & SPARC, from <ecd@skynet.be>.
415 Fix lastPCI to correctly work with compiled in
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400416 kernels and modules from bug report by
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 <Zlatko.Calusic@CARNet.hr> et al.
418 0.542 15-Sep-98 Fix dc2114x_autoconf() to stop multiple messages
419 when media is unconnected.
420 Change dev->interrupt to lp->interrupt to ensure
421 alignment for Alpha's and avoid their unaligned
422 access traps. This flag is merely for log messages:
423 should do something more definitive though...
424 0.543 30-Dec-98 Add SMP spin locking.
425 0.544 8-May-99 Fix for buggy SROM in Motorola embedded boards using
426 a 21143 by <mmporter@home.com>.
427 Change PCI/EISA bus probing order.
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400428 0.545 28-Nov-99 Further Moto SROM bug fix from
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 <mporter@eng.mcd.mot.com>
430 Remove double checking for DEBUG_RX in de4x5_dbg_rx()
431 from report by <geert@linux-m68k.org>
432 0.546 22-Feb-01 Fixes Alpha XP1000 oops. The srom_search function
433 was causing a page fault when initializing the
434 variable 'pb', on a non de4x5 PCI device, in this
435 case a PCI bridge (DEC chip 21152). The value of
436 'pb' is now only initialized if a de4x5 chip is
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400437 present.
438 <france@handhelds.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 0.547 08-Nov-01 Use library crc32 functions by <Matt_Domsch@dell.com>
440 0.548 30-Aug-03 Big 2.6 cleanup. Ported to PCI/EISA probing and
441 generic DMA APIs. Fixed DE425 support on Alpha.
442 <maz@wild-wind.fr.eu.org>
443 =========================================================================
444*/
445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446#include <linux/module.h>
447#include <linux/kernel.h>
448#include <linux/string.h>
449#include <linux/interrupt.h>
450#include <linux/ptrace.h>
451#include <linux/errno.h>
452#include <linux/ioport.h>
453#include <linux/slab.h>
454#include <linux/pci.h>
455#include <linux/eisa.h>
456#include <linux/delay.h>
457#include <linux/init.h>
458#include <linux/spinlock.h>
459#include <linux/crc32.h>
460#include <linux/netdevice.h>
461#include <linux/etherdevice.h>
462#include <linux/skbuff.h>
463#include <linux/time.h>
464#include <linux/types.h>
465#include <linux/unistd.h>
466#include <linux/ctype.h>
467#include <linux/dma-mapping.h>
468#include <linux/moduleparam.h>
469#include <linux/bitops.h>
470
471#include <asm/io.h>
472#include <asm/dma.h>
473#include <asm/byteorder.h>
474#include <asm/unaligned.h>
475#include <asm/uaccess.h>
s.hauer@pengutronix.debfaadca2006-11-02 13:55:57 +0100476#ifdef CONFIG_PPC_PMAC
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#include <asm/machdep.h>
s.hauer@pengutronix.debfaadca2006-11-02 13:55:57 +0100478#endif /* CONFIG_PPC_PMAC */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
480#include "de4x5.h"
481
482static char version[] __devinitdata = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
483
484#define c_char const char
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
486/*
487** MII Information
488*/
489struct phy_table {
490 int reset; /* Hard reset required? */
491 int id; /* IEEE OUI */
492 int ta; /* One cycle TA time - 802.3u is confusing here */
493 struct { /* Non autonegotiation (parallel) speed det. */
494 int reg;
495 int mask;
496 int value;
497 } spd;
498};
499
500struct mii_phy {
501 int reset; /* Hard reset required? */
502 int id; /* IEEE OUI */
503 int ta; /* One cycle TA time */
504 struct { /* Non autonegotiation (parallel) speed det. */
505 int reg;
506 int mask;
507 int value;
508 } spd;
509 int addr; /* MII address for the PHY */
510 u_char *gep; /* Start of GEP sequence block in SROM */
511 u_char *rst; /* Start of reset sequence in SROM */
512 u_int mc; /* Media Capabilities */
513 u_int ana; /* NWay Advertisement */
Alexey Dobriyan7f927fc2006-03-28 01:56:53 -0800514 u_int fdx; /* Full DupleX capabilities for each media */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 u_int ttm; /* Transmit Threshold Mode for each media */
516 u_int mci; /* 21142 MII Connector Interrupt info */
517};
518
519#define DE4X5_MAX_PHY 8 /* Allow upto 8 attached PHY devices per board */
520
521struct sia_phy {
522 u_char mc; /* Media Code */
523 u_char ext; /* csr13-15 valid when set */
524 int csr13; /* SIA Connectivity Register */
525 int csr14; /* SIA TX/RX Register */
526 int csr15; /* SIA General Register */
527 int gepc; /* SIA GEP Control Information */
528 int gep; /* SIA GEP Data */
529};
530
531/*
532** Define the know universe of PHY devices that can be
533** recognised by this driver.
534*/
535static struct phy_table phy_info[] = {
536 {0, NATIONAL_TX, 1, {0x19, 0x40, 0x00}}, /* National TX */
537 {1, BROADCOM_T4, 1, {0x10, 0x02, 0x02}}, /* Broadcom T4 */
538 {0, SEEQ_T4 , 1, {0x12, 0x10, 0x10}}, /* SEEQ T4 */
539 {0, CYPRESS_T4 , 1, {0x05, 0x20, 0x20}}, /* Cypress T4 */
540 {0, 0x7810 , 1, {0x14, 0x0800, 0x0800}} /* Level One LTX970 */
541};
542
543/*
544** These GENERIC values assumes that the PHY devices follow 802.3u and
545** allow parallel detection to set the link partner ability register.
546** Detection of 100Base-TX [H/F Duplex] and 100Base-T4 is supported.
547*/
548#define GENERIC_REG 0x05 /* Autoneg. Link Partner Advertisement Reg. */
549#define GENERIC_MASK MII_ANLPA_100M /* All 100Mb/s Technologies */
550#define GENERIC_VALUE MII_ANLPA_100M /* 100B-TX, 100B-TX FDX, 100B-T4 */
551
552/*
553** Define special SROM detection cases
554*/
555static c_char enet_det[][ETH_ALEN] = {
556 {0x00, 0x00, 0xc0, 0x00, 0x00, 0x00},
557 {0x00, 0x00, 0xe8, 0x00, 0x00, 0x00}
558};
559
560#define SMC 1
561#define ACCTON 2
562
563/*
564** SROM Repair definitions. If a broken SROM is detected a card may
565** use this information to help figure out what to do. This is a
566** "stab in the dark" and so far for SMC9332's only.
567*/
568static c_char srom_repair_info[][100] = {
569 {0x00,0x1e,0x00,0x00,0x00,0x08, /* SMC9332 */
570 0x1f,0x01,0x8f,0x01,0x00,0x01,0x00,0x02,
571 0x01,0x00,0x00,0x78,0xe0,0x01,0x00,0x50,
572 0x00,0x18,}
573};
574
575
576#ifdef DE4X5_DEBUG
577static int de4x5_debug = DE4X5_DEBUG;
578#else
579/*static int de4x5_debug = (DEBUG_MII | DEBUG_SROM | DEBUG_PCICFG | DEBUG_MEDIA | DEBUG_VERSION);*/
580static int de4x5_debug = (DEBUG_MEDIA | DEBUG_VERSION);
581#endif
582
583/*
584** Allow per adapter set up. For modules this is simply a command line
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400585** parameter, e.g.:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586** insmod de4x5 args='eth1:fdx autosense=BNC eth0:autosense=100Mb'.
587**
588** For a compiled in driver, place e.g.
589** #define DE4X5_PARM "eth0:fdx autosense=AUI eth2:autosense=TP"
590** here
591*/
592#ifdef DE4X5_PARM
593static char *args = DE4X5_PARM;
594#else
595static char *args;
596#endif
597
598struct parameters {
Richard Knutssoneb034a72007-05-19 22:18:10 +0200599 bool fdx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 int autosense;
601};
602
603#define DE4X5_AUTOSENSE_MS 250 /* msec autosense tick (DE500) */
604
605#define DE4X5_NDA 0xffe0 /* No Device (I/O) Address */
606
607/*
608** Ethernet PROM defines
609*/
610#define PROBE_LENGTH 32
611#define ETH_PROM_SIG 0xAA5500FFUL
612
613/*
614** Ethernet Info
615*/
616#define PKT_BUF_SZ 1536 /* Buffer size for each Tx/Rx buffer */
617#define IEEE802_3_SZ 1518 /* Packet + CRC */
618#define MAX_PKT_SZ 1514 /* Maximum ethernet packet length */
619#define MAX_DAT_SZ 1500 /* Maximum ethernet data length */
620#define MIN_DAT_SZ 1 /* Minimum ethernet data length */
621#define PKT_HDR_LEN 14 /* Addresses and data length info */
622#define FAKE_FRAME_LEN (MAX_PKT_SZ + 1)
623#define QUEUE_PKT_TIMEOUT (3*HZ) /* 3 second timeout */
624
625
626/*
627** EISA bus defines
628*/
629#define DE4X5_EISA_IO_PORTS 0x0c00 /* I/O port base address, slot 0 */
630#define DE4X5_EISA_TOTAL_SIZE 0x100 /* I/O address extent */
631
632#define EISA_ALLOWED_IRQ_LIST {5, 9, 10, 11}
633
634#define DE4X5_SIGNATURE {"DE425","DE434","DE435","DE450","DE500"}
635#define DE4X5_NAME_LENGTH 8
636
637static c_char *de4x5_signatures[] = DE4X5_SIGNATURE;
638
639/*
640** Ethernet PROM defines for DC21040
641*/
642#define PROBE_LENGTH 32
643#define ETH_PROM_SIG 0xAA5500FFUL
644
645/*
646** PCI Bus defines
647*/
648#define PCI_MAX_BUS_NUM 8
649#define DE4X5_PCI_TOTAL_SIZE 0x80 /* I/O address extent */
650#define DE4X5_CLASS_CODE 0x00020000 /* Network controller, Ethernet */
651
652/*
653** Memory Alignment. Each descriptor is 4 longwords long. To force a
654** particular alignment on the TX descriptor, adjust DESC_SKIP_LEN and
655** DESC_ALIGN. ALIGN aligns the start address of the private memory area
Jeff Garzikf3b197a2006-05-26 21:39:03 -0400656** and hence the RX descriptor ring's first entry.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657*/
658#define DE4X5_ALIGN4 ((u_long)4 - 1) /* 1 longword align */
659#define DE4X5_ALIGN8 ((u_long)8 - 1) /* 2 longword align */
660#define DE4X5_ALIGN16 ((u_long)16 - 1) /* 4 longword align */
661#define DE4X5_ALIGN32 ((u_long)32 - 1) /* 8 longword align */
662#define DE4X5_ALIGN64 ((u_long)64 - 1) /* 16 longword align */
663#define DE4X5_ALIGN128 ((u_long)128 - 1) /* 32 longword align */
664
665#define DE4X5_ALIGN DE4X5_ALIGN32 /* Keep the DC21040 happy... */
666#define DE4X5_CACHE_ALIGN CAL_16LONG
667#define DESC_SKIP_LEN DSL_0 /* Must agree with DESC_ALIGN */
668/*#define DESC_ALIGN u32 dummy[4]; / * Must agree with DESC_SKIP_LEN */
669#define DESC_ALIGN
670
671#ifndef DEC_ONLY /* See README.de4x5 for using this */
672static int dec_only;
673#else
674static int dec_only = 1;
675#endif
676
677/*
678** DE4X5 IRQ ENABLE/DISABLE
679*/
680#define ENABLE_IRQs { \
681 imr |= lp->irq_en;\
682 outl(imr, DE4X5_IMR); /* Enable the IRQs */\
683}
684
685#define DISABLE_IRQs {\
686 imr = inl(DE4X5_IMR);\
687 imr &= ~lp->irq_en;\
688 outl(imr, DE4X5_IMR); /* Disable the IRQs */\
689}
690
691#define UNMASK_IRQs {\
692 imr |= lp->irq_mask;\
693 outl(imr, DE4X5_IMR); /* Unmask the IRQs */\
694}
695
696#define MASK_IRQs {\
697 imr = inl(DE4X5_IMR);\
698 imr &= ~lp->irq_mask;\
699 outl(imr, DE4X5_IMR); /* Mask the IRQs */\
700}
701
702/*
703** DE4X5 START/STOP
704*/
705#define START_DE4X5 {\
706 omr = inl(DE4X5_OMR);\
707 omr |= OMR_ST | OMR_SR;\
708 outl(omr, DE4X5_OMR); /* Enable the TX and/or RX */\
709}
710
711#define STOP_DE4X5 {\
712 omr = inl(DE4X5_OMR);\
713 omr &= ~(OMR_ST|OMR_SR);\
714 outl(omr, DE4X5_OMR); /* Disable the TX and/or RX */ \
715}
716
717/*
718** DE4X5 SIA RESET
719*/
720#define RESET_SIA outl(0, DE4X5_SICR); /* Reset SIA connectivity regs */
721
722/*
723** DE500 AUTOSENSE TIMER INTERVAL (MILLISECS)
724*/
725#define DE4X5_AUTOSENSE_MS 250
726
727/*
728** SROM Structure
729*/
730struct de4x5_srom {
731 char sub_vendor_id[2];
732 char sub_system_id[2];
733 char reserved[12];
734 char id_block_crc;
735 char reserved2;
736 char version;
737 char num_controllers;
738 char ieee_addr[6];
739 char info[100];
740 short chksum;
741};
742#define SUB_VENDOR_ID 0x500a
743
744/*
745** DE4X5 Descriptors. Make sure that all the RX buffers are contiguous
746** and have sizes of both a power of 2 and a multiple of 4.
747** A size of 256 bytes for each buffer could be chosen because over 90% of
748** all packets in our network are <256 bytes long and 64 longword alignment
749** is possible. 1536 showed better 'ttcp' performance. Take your pick. 32 TX
750** descriptors are needed for machines with an ALPHA CPU.
751*/
752#define NUM_RX_DESC 8 /* Number of RX descriptors */
753#define NUM_TX_DESC 32 /* Number of TX descriptors */
754#define RX_BUFF_SZ 1536 /* Power of 2 for kmalloc and */
755 /* Multiple of 4 for DC21040 */
756 /* Allows 512 byte alignment */
757struct de4x5_desc {
Al Viroc559a5b2007-08-23 00:43:22 -0400758 volatile __le32 status;
759 __le32 des1;
760 __le32 buf;
761 __le32 next;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 DESC_ALIGN
763};
764
765/*
766** The DE4X5 private structure
767*/
768#define DE4X5_PKT_STAT_SZ 16
769#define DE4X5_PKT_BIN_SZ 128 /* Should be >=100 unless you
770 increase DE4X5_PKT_STAT_SZ */
771
772struct pkt_stats {
773 u_int bins[DE4X5_PKT_STAT_SZ]; /* Private stats counters */
774 u_int unicast;
775 u_int multicast;
776 u_int broadcast;
777 u_int excessive_collisions;
778 u_int tx_underruns;
779 u_int excessive_underruns;
780 u_int rx_runt_frames;
781 u_int rx_collision;
782 u_int rx_dribble;
783 u_int rx_overflow;
784};
785
786struct de4x5_private {
787 char adapter_name[80]; /* Adapter name */
788 u_long interrupt; /* Aligned ISR flag */
789 struct de4x5_desc *rx_ring; /* RX descriptor ring */
790 struct de4x5_desc *tx_ring; /* TX descriptor ring */
791 struct sk_buff *tx_skb[NUM_TX_DESC]; /* TX skb for freeing when sent */
792 struct sk_buff *rx_skb[NUM_RX_DESC]; /* RX skb's */
793 int rx_new, rx_old; /* RX descriptor ring pointers */
794 int tx_new, tx_old; /* TX descriptor ring pointers */
795 char setup_frame[SETUP_FRAME_LEN]; /* Holds MCA and PA info. */
796 char frame[64]; /* Min sized packet for loopback*/
797 spinlock_t lock; /* Adapter specific spinlock */
798 struct net_device_stats stats; /* Public stats */
799 struct pkt_stats pktStats; /* Private stats counters */
800 char rxRingSize;
801 char txRingSize;
802 int bus; /* EISA or PCI */
803 int bus_num; /* PCI Bus number */
804 int device; /* Device number on PCI bus */
805 int state; /* Adapter OPENED or CLOSED */
806 int chipset; /* DC21040, DC21041 or DC21140 */
807 s32 irq_mask; /* Interrupt Mask (Enable) bits */
808 s32 irq_en; /* Summary interrupt bits */
809 int media; /* Media (eg TP), mode (eg 100B)*/
810 int c_media; /* Remember the last media conn */
Richard Knutssoneb034a72007-05-19 22:18:10 +0200811 bool fdx; /* media full duplex flag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 int linkOK; /* Link is OK */
813 int autosense; /* Allow/disallow autosensing */
Richard Knutssoneb034a72007-05-19 22:18:10 +0200814 bool tx_enable; /* Enable descriptor polling */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 int setup_f; /* Setup frame filtering type */
816 int local_state; /* State within a 'media' state */
817 struct mii_phy phy[DE4X5_MAX_PHY]; /* List of attached PHY devices */
818 struct sia_phy sia; /* SIA PHY Information */
819 int active; /* Index to active PHY device */
820 int mii_cnt; /* Number of attached PHY's */
821 int timeout; /* Scheduling counter */
822 struct timer_list timer; /* Timer info for kernel */
823 int tmp; /* Temporary global per card */
824 struct {
825 u_long lock; /* Lock the cache accesses */
826 s32 csr0; /* Saved Bus Mode Register */
827 s32 csr6; /* Saved Operating Mode Reg. */
828 s32 csr7; /* Saved IRQ Mask Register */
829 s32 gep; /* Saved General Purpose Reg. */
830 s32 gepc; /* Control info for GEP */
831 s32 csr13; /* Saved SIA Connectivity Reg. */
832 s32 csr14; /* Saved SIA TX/RX Register */
833 s32 csr15; /* Saved SIA General Register */
834 int save_cnt; /* Flag if state already saved */
David S. Miller2aad7c82008-09-23 00:19:19 -0700835 struct sk_buff_head queue; /* Save the (re-ordered) skb's */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 } cache;
837 struct de4x5_srom srom; /* A copy of the SROM */
838 int cfrv; /* Card CFRV copy */
839 int rx_ovf; /* Check for 'RX overflow' tag */
Richard Knutssoneb034a72007-05-19 22:18:10 +0200840 bool useSROM; /* For non-DEC card use SROM */
841 bool useMII; /* Infoblock using the MII */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 int asBitValid; /* Autosense bits in GEP? */
843 int asPolarity; /* 0 => asserted high */
844 int asBit; /* Autosense bit number in GEP */
845 int defMedium; /* SROM default medium */
846 int tcount; /* Last infoblock number */
847 int infoblock_init; /* Initialised this infoblock? */
848 int infoleaf_offset; /* SROM infoleaf for controller */
849 s32 infoblock_csr6; /* csr6 value in SROM infoblock */
850 int infoblock_media; /* infoblock media */
851 int (*infoleaf_fn)(struct net_device *); /* Pointer to infoleaf function */
852 u_char *rst; /* Pointer to Type 5 reset info */
853 u_char ibn; /* Infoblock number */
854 struct parameters params; /* Command line/ #defined params */
855 struct device *gendev; /* Generic device */
856 dma_addr_t dma_rings; /* DMA handle for rings */
857 int dma_size; /* Size of the DMA area */
858 char *rx_bufs; /* rx bufs on alpha, sparc, ... */
859};
860
861/*
862** To get around certain poxy cards that don't provide an SROM
863** for the second and more DECchip, I have to key off the first
864** chip's address. I'll assume there's not a bad SROM iff:
865**
866** o the chipset is the same
867** o the bus number is the same and > 0
868** o the sum of all the returned hw address bytes is 0 or 0x5fa
869**
870** Also have to save the irq for those cards whose hardware designers
871** can't follow the PCI to PCI Bridge Architecture spec.
872*/
873static struct {
874 int chipset;
875 int bus;
876 int irq;
877 u_char addr[ETH_ALEN];
878} last = {0,};
879
880/*
881** The transmit ring full condition is described by the tx_old and tx_new
882** pointers by:
883** tx_old = tx_new Empty ring
884** tx_old = tx_new+1 Full ring
885** tx_old+txRingSize = tx_new+1 Full ring (wrapped condition)
886*/
887#define TX_BUFFS_AVAIL ((lp->tx_old<=lp->tx_new)?\
888 lp->tx_old+lp->txRingSize-lp->tx_new-1:\
889 lp->tx_old -lp->tx_new-1)
890
891#define TX_PKT_PENDING (lp->tx_old != lp->tx_new)
892
893/*
894** Public Functions
895*/
896static int de4x5_open(struct net_device *dev);
897static int de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100898static irqreturn_t de4x5_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899static int de4x5_close(struct net_device *dev);
900static struct net_device_stats *de4x5_get_stats(struct net_device *dev);
901static void de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len);
902static void set_multicast_list(struct net_device *dev);
903static int de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
904
905/*
906** Private functions
907*/
908static int de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev);
909static int de4x5_init(struct net_device *dev);
910static int de4x5_sw_reset(struct net_device *dev);
911static int de4x5_rx(struct net_device *dev);
912static int de4x5_tx(struct net_device *dev);
Al Viro561b4fb2007-12-23 20:01:04 +0000913static void de4x5_ast(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914static int de4x5_txur(struct net_device *dev);
915static int de4x5_rx_ovfc(struct net_device *dev);
916
917static int autoconf_media(struct net_device *dev);
918static void create_packet(struct net_device *dev, char *frame, int len);
919static void load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb);
920static int dc21040_autoconf(struct net_device *dev);
921static int dc21041_autoconf(struct net_device *dev);
922static int dc21140m_autoconf(struct net_device *dev);
923static int dc2114x_autoconf(struct net_device *dev);
924static int srom_autoconf(struct net_device *dev);
925static int de4x5_suspect_state(struct net_device *dev, int timeout, int prev_state, int (*fn)(struct net_device *, int), int (*asfn)(struct net_device *));
926static int dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout, int next_state, int suspect_state, int (*fn)(struct net_device *, int));
927static int test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec);
928static int test_for_100Mb(struct net_device *dev, int msec);
929static int wait_for_link(struct net_device *dev);
Richard Knutssoneb034a72007-05-19 22:18:10 +0200930static int test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931static int is_spd_100(struct net_device *dev);
932static int is_100_up(struct net_device *dev);
933static int is_10_up(struct net_device *dev);
934static int is_anc_capable(struct net_device *dev);
935static int ping_media(struct net_device *dev, int msec);
936static struct sk_buff *de4x5_alloc_rx_buff(struct net_device *dev, int index, int len);
937static void de4x5_free_rx_buffs(struct net_device *dev);
938static void de4x5_free_tx_buffs(struct net_device *dev);
939static void de4x5_save_skbs(struct net_device *dev);
940static void de4x5_rst_desc_ring(struct net_device *dev);
941static void de4x5_cache_state(struct net_device *dev, int flag);
942static void de4x5_put_cache(struct net_device *dev, struct sk_buff *skb);
943static void de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb);
944static struct sk_buff *de4x5_get_cache(struct net_device *dev);
945static void de4x5_setup_intr(struct net_device *dev);
946static void de4x5_init_connection(struct net_device *dev);
947static int de4x5_reset_phy(struct net_device *dev);
948static void reset_init_sia(struct net_device *dev, s32 sicr, s32 strr, s32 sigr);
949static int test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec);
950static int test_tp(struct net_device *dev, s32 msec);
951static int EISA_signature(char *name, struct device *device);
952static int PCI_signature(char *name, struct de4x5_private *lp);
953static void DevicePresent(struct net_device *dev, u_long iobase);
954static void enet_addr_rst(u_long aprom_addr);
955static int de4x5_bad_srom(struct de4x5_private *lp);
956static short srom_rd(u_long address, u_char offset);
957static void srom_latch(u_int command, u_long address);
958static void srom_command(u_int command, u_long address);
959static void srom_address(u_int command, u_long address, u_char offset);
960static short srom_data(u_int command, u_long address);
961/*static void srom_busy(u_int command, u_long address);*/
962static void sendto_srom(u_int command, u_long addr);
963static int getfrom_srom(u_long addr);
964static int srom_map_media(struct net_device *dev);
965static int srom_infoleaf_info(struct net_device *dev);
966static void srom_init(struct net_device *dev);
967static void srom_exec(struct net_device *dev, u_char *p);
968static int mii_rd(u_char phyreg, u_char phyaddr, u_long ioaddr);
969static void mii_wr(int data, u_char phyreg, u_char phyaddr, u_long ioaddr);
970static int mii_rdata(u_long ioaddr);
971static void mii_wdata(int data, int len, u_long ioaddr);
972static void mii_ta(u_long rw, u_long ioaddr);
973static int mii_swap(int data, int len);
974static void mii_address(u_char addr, u_long ioaddr);
975static void sendto_mii(u32 command, int data, u_long ioaddr);
976static int getfrom_mii(u32 command, u_long ioaddr);
977static int mii_get_oui(u_char phyaddr, u_long ioaddr);
978static int mii_get_phy(struct net_device *dev);
979static void SetMulticastFilter(struct net_device *dev);
980static int get_hw_addr(struct net_device *dev);
981static void srom_repair(struct net_device *dev, int card);
982static int test_bad_enet(struct net_device *dev, int status);
983static int an_exception(struct de4x5_private *lp);
984static char *build_setup_frame(struct net_device *dev, int mode);
985static void disable_ast(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986static long de4x5_switch_mac_port(struct net_device *dev);
987static int gep_rd(struct net_device *dev);
988static void gep_wr(s32 data, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989static void yawn(struct net_device *dev, int state);
990static void de4x5_parse_params(struct net_device *dev);
991static void de4x5_dbg_open(struct net_device *dev);
992static void de4x5_dbg_mii(struct net_device *dev, int k);
993static void de4x5_dbg_media(struct net_device *dev);
994static void de4x5_dbg_srom(struct de4x5_srom *p);
995static void de4x5_dbg_rx(struct sk_buff *skb, int len);
996static int de4x5_strncmp(char *a, char *b, int n);
997static int dc21041_infoleaf(struct net_device *dev);
998static int dc21140_infoleaf(struct net_device *dev);
999static int dc21142_infoleaf(struct net_device *dev);
1000static int dc21143_infoleaf(struct net_device *dev);
1001static int type0_infoblock(struct net_device *dev, u_char count, u_char *p);
1002static int type1_infoblock(struct net_device *dev, u_char count, u_char *p);
1003static int type2_infoblock(struct net_device *dev, u_char count, u_char *p);
1004static int type3_infoblock(struct net_device *dev, u_char count, u_char *p);
1005static int type4_infoblock(struct net_device *dev, u_char count, u_char *p);
1006static int type5_infoblock(struct net_device *dev, u_char count, u_char *p);
1007static int compact_infoblock(struct net_device *dev, u_char count, u_char *p);
1008
1009/*
1010** Note now that module autoprobing is allowed under EISA and PCI. The
1011** IRQ lines will not be auto-detected; instead I'll rely on the BIOSes
1012** to "do the right thing".
1013*/
1014
1015static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */
1016
1017module_param(io, int, 0);
1018module_param(de4x5_debug, int, 0);
1019module_param(dec_only, int, 0);
1020module_param(args, charp, 0);
1021
1022MODULE_PARM_DESC(io, "de4x5 I/O base address");
1023MODULE_PARM_DESC(de4x5_debug, "de4x5 debug mask");
1024MODULE_PARM_DESC(dec_only, "de4x5 probe only for Digital boards (0-1)");
1025MODULE_PARM_DESC(args, "de4x5 full duplex and media type settings; see de4x5.c for details");
1026MODULE_LICENSE("GPL");
1027
1028/*
1029** List the SROM infoleaf functions and chipsets
1030*/
1031struct InfoLeaf {
1032 int chipset;
1033 int (*fn)(struct net_device *);
1034};
1035static struct InfoLeaf infoleaf_array[] = {
1036 {DC21041, dc21041_infoleaf},
1037 {DC21140, dc21140_infoleaf},
1038 {DC21142, dc21142_infoleaf},
1039 {DC21143, dc21143_infoleaf}
1040};
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001041#define INFOLEAF_SIZE ARRAY_SIZE(infoleaf_array)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
1043/*
1044** List the SROM info block functions
1045*/
1046static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = {
1047 type0_infoblock,
1048 type1_infoblock,
1049 type2_infoblock,
1050 type3_infoblock,
1051 type4_infoblock,
1052 type5_infoblock,
1053 compact_infoblock
1054};
1055
Alejandro Martinez Ruize9edda62007-10-15 03:37:43 +02001056#define COMPACT (ARRAY_SIZE(dc_infoblock) - 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058/*
1059** Miscellaneous defines...
1060*/
1061#define RESET_DE4X5 {\
1062 int i;\
1063 i=inl(DE4X5_BMR);\
1064 mdelay(1);\
1065 outl(i | BMR_SWR, DE4X5_BMR);\
1066 mdelay(1);\
1067 outl(i, DE4X5_BMR);\
1068 mdelay(1);\
1069 for (i=0;i<5;i++) {inl(DE4X5_BMR); mdelay(1);}\
1070 mdelay(1);\
1071}
1072
1073#define PHY_HARD_RESET {\
1074 outl(GEP_HRST, DE4X5_GEP); /* Hard RESET the PHY dev. */\
1075 mdelay(1); /* Assert for 1ms */\
1076 outl(0x00, DE4X5_GEP);\
1077 mdelay(2); /* Wait for 2ms */\
1078}
1079
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001080
1081static int __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
1083{
1084 char name[DE4X5_NAME_LENGTH + 1];
1085 struct de4x5_private *lp = netdev_priv(dev);
1086 struct pci_dev *pdev = NULL;
1087 int i, status=0;
1088
1089 gendev->driver_data = dev;
1090
1091 /* Ensure we're not sleeping */
1092 if (lp->bus == EISA) {
1093 outb(WAKEUP, PCI_CFPM);
1094 } else {
1095 pdev = to_pci_dev (gendev);
1096 pci_write_config_byte(pdev, PCI_CFDA_PSM, WAKEUP);
1097 }
1098 mdelay(10);
1099
1100 RESET_DE4X5;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001101
Linus Torvalds1da177e2005-04-16 15:20:36 -07001102 if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0) {
1103 return -ENXIO; /* Hardware could not reset */
1104 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001105
1106 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 ** Now find out what kind of DC21040/DC21041/DC21140 board we have.
1108 */
Richard Knutssoneb034a72007-05-19 22:18:10 +02001109 lp->useSROM = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 if (lp->bus == PCI) {
1111 PCI_signature(name, lp);
1112 } else {
1113 EISA_signature(name, gendev);
1114 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001115
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 if (*name == '\0') { /* Not found a board signature */
1117 return -ENXIO;
1118 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 dev->base_addr = iobase;
Kay Sieversfb28ad32008-11-10 13:55:14 -08001121 printk ("%s: %s at 0x%04lx", dev_name(gendev), name, iobase);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001122
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 status = get_hw_addr(dev);
Johannes Berge1749612008-10-27 15:59:26 -07001124 printk(", h/w address %pM\n", dev->dev_addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001125
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 if (status != 0) {
1127 printk(" which has an Ethernet PROM CRC error.\n");
1128 return -ENXIO;
1129 } else {
David S. Miller2aad7c82008-09-23 00:19:19 -07001130 skb_queue_head_init(&lp->cache.queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 lp->cache.gepc = GEP_INIT;
1132 lp->asBit = GEP_SLNK;
1133 lp->asPolarity = GEP_SLNK;
Richard Knutssoneb034a72007-05-19 22:18:10 +02001134 lp->asBitValid = ~0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 lp->timeout = -1;
1136 lp->gendev = gendev;
1137 spin_lock_init(&lp->lock);
1138 init_timer(&lp->timer);
Al Viro561b4fb2007-12-23 20:01:04 +00001139 lp->timer.function = (void (*)(unsigned long))de4x5_ast;
1140 lp->timer.data = (unsigned long)dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 de4x5_parse_params(dev);
1142
1143 /*
1144 ** Choose correct autosensing in case someone messed up
1145 */
1146 lp->autosense = lp->params.autosense;
1147 if (lp->chipset != DC21140) {
1148 if ((lp->chipset==DC21040) && (lp->params.autosense&TP_NW)) {
1149 lp->params.autosense = TP;
1150 }
1151 if ((lp->chipset==DC21041) && (lp->params.autosense&BNC_AUI)) {
1152 lp->params.autosense = BNC;
1153 }
1154 }
1155 lp->fdx = lp->params.fdx;
Kay Sieversfb28ad32008-11-10 13:55:14 -08001156 sprintf(lp->adapter_name,"%s (%s)", name, dev_name(gendev));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157
1158 lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);
David S. Miller49345102007-03-29 01:39:44 -07001159#if defined(__alpha__) || defined(__powerpc__) || defined(CONFIG_SPARC) || defined(DE4X5_DO_MEMCPY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 lp->dma_size += RX_BUFF_SZ * NUM_RX_DESC + DE4X5_ALIGN;
1161#endif
1162 lp->rx_ring = dma_alloc_coherent(gendev, lp->dma_size,
1163 &lp->dma_rings, GFP_ATOMIC);
1164 if (lp->rx_ring == NULL) {
1165 return -ENOMEM;
1166 }
1167
1168 lp->tx_ring = lp->rx_ring + NUM_RX_DESC;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 /*
1171 ** Set up the RX descriptor ring (Intels)
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001172 ** Allocate contiguous receive buffers, long word aligned (Alphas)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 */
David S. Miller49345102007-03-29 01:39:44 -07001174#if !defined(__alpha__) && !defined(__powerpc__) && !defined(CONFIG_SPARC) && !defined(DE4X5_DO_MEMCPY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 for (i=0; i<NUM_RX_DESC; i++) {
1176 lp->rx_ring[i].status = 0;
1177 lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
1178 lp->rx_ring[i].buf = 0;
1179 lp->rx_ring[i].next = 0;
1180 lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */
1181 }
1182
1183#else
1184 {
1185 dma_addr_t dma_rx_bufs;
1186
1187 dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC)
1188 * sizeof(struct de4x5_desc);
1189 dma_rx_bufs = (dma_rx_bufs + DE4X5_ALIGN) & ~DE4X5_ALIGN;
1190 lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC
1191 + NUM_TX_DESC) + DE4X5_ALIGN) & ~DE4X5_ALIGN);
1192 for (i=0; i<NUM_RX_DESC; i++) {
1193 lp->rx_ring[i].status = 0;
1194 lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);
1195 lp->rx_ring[i].buf =
1196 cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ);
1197 lp->rx_ring[i].next = 0;
1198 lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */
1199 }
1200
1201 }
1202#endif
1203
1204 barrier();
1205
1206 lp->rxRingSize = NUM_RX_DESC;
1207 lp->txRingSize = NUM_TX_DESC;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001208
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 /* Write the end of list marker to the descriptor lists */
1210 lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);
1211 lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER);
1212
1213 /* Tell the adapter where the TX/RX rings are located. */
1214 outl(lp->dma_rings, DE4X5_RRBA);
1215 outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
1216 DE4X5_TRBA);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 /* Initialise the IRQ mask and Enable/Disable */
1219 lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM;
1220 lp->irq_en = IMR_NIM | IMR_AIM;
1221
1222 /* Create a loopback packet frame for later media probing */
1223 create_packet(dev, lp->frame, sizeof(lp->frame));
1224
1225 /* Check if the RX overflow bug needs testing for */
1226 i = lp->cfrv & 0x000000fe;
1227 if ((lp->chipset == DC21140) && (i == 0x20)) {
1228 lp->rx_ovf = 1;
1229 }
1230
1231 /* Initialise the SROM pointers if possible */
1232 if (lp->useSROM) {
1233 lp->state = INITIALISED;
1234 if (srom_infoleaf_info(dev)) {
1235 dma_free_coherent (gendev, lp->dma_size,
1236 lp->rx_ring, lp->dma_rings);
1237 return -ENXIO;
1238 }
1239 srom_init(dev);
1240 }
1241
1242 lp->state = CLOSED;
1243
1244 /*
1245 ** Check for an MII interface
1246 */
1247 if ((lp->chipset != DC21040) && (lp->chipset != DC21041)) {
1248 mii_get_phy(dev);
1249 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 printk(" and requires IRQ%d (provided by %s).\n", dev->irq,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 ((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG"));
1253 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 if (de4x5_debug & DEBUG_VERSION) {
1256 printk(version);
1257 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001258
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 /* The DE4X5-specific entries in the device structure. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 SET_NETDEV_DEV(dev, gendev);
1261 dev->open = &de4x5_open;
1262 dev->hard_start_xmit = &de4x5_queue_pkt;
1263 dev->stop = &de4x5_close;
1264 dev->get_stats = &de4x5_get_stats;
1265 dev->set_multicast_list = &set_multicast_list;
1266 dev->do_ioctl = &de4x5_ioctl;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001267
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 dev->mem_start = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 /* Fill in the generic fields of the device structure. */
1271 if ((status = register_netdev (dev))) {
1272 dma_free_coherent (gendev, lp->dma_size,
1273 lp->rx_ring, lp->dma_rings);
1274 return status;
1275 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 /* Let the adapter sleep to save power */
1278 yawn(dev, SLEEP);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001279
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return status;
1281}
1282
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284static int
1285de4x5_open(struct net_device *dev)
1286{
1287 struct de4x5_private *lp = netdev_priv(dev);
1288 u_long iobase = dev->base_addr;
1289 int i, status = 0;
1290 s32 omr;
1291
1292 /* Allocate the RX buffers */
1293 for (i=0; i<lp->rxRingSize; i++) {
1294 if (de4x5_alloc_rx_buff(dev, i, 0) == NULL) {
1295 de4x5_free_rx_buffs(dev);
1296 return -EAGAIN;
1297 }
1298 }
1299
1300 /*
1301 ** Wake up the adapter
1302 */
1303 yawn(dev, WAKEUP);
1304
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001305 /*
1306 ** Re-initialize the DE4X5...
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 */
1308 status = de4x5_init(dev);
1309 spin_lock_init(&lp->lock);
1310 lp->state = OPEN;
1311 de4x5_dbg_open(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001312
Al Viro561b4fb2007-12-23 20:01:04 +00001313 if (request_irq(dev->irq, de4x5_interrupt, IRQF_SHARED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 lp->adapter_name, dev)) {
1315 printk("de4x5_open(): Requested IRQ%d is busy - attemping FAST/SHARE...", dev->irq);
Thomas Gleixner1fb9df52006-07-01 19:29:39 -07001316 if (request_irq(dev->irq, de4x5_interrupt, IRQF_DISABLED | IRQF_SHARED,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 lp->adapter_name, dev)) {
1318 printk("\n Cannot get IRQ- reconfigure your hardware.\n");
1319 disable_ast(dev);
1320 de4x5_free_rx_buffs(dev);
1321 de4x5_free_tx_buffs(dev);
1322 yawn(dev, SLEEP);
1323 lp->state = CLOSED;
1324 return -EAGAIN;
1325 } else {
1326 printk("\n Succeeded, but you should reconfigure your hardware to avoid this.\n");
1327 printk("WARNING: there may be IRQ related problems in heavily loaded systems.\n");
1328 }
1329 }
1330
1331 lp->interrupt = UNMASK_INTERRUPTS;
1332 dev->trans_start = jiffies;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 START_DE4X5;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001335
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 de4x5_setup_intr(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (de4x5_debug & DEBUG_OPEN) {
1339 printk("\tsts: 0x%08x\n", inl(DE4X5_STS));
1340 printk("\tbmr: 0x%08x\n", inl(DE4X5_BMR));
1341 printk("\timr: 0x%08x\n", inl(DE4X5_IMR));
1342 printk("\tomr: 0x%08x\n", inl(DE4X5_OMR));
1343 printk("\tsisr: 0x%08x\n", inl(DE4X5_SISR));
1344 printk("\tsicr: 0x%08x\n", inl(DE4X5_SICR));
1345 printk("\tstrr: 0x%08x\n", inl(DE4X5_STRR));
1346 printk("\tsigr: 0x%08x\n", inl(DE4X5_SIGR));
1347 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 return status;
1350}
1351
1352/*
1353** Initialize the DE4X5 operating conditions. NB: a chip problem with the
1354** DC21140 requires using perfect filtering mode for that chip. Since I can't
1355** see why I'd want > 14 multicast addresses, I have changed all chips to use
1356** the perfect filtering mode. Keep the DMA burst length at 8: there seems
1357** to be data corruption problems if it is larger (UDP errors seen from a
1358** ttcp source).
1359*/
1360static int
1361de4x5_init(struct net_device *dev)
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001362{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 /* Lock out other processes whilst setting up the hardware */
1364 netif_stop_queue(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 de4x5_sw_reset(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001367
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 /* Autoconfigure the connected port */
1369 autoconf_media(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001370
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 return 0;
1372}
1373
1374static int
1375de4x5_sw_reset(struct net_device *dev)
1376{
1377 struct de4x5_private *lp = netdev_priv(dev);
1378 u_long iobase = dev->base_addr;
1379 int i, j, status = 0;
1380 s32 bmr, omr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 /* Select the MII or SRL port now and RESET the MAC */
1383 if (!lp->useSROM) {
1384 if (lp->phy[lp->active].id != 0) {
1385 lp->infoblock_csr6 = OMR_SDP | OMR_PS | OMR_HBD;
1386 } else {
1387 lp->infoblock_csr6 = OMR_SDP | OMR_TTM;
1388 }
1389 de4x5_switch_mac_port(dev);
1390 }
1391
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001392 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 ** Set the programmable burst length to 8 longwords for all the DC21140
1394 ** Fasternet chips and 4 longwords for all others: DMA errors result
1395 ** without these values. Cache align 16 long.
1396 */
1397 bmr = (lp->chipset==DC21140 ? PBL_8 : PBL_4) | DESC_SKIP_LEN | DE4X5_CACHE_ALIGN;
1398 bmr |= ((lp->chipset & ~0x00ff)==DC2114x ? BMR_RML : 0);
1399 outl(bmr, DE4X5_BMR);
1400
1401 omr = inl(DE4X5_OMR) & ~OMR_PR; /* Turn off promiscuous mode */
1402 if (lp->chipset == DC21140) {
1403 omr |= (OMR_SDP | OMR_SB);
1404 }
1405 lp->setup_f = PERFECT;
1406 outl(lp->dma_rings, DE4X5_RRBA);
1407 outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
1408 DE4X5_TRBA);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 lp->rx_new = lp->rx_old = 0;
1411 lp->tx_new = lp->tx_old = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001412
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 for (i = 0; i < lp->rxRingSize; i++) {
1414 lp->rx_ring[i].status = cpu_to_le32(R_OWN);
1415 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 for (i = 0; i < lp->txRingSize; i++) {
1418 lp->tx_ring[i].status = cpu_to_le32(0);
1419 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001420
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 barrier();
1422
1423 /* Build the setup frame depending on filtering mode */
1424 SetMulticastFilter(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001425
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 load_packet(dev, lp->setup_frame, PERFECT_F|TD_SET|SETUP_FRAME_LEN, (struct sk_buff *)1);
1427 outl(omr|OMR_ST, DE4X5_OMR);
1428
1429 /* Poll for setup frame completion (adapter interrupts are disabled now) */
1430
1431 for (j=0, i=0;(i<500) && (j==0);i++) { /* Upto 500ms delay */
1432 mdelay(1);
1433 if ((s32)le32_to_cpu(lp->tx_ring[lp->tx_new].status) >= 0) j=1;
1434 }
1435 outl(omr, DE4X5_OMR); /* Stop everything! */
1436
1437 if (j == 0) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001438 printk("%s: Setup frame timed out, status %08x\n", dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 inl(DE4X5_STS));
1440 status = -EIO;
1441 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 lp->tx_new = (++lp->tx_new) % lp->txRingSize;
1444 lp->tx_old = lp->tx_new;
1445
1446 return status;
1447}
1448
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001449/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450** Writes a socket buffer address to the next available transmit descriptor.
1451*/
1452static int
1453de4x5_queue_pkt(struct sk_buff *skb, struct net_device *dev)
1454{
1455 struct de4x5_private *lp = netdev_priv(dev);
1456 u_long iobase = dev->base_addr;
1457 int status = 0;
1458 u_long flags = 0;
1459
1460 netif_stop_queue(dev);
Richard Knutssoneb034a72007-05-19 22:18:10 +02001461 if (!lp->tx_enable) { /* Cannot send for now */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001462 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001464
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 /*
1466 ** Clean out the TX ring asynchronously to interrupts - sometimes the
1467 ** interrupts are lost by delayed descriptor status updates relative to
1468 ** the irq assertion, especially with a busy PCI bus.
1469 */
1470 spin_lock_irqsave(&lp->lock, flags);
1471 de4x5_tx(dev);
1472 spin_unlock_irqrestore(&lp->lock, flags);
1473
1474 /* Test if cache is already locked - requeue skb if so */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001475 if (test_and_set_bit(0, (void *)&lp->cache.lock) && !lp->interrupt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 return -1;
1477
1478 /* Transmit descriptor ring full or stale skb */
1479 if (netif_queue_stopped(dev) || (u_long) lp->tx_skb[lp->tx_new] > 1) {
1480 if (lp->interrupt) {
1481 de4x5_putb_cache(dev, skb); /* Requeue the buffer */
1482 } else {
1483 de4x5_put_cache(dev, skb);
1484 }
1485 if (de4x5_debug & DEBUG_TX) {
1486 printk("%s: transmit busy, lost media or stale skb found:\n STS:%08x\n tbusy:%d\n IMR:%08x\n OMR:%08x\n Stale skb: %s\n",dev->name, inl(DE4X5_STS), netif_queue_stopped(dev), inl(DE4X5_IMR), inl(DE4X5_OMR), ((u_long) lp->tx_skb[lp->tx_new] > 1) ? "YES" : "NO");
1487 }
1488 } else if (skb->len > 0) {
1489 /* If we already have stuff queued locally, use that first */
David S. Miller2aad7c82008-09-23 00:19:19 -07001490 if (!skb_queue_empty(&lp->cache.queue) && !lp->interrupt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 de4x5_put_cache(dev, skb);
1492 skb = de4x5_get_cache(dev);
1493 }
1494
1495 while (skb && !netif_queue_stopped(dev) &&
1496 (u_long) lp->tx_skb[lp->tx_new] <= 1) {
1497 spin_lock_irqsave(&lp->lock, flags);
1498 netif_stop_queue(dev);
1499 load_packet(dev, skb->data, TD_IC | TD_LS | TD_FS | skb->len, skb);
1500 lp->stats.tx_bytes += skb->len;
1501 outl(POLL_DEMAND, DE4X5_TPD);/* Start the TX */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001502
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 lp->tx_new = (++lp->tx_new) % lp->txRingSize;
1504 dev->trans_start = jiffies;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 if (TX_BUFFS_AVAIL) {
1507 netif_start_queue(dev); /* Another pkt may be queued */
1508 }
1509 skb = de4x5_get_cache(dev);
1510 spin_unlock_irqrestore(&lp->lock, flags);
1511 }
1512 if (skb) de4x5_putb_cache(dev, skb);
1513 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001514
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 lp->cache.lock = 0;
1516
1517 return status;
1518}
1519
1520/*
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001521** The DE4X5 interrupt handler.
1522**
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523** I/O Read/Writes through intermediate PCI bridges are never 'posted',
1524** so that the asserted interrupt always has some real data to work with -
1525** if these I/O accesses are ever changed to memory accesses, ensure the
1526** STS write is read immediately to complete the transaction if the adapter
1527** is not on bus 0. Lost interrupts can still occur when the PCI bus load
1528** is high and descriptor status bits cannot be set before the associated
1529** interrupt is asserted and this routine entered.
1530*/
1531static irqreturn_t
David Howells7d12e782006-10-05 14:55:46 +01001532de4x5_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
Jeff Garzikc31f28e2006-10-06 14:56:04 -04001534 struct net_device *dev = dev_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 struct de4x5_private *lp;
1536 s32 imr, omr, sts, limit;
1537 u_long iobase;
1538 unsigned int handled = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001539
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 lp = netdev_priv(dev);
1541 spin_lock(&lp->lock);
1542 iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001543
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 DISABLE_IRQs; /* Ensure non re-entrancy */
1545
1546 if (test_and_set_bit(MASK_INTERRUPTS, (void*) &lp->interrupt))
1547 printk("%s: Re-entering the interrupt handler.\n", dev->name);
1548
1549 synchronize_irq(dev->irq);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001550
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 for (limit=0; limit<8; limit++) {
1552 sts = inl(DE4X5_STS); /* Read IRQ status */
1553 outl(sts, DE4X5_STS); /* Reset the board interrupts */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001554
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 if (!(sts & lp->irq_mask)) break;/* All done */
1556 handled = 1;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001557
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 if (sts & (STS_RI | STS_RU)) /* Rx interrupt (packet[s] arrived) */
1559 de4x5_rx(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001560
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 if (sts & (STS_TI | STS_TU)) /* Tx interrupt (packet sent) */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001562 de4x5_tx(dev);
1563
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 if (sts & STS_LNF) { /* TP Link has failed */
1565 lp->irq_mask &= ~IMR_LFM;
1566 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001567
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 if (sts & STS_UNF) { /* Transmit underrun */
1569 de4x5_txur(dev);
1570 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001571
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 if (sts & STS_SE) { /* Bus Error */
1573 STOP_DE4X5;
1574 printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
1575 dev->name, sts);
1576 spin_unlock(&lp->lock);
1577 return IRQ_HANDLED;
1578 }
1579 }
1580
1581 /* Load the TX ring with any locally stored packets */
1582 if (!test_and_set_bit(0, (void *)&lp->cache.lock)) {
David S. Miller2aad7c82008-09-23 00:19:19 -07001583 while (!skb_queue_empty(&lp->cache.queue) && !netif_queue_stopped(dev) && lp->tx_enable) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 de4x5_queue_pkt(de4x5_get_cache(dev), dev);
1585 }
1586 lp->cache.lock = 0;
1587 }
1588
1589 lp->interrupt = UNMASK_INTERRUPTS;
1590 ENABLE_IRQs;
1591 spin_unlock(&lp->lock);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001592
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 return IRQ_RETVAL(handled);
1594}
1595
1596static int
1597de4x5_rx(struct net_device *dev)
1598{
1599 struct de4x5_private *lp = netdev_priv(dev);
1600 u_long iobase = dev->base_addr;
1601 int entry;
1602 s32 status;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 for (entry=lp->rx_new; (s32)le32_to_cpu(lp->rx_ring[entry].status)>=0;
1605 entry=lp->rx_new) {
1606 status = (s32)le32_to_cpu(lp->rx_ring[entry].status);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 if (lp->rx_ovf) {
1609 if (inl(DE4X5_MFC) & MFC_FOCM) {
1610 de4x5_rx_ovfc(dev);
1611 break;
1612 }
1613 }
1614
1615 if (status & RD_FS) { /* Remember the start of frame */
1616 lp->rx_old = entry;
1617 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001618
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 if (status & RD_LS) { /* Valid frame status */
1620 if (lp->tx_enable) lp->linkOK++;
1621 if (status & RD_ES) { /* There was an error. */
1622 lp->stats.rx_errors++; /* Update the error stats. */
1623 if (status & (RD_RF | RD_TL)) lp->stats.rx_frame_errors++;
1624 if (status & RD_CE) lp->stats.rx_crc_errors++;
1625 if (status & RD_OF) lp->stats.rx_fifo_errors++;
1626 if (status & RD_TL) lp->stats.rx_length_errors++;
1627 if (status & RD_RF) lp->pktStats.rx_runt_frames++;
1628 if (status & RD_CS) lp->pktStats.rx_collision++;
1629 if (status & RD_DB) lp->pktStats.rx_dribble++;
1630 if (status & RD_OF) lp->pktStats.rx_overflow++;
1631 } else { /* A valid frame received */
1632 struct sk_buff *skb;
1633 short pkt_len = (short)(le32_to_cpu(lp->rx_ring[entry].status)
1634 >> 16) - 4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001635
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 if ((skb = de4x5_alloc_rx_buff(dev, entry, pkt_len)) == NULL) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001637 printk("%s: Insufficient memory; nuking packet.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 dev->name);
1639 lp->stats.rx_dropped++;
1640 } else {
1641 de4x5_dbg_rx(skb, pkt_len);
1642
1643 /* Push up the protocol stack */
1644 skb->protocol=eth_type_trans(skb,dev);
1645 de4x5_local_stats(dev, skb->data, pkt_len);
1646 netif_rx(skb);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001647
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 /* Update stats */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 lp->stats.rx_packets++;
1650 lp->stats.rx_bytes += pkt_len;
1651 }
1652 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001653
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 /* Change buffer ownership for this frame, back to the adapter */
1655 for (;lp->rx_old!=entry;lp->rx_old=(++lp->rx_old)%lp->rxRingSize) {
1656 lp->rx_ring[lp->rx_old].status = cpu_to_le32(R_OWN);
1657 barrier();
1658 }
1659 lp->rx_ring[entry].status = cpu_to_le32(R_OWN);
1660 barrier();
1661 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 /*
1664 ** Update entry information
1665 */
1666 lp->rx_new = (++lp->rx_new) % lp->rxRingSize;
1667 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 return 0;
1670}
1671
1672static inline void
1673de4x5_free_tx_buff(struct de4x5_private *lp, int entry)
1674{
1675 dma_unmap_single(lp->gendev, le32_to_cpu(lp->tx_ring[entry].buf),
1676 le32_to_cpu(lp->tx_ring[entry].des1) & TD_TBS1,
1677 DMA_TO_DEVICE);
1678 if ((u_long) lp->tx_skb[entry] > 1)
1679 dev_kfree_skb_irq(lp->tx_skb[entry]);
1680 lp->tx_skb[entry] = NULL;
1681}
1682
1683/*
1684** Buffer sent - check for TX buffer errors.
1685*/
1686static int
1687de4x5_tx(struct net_device *dev)
1688{
1689 struct de4x5_private *lp = netdev_priv(dev);
1690 u_long iobase = dev->base_addr;
1691 int entry;
1692 s32 status;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001693
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) {
1695 status = (s32)le32_to_cpu(lp->tx_ring[entry].status);
1696 if (status < 0) { /* Buffer not sent yet */
1697 break;
1698 } else if (status != 0x7fffffff) { /* Not setup frame */
1699 if (status & TD_ES) { /* An error happened */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001700 lp->stats.tx_errors++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 if (status & TD_NC) lp->stats.tx_carrier_errors++;
1702 if (status & TD_LC) lp->stats.tx_window_errors++;
1703 if (status & TD_UF) lp->stats.tx_fifo_errors++;
1704 if (status & TD_EC) lp->pktStats.excessive_collisions++;
1705 if (status & TD_DE) lp->stats.tx_aborted_errors++;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001706
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if (TX_PKT_PENDING) {
1708 outl(POLL_DEMAND, DE4X5_TPD);/* Restart a stalled TX */
1709 }
1710 } else { /* Packet sent */
1711 lp->stats.tx_packets++;
1712 if (lp->tx_enable) lp->linkOK++;
1713 }
1714 /* Update the collision counter */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001715 lp->stats.collisions += ((status & TD_EC) ? 16 :
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 ((status & TD_CC) >> 3));
1717
1718 /* Free the buffer. */
1719 if (lp->tx_skb[entry] != NULL)
1720 de4x5_free_tx_buff(lp, entry);
1721 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001722
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 /* Update all the pointers */
1724 lp->tx_old = (++lp->tx_old) % lp->txRingSize;
1725 }
1726
1727 /* Any resources available? */
1728 if (TX_BUFFS_AVAIL && netif_queue_stopped(dev)) {
1729 if (lp->interrupt)
1730 netif_wake_queue(dev);
1731 else
1732 netif_start_queue(dev);
1733 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001734
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 return 0;
1736}
1737
Al Viro561b4fb2007-12-23 20:01:04 +00001738static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739de4x5_ast(struct net_device *dev)
1740{
Al Viro561b4fb2007-12-23 20:01:04 +00001741 struct de4x5_private *lp = netdev_priv(dev);
1742 int next_tick = DE4X5_AUTOSENSE_MS;
1743 int dt;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001744
Al Viro561b4fb2007-12-23 20:01:04 +00001745 if (lp->useSROM)
1746 next_tick = srom_autoconf(dev);
1747 else if (lp->chipset == DC21140)
1748 next_tick = dc21140m_autoconf(dev);
1749 else if (lp->chipset == DC21041)
1750 next_tick = dc21041_autoconf(dev);
1751 else if (lp->chipset == DC21040)
1752 next_tick = dc21040_autoconf(dev);
1753 lp->linkOK = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001754
Al Viro561b4fb2007-12-23 20:01:04 +00001755 dt = (next_tick * HZ) / 1000;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001756
Al Viro561b4fb2007-12-23 20:01:04 +00001757 if (!dt)
1758 dt = 1;
1759
1760 mod_timer(&lp->timer, jiffies + dt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761}
1762
1763static int
1764de4x5_txur(struct net_device *dev)
1765{
1766 struct de4x5_private *lp = netdev_priv(dev);
1767 u_long iobase = dev->base_addr;
1768 int omr;
1769
1770 omr = inl(DE4X5_OMR);
1771 if (!(omr & OMR_SF) || (lp->chipset==DC21041) || (lp->chipset==DC21040)) {
1772 omr &= ~(OMR_ST|OMR_SR);
1773 outl(omr, DE4X5_OMR);
1774 while (inl(DE4X5_STS) & STS_TS);
1775 if ((omr & OMR_TR) < OMR_TR) {
1776 omr += 0x4000;
1777 } else {
1778 omr |= OMR_SF;
1779 }
1780 outl(omr | OMR_ST | OMR_SR, DE4X5_OMR);
1781 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001782
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 return 0;
1784}
1785
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001786static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787de4x5_rx_ovfc(struct net_device *dev)
1788{
1789 struct de4x5_private *lp = netdev_priv(dev);
1790 u_long iobase = dev->base_addr;
1791 int omr;
1792
1793 omr = inl(DE4X5_OMR);
1794 outl(omr & ~OMR_SR, DE4X5_OMR);
1795 while (inl(DE4X5_STS) & STS_RS);
1796
1797 for (; (s32)le32_to_cpu(lp->rx_ring[lp->rx_new].status)>=0;) {
1798 lp->rx_ring[lp->rx_new].status = cpu_to_le32(R_OWN);
1799 lp->rx_new = (++lp->rx_new % lp->rxRingSize);
1800 }
1801
1802 outl(omr, DE4X5_OMR);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001803
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 return 0;
1805}
1806
1807static int
1808de4x5_close(struct net_device *dev)
1809{
1810 struct de4x5_private *lp = netdev_priv(dev);
1811 u_long iobase = dev->base_addr;
1812 s32 imr, omr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001813
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 disable_ast(dev);
1815
1816 netif_stop_queue(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001817
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818 if (de4x5_debug & DEBUG_CLOSE) {
1819 printk("%s: Shutting down ethercard, status was %8.8x.\n",
1820 dev->name, inl(DE4X5_STS));
1821 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001822
1823 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 ** We stop the DE4X5 here... mask interrupts and stop TX & RX
1825 */
1826 DISABLE_IRQs;
1827 STOP_DE4X5;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001828
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 /* Free the associated irq */
1830 free_irq(dev->irq, dev);
1831 lp->state = CLOSED;
1832
1833 /* Free any socket buffers */
1834 de4x5_free_rx_buffs(dev);
1835 de4x5_free_tx_buffs(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001836
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 /* Put the adapter to sleep to save power */
1838 yawn(dev, SLEEP);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001839
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 return 0;
1841}
1842
1843static struct net_device_stats *
1844de4x5_get_stats(struct net_device *dev)
1845{
1846 struct de4x5_private *lp = netdev_priv(dev);
1847 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001848
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 lp->stats.rx_missed_errors = (int)(inl(DE4X5_MFC) & (MFC_OVFL | MFC_CNTR));
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001850
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 return &lp->stats;
1852}
1853
1854static void
1855de4x5_local_stats(struct net_device *dev, char *buf, int pkt_len)
1856{
1857 struct de4x5_private *lp = netdev_priv(dev);
1858 int i;
1859
1860 for (i=1; i<DE4X5_PKT_STAT_SZ-1; i++) {
1861 if (pkt_len < (i*DE4X5_PKT_BIN_SZ)) {
1862 lp->pktStats.bins[i]++;
1863 i = DE4X5_PKT_STAT_SZ;
1864 }
1865 }
1866 if (buf[0] & 0x01) { /* Multicast/Broadcast */
1867 if ((*(s32 *)&buf[0] == -1) && (*(s16 *)&buf[4] == -1)) {
1868 lp->pktStats.broadcast++;
1869 } else {
1870 lp->pktStats.multicast++;
1871 }
1872 } else if ((*(s32 *)&buf[0] == *(s32 *)&dev->dev_addr[0]) &&
1873 (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) {
1874 lp->pktStats.unicast++;
1875 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001876
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */
1878 if (lp->pktStats.bins[0] == 0) { /* Reset counters */
1879 memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats));
1880 }
1881
1882 return;
1883}
1884
1885/*
1886** Removes the TD_IC flag from previous descriptor to improve TX performance.
1887** If the flag is changed on a descriptor that is being read by the hardware,
1888** I assume PCI transaction ordering will mean you are either successful or
1889** just miss asserting the change to the hardware. Anyway you're messing with
1890** a descriptor you don't own, but this shouldn't kill the chip provided
1891** the descriptor register is read only to the hardware.
1892*/
1893static void
1894load_packet(struct net_device *dev, char *buf, u32 flags, struct sk_buff *skb)
1895{
1896 struct de4x5_private *lp = netdev_priv(dev);
1897 int entry = (lp->tx_new ? lp->tx_new-1 : lp->txRingSize-1);
1898 dma_addr_t buf_dma = dma_map_single(lp->gendev, buf, flags & TD_TBS1, DMA_TO_DEVICE);
1899
1900 lp->tx_ring[lp->tx_new].buf = cpu_to_le32(buf_dma);
1901 lp->tx_ring[lp->tx_new].des1 &= cpu_to_le32(TD_TER);
1902 lp->tx_ring[lp->tx_new].des1 |= cpu_to_le32(flags);
1903 lp->tx_skb[lp->tx_new] = skb;
1904 lp->tx_ring[entry].des1 &= cpu_to_le32(~TD_IC);
1905 barrier();
1906
1907 lp->tx_ring[lp->tx_new].status = cpu_to_le32(T_OWN);
1908 barrier();
1909}
1910
1911/*
1912** Set or clear the multicast filter for this adaptor.
1913*/
1914static void
1915set_multicast_list(struct net_device *dev)
1916{
1917 struct de4x5_private *lp = netdev_priv(dev);
1918 u_long iobase = dev->base_addr;
1919
1920 /* First, double check that the adapter is open */
1921 if (lp->state == OPEN) {
1922 if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */
1923 u32 omr;
1924 omr = inl(DE4X5_OMR);
1925 omr |= OMR_PR;
1926 outl(omr, DE4X5_OMR);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001927 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 SetMulticastFilter(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001929 load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001930 SETUP_FRAME_LEN, (struct sk_buff *)1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001931
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 lp->tx_new = (++lp->tx_new) % lp->txRingSize;
1933 outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
1934 dev->trans_start = jiffies;
1935 }
1936 }
1937}
1938
1939/*
1940** Calculate the hash code and update the logical address filter
1941** from a list of ethernet multicast addresses.
1942** Little endian crc one liner from Matt Thomas, DEC.
1943*/
1944static void
1945SetMulticastFilter(struct net_device *dev)
1946{
1947 struct de4x5_private *lp = netdev_priv(dev);
1948 struct dev_mc_list *dmi=dev->mc_list;
1949 u_long iobase = dev->base_addr;
1950 int i, j, bit, byte;
1951 u16 hashcode;
1952 u32 omr, crc;
1953 char *pa;
1954 unsigned char *addrs;
1955
1956 omr = inl(DE4X5_OMR);
1957 omr &= ~(OMR_PR | OMR_PM);
1958 pa = build_setup_frame(dev, ALL); /* Build the basic frame */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001959
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 if ((dev->flags & IFF_ALLMULTI) || (dev->mc_count > 14)) {
1961 omr |= OMR_PM; /* Pass all multicasts */
1962 } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */
1963 for (i=0;i<dev->mc_count;i++) { /* for each address in the list */
1964 addrs=dmi->dmi_addr;
1965 dmi=dmi->next;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001966 if ((*addrs & 0x01) == 1) { /* multicast address? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967 crc = ether_crc_le(ETH_ALEN, addrs);
1968 hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001969
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 byte = hashcode >> 3; /* bit[3-8] -> byte in filter */
1971 bit = 1 << (hashcode & 0x07);/* bit[0-2] -> bit in byte */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001972
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973 byte <<= 1; /* calc offset into setup frame */
1974 if (byte & 0x02) {
1975 byte -= 1;
1976 }
1977 lp->setup_frame[byte] |= bit;
1978 }
1979 }
1980 } else { /* Perfect filtering */
1981 for (j=0; j<dev->mc_count; j++) {
1982 addrs=dmi->dmi_addr;
1983 dmi=dmi->next;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001984 for (i=0; i<ETH_ALEN; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 *(pa + (i&1)) = *addrs++;
1986 if (i & 0x01) pa += 4;
1987 }
1988 }
1989 }
1990 outl(omr, DE4X5_OMR);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04001991
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992 return;
1993}
1994
1995#ifdef CONFIG_EISA
1996
1997static u_char de4x5_irq[] = EISA_ALLOWED_IRQ_LIST;
1998
1999static int __init de4x5_eisa_probe (struct device *gendev)
2000{
2001 struct eisa_device *edev;
2002 u_long iobase;
2003 u_char irq, regval;
2004 u_short vendor;
2005 u32 cfid;
2006 int status, device;
2007 struct net_device *dev;
2008 struct de4x5_private *lp;
2009
2010 edev = to_eisa_device (gendev);
2011 iobase = edev->base_addr;
2012
2013 if (!request_region (iobase, DE4X5_EISA_TOTAL_SIZE, "de4x5"))
2014 return -EBUSY;
2015
2016 if (!request_region (iobase + DE4X5_EISA_IO_PORTS,
2017 DE4X5_EISA_TOTAL_SIZE, "de4x5")) {
2018 status = -EBUSY;
2019 goto release_reg_1;
2020 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002021
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022 if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
2023 status = -ENOMEM;
2024 goto release_reg_2;
2025 }
2026 lp = netdev_priv(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 cfid = (u32) inl(PCI_CFID);
2029 lp->cfrv = (u_short) inl(PCI_CFRV);
2030 device = (cfid >> 8) & 0x00ffff00;
2031 vendor = (u_short) cfid;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 /* Read the EISA Configuration Registers */
2034 regval = inb(EISA_REG0) & (ER0_INTL | ER0_INTT);
2035#ifdef CONFIG_ALPHA
2036 /* Looks like the Jensen firmware (rev 2.2) doesn't really
2037 * care about the EISA configuration, and thus doesn't
2038 * configure the PLX bridge properly. Oh well... Simply mimic
2039 * the EISA config file to sort it out. */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002040
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041 /* EISA REG1: Assert DecChip 21040 HW Reset */
2042 outb (ER1_IAM | 1, EISA_REG1);
2043 mdelay (1);
2044
2045 /* EISA REG1: Deassert DecChip 21040 HW Reset */
2046 outb (ER1_IAM, EISA_REG1);
2047 mdelay (1);
2048
2049 /* EISA REG3: R/W Burst Transfer Enable */
2050 outb (ER3_BWE | ER3_BRE, EISA_REG3);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002051
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052 /* 32_bit slave/master, Preempt Time=23 bclks, Unlatched Interrupt */
2053 outb (ER0_BSW | ER0_BMW | ER0_EPT | regval, EISA_REG0);
2054#endif
2055 irq = de4x5_irq[(regval >> 1) & 0x03];
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002056
Linus Torvalds1da177e2005-04-16 15:20:36 -07002057 if (is_DC2114x) {
2058 device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
2059 }
2060 lp->chipset = device;
2061 lp->bus = EISA;
2062
2063 /* Write the PCI Configuration Registers */
2064 outl(PCI_COMMAND_IO | PCI_COMMAND_MASTER, PCI_CFCS);
2065 outl(0x00006000, PCI_CFLT);
2066 outl(iobase, PCI_CBIO);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002067
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068 DevicePresent(dev, EISA_APROM);
2069
2070 dev->irq = irq;
2071
2072 if (!(status = de4x5_hw_init (dev, iobase, gendev))) {
2073 return 0;
2074 }
2075
2076 free_netdev (dev);
2077 release_reg_2:
2078 release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE);
2079 release_reg_1:
2080 release_region (iobase, DE4X5_EISA_TOTAL_SIZE);
2081
2082 return status;
2083}
2084
2085static int __devexit de4x5_eisa_remove (struct device *device)
2086{
2087 struct net_device *dev;
2088 u_long iobase;
2089
2090 dev = device->driver_data;
2091 iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 unregister_netdev (dev);
2094 free_netdev (dev);
2095 release_region (iobase + DE4X5_EISA_IO_PORTS, DE4X5_EISA_TOTAL_SIZE);
2096 release_region (iobase, DE4X5_EISA_TOTAL_SIZE);
2097
2098 return 0;
2099}
2100
2101static struct eisa_device_id de4x5_eisa_ids[] = {
2102 { "DEC4250", 0 }, /* 0 is the board name index... */
2103 { "" }
2104};
Michael Tokarev07563c72006-09-27 01:50:56 -07002105MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
2107static struct eisa_driver de4x5_eisa_driver = {
2108 .id_table = de4x5_eisa_ids,
2109 .driver = {
2110 .name = "de4x5",
2111 .probe = de4x5_eisa_probe,
2112 .remove = __devexit_p (de4x5_eisa_remove),
2113 }
2114};
2115MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
2116#endif
2117
2118#ifdef CONFIG_PCI
2119
2120/*
2121** This function searches the current bus (which is >0) for a DECchip with an
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002122** SROM, so that in multiport cards that have one SROM shared between multiple
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
2124** For single port cards this is a time waster...
2125*/
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002126static void __devinit
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127srom_search(struct net_device *dev, struct pci_dev *pdev)
2128{
2129 u_char pb;
2130 u_short vendor, status;
2131 u_int irq = 0, device;
2132 u_long iobase = 0; /* Clear upper 32 bits in Alphas */
Auke Kok44c10132007-06-08 15:46:36 -07002133 int i, j;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134 struct de4x5_private *lp = netdev_priv(dev);
Domen Puncer0c5719c2005-09-10 00:27:10 -07002135 struct list_head *walk;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
Domen Puncer0c5719c2005-09-10 00:27:10 -07002137 list_for_each(walk, &pdev->bus_list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138 struct pci_dev *this_dev = pci_dev_b(walk);
2139
2140 /* Skip the pci_bus list entry */
2141 if (list_entry(walk, struct pci_bus, devices) == pdev->bus) continue;
2142
2143 vendor = this_dev->vendor;
2144 device = this_dev->device << 8;
2145 if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
2146
2147 /* Get the chip configuration revision register */
2148 pb = this_dev->bus->number;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
2150 /* Set the device number information */
2151 lp->device = PCI_SLOT(this_dev->devfn);
2152 lp->bus_num = pb;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 /* Set the chipset information */
2155 if (is_DC2114x) {
Auke Kok44c10132007-06-08 15:46:36 -07002156 device = ((this_dev->revision & CFRV_RN) < DC2114x_BRK
2157 ? DC21142 : DC21143);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159 lp->chipset = device;
2160
2161 /* Get the board I/O address (64 bits on sparc64) */
2162 iobase = pci_resource_start(this_dev, 0);
2163
2164 /* Fetch the IRQ to be used */
2165 irq = this_dev->irq;
2166 if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002167
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 /* Check if I/O accesses are enabled */
2169 pci_read_config_word(this_dev, PCI_COMMAND, &status);
2170 if (!(status & PCI_COMMAND_IO)) continue;
2171
2172 /* Search for a valid SROM attached to this DECchip */
2173 DevicePresent(dev, DE4X5_APROM);
2174 for (j=0, i=0; i<ETH_ALEN; i++) {
2175 j += (u_char) *((u_char *)&lp->srom + SROM_HWADD + i);
2176 }
Al Viro561b4fb2007-12-23 20:01:04 +00002177 if (j != 0 && j != 6 * 0xff) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178 last.chipset = device;
2179 last.bus = pb;
2180 last.irq = irq;
2181 for (i=0; i<ETH_ALEN; i++) {
2182 last.addr[i] = (u_char)*((u_char *)&lp->srom + SROM_HWADD + i);
2183 }
2184 return;
2185 }
2186 }
2187
2188 return;
2189}
2190
2191/*
2192** PCI bus I/O device probe
2193** NB: PCI I/O accesses and Bus Mastering are enabled by the PCI BIOS, not
2194** the driver. Some PCI BIOS's, pre V2.1, need the slot + features to be
2195** enabled by the user first in the set up utility. Hence we just check for
2196** enabled features and silently ignore the card if they're not.
2197**
2198** STOP PRESS: Some BIOS's __require__ the driver to enable the bus mastering
2199** bit. Here, check for I/O accesses and then set BM. If you put the card in
2200** a non BM slot, you're on your own (and complain to the PC vendor that your
2201** PC doesn't conform to the PCI standard)!
2202**
2203** This function is only compatible with the *latest* 2.1.x kernels. For 2.0.x
2204** kernels use the V0.535[n] drivers.
2205*/
2206
2207static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
2208 const struct pci_device_id *ent)
2209{
2210 u_char pb, pbus = 0, dev_num, dnum = 0, timer;
2211 u_short vendor, status;
2212 u_int irq = 0, device;
2213 u_long iobase = 0; /* Clear upper 32 bits in Alphas */
2214 int error;
2215 struct net_device *dev;
2216 struct de4x5_private *lp;
2217
2218 dev_num = PCI_SLOT(pdev->devfn);
2219 pb = pdev->bus->number;
2220
2221 if (io) { /* probe a single PCI device */
2222 pbus = (u_short)(io >> 8);
2223 dnum = (u_short)(io & 0xff);
2224 if ((pbus != pb) || (dnum != dev_num))
2225 return -ENODEV;
2226 }
2227
2228 vendor = pdev->vendor;
2229 device = pdev->device << 8;
2230 if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x))
2231 return -ENODEV;
2232
2233 /* Ok, the device seems to be for us. */
2234 if ((error = pci_enable_device (pdev)))
2235 return error;
2236
2237 if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
2238 error = -ENOMEM;
2239 goto disable_dev;
2240 }
2241
2242 lp = netdev_priv(dev);
2243 lp->bus = PCI;
2244 lp->bus_num = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002245
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 /* Search for an SROM on this bus */
2247 if (lp->bus_num != pb) {
2248 lp->bus_num = pb;
2249 srom_search(dev, pdev);
2250 }
2251
2252 /* Get the chip configuration revision register */
Auke Kok44c10132007-06-08 15:46:36 -07002253 lp->cfrv = pdev->revision;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
2255 /* Set the device number information */
2256 lp->device = dev_num;
2257 lp->bus_num = pb;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002258
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 /* Set the chipset information */
2260 if (is_DC2114x) {
2261 device = ((lp->cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);
2262 }
2263 lp->chipset = device;
2264
2265 /* Get the board I/O address (64 bits on sparc64) */
2266 iobase = pci_resource_start(pdev, 0);
2267
2268 /* Fetch the IRQ to be used */
2269 irq = pdev->irq;
2270 if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) {
2271 error = -ENODEV;
2272 goto free_dev;
2273 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002274
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 /* Check if I/O accesses and Bus Mastering are enabled */
2276 pci_read_config_word(pdev, PCI_COMMAND, &status);
2277#ifdef __powerpc__
2278 if (!(status & PCI_COMMAND_IO)) {
2279 status |= PCI_COMMAND_IO;
2280 pci_write_config_word(pdev, PCI_COMMAND, status);
2281 pci_read_config_word(pdev, PCI_COMMAND, &status);
2282 }
2283#endif /* __powerpc__ */
2284 if (!(status & PCI_COMMAND_IO)) {
2285 error = -ENODEV;
2286 goto free_dev;
2287 }
2288
2289 if (!(status & PCI_COMMAND_MASTER)) {
2290 status |= PCI_COMMAND_MASTER;
2291 pci_write_config_word(pdev, PCI_COMMAND, status);
2292 pci_read_config_word(pdev, PCI_COMMAND, &status);
2293 }
2294 if (!(status & PCI_COMMAND_MASTER)) {
2295 error = -ENODEV;
2296 goto free_dev;
2297 }
2298
2299 /* Check the latency timer for values >= 0x60 */
2300 pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &timer);
2301 if (timer < 0x60) {
2302 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x60);
2303 }
2304
2305 DevicePresent(dev, DE4X5_APROM);
2306
2307 if (!request_region (iobase, DE4X5_PCI_TOTAL_SIZE, "de4x5")) {
2308 error = -EBUSY;
2309 goto free_dev;
2310 }
2311
2312 dev->irq = irq;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002313
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 if ((error = de4x5_hw_init(dev, iobase, &pdev->dev))) {
2315 goto release;
2316 }
2317
2318 return 0;
2319
2320 release:
2321 release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
2322 free_dev:
2323 free_netdev (dev);
2324 disable_dev:
2325 pci_disable_device (pdev);
2326 return error;
2327}
2328
2329static void __devexit de4x5_pci_remove (struct pci_dev *pdev)
2330{
2331 struct net_device *dev;
2332 u_long iobase;
2333
2334 dev = pdev->dev.driver_data;
2335 iobase = dev->base_addr;
2336
2337 unregister_netdev (dev);
2338 free_netdev (dev);
2339 release_region (iobase, DE4X5_PCI_TOTAL_SIZE);
2340 pci_disable_device (pdev);
2341}
2342
2343static struct pci_device_id de4x5_pci_tbl[] = {
2344 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
2345 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
2346 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
2347 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
2348 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST,
2349 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
2350 { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
2351 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
2352 { },
2353};
2354
2355static struct pci_driver de4x5_pci_driver = {
2356 .name = "de4x5",
2357 .id_table = de4x5_pci_tbl,
2358 .probe = de4x5_pci_probe,
2359 .remove = __devexit_p (de4x5_pci_remove),
2360};
2361
2362#endif
2363
2364/*
2365** Auto configure the media here rather than setting the port at compile
2366** time. This routine is called by de4x5_init() and when a loss of media is
2367** detected (excessive collisions, loss of carrier, no carrier or link fail
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002368** [TP] or no recent receive activity) to check whether the user has been
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369** sneaky and changed the port on us.
2370*/
2371static int
2372autoconf_media(struct net_device *dev)
2373{
Al Viro561b4fb2007-12-23 20:01:04 +00002374 struct de4x5_private *lp = netdev_priv(dev);
2375 u_long iobase = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Al Viro561b4fb2007-12-23 20:01:04 +00002377 disable_ast(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Al Viro561b4fb2007-12-23 20:01:04 +00002379 lp->c_media = AUTO; /* Bogus last media */
2380 inl(DE4X5_MFC); /* Zero the lost frames counter */
2381 lp->media = INIT;
2382 lp->tcount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383
Al Viro561b4fb2007-12-23 20:01:04 +00002384 de4x5_ast(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002385
Al Viro561b4fb2007-12-23 20:01:04 +00002386 return lp->media;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387}
2388
2389/*
2390** Autoconfigure the media when using the DC21040. AUI cannot be distinguished
2391** from BNC as the port has a jumper to set thick or thin wire. When set for
2392** BNC, the BNC port will indicate activity if it's not terminated correctly.
2393** The only way to test for that is to place a loopback packet onto the
2394** network and watch for errors. Since we're messing with the interrupt mask
2395** register, disable the board interrupts and do not allow any more packets to
2396** be queued to the hardware. Re-enable everything only when the media is
2397** found.
2398** I may have to "age out" locally queued packets so that the higher layer
2399** timeouts don't effectively duplicate packets on the network.
2400*/
2401static int
2402dc21040_autoconf(struct net_device *dev)
2403{
2404 struct de4x5_private *lp = netdev_priv(dev);
2405 u_long iobase = dev->base_addr;
2406 int next_tick = DE4X5_AUTOSENSE_MS;
2407 s32 imr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002408
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 switch (lp->media) {
2410 case INIT:
2411 DISABLE_IRQs;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002412 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 lp->timeout = -1;
2414 de4x5_save_skbs(dev);
2415 if ((lp->autosense == AUTO) || (lp->autosense == TP)) {
2416 lp->media = TP;
2417 } else if ((lp->autosense == BNC) || (lp->autosense == AUI) || (lp->autosense == BNC_AUI)) {
2418 lp->media = BNC_AUI;
2419 } else if (lp->autosense == EXT_SIA) {
2420 lp->media = EXT_SIA;
2421 } else {
2422 lp->media = NC;
2423 }
2424 lp->local_state = 0;
2425 next_tick = dc21040_autoconf(dev);
2426 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002427
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 case TP:
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002429 next_tick = dc21040_state(dev, 0x8f01, 0xffff, 0x0000, 3000, BNC_AUI,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 TP_SUSPECT, test_tp);
2431 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002432
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 case TP_SUSPECT:
2434 next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21040_autoconf);
2435 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002436
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 case BNC:
2438 case AUI:
2439 case BNC_AUI:
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002440 next_tick = dc21040_state(dev, 0x8f09, 0x0705, 0x0006, 3000, EXT_SIA,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 BNC_AUI_SUSPECT, ping_media);
2442 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002443
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 case BNC_AUI_SUSPECT:
2445 next_tick = de4x5_suspect_state(dev, 1000, BNC_AUI, ping_media, dc21040_autoconf);
2446 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002447
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 case EXT_SIA:
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002449 next_tick = dc21040_state(dev, 0x3041, 0x0000, 0x0006, 3000,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 NC, EXT_SIA_SUSPECT, ping_media);
2451 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002452
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 case EXT_SIA_SUSPECT:
2454 next_tick = de4x5_suspect_state(dev, 1000, EXT_SIA, ping_media, dc21040_autoconf);
2455 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002456
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 case NC:
2458 /* default to TP for all */
2459 reset_init_sia(dev, 0x8f01, 0xffff, 0x0000);
2460 if (lp->media != lp->c_media) {
2461 de4x5_dbg_media(dev);
2462 lp->c_media = lp->media;
2463 }
2464 lp->media = INIT;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002465 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 break;
2467 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002468
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 return next_tick;
2470}
2471
2472static int
2473dc21040_state(struct net_device *dev, int csr13, int csr14, int csr15, int timeout,
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002474 int next_state, int suspect_state,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 int (*fn)(struct net_device *, int))
2476{
2477 struct de4x5_private *lp = netdev_priv(dev);
2478 int next_tick = DE4X5_AUTOSENSE_MS;
2479 int linkBad;
2480
2481 switch (lp->local_state) {
2482 case 0:
2483 reset_init_sia(dev, csr13, csr14, csr15);
2484 lp->local_state++;
2485 next_tick = 500;
2486 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002487
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 case 1:
2489 if (!lp->tx_enable) {
2490 linkBad = fn(dev, timeout);
2491 if (linkBad < 0) {
2492 next_tick = linkBad & ~TIMER_CB;
2493 } else {
2494 if (linkBad && (lp->autosense == AUTO)) {
2495 lp->local_state = 0;
2496 lp->media = next_state;
2497 } else {
2498 de4x5_init_connection(dev);
2499 }
2500 }
2501 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
2502 lp->media = suspect_state;
2503 next_tick = 3000;
2504 }
2505 break;
2506 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002507
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 return next_tick;
2509}
2510
2511static int
2512de4x5_suspect_state(struct net_device *dev, int timeout, int prev_state,
2513 int (*fn)(struct net_device *, int),
2514 int (*asfn)(struct net_device *))
2515{
2516 struct de4x5_private *lp = netdev_priv(dev);
2517 int next_tick = DE4X5_AUTOSENSE_MS;
2518 int linkBad;
2519
2520 switch (lp->local_state) {
2521 case 1:
2522 if (lp->linkOK) {
2523 lp->media = prev_state;
2524 } else {
2525 lp->local_state++;
2526 next_tick = asfn(dev);
2527 }
2528 break;
2529
2530 case 2:
2531 linkBad = fn(dev, timeout);
2532 if (linkBad < 0) {
2533 next_tick = linkBad & ~TIMER_CB;
2534 } else if (!linkBad) {
2535 lp->local_state--;
2536 lp->media = prev_state;
2537 } else {
2538 lp->media = INIT;
2539 lp->tcount++;
2540 }
2541 }
2542
2543 return next_tick;
2544}
2545
2546/*
2547** Autoconfigure the media when using the DC21041. AUI needs to be tested
2548** before BNC, because the BNC port will indicate activity if it's not
2549** terminated correctly. The only way to test for that is to place a loopback
2550** packet onto the network and watch for errors. Since we're messing with
2551** the interrupt mask register, disable the board interrupts and do not allow
2552** any more packets to be queued to the hardware. Re-enable everything only
2553** when the media is found.
2554*/
2555static int
2556dc21041_autoconf(struct net_device *dev)
2557{
2558 struct de4x5_private *lp = netdev_priv(dev);
2559 u_long iobase = dev->base_addr;
2560 s32 sts, irqs, irq_mask, imr, omr;
2561 int next_tick = DE4X5_AUTOSENSE_MS;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 switch (lp->media) {
2564 case INIT:
2565 DISABLE_IRQs;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002566 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 lp->timeout = -1;
2568 de4x5_save_skbs(dev); /* Save non transmitted skb's */
2569 if ((lp->autosense == AUTO) || (lp->autosense == TP_NW)) {
2570 lp->media = TP; /* On chip auto negotiation is broken */
2571 } else if (lp->autosense == TP) {
2572 lp->media = TP;
2573 } else if (lp->autosense == BNC) {
2574 lp->media = BNC;
2575 } else if (lp->autosense == AUI) {
2576 lp->media = AUI;
2577 } else {
2578 lp->media = NC;
2579 }
2580 lp->local_state = 0;
2581 next_tick = dc21041_autoconf(dev);
2582 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 case TP_NW:
2585 if (lp->timeout < 0) {
2586 omr = inl(DE4X5_OMR);/* Set up full duplex for the autonegotiate */
2587 outl(omr | OMR_FDX, DE4X5_OMR);
2588 }
2589 irqs = STS_LNF | STS_LNP;
2590 irq_mask = IMR_LFM | IMR_LPM;
2591 sts = test_media(dev, irqs, irq_mask, 0xef01, 0xffff, 0x0008, 2400);
2592 if (sts < 0) {
2593 next_tick = sts & ~TIMER_CB;
2594 } else {
2595 if (sts & STS_LNP) {
2596 lp->media = ANS;
2597 } else {
2598 lp->media = AUI;
2599 }
2600 next_tick = dc21041_autoconf(dev);
2601 }
2602 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002603
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 case ANS:
2605 if (!lp->tx_enable) {
2606 irqs = STS_LNP;
2607 irq_mask = IMR_LPM;
2608 sts = test_ans(dev, irqs, irq_mask, 3000);
2609 if (sts < 0) {
2610 next_tick = sts & ~TIMER_CB;
2611 } else {
2612 if (!(sts & STS_LNP) && (lp->autosense == AUTO)) {
2613 lp->media = TP;
2614 next_tick = dc21041_autoconf(dev);
2615 } else {
2616 lp->local_state = 1;
2617 de4x5_init_connection(dev);
2618 }
2619 }
2620 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
2621 lp->media = ANS_SUSPECT;
2622 next_tick = 3000;
2623 }
2624 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002625
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 case ANS_SUSPECT:
2627 next_tick = de4x5_suspect_state(dev, 1000, ANS, test_tp, dc21041_autoconf);
2628 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002629
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 case TP:
2631 if (!lp->tx_enable) {
2632 if (lp->timeout < 0) {
2633 omr = inl(DE4X5_OMR); /* Set up half duplex for TP */
2634 outl(omr & ~OMR_FDX, DE4X5_OMR);
2635 }
2636 irqs = STS_LNF | STS_LNP;
2637 irq_mask = IMR_LFM | IMR_LPM;
2638 sts = test_media(dev,irqs, irq_mask, 0xef01, 0xff3f, 0x0008, 2400);
2639 if (sts < 0) {
2640 next_tick = sts & ~TIMER_CB;
2641 } else {
2642 if (!(sts & STS_LNP) && (lp->autosense == AUTO)) {
2643 if (inl(DE4X5_SISR) & SISR_NRA) {
2644 lp->media = AUI; /* Non selected port activity */
2645 } else {
2646 lp->media = BNC;
2647 }
2648 next_tick = dc21041_autoconf(dev);
2649 } else {
2650 lp->local_state = 1;
2651 de4x5_init_connection(dev);
2652 }
2653 }
2654 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
2655 lp->media = TP_SUSPECT;
2656 next_tick = 3000;
2657 }
2658 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002659
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 case TP_SUSPECT:
2661 next_tick = de4x5_suspect_state(dev, 1000, TP, test_tp, dc21041_autoconf);
2662 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002663
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 case AUI:
2665 if (!lp->tx_enable) {
2666 if (lp->timeout < 0) {
2667 omr = inl(DE4X5_OMR); /* Set up half duplex for AUI */
2668 outl(omr & ~OMR_FDX, DE4X5_OMR);
2669 }
2670 irqs = 0;
2671 irq_mask = 0;
2672 sts = test_media(dev,irqs, irq_mask, 0xef09, 0xf73d, 0x000e, 1000);
2673 if (sts < 0) {
2674 next_tick = sts & ~TIMER_CB;
2675 } else {
2676 if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) {
2677 lp->media = BNC;
2678 next_tick = dc21041_autoconf(dev);
2679 } else {
2680 lp->local_state = 1;
2681 de4x5_init_connection(dev);
2682 }
2683 }
2684 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
2685 lp->media = AUI_SUSPECT;
2686 next_tick = 3000;
2687 }
2688 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002689
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 case AUI_SUSPECT:
2691 next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc21041_autoconf);
2692 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002693
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 case BNC:
2695 switch (lp->local_state) {
2696 case 0:
2697 if (lp->timeout < 0) {
2698 omr = inl(DE4X5_OMR); /* Set up half duplex for BNC */
2699 outl(omr & ~OMR_FDX, DE4X5_OMR);
2700 }
2701 irqs = 0;
2702 irq_mask = 0;
2703 sts = test_media(dev,irqs, irq_mask, 0xef09, 0xf73d, 0x0006, 1000);
2704 if (sts < 0) {
2705 next_tick = sts & ~TIMER_CB;
2706 } else {
2707 lp->local_state++; /* Ensure media connected */
2708 next_tick = dc21041_autoconf(dev);
2709 }
2710 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002711
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 case 1:
2713 if (!lp->tx_enable) {
2714 if ((sts = ping_media(dev, 3000)) < 0) {
2715 next_tick = sts & ~TIMER_CB;
2716 } else {
2717 if (sts) {
2718 lp->local_state = 0;
2719 lp->media = NC;
2720 } else {
2721 de4x5_init_connection(dev);
2722 }
2723 }
2724 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
2725 lp->media = BNC_SUSPECT;
2726 next_tick = 3000;
2727 }
2728 break;
2729 }
2730 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002731
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 case BNC_SUSPECT:
2733 next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc21041_autoconf);
2734 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002735
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736 case NC:
2737 omr = inl(DE4X5_OMR); /* Set up full duplex for the autonegotiate */
2738 outl(omr | OMR_FDX, DE4X5_OMR);
2739 reset_init_sia(dev, 0xef01, 0xffff, 0x0008);/* Initialise the SIA */
2740 if (lp->media != lp->c_media) {
2741 de4x5_dbg_media(dev);
2742 lp->c_media = lp->media;
2743 }
2744 lp->media = INIT;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002745 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 break;
2747 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002748
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 return next_tick;
2750}
2751
2752/*
2753** Some autonegotiation chips are broken in that they do not return the
2754** acknowledge bit (anlpa & MII_ANLPA_ACK) in the link partner advertisement
2755** register, except at the first power up negotiation.
2756*/
2757static int
2758dc21140m_autoconf(struct net_device *dev)
2759{
2760 struct de4x5_private *lp = netdev_priv(dev);
2761 int ana, anlpa, cap, cr, slnk, sr;
2762 int next_tick = DE4X5_AUTOSENSE_MS;
2763 u_long imr, omr, iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002764
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 switch(lp->media) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002766 case INIT:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 if (lp->timeout < 0) {
2768 DISABLE_IRQs;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002769 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 lp->linkOK = 0;
2771 de4x5_save_skbs(dev); /* Save non transmitted skb's */
2772 }
2773 if ((next_tick = de4x5_reset_phy(dev)) < 0) {
2774 next_tick &= ~TIMER_CB;
2775 } else {
2776 if (lp->useSROM) {
2777 if (srom_map_media(dev) < 0) {
2778 lp->tcount++;
2779 return next_tick;
2780 }
2781 srom_exec(dev, lp->phy[lp->active].gep);
2782 if (lp->infoblock_media == ANS) {
2783 ana = lp->phy[lp->active].ana | MII_ANA_CSMA;
2784 mii_wr(ana, MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
2785 }
2786 } else {
2787 lp->tmp = MII_SR_ASSC; /* Fake out the MII speed set */
2788 SET_10Mb;
2789 if (lp->autosense == _100Mb) {
2790 lp->media = _100Mb;
2791 } else if (lp->autosense == _10Mb) {
2792 lp->media = _10Mb;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002793 } else if ((lp->autosense == AUTO) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
2795 ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
2796 ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
2797 mii_wr(ana, MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
2798 lp->media = ANS;
2799 } else if (lp->autosense == AUTO) {
2800 lp->media = SPD_DET;
2801 } else if (is_spd_100(dev) && is_100_up(dev)) {
2802 lp->media = _100Mb;
2803 } else {
2804 lp->media = NC;
2805 }
2806 }
2807 lp->local_state = 0;
2808 next_tick = dc21140m_autoconf(dev);
2809 }
2810 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002811
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 case ANS:
2813 switch (lp->local_state) {
2814 case 0:
2815 if (lp->timeout < 0) {
2816 mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
2817 }
Richard Knutssoneb034a72007-05-19 22:18:10 +02002818 cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 if (cr < 0) {
2820 next_tick = cr & ~TIMER_CB;
2821 } else {
2822 if (cr) {
2823 lp->local_state = 0;
2824 lp->media = SPD_DET;
2825 } else {
2826 lp->local_state++;
2827 }
2828 next_tick = dc21140m_autoconf(dev);
2829 }
2830 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002831
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 case 1:
Richard Knutssoneb034a72007-05-19 22:18:10 +02002833 if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000)) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 next_tick = sr & ~TIMER_CB;
2835 } else {
2836 lp->media = SPD_DET;
2837 lp->local_state = 0;
2838 if (sr) { /* Success! */
2839 lp->tmp = MII_SR_ASSC;
2840 anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
2841 ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002842 if (!(anlpa & MII_ANLPA_RF) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 (cap = anlpa & MII_ANLPA_TAF & ana)) {
2844 if (cap & MII_ANA_100M) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02002845 lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 lp->media = _100Mb;
2847 } else if (cap & MII_ANA_10M) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02002848 lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002849
2850 lp->media = _10Mb;
2851 }
2852 }
2853 } /* Auto Negotiation failed to finish */
2854 next_tick = dc21140m_autoconf(dev);
2855 } /* Auto Negotiation failed to start */
2856 break;
2857 }
2858 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002859
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 case SPD_DET: /* Choose 10Mb/s or 100Mb/s */
2861 if (lp->timeout < 0) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002862 lp->tmp = (lp->phy[lp->active].id ? MII_SR_LKS :
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863 (~gep_rd(dev) & GEP_LNP));
2864 SET_100Mb_PDET;
2865 }
2866 if ((slnk = test_for_100Mb(dev, 6500)) < 0) {
2867 next_tick = slnk & ~TIMER_CB;
2868 } else {
2869 if (is_spd_100(dev) && is_100_up(dev)) {
2870 lp->media = _100Mb;
2871 } else if ((!is_spd_100(dev) && (is_10_up(dev) & lp->tmp))) {
2872 lp->media = _10Mb;
2873 } else {
2874 lp->media = NC;
2875 }
2876 next_tick = dc21140m_autoconf(dev);
2877 }
2878 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002879
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880 case _100Mb: /* Set 100Mb/s */
2881 next_tick = 3000;
2882 if (!lp->tx_enable) {
2883 SET_100Mb;
2884 de4x5_init_connection(dev);
2885 } else {
2886 if (!lp->linkOK && (lp->autosense == AUTO)) {
2887 if (!is_100_up(dev) || (!lp->useSROM && !is_spd_100(dev))) {
2888 lp->media = INIT;
2889 lp->tcount++;
2890 next_tick = DE4X5_AUTOSENSE_MS;
2891 }
2892 }
2893 }
2894 break;
2895
2896 case BNC:
2897 case AUI:
2898 case _10Mb: /* Set 10Mb/s */
2899 next_tick = 3000;
2900 if (!lp->tx_enable) {
2901 SET_10Mb;
2902 de4x5_init_connection(dev);
2903 } else {
2904 if (!lp->linkOK && (lp->autosense == AUTO)) {
2905 if (!is_10_up(dev) || (!lp->useSROM && is_spd_100(dev))) {
2906 lp->media = INIT;
2907 lp->tcount++;
2908 next_tick = DE4X5_AUTOSENSE_MS;
2909 }
2910 }
2911 }
2912 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002913
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914 case NC:
2915 if (lp->media != lp->c_media) {
2916 de4x5_dbg_media(dev);
2917 lp->c_media = lp->media;
2918 }
2919 lp->media = INIT;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002920 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 break;
2922 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002923
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 return next_tick;
2925}
2926
2927/*
2928** This routine may be merged into dc21140m_autoconf() sometime as I'm
2929** changing how I figure out the media - but trying to keep it backwards
2930** compatible with the de500-xa and de500-aa.
2931** Whether it's BNC, AUI, SYM or MII is sorted out in the infoblock
2932** functions and set during de4x5_mac_port() and/or de4x5_reset_phy().
2933** This routine just has to figure out whether 10Mb/s or 100Mb/s is
2934** active.
2935** When autonegotiation is working, the ANS part searches the SROM for
2936** the highest common speed (TP) link that both can run and if that can
2937** be full duplex. That infoblock is executed and then the link speed set.
2938**
2939** Only _10Mb and _100Mb are tested here.
2940*/
2941static int
2942dc2114x_autoconf(struct net_device *dev)
2943{
2944 struct de4x5_private *lp = netdev_priv(dev);
2945 u_long iobase = dev->base_addr;
2946 s32 cr, anlpa, ana, cap, irqs, irq_mask, imr, omr, slnk, sr, sts;
2947 int next_tick = DE4X5_AUTOSENSE_MS;
2948
2949 switch (lp->media) {
2950 case INIT:
2951 if (lp->timeout < 0) {
2952 DISABLE_IRQs;
Richard Knutssoneb034a72007-05-19 22:18:10 +02002953 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 lp->linkOK = 0;
2955 lp->timeout = -1;
2956 de4x5_save_skbs(dev); /* Save non transmitted skb's */
2957 if (lp->params.autosense & ~AUTO) {
2958 srom_map_media(dev); /* Fixed media requested */
2959 if (lp->media != lp->params.autosense) {
2960 lp->tcount++;
2961 lp->media = INIT;
2962 return next_tick;
2963 }
2964 lp->media = INIT;
2965 }
2966 }
2967 if ((next_tick = de4x5_reset_phy(dev)) < 0) {
2968 next_tick &= ~TIMER_CB;
2969 } else {
2970 if (lp->autosense == _100Mb) {
2971 lp->media = _100Mb;
2972 } else if (lp->autosense == _10Mb) {
2973 lp->media = _10Mb;
2974 } else if (lp->autosense == TP) {
2975 lp->media = TP;
2976 } else if (lp->autosense == BNC) {
2977 lp->media = BNC;
2978 } else if (lp->autosense == AUI) {
2979 lp->media = AUI;
2980 } else {
2981 lp->media = SPD_DET;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002982 if ((lp->infoblock_media == ANS) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
2984 ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
2985 ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
2986 mii_wr(ana, MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
2987 lp->media = ANS;
2988 }
2989 }
2990 lp->local_state = 0;
2991 next_tick = dc2114x_autoconf(dev);
2992 }
2993 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04002994
Linus Torvalds1da177e2005-04-16 15:20:36 -07002995 case ANS:
2996 switch (lp->local_state) {
2997 case 0:
2998 if (lp->timeout < 0) {
2999 mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
3000 }
Richard Knutssoneb034a72007-05-19 22:18:10 +02003001 cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, false, 500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 if (cr < 0) {
3003 next_tick = cr & ~TIMER_CB;
3004 } else {
3005 if (cr) {
3006 lp->local_state = 0;
3007 lp->media = SPD_DET;
3008 } else {
3009 lp->local_state++;
3010 }
3011 next_tick = dc2114x_autoconf(dev);
3012 }
3013 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003014
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 case 1:
Richard Knutssoneb034a72007-05-19 22:18:10 +02003016 sr = test_mii_reg(dev, MII_SR, MII_SR_ASSC, true, 2000);
3017 if (sr < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 next_tick = sr & ~TIMER_CB;
3019 } else {
3020 lp->media = SPD_DET;
3021 lp->local_state = 0;
3022 if (sr) { /* Success! */
3023 lp->tmp = MII_SR_ASSC;
3024 anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
3025 ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003026 if (!(anlpa & MII_ANLPA_RF) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027 (cap = anlpa & MII_ANLPA_TAF & ana)) {
3028 if (cap & MII_ANA_100M) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02003029 lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 lp->media = _100Mb;
3031 } else if (cap & MII_ANA_10M) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02003032 lp->fdx = (ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 lp->media = _10Mb;
3034 }
3035 }
3036 } /* Auto Negotiation failed to finish */
3037 next_tick = dc2114x_autoconf(dev);
3038 } /* Auto Negotiation failed to start */
3039 break;
3040 }
3041 break;
3042
3043 case AUI:
3044 if (!lp->tx_enable) {
3045 if (lp->timeout < 0) {
3046 omr = inl(DE4X5_OMR); /* Set up half duplex for AUI */
3047 outl(omr & ~OMR_FDX, DE4X5_OMR);
3048 }
3049 irqs = 0;
3050 irq_mask = 0;
3051 sts = test_media(dev,irqs, irq_mask, 0, 0, 0, 1000);
3052 if (sts < 0) {
3053 next_tick = sts & ~TIMER_CB;
3054 } else {
3055 if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) {
3056 lp->media = BNC;
3057 next_tick = dc2114x_autoconf(dev);
3058 } else {
3059 lp->local_state = 1;
3060 de4x5_init_connection(dev);
3061 }
3062 }
3063 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
3064 lp->media = AUI_SUSPECT;
3065 next_tick = 3000;
3066 }
3067 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003068
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 case AUI_SUSPECT:
3070 next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf);
3071 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003072
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 case BNC:
3074 switch (lp->local_state) {
3075 case 0:
3076 if (lp->timeout < 0) {
3077 omr = inl(DE4X5_OMR); /* Set up half duplex for BNC */
3078 outl(omr & ~OMR_FDX, DE4X5_OMR);
3079 }
3080 irqs = 0;
3081 irq_mask = 0;
3082 sts = test_media(dev,irqs, irq_mask, 0, 0, 0, 1000);
3083 if (sts < 0) {
3084 next_tick = sts & ~TIMER_CB;
3085 } else {
3086 lp->local_state++; /* Ensure media connected */
3087 next_tick = dc2114x_autoconf(dev);
3088 }
3089 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003090
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 case 1:
3092 if (!lp->tx_enable) {
3093 if ((sts = ping_media(dev, 3000)) < 0) {
3094 next_tick = sts & ~TIMER_CB;
3095 } else {
3096 if (sts) {
3097 lp->local_state = 0;
3098 lp->tcount++;
3099 lp->media = INIT;
3100 } else {
3101 de4x5_init_connection(dev);
3102 }
3103 }
3104 } else if (!lp->linkOK && (lp->autosense == AUTO)) {
3105 lp->media = BNC_SUSPECT;
3106 next_tick = 3000;
3107 }
3108 break;
3109 }
3110 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003111
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 case BNC_SUSPECT:
3113 next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf);
3114 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003115
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 case SPD_DET: /* Choose 10Mb/s or 100Mb/s */
3117 if (srom_map_media(dev) < 0) {
3118 lp->tcount++;
3119 lp->media = INIT;
3120 return next_tick;
3121 }
3122 if (lp->media == _100Mb) {
3123 if ((slnk = test_for_100Mb(dev, 6500)) < 0) {
3124 lp->media = SPD_DET;
3125 return (slnk & ~TIMER_CB);
3126 }
3127 } else {
3128 if (wait_for_link(dev) < 0) {
3129 lp->media = SPD_DET;
3130 return PDET_LINK_WAIT;
3131 }
3132 }
3133 if (lp->media == ANS) { /* Do MII parallel detection */
3134 if (is_spd_100(dev)) {
3135 lp->media = _100Mb;
3136 } else {
3137 lp->media = _10Mb;
3138 }
3139 next_tick = dc2114x_autoconf(dev);
3140 } else if (((lp->media == _100Mb) && is_100_up(dev)) ||
3141 (((lp->media == _10Mb) || (lp->media == TP) ||
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003142 (lp->media == BNC) || (lp->media == AUI)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 is_10_up(dev))) {
3144 next_tick = dc2114x_autoconf(dev);
3145 } else {
3146 lp->tcount++;
3147 lp->media = INIT;
3148 }
3149 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003150
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 case _10Mb:
3152 next_tick = 3000;
3153 if (!lp->tx_enable) {
3154 SET_10Mb;
3155 de4x5_init_connection(dev);
3156 } else {
3157 if (!lp->linkOK && (lp->autosense == AUTO)) {
3158 if (!is_10_up(dev) || (!lp->useSROM && is_spd_100(dev))) {
3159 lp->media = INIT;
3160 lp->tcount++;
3161 next_tick = DE4X5_AUTOSENSE_MS;
3162 }
3163 }
3164 }
3165 break;
3166
3167 case _100Mb:
3168 next_tick = 3000;
3169 if (!lp->tx_enable) {
3170 SET_100Mb;
3171 de4x5_init_connection(dev);
3172 } else {
3173 if (!lp->linkOK && (lp->autosense == AUTO)) {
3174 if (!is_100_up(dev) || (!lp->useSROM && !is_spd_100(dev))) {
3175 lp->media = INIT;
3176 lp->tcount++;
3177 next_tick = DE4X5_AUTOSENSE_MS;
3178 }
3179 }
3180 }
3181 break;
3182
3183 default:
3184 lp->tcount++;
3185printk("Huh?: media:%02x\n", lp->media);
3186 lp->media = INIT;
3187 break;
3188 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003189
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 return next_tick;
3191}
3192
3193static int
3194srom_autoconf(struct net_device *dev)
3195{
3196 struct de4x5_private *lp = netdev_priv(dev);
3197
3198 return lp->infoleaf_fn(dev);
3199}
3200
3201/*
3202** This mapping keeps the original media codes and FDX flag unchanged.
3203** While it isn't strictly necessary, it helps me for the moment...
3204** The early return avoids a media state / SROM media space clash.
3205*/
3206static int
3207srom_map_media(struct net_device *dev)
3208{
3209 struct de4x5_private *lp = netdev_priv(dev);
3210
Richard Knutssoneb034a72007-05-19 22:18:10 +02003211 lp->fdx = false;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003212 if (lp->infoblock_media == lp->media)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 return 0;
3214
3215 switch(lp->infoblock_media) {
3216 case SROM_10BASETF:
3217 if (!lp->params.fdx) return -1;
Richard Knutssoneb034a72007-05-19 22:18:10 +02003218 lp->fdx = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 case SROM_10BASET:
3220 if (lp->params.fdx && !lp->fdx) return -1;
3221 if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
3222 lp->media = _10Mb;
3223 } else {
3224 lp->media = TP;
3225 }
3226 break;
3227
3228 case SROM_10BASE2:
3229 lp->media = BNC;
3230 break;
3231
3232 case SROM_10BASE5:
3233 lp->media = AUI;
3234 break;
3235
3236 case SROM_100BASETF:
3237 if (!lp->params.fdx) return -1;
Richard Knutssoneb034a72007-05-19 22:18:10 +02003238 lp->fdx = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 case SROM_100BASET:
3240 if (lp->params.fdx && !lp->fdx) return -1;
3241 lp->media = _100Mb;
3242 break;
3243
3244 case SROM_100BASET4:
3245 lp->media = _100Mb;
3246 break;
3247
3248 case SROM_100BASEFF:
3249 if (!lp->params.fdx) return -1;
Richard Knutssoneb034a72007-05-19 22:18:10 +02003250 lp->fdx = true;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003251 case SROM_100BASEF:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 if (lp->params.fdx && !lp->fdx) return -1;
3253 lp->media = _100Mb;
3254 break;
3255
3256 case ANS:
3257 lp->media = ANS;
3258 lp->fdx = lp->params.fdx;
3259 break;
3260
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003261 default:
3262 printk("%s: Bad media code [%d] detected in SROM!\n", dev->name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 lp->infoblock_media);
3264 return -1;
3265 break;
3266 }
3267
3268 return 0;
3269}
3270
3271static void
3272de4x5_init_connection(struct net_device *dev)
3273{
3274 struct de4x5_private *lp = netdev_priv(dev);
3275 u_long iobase = dev->base_addr;
3276 u_long flags = 0;
3277
3278 if (lp->media != lp->c_media) {
3279 de4x5_dbg_media(dev);
3280 lp->c_media = lp->media; /* Stop scrolling media messages */
3281 }
3282
3283 spin_lock_irqsave(&lp->lock, flags);
3284 de4x5_rst_desc_ring(dev);
3285 de4x5_setup_intr(dev);
Richard Knutssoneb034a72007-05-19 22:18:10 +02003286 lp->tx_enable = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287 spin_unlock_irqrestore(&lp->lock, flags);
3288 outl(POLL_DEMAND, DE4X5_TPD);
3289
3290 netif_wake_queue(dev);
3291
3292 return;
3293}
3294
3295/*
3296** General PHY reset function. Some MII devices don't reset correctly
3297** since their MII address pins can float at voltages that are dependent
3298** on the signal pin use. Do a double reset to ensure a reset.
3299*/
3300static int
3301de4x5_reset_phy(struct net_device *dev)
3302{
3303 struct de4x5_private *lp = netdev_priv(dev);
3304 u_long iobase = dev->base_addr;
3305 int next_tick = 0;
3306
3307 if ((lp->useSROM) || (lp->phy[lp->active].id)) {
3308 if (lp->timeout < 0) {
3309 if (lp->useSROM) {
3310 if (lp->phy[lp->active].rst) {
3311 srom_exec(dev, lp->phy[lp->active].rst);
3312 srom_exec(dev, lp->phy[lp->active].rst);
3313 } else if (lp->rst) { /* Type 5 infoblock reset */
3314 srom_exec(dev, lp->rst);
3315 srom_exec(dev, lp->rst);
3316 }
3317 } else {
3318 PHY_HARD_RESET;
3319 }
3320 if (lp->useMII) {
3321 mii_wr(MII_CR_RST, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
3322 }
3323 }
3324 if (lp->useMII) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02003325 next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, false, 500);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326 }
3327 } else if (lp->chipset == DC21140) {
3328 PHY_HARD_RESET;
3329 }
3330
3331 return next_tick;
3332}
3333
3334static int
3335test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec)
3336{
3337 struct de4x5_private *lp = netdev_priv(dev);
3338 u_long iobase = dev->base_addr;
3339 s32 sts, csr12;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003340
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341 if (lp->timeout < 0) {
3342 lp->timeout = msec/100;
3343 if (!lp->useSROM) { /* Already done if by SROM, else dc2104[01] */
3344 reset_init_sia(dev, csr13, csr14, csr15);
3345 }
3346
3347 /* set up the interrupt mask */
3348 outl(irq_mask, DE4X5_IMR);
3349
3350 /* clear all pending interrupts */
3351 sts = inl(DE4X5_STS);
3352 outl(sts, DE4X5_STS);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003353
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354 /* clear csr12 NRA and SRA bits */
3355 if ((lp->chipset == DC21041) || lp->useSROM) {
3356 csr12 = inl(DE4X5_SISR);
3357 outl(csr12, DE4X5_SISR);
3358 }
3359 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003360
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361 sts = inl(DE4X5_STS) & ~TIMER_CB;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003362
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363 if (!(sts & irqs) && --lp->timeout) {
3364 sts = 100 | TIMER_CB;
3365 } else {
3366 lp->timeout = -1;
3367 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003368
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369 return sts;
3370}
3371
3372static int
3373test_tp(struct net_device *dev, s32 msec)
3374{
3375 struct de4x5_private *lp = netdev_priv(dev);
3376 u_long iobase = dev->base_addr;
3377 int sisr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003378
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379 if (lp->timeout < 0) {
3380 lp->timeout = msec/100;
3381 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003382
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383 sisr = (inl(DE4X5_SISR) & ~TIMER_CB) & (SISR_LKF | SISR_NCR);
3384
3385 if (sisr && --lp->timeout) {
3386 sisr = 100 | TIMER_CB;
3387 } else {
3388 lp->timeout = -1;
3389 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 return sisr;
3392}
3393
3394/*
3395** Samples the 100Mb Link State Signal. The sample interval is important
3396** because too fast a rate can give erroneous results and confuse the
3397** speed sense algorithm.
3398*/
3399#define SAMPLE_INTERVAL 500 /* ms */
3400#define SAMPLE_DELAY 2000 /* ms */
3401static int
3402test_for_100Mb(struct net_device *dev, int msec)
3403{
3404 struct de4x5_private *lp = netdev_priv(dev);
3405 int gep = 0, ret = ((lp->chipset & ~0x00ff)==DC2114x? -1 :GEP_SLNK);
3406
3407 if (lp->timeout < 0) {
3408 if ((msec/SAMPLE_INTERVAL) <= 0) return 0;
3409 if (msec > SAMPLE_DELAY) {
3410 lp->timeout = (msec - SAMPLE_DELAY)/SAMPLE_INTERVAL;
3411 gep = SAMPLE_DELAY | TIMER_CB;
3412 return gep;
3413 } else {
3414 lp->timeout = msec/SAMPLE_INTERVAL;
3415 }
3416 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003417
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418 if (lp->phy[lp->active].id || lp->useSROM) {
3419 gep = is_100_up(dev) | is_spd_100(dev);
3420 } else {
3421 gep = (~gep_rd(dev) & (GEP_SLNK | GEP_LNP));
3422 }
3423 if (!(gep & ret) && --lp->timeout) {
3424 gep = SAMPLE_INTERVAL | TIMER_CB;
3425 } else {
3426 lp->timeout = -1;
3427 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003428
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429 return gep;
3430}
3431
3432static int
3433wait_for_link(struct net_device *dev)
3434{
3435 struct de4x5_private *lp = netdev_priv(dev);
3436
3437 if (lp->timeout < 0) {
3438 lp->timeout = 1;
3439 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003440
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441 if (lp->timeout--) {
3442 return TIMER_CB;
3443 } else {
3444 lp->timeout = -1;
3445 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003446
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 return 0;
3448}
3449
3450/*
3451**
3452**
3453*/
3454static int
Richard Knutssoneb034a72007-05-19 22:18:10 +02003455test_mii_reg(struct net_device *dev, int reg, int mask, bool pol, long msec)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456{
3457 struct de4x5_private *lp = netdev_priv(dev);
3458 int test;
3459 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003460
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461 if (lp->timeout < 0) {
3462 lp->timeout = msec/100;
3463 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003464
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
Richard Knutssoneb034a72007-05-19 22:18:10 +02003466 test = (reg ^ (pol ? ~0 : 0)) & mask;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003467
Linus Torvalds1da177e2005-04-16 15:20:36 -07003468 if (test && --lp->timeout) {
3469 reg = 100 | TIMER_CB;
3470 } else {
3471 lp->timeout = -1;
3472 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003473
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 return reg;
3475}
3476
3477static int
3478is_spd_100(struct net_device *dev)
3479{
3480 struct de4x5_private *lp = netdev_priv(dev);
3481 u_long iobase = dev->base_addr;
3482 int spd;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003483
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 if (lp->useMII) {
3485 spd = mii_rd(lp->phy[lp->active].spd.reg, lp->phy[lp->active].addr, DE4X5_MII);
3486 spd = ~(spd ^ lp->phy[lp->active].spd.value);
3487 spd &= lp->phy[lp->active].spd.mask;
3488 } else if (!lp->useSROM) { /* de500-xa */
3489 spd = ((~gep_rd(dev)) & GEP_SLNK);
3490 } else {
3491 if ((lp->ibn == 2) || !lp->asBitValid)
3492 return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
3493
3494 spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
3495 (lp->linkOK & ~lp->asBitValid);
3496 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003497
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 return spd;
3499}
3500
3501static int
3502is_100_up(struct net_device *dev)
3503{
3504 struct de4x5_private *lp = netdev_priv(dev);
3505 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003506
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 if (lp->useMII) {
3508 /* Double read for sticky bits & temporary drops */
3509 mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
3510 return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
3511 } else if (!lp->useSROM) { /* de500-xa */
3512 return ((~gep_rd(dev)) & GEP_SLNK);
3513 } else {
3514 if ((lp->ibn == 2) || !lp->asBitValid)
3515 return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
3516
3517 return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
3518 (lp->linkOK & ~lp->asBitValid));
3519 }
3520}
3521
3522static int
3523is_10_up(struct net_device *dev)
3524{
3525 struct de4x5_private *lp = netdev_priv(dev);
3526 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003527
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528 if (lp->useMII) {
3529 /* Double read for sticky bits & temporary drops */
3530 mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
3531 return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
3532 } else if (!lp->useSROM) { /* de500-xa */
3533 return ((~gep_rd(dev)) & GEP_LNP);
3534 } else {
3535 if ((lp->ibn == 2) || !lp->asBitValid)
3536 return (((lp->chipset & ~0x00ff) == DC2114x) ?
3537 (~inl(DE4X5_SISR)&SISR_LS10):
3538 0);
3539
3540 return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
3541 (lp->linkOK & ~lp->asBitValid));
3542 }
3543}
3544
3545static int
3546is_anc_capable(struct net_device *dev)
3547{
3548 struct de4x5_private *lp = netdev_priv(dev);
3549 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003550
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551 if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
3552 return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
3553 } else if ((lp->chipset & ~0x00ff) == DC2114x) {
3554 return (inl(DE4X5_SISR) & SISR_LPN) >> 12;
3555 } else {
3556 return 0;
3557 }
3558}
3559
3560/*
3561** Send a packet onto the media and watch for send errors that indicate the
3562** media is bad or unconnected.
3563*/
3564static int
3565ping_media(struct net_device *dev, int msec)
3566{
3567 struct de4x5_private *lp = netdev_priv(dev);
3568 u_long iobase = dev->base_addr;
3569 int sisr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003570
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571 if (lp->timeout < 0) {
3572 lp->timeout = msec/100;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003573
Linus Torvalds1da177e2005-04-16 15:20:36 -07003574 lp->tmp = lp->tx_new; /* Remember the ring position */
3575 load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
3576 lp->tx_new = (++lp->tx_new) % lp->txRingSize;
3577 outl(POLL_DEMAND, DE4X5_TPD);
3578 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003579
Linus Torvalds1da177e2005-04-16 15:20:36 -07003580 sisr = inl(DE4X5_SISR);
3581
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003582 if ((!(sisr & SISR_NCR)) &&
3583 ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003584 (--lp->timeout)) {
3585 sisr = 100 | TIMER_CB;
3586 } else {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003587 if ((!(sisr & SISR_NCR)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 !(le32_to_cpu(lp->tx_ring[lp->tmp].status) & (T_OWN | TD_ES)) &&
3589 lp->timeout) {
3590 sisr = 0;
3591 } else {
3592 sisr = 1;
3593 }
3594 lp->timeout = -1;
3595 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003596
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 return sisr;
3598}
3599
3600/*
3601** This function does 2 things: on Intels it kmalloc's another buffer to
3602** replace the one about to be passed up. On Alpha's it kmallocs a buffer
3603** into which the packet is copied.
3604*/
3605static struct sk_buff *
3606de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
3607{
3608 struct de4x5_private *lp = netdev_priv(dev);
3609 struct sk_buff *p;
3610
David S. Miller49345102007-03-29 01:39:44 -07003611#if !defined(__alpha__) && !defined(__powerpc__) && !defined(CONFIG_SPARC) && !defined(DE4X5_DO_MEMCPY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612 struct sk_buff *ret;
3613 u_long i=0, tmp;
3614
3615 p = dev_alloc_skb(IEEE802_3_SZ + DE4X5_ALIGN + 2);
3616 if (!p) return NULL;
3617
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618 tmp = virt_to_bus(p->data);
3619 i = ((tmp + DE4X5_ALIGN) & ~DE4X5_ALIGN) - tmp;
3620 skb_reserve(p, i);
3621 lp->rx_ring[index].buf = cpu_to_le32(tmp + i);
3622
3623 ret = lp->rx_skb[index];
3624 lp->rx_skb[index] = p;
3625
3626 if ((u_long) ret > 1) {
3627 skb_put(ret, len);
3628 }
3629
3630 return ret;
3631
3632#else
3633 if (lp->state != OPEN) return (struct sk_buff *)1; /* Fake out the open */
3634
3635 p = dev_alloc_skb(len + 2);
3636 if (!p) return NULL;
3637
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638 skb_reserve(p, 2); /* Align */
3639 if (index < lp->rx_old) { /* Wrapped buffer */
3640 short tlen = (lp->rxRingSize - lp->rx_old) * RX_BUFF_SZ;
3641 memcpy(skb_put(p,tlen),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,tlen);
3642 memcpy(skb_put(p,len-tlen),lp->rx_bufs,len-tlen);
3643 } else { /* Linear buffer */
3644 memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len);
3645 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003646
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647 return p;
3648#endif
3649}
3650
3651static void
3652de4x5_free_rx_buffs(struct net_device *dev)
3653{
3654 struct de4x5_private *lp = netdev_priv(dev);
3655 int i;
3656
3657 for (i=0; i<lp->rxRingSize; i++) {
3658 if ((u_long) lp->rx_skb[i] > 1) {
3659 dev_kfree_skb(lp->rx_skb[i]);
3660 }
3661 lp->rx_ring[i].status = 0;
3662 lp->rx_skb[i] = (struct sk_buff *)1; /* Dummy entry */
3663 }
3664
3665 return;
3666}
3667
3668static void
3669de4x5_free_tx_buffs(struct net_device *dev)
3670{
3671 struct de4x5_private *lp = netdev_priv(dev);
3672 int i;
3673
3674 for (i=0; i<lp->txRingSize; i++) {
3675 if (lp->tx_skb[i])
3676 de4x5_free_tx_buff(lp, i);
3677 lp->tx_ring[i].status = 0;
3678 }
3679
3680 /* Unload the locally queued packets */
David S. Miller2aad7c82008-09-23 00:19:19 -07003681 __skb_queue_purge(&lp->cache.queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682}
3683
3684/*
3685** When a user pulls a connection, the DECchip can end up in a
3686** 'running - waiting for end of transmission' state. This means that we
3687** have to perform a chip soft reset to ensure that we can synchronize
3688** the hardware and software and make any media probes using a loopback
3689** packet meaningful.
3690*/
3691static void
3692de4x5_save_skbs(struct net_device *dev)
3693{
3694 struct de4x5_private *lp = netdev_priv(dev);
3695 u_long iobase = dev->base_addr;
3696 s32 omr;
3697
3698 if (!lp->cache.save_cnt) {
3699 STOP_DE4X5;
3700 de4x5_tx(dev); /* Flush any sent skb's */
3701 de4x5_free_tx_buffs(dev);
3702 de4x5_cache_state(dev, DE4X5_SAVE_STATE);
3703 de4x5_sw_reset(dev);
3704 de4x5_cache_state(dev, DE4X5_RESTORE_STATE);
3705 lp->cache.save_cnt++;
3706 START_DE4X5;
3707 }
3708
3709 return;
3710}
3711
3712static void
3713de4x5_rst_desc_ring(struct net_device *dev)
3714{
3715 struct de4x5_private *lp = netdev_priv(dev);
3716 u_long iobase = dev->base_addr;
3717 int i;
3718 s32 omr;
3719
3720 if (lp->cache.save_cnt) {
3721 STOP_DE4X5;
3722 outl(lp->dma_rings, DE4X5_RRBA);
3723 outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
3724 DE4X5_TRBA);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003725
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 lp->rx_new = lp->rx_old = 0;
3727 lp->tx_new = lp->tx_old = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003728
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729 for (i = 0; i < lp->rxRingSize; i++) {
3730 lp->rx_ring[i].status = cpu_to_le32(R_OWN);
3731 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003732
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733 for (i = 0; i < lp->txRingSize; i++) {
3734 lp->tx_ring[i].status = cpu_to_le32(0);
3735 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003736
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 barrier();
3738 lp->cache.save_cnt--;
3739 START_DE4X5;
3740 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003741
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742 return;
3743}
3744
3745static void
3746de4x5_cache_state(struct net_device *dev, int flag)
3747{
3748 struct de4x5_private *lp = netdev_priv(dev);
3749 u_long iobase = dev->base_addr;
3750
3751 switch(flag) {
3752 case DE4X5_SAVE_STATE:
3753 lp->cache.csr0 = inl(DE4X5_BMR);
3754 lp->cache.csr6 = (inl(DE4X5_OMR) & ~(OMR_ST | OMR_SR));
3755 lp->cache.csr7 = inl(DE4X5_IMR);
3756 break;
3757
3758 case DE4X5_RESTORE_STATE:
3759 outl(lp->cache.csr0, DE4X5_BMR);
3760 outl(lp->cache.csr6, DE4X5_OMR);
3761 outl(lp->cache.csr7, DE4X5_IMR);
3762 if (lp->chipset == DC21140) {
3763 gep_wr(lp->cache.gepc, dev);
3764 gep_wr(lp->cache.gep, dev);
3765 } else {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003766 reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767 lp->cache.csr15);
3768 }
3769 break;
3770 }
3771
3772 return;
3773}
3774
3775static void
3776de4x5_put_cache(struct net_device *dev, struct sk_buff *skb)
3777{
3778 struct de4x5_private *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
David S. Miller2aad7c82008-09-23 00:19:19 -07003780 __skb_queue_tail(&lp->cache.queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781}
3782
3783static void
3784de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb)
3785{
3786 struct de4x5_private *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
David S. Miller2aad7c82008-09-23 00:19:19 -07003788 __skb_queue_head(&lp->cache.queue, skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003789}
3790
3791static struct sk_buff *
3792de4x5_get_cache(struct net_device *dev)
3793{
3794 struct de4x5_private *lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
David S. Miller2aad7c82008-09-23 00:19:19 -07003796 return __skb_dequeue(&lp->cache.queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003797}
3798
3799/*
3800** Check the Auto Negotiation State. Return OK when a link pass interrupt
3801** is received and the auto-negotiation status is NWAY OK.
3802*/
3803static int
3804test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec)
3805{
3806 struct de4x5_private *lp = netdev_priv(dev);
3807 u_long iobase = dev->base_addr;
3808 s32 sts, ans;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003809
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 if (lp->timeout < 0) {
3811 lp->timeout = msec/100;
3812 outl(irq_mask, DE4X5_IMR);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003813
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 /* clear all pending interrupts */
3815 sts = inl(DE4X5_STS);
3816 outl(sts, DE4X5_STS);
3817 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003818
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 ans = inl(DE4X5_SISR) & SISR_ANS;
3820 sts = inl(DE4X5_STS) & ~TIMER_CB;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003821
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 if (!(sts & irqs) && (ans ^ ANS_NWOK) && --lp->timeout) {
3823 sts = 100 | TIMER_CB;
3824 } else {
3825 lp->timeout = -1;
3826 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003827
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 return sts;
3829}
3830
3831static void
3832de4x5_setup_intr(struct net_device *dev)
3833{
3834 struct de4x5_private *lp = netdev_priv(dev);
3835 u_long iobase = dev->base_addr;
3836 s32 imr, sts;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003837
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838 if (inl(DE4X5_OMR) & OMR_SR) { /* Only unmask if TX/RX is enabled */
3839 imr = 0;
3840 UNMASK_IRQs;
3841 sts = inl(DE4X5_STS); /* Reset any pending (stale) interrupts */
3842 outl(sts, DE4X5_STS);
3843 ENABLE_IRQs;
3844 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003845
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846 return;
3847}
3848
3849/*
3850**
3851*/
3852static void
3853reset_init_sia(struct net_device *dev, s32 csr13, s32 csr14, s32 csr15)
3854{
3855 struct de4x5_private *lp = netdev_priv(dev);
3856 u_long iobase = dev->base_addr;
3857
3858 RESET_SIA;
3859 if (lp->useSROM) {
3860 if (lp->ibn == 3) {
3861 srom_exec(dev, lp->phy[lp->active].rst);
3862 srom_exec(dev, lp->phy[lp->active].gep);
3863 outl(1, DE4X5_SICR);
3864 return;
3865 } else {
3866 csr15 = lp->cache.csr15;
3867 csr14 = lp->cache.csr14;
3868 csr13 = lp->cache.csr13;
3869 outl(csr15 | lp->cache.gepc, DE4X5_SIGR);
3870 outl(csr15 | lp->cache.gep, DE4X5_SIGR);
3871 }
3872 } else {
3873 outl(csr15, DE4X5_SIGR);
3874 }
3875 outl(csr14, DE4X5_STRR);
3876 outl(csr13, DE4X5_SICR);
3877
3878 mdelay(10);
3879
3880 return;
3881}
3882
3883/*
3884** Create a loopback ethernet packet
3885*/
3886static void
3887create_packet(struct net_device *dev, char *frame, int len)
3888{
3889 int i;
3890 char *buf = frame;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003891
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892 for (i=0; i<ETH_ALEN; i++) { /* Use this source address */
3893 *buf++ = dev->dev_addr[i];
3894 }
3895 for (i=0; i<ETH_ALEN; i++) { /* Use this destination address */
3896 *buf++ = dev->dev_addr[i];
3897 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003898
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899 *buf++ = 0; /* Packet length (2 bytes) */
3900 *buf++ = 1;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003901
Linus Torvalds1da177e2005-04-16 15:20:36 -07003902 return;
3903}
3904
3905/*
3906** Look for a particular board name in the EISA configuration space
3907*/
3908static int
3909EISA_signature(char *name, struct device *device)
3910{
Denis Chengff8ac602007-09-02 18:30:18 +08003911 int i, status = 0, siglen = ARRAY_SIZE(de4x5_signatures);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 struct eisa_device *edev;
3913
3914 *name = '\0';
3915 edev = to_eisa_device (device);
3916 i = edev->id.driver_data;
3917
3918 if (i >= 0 && i < siglen) {
3919 strcpy (name, de4x5_signatures[i]);
3920 status = 1;
3921 }
3922
3923 return status; /* return the device name string */
3924}
3925
3926/*
3927** Look for a particular board name in the PCI configuration space
3928*/
3929static int
3930PCI_signature(char *name, struct de4x5_private *lp)
3931{
Denis Chengff8ac602007-09-02 18:30:18 +08003932 int i, status = 0, siglen = ARRAY_SIZE(de4x5_signatures);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003933
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934 if (lp->chipset == DC21040) {
3935 strcpy(name, "DE434/5");
3936 return status;
3937 } else { /* Search for a DEC name in the SROM */
3938 int i = *((char *)&lp->srom + 19) * 3;
3939 strncpy(name, (char *)&lp->srom + 26 + i, 8);
3940 }
3941 name[8] = '\0';
3942 for (i=0; i<siglen; i++) {
3943 if (strstr(name,de4x5_signatures[i])!=NULL) break;
3944 }
3945 if (i == siglen) {
3946 if (dec_only) {
3947 *name = '\0';
3948 } else { /* Use chip name to avoid confusion */
3949 strcpy(name, (((lp->chipset == DC21040) ? "DC21040" :
3950 ((lp->chipset == DC21041) ? "DC21041" :
3951 ((lp->chipset == DC21140) ? "DC21140" :
3952 ((lp->chipset == DC21142) ? "DC21142" :
3953 ((lp->chipset == DC21143) ? "DC21143" : "UNKNOWN"
3954 )))))));
3955 }
3956 if (lp->chipset != DC21041) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02003957 lp->useSROM = true; /* card is not recognisably DEC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 }
3959 } else if ((lp->chipset & ~0x00ff) == DC2114x) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02003960 lp->useSROM = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003962
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 return status;
3964}
3965
3966/*
3967** Set up the Ethernet PROM counter to the start of the Ethernet address on
3968** the DC21040, else read the SROM for the other chips.
3969** The SROM may not be present in a multi-MAC card, so first read the
3970** MAC address and check for a bad address. If there is a bad one then exit
3971** immediately with the prior srom contents intact (the h/w address will
3972** be fixed up later).
3973*/
3974static void
3975DevicePresent(struct net_device *dev, u_long aprom_addr)
3976{
3977 int i, j=0;
3978 struct de4x5_private *lp = netdev_priv(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04003979
Linus Torvalds1da177e2005-04-16 15:20:36 -07003980 if (lp->chipset == DC21040) {
3981 if (lp->bus == EISA) {
3982 enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */
3983 } else {
3984 outl(0, aprom_addr); /* Reset Ethernet Address ROM Pointer */
3985 }
3986 } else { /* Read new srom */
Al Viro561b4fb2007-12-23 20:01:04 +00003987 u_short tmp;
3988 __le16 *p = (__le16 *)((char *)&lp->srom + SROM_HWADD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989 for (i=0; i<(ETH_ALEN>>1); i++) {
3990 tmp = srom_rd(aprom_addr, (SROM_HWADD>>1) + i);
Al Viro561b4fb2007-12-23 20:01:04 +00003991 j += tmp; /* for check for 0:0:0:0:0:0 or ff:ff:ff:ff:ff:ff */
3992 *p = cpu_to_le16(tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993 }
Al Viro561b4fb2007-12-23 20:01:04 +00003994 if (j == 0 || j == 3 * 0xffff) {
3995 /* could get 0 only from all-0 and 3 * 0xffff only from all-1 */
3996 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997 }
3998
Al Viro561b4fb2007-12-23 20:01:04 +00003999 p = (__le16 *)&lp->srom;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004000 for (i=0; i<(sizeof(struct de4x5_srom)>>1); i++) {
4001 tmp = srom_rd(aprom_addr, i);
Al Viro561b4fb2007-12-23 20:01:04 +00004002 *p++ = cpu_to_le16(tmp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004003 }
4004 de4x5_dbg_srom((struct de4x5_srom *)&lp->srom);
4005 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004006
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 return;
4008}
4009
4010/*
4011** Since the write on the Enet PROM register doesn't seem to reset the PROM
4012** pointer correctly (at least on my DE425 EISA card), this routine should do
4013** it...from depca.c.
4014*/
4015static void
4016enet_addr_rst(u_long aprom_addr)
4017{
4018 union {
4019 struct {
4020 u32 a;
4021 u32 b;
4022 } llsig;
4023 char Sig[sizeof(u32) << 1];
4024 } dev;
4025 short sigLength=0;
4026 s8 data;
4027 int i, j;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004028
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 dev.llsig.a = ETH_PROM_SIG;
4030 dev.llsig.b = ETH_PROM_SIG;
4031 sigLength = sizeof(u32) << 1;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004032
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033 for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
4034 data = inb(aprom_addr);
4035 if (dev.Sig[j] == data) { /* track signature */
4036 j++;
4037 } else { /* lost signature; begin search again */
4038 if (data == dev.Sig[0]) { /* rare case.... */
4039 j=1;
4040 } else {
4041 j=0;
4042 }
4043 }
4044 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004045
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046 return;
4047}
4048
4049/*
4050** For the bad status case and no SROM, then add one to the previous
4051** address. However, need to add one backwards in case we have 0xff
4052** as one or more of the bytes. Only the last 3 bytes should be checked
4053** as the first three are invariant - assigned to an organisation.
4054*/
4055static int
4056get_hw_addr(struct net_device *dev)
4057{
4058 u_long iobase = dev->base_addr;
4059 int broken, i, k, tmp, status = 0;
4060 u_short j,chksum;
4061 struct de4x5_private *lp = netdev_priv(dev);
4062
4063 broken = de4x5_bad_srom(lp);
4064
4065 for (i=0,k=0,j=0;j<3;j++) {
4066 k <<= 1;
4067 if (k > 0xffff) k-=0xffff;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004068
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069 if (lp->bus == PCI) {
4070 if (lp->chipset == DC21040) {
4071 while ((tmp = inl(DE4X5_APROM)) < 0);
4072 k += (u_char) tmp;
4073 dev->dev_addr[i++] = (u_char) tmp;
4074 while ((tmp = inl(DE4X5_APROM)) < 0);
4075 k += (u_short) (tmp << 8);
4076 dev->dev_addr[i++] = (u_char) tmp;
4077 } else if (!broken) {
4078 dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
4079 dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
4080 } else if ((broken == SMC) || (broken == ACCTON)) {
4081 dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
4082 dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
4083 }
4084 } else {
4085 k += (u_char) (tmp = inb(EISA_APROM));
4086 dev->dev_addr[i++] = (u_char) tmp;
4087 k += (u_short) ((tmp = inb(EISA_APROM)) << 8);
4088 dev->dev_addr[i++] = (u_char) tmp;
4089 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004090
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091 if (k > 0xffff) k-=0xffff;
4092 }
4093 if (k == 0xffff) k=0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004094
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 if (lp->bus == PCI) {
4096 if (lp->chipset == DC21040) {
4097 while ((tmp = inl(DE4X5_APROM)) < 0);
4098 chksum = (u_char) tmp;
4099 while ((tmp = inl(DE4X5_APROM)) < 0);
4100 chksum |= (u_short) (tmp << 8);
4101 if ((k != chksum) && (dec_only)) status = -1;
4102 }
4103 } else {
4104 chksum = (u_char) inb(EISA_APROM);
4105 chksum |= (u_short) (inb(EISA_APROM) << 8);
4106 if ((k != chksum) && (dec_only)) status = -1;
4107 }
4108
4109 /* If possible, try to fix a broken card - SMC only so far */
4110 srom_repair(dev, broken);
4111
s.hauer@pengutronix.debfaadca2006-11-02 13:55:57 +01004112#ifdef CONFIG_PPC_PMAC
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004113 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114 ** If the address starts with 00 a0, we have to bit-reverse
4115 ** each byte of the address.
4116 */
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11004117 if ( machine_is(powermac) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118 (dev->dev_addr[0] == 0) &&
4119 (dev->dev_addr[1] == 0xa0) )
4120 {
4121 for (i = 0; i < ETH_ALEN; ++i)
4122 {
4123 int x = dev->dev_addr[i];
4124 x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
4125 x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
4126 dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
4127 }
4128 }
s.hauer@pengutronix.debfaadca2006-11-02 13:55:57 +01004129#endif /* CONFIG_PPC_PMAC */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
4131 /* Test for a bad enet address */
4132 status = test_bad_enet(dev, status);
4133
4134 return status;
4135}
4136
4137/*
4138** Test for enet addresses in the first 32 bytes. The built-in strncmp
4139** didn't seem to work here...?
4140*/
4141static int
4142de4x5_bad_srom(struct de4x5_private *lp)
4143{
4144 int i, status = 0;
4145
Jeff Garzikcba05162007-11-23 21:50:34 -05004146 for (i = 0; i < ARRAY_SIZE(enet_det); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147 if (!de4x5_strncmp((char *)&lp->srom, (char *)&enet_det[i], 3) &&
4148 !de4x5_strncmp((char *)&lp->srom+0x10, (char *)&enet_det[i], 3)) {
4149 if (i == 0) {
4150 status = SMC;
4151 } else if (i == 1) {
4152 status = ACCTON;
4153 }
4154 break;
4155 }
4156 }
4157
4158 return status;
4159}
4160
4161static int
4162de4x5_strncmp(char *a, char *b, int n)
4163{
4164 int ret=0;
4165
Jeff Garzikcba05162007-11-23 21:50:34 -05004166 for (;n && !ret; n--) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 ret = *a++ - *b++;
4168 }
4169
4170 return ret;
4171}
4172
4173static void
4174srom_repair(struct net_device *dev, int card)
4175{
4176 struct de4x5_private *lp = netdev_priv(dev);
4177
4178 switch(card) {
4179 case SMC:
4180 memset((char *)&lp->srom, 0, sizeof(struct de4x5_srom));
4181 memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
4182 memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
Richard Knutssoneb034a72007-05-19 22:18:10 +02004183 lp->useSROM = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184 break;
4185 }
4186
4187 return;
4188}
4189
4190/*
4191** Assume that the irq's do not follow the PCI spec - this is seems
4192** to be true so far (2 for 2).
4193*/
4194static int
4195test_bad_enet(struct net_device *dev, int status)
4196{
4197 struct de4x5_private *lp = netdev_priv(dev);
4198 int i, tmp;
4199
4200 for (tmp=0,i=0; i<ETH_ALEN; i++) tmp += (u_char)dev->dev_addr[i];
4201 if ((tmp == 0) || (tmp == 0x5fa)) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004202 if ((lp->chipset == last.chipset) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 (lp->bus_num == last.bus) && (lp->bus_num > 0)) {
4204 for (i=0; i<ETH_ALEN; i++) dev->dev_addr[i] = last.addr[i];
4205 for (i=ETH_ALEN-1; i>2; --i) {
4206 dev->dev_addr[i] += 1;
4207 if (dev->dev_addr[i] != 0) break;
4208 }
4209 for (i=0; i<ETH_ALEN; i++) last.addr[i] = dev->dev_addr[i];
4210 if (!an_exception(lp)) {
4211 dev->irq = last.irq;
4212 }
4213
4214 status = 0;
4215 }
4216 } else if (!status) {
4217 last.chipset = lp->chipset;
4218 last.bus = lp->bus_num;
4219 last.irq = dev->irq;
4220 for (i=0; i<ETH_ALEN; i++) last.addr[i] = dev->dev_addr[i];
4221 }
4222
4223 return status;
4224}
4225
4226/*
4227** List of board exceptions with correctly wired IRQs
4228*/
4229static int
4230an_exception(struct de4x5_private *lp)
4231{
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004232 if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233 (*(u_short *)lp->srom.sub_system_id == 0x95e0)) {
4234 return -1;
4235 }
4236
4237 return 0;
4238}
4239
4240/*
4241** SROM Read
4242*/
4243static short
4244srom_rd(u_long addr, u_char offset)
4245{
4246 sendto_srom(SROM_RD | SROM_SR, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004247
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 srom_latch(SROM_RD | SROM_SR | DT_CS, addr);
4249 srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
4250 srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004251
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252 return srom_data(SROM_RD | SROM_SR | DT_CS, addr);
4253}
4254
4255static void
4256srom_latch(u_int command, u_long addr)
4257{
4258 sendto_srom(command, addr);
4259 sendto_srom(command | DT_CLK, addr);
4260 sendto_srom(command, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004261
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 return;
4263}
4264
4265static void
4266srom_command(u_int command, u_long addr)
4267{
4268 srom_latch(command, addr);
4269 srom_latch(command, addr);
4270 srom_latch((command & 0x0000ff00) | DT_CS, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004271
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272 return;
4273}
4274
4275static void
4276srom_address(u_int command, u_long addr, u_char offset)
4277{
4278 int i, a;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004279
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 a = offset << 2;
4281 for (i=0; i<6; i++, a <<= 1) {
4282 srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr);
4283 }
4284 udelay(1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004285
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 i = (getfrom_srom(addr) >> 3) & 0x01;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004287
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 return;
4289}
4290
4291static short
4292srom_data(u_int command, u_long addr)
4293{
4294 int i;
4295 short word = 0;
4296 s32 tmp;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004297
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 for (i=0; i<16; i++) {
4299 sendto_srom(command | DT_CLK, addr);
4300 tmp = getfrom_srom(addr);
4301 sendto_srom(command, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004302
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 word = (word << 1) | ((tmp >> 3) & 0x01);
4304 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004305
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 sendto_srom(command & 0x0000ff00, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004307
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 return word;
4309}
4310
4311/*
4312static void
4313srom_busy(u_int command, u_long addr)
4314{
4315 sendto_srom((command & 0x0000ff00) | DT_CS, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004316
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 while (!((getfrom_srom(addr) >> 3) & 0x01)) {
4318 mdelay(1);
4319 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004320
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321 sendto_srom(command & 0x0000ff00, addr);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004322
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 return;
4324}
4325*/
4326
4327static void
4328sendto_srom(u_int command, u_long addr)
4329{
4330 outl(command, addr);
4331 udelay(1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 return;
4334}
4335
4336static int
4337getfrom_srom(u_long addr)
4338{
4339 s32 tmp;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004340
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341 tmp = inl(addr);
4342 udelay(1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004343
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344 return tmp;
4345}
4346
4347static int
4348srom_infoleaf_info(struct net_device *dev)
4349{
4350 struct de4x5_private *lp = netdev_priv(dev);
4351 int i, count;
4352 u_char *p;
4353
4354 /* Find the infoleaf decoder function that matches this chipset */
4355 for (i=0; i<INFOLEAF_SIZE; i++) {
4356 if (lp->chipset == infoleaf_array[i].chipset) break;
4357 }
4358 if (i == INFOLEAF_SIZE) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02004359 lp->useSROM = false;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004360 printk("%s: Cannot find correct chipset for SROM decoding!\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361 dev->name);
4362 return -ENXIO;
4363 }
4364
4365 lp->infoleaf_fn = infoleaf_array[i].fn;
4366
4367 /* Find the information offset that this function should use */
4368 count = *((u_char *)&lp->srom + 19);
4369 p = (u_char *)&lp->srom + 26;
4370
4371 if (count > 1) {
4372 for (i=count; i; --i, p+=3) {
4373 if (lp->device == *p) break;
4374 }
4375 if (i == 0) {
Richard Knutssoneb034a72007-05-19 22:18:10 +02004376 lp->useSROM = false;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004377 printk("%s: Cannot find correct PCI device [%d] for SROM decoding!\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378 dev->name, lp->device);
4379 return -ENXIO;
4380 }
4381 }
4382
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004383 lp->infoleaf_offset = get_unaligned_le16(p + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
4385 return 0;
4386}
4387
4388/*
4389** This routine loads any type 1 or 3 MII info into the mii device
4390** struct and executes any type 5 code to reset PHY devices for this
4391** controller.
4392** The info for the MII devices will be valid since the index used
4393** will follow the discovery process from MII address 1-31 then 0.
4394*/
4395static void
4396srom_init(struct net_device *dev)
4397{
4398 struct de4x5_private *lp = netdev_priv(dev);
4399 u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
4400 u_char count;
4401
4402 p+=2;
4403 if (lp->chipset == DC21140) {
4404 lp->cache.gepc = (*p++ | GEP_CTRL);
4405 gep_wr(lp->cache.gepc, dev);
4406 }
4407
4408 /* Block count */
4409 count = *p++;
4410
4411 /* Jump the infoblocks to find types */
4412 for (;count; --count) {
4413 if (*p < 128) {
4414 p += COMPACT_LEN;
4415 } else if (*(p+1) == 5) {
4416 type5_infoblock(dev, 1, p);
4417 p += ((*p & BLOCK_LEN) + 1);
4418 } else if (*(p+1) == 4) {
4419 p += ((*p & BLOCK_LEN) + 1);
4420 } else if (*(p+1) == 3) {
4421 type3_infoblock(dev, 1, p);
4422 p += ((*p & BLOCK_LEN) + 1);
4423 } else if (*(p+1) == 2) {
4424 p += ((*p & BLOCK_LEN) + 1);
4425 } else if (*(p+1) == 1) {
4426 type1_infoblock(dev, 1, p);
4427 p += ((*p & BLOCK_LEN) + 1);
4428 } else {
4429 p += ((*p & BLOCK_LEN) + 1);
4430 }
4431 }
4432
4433 return;
4434}
4435
4436/*
4437** A generic routine that writes GEP control, data and reset information
4438** to the GEP register (21140) or csr15 GEP portion (2114[23]).
4439*/
4440static void
4441srom_exec(struct net_device *dev, u_char *p)
4442{
4443 struct de4x5_private *lp = netdev_priv(dev);
4444 u_long iobase = dev->base_addr;
4445 u_char count = (p ? *p++ : 0);
4446 u_short *w = (u_short *)p;
4447
4448 if (((lp->ibn != 1) && (lp->ibn != 3) && (lp->ibn != 5)) || !count) return;
4449
4450 if (lp->chipset != DC21140) RESET_SIA;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004451
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452 while (count--) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004453 gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004454 *p++ : get_unaligned_le16(w++)), dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455 mdelay(2); /* 2ms per action */
4456 }
4457
4458 if (lp->chipset != DC21140) {
4459 outl(lp->cache.csr14, DE4X5_STRR);
4460 outl(lp->cache.csr13, DE4X5_SICR);
4461 }
4462
4463 return;
4464}
4465
4466/*
4467** Basically this function is a NOP since it will never be called,
4468** unless I implement the DC21041 SROM functions. There's no need
4469** since the existing code will be satisfactory for all boards.
4470*/
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004471static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472dc21041_infoleaf(struct net_device *dev)
4473{
4474 return DE4X5_AUTOSENSE_MS;
4475}
4476
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004477static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478dc21140_infoleaf(struct net_device *dev)
4479{
4480 struct de4x5_private *lp = netdev_priv(dev);
4481 u_char count = 0;
4482 u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
4483 int next_tick = DE4X5_AUTOSENSE_MS;
4484
4485 /* Read the connection type */
4486 p+=2;
4487
4488 /* GEP control */
4489 lp->cache.gepc = (*p++ | GEP_CTRL);
4490
4491 /* Block count */
4492 count = *p++;
4493
4494 /* Recursively figure out the info blocks */
4495 if (*p < 128) {
4496 next_tick = dc_infoblock[COMPACT](dev, count, p);
4497 } else {
4498 next_tick = dc_infoblock[*(p+1)](dev, count, p);
4499 }
4500
4501 if (lp->tcount == count) {
4502 lp->media = NC;
4503 if (lp->media != lp->c_media) {
4504 de4x5_dbg_media(dev);
4505 lp->c_media = lp->media;
4506 }
4507 lp->media = INIT;
4508 lp->tcount = 0;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004509 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510 }
4511
4512 return next_tick & ~TIMER_CB;
4513}
4514
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004515static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516dc21142_infoleaf(struct net_device *dev)
4517{
4518 struct de4x5_private *lp = netdev_priv(dev);
4519 u_char count = 0;
4520 u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
4521 int next_tick = DE4X5_AUTOSENSE_MS;
4522
4523 /* Read the connection type */
4524 p+=2;
4525
4526 /* Block count */
4527 count = *p++;
4528
4529 /* Recursively figure out the info blocks */
4530 if (*p < 128) {
4531 next_tick = dc_infoblock[COMPACT](dev, count, p);
4532 } else {
4533 next_tick = dc_infoblock[*(p+1)](dev, count, p);
4534 }
4535
4536 if (lp->tcount == count) {
4537 lp->media = NC;
4538 if (lp->media != lp->c_media) {
4539 de4x5_dbg_media(dev);
4540 lp->c_media = lp->media;
4541 }
4542 lp->media = INIT;
4543 lp->tcount = 0;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004544 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545 }
4546
4547 return next_tick & ~TIMER_CB;
4548}
4549
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004550static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551dc21143_infoleaf(struct net_device *dev)
4552{
4553 struct de4x5_private *lp = netdev_priv(dev);
4554 u_char count = 0;
4555 u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
4556 int next_tick = DE4X5_AUTOSENSE_MS;
4557
4558 /* Read the connection type */
4559 p+=2;
4560
4561 /* Block count */
4562 count = *p++;
4563
4564 /* Recursively figure out the info blocks */
4565 if (*p < 128) {
4566 next_tick = dc_infoblock[COMPACT](dev, count, p);
4567 } else {
4568 next_tick = dc_infoblock[*(p+1)](dev, count, p);
4569 }
4570 if (lp->tcount == count) {
4571 lp->media = NC;
4572 if (lp->media != lp->c_media) {
4573 de4x5_dbg_media(dev);
4574 lp->c_media = lp->media;
4575 }
4576 lp->media = INIT;
4577 lp->tcount = 0;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004578 lp->tx_enable = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004579 }
4580
4581 return next_tick & ~TIMER_CB;
4582}
4583
4584/*
4585** The compact infoblock is only designed for DC21140[A] chips, so
4586** we'll reuse the dc21140m_autoconf function. Non MII media only.
4587*/
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004588static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004589compact_infoblock(struct net_device *dev, u_char count, u_char *p)
4590{
4591 struct de4x5_private *lp = netdev_priv(dev);
4592 u_char flags, csr6;
4593
4594 /* Recursively figure out the info blocks */
4595 if (--count > lp->tcount) {
4596 if (*(p+COMPACT_LEN) < 128) {
4597 return dc_infoblock[COMPACT](dev, count, p+COMPACT_LEN);
4598 } else {
4599 return dc_infoblock[*(p+COMPACT_LEN+1)](dev, count, p+COMPACT_LEN);
4600 }
4601 }
4602
4603 if ((lp->media == INIT) && (lp->timeout < 0)) {
4604 lp->ibn = COMPACT;
4605 lp->active = 0;
4606 gep_wr(lp->cache.gepc, dev);
4607 lp->infoblock_media = (*p++) & COMPACT_MC;
4608 lp->cache.gep = *p++;
4609 csr6 = *p++;
4610 flags = *p++;
4611
4612 lp->asBitValid = (flags & 0x80) ? 0 : -1;
4613 lp->defMedium = (flags & 0x40) ? -1 : 0;
4614 lp->asBit = 1 << ((csr6 >> 1) & 0x07);
4615 lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
4616 lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
Richard Knutssoneb034a72007-05-19 22:18:10 +02004617 lp->useMII = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004618
4619 de4x5_switch_mac_port(dev);
4620 }
4621
4622 return dc21140m_autoconf(dev);
4623}
4624
4625/*
4626** This block describes non MII media for the DC21140[A] only.
4627*/
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004628static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629type0_infoblock(struct net_device *dev, u_char count, u_char *p)
4630{
4631 struct de4x5_private *lp = netdev_priv(dev);
4632 u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
4633
4634 /* Recursively figure out the info blocks */
4635 if (--count > lp->tcount) {
4636 if (*(p+len) < 128) {
4637 return dc_infoblock[COMPACT](dev, count, p+len);
4638 } else {
4639 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4640 }
4641 }
4642
4643 if ((lp->media == INIT) && (lp->timeout < 0)) {
4644 lp->ibn = 0;
4645 lp->active = 0;
4646 gep_wr(lp->cache.gepc, dev);
4647 p+=2;
4648 lp->infoblock_media = (*p++) & BLOCK0_MC;
4649 lp->cache.gep = *p++;
4650 csr6 = *p++;
4651 flags = *p++;
4652
4653 lp->asBitValid = (flags & 0x80) ? 0 : -1;
4654 lp->defMedium = (flags & 0x40) ? -1 : 0;
4655 lp->asBit = 1 << ((csr6 >> 1) & 0x07);
4656 lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
4657 lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
Richard Knutssoneb034a72007-05-19 22:18:10 +02004658 lp->useMII = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659
4660 de4x5_switch_mac_port(dev);
4661 }
4662
4663 return dc21140m_autoconf(dev);
4664}
4665
4666/* These functions are under construction! */
4667
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004668static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669type1_infoblock(struct net_device *dev, u_char count, u_char *p)
4670{
4671 struct de4x5_private *lp = netdev_priv(dev);
4672 u_char len = (*p & BLOCK_LEN)+1;
4673
4674 /* Recursively figure out the info blocks */
4675 if (--count > lp->tcount) {
4676 if (*(p+len) < 128) {
4677 return dc_infoblock[COMPACT](dev, count, p+len);
4678 } else {
4679 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4680 }
4681 }
4682
4683 p += 2;
4684 if (lp->state == INITIALISED) {
4685 lp->ibn = 1;
4686 lp->active = *p++;
4687 lp->phy[lp->active].gep = (*p ? p : NULL); p += (*p + 1);
4688 lp->phy[lp->active].rst = (*p ? p : NULL); p += (*p + 1);
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004689 lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2;
4690 lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
4691 lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
4692 lp->phy[lp->active].ttm = get_unaligned_le16(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693 return 0;
4694 } else if ((lp->media == INIT) && (lp->timeout < 0)) {
4695 lp->ibn = 1;
4696 lp->active = *p;
4697 lp->infoblock_csr6 = OMR_MII_100;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004698 lp->useMII = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699 lp->infoblock_media = ANS;
4700
4701 de4x5_switch_mac_port(dev);
4702 }
4703
4704 return dc21140m_autoconf(dev);
4705}
4706
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004707static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708type2_infoblock(struct net_device *dev, u_char count, u_char *p)
4709{
4710 struct de4x5_private *lp = netdev_priv(dev);
4711 u_char len = (*p & BLOCK_LEN)+1;
4712
4713 /* Recursively figure out the info blocks */
4714 if (--count > lp->tcount) {
4715 if (*(p+len) < 128) {
4716 return dc_infoblock[COMPACT](dev, count, p+len);
4717 } else {
4718 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4719 }
4720 }
4721
4722 if ((lp->media == INIT) && (lp->timeout < 0)) {
4723 lp->ibn = 2;
4724 lp->active = 0;
4725 p += 2;
4726 lp->infoblock_media = (*p) & MEDIA_CODE;
4727
4728 if ((*p++) & EXT_FIELD) {
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004729 lp->cache.csr13 = get_unaligned_le16(p); p += 2;
4730 lp->cache.csr14 = get_unaligned_le16(p); p += 2;
4731 lp->cache.csr15 = get_unaligned_le16(p); p += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732 } else {
4733 lp->cache.csr13 = CSR13;
4734 lp->cache.csr14 = CSR14;
4735 lp->cache.csr15 = CSR15;
4736 }
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004737 lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
4738 lp->cache.gep = ((s32)(get_unaligned_le16(p)) << 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739 lp->infoblock_csr6 = OMR_SIA;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004740 lp->useMII = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
4742 de4x5_switch_mac_port(dev);
4743 }
4744
4745 return dc2114x_autoconf(dev);
4746}
4747
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004748static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004749type3_infoblock(struct net_device *dev, u_char count, u_char *p)
4750{
4751 struct de4x5_private *lp = netdev_priv(dev);
4752 u_char len = (*p & BLOCK_LEN)+1;
4753
4754 /* Recursively figure out the info blocks */
4755 if (--count > lp->tcount) {
4756 if (*(p+len) < 128) {
4757 return dc_infoblock[COMPACT](dev, count, p+len);
4758 } else {
4759 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4760 }
4761 }
4762
4763 p += 2;
4764 if (lp->state == INITIALISED) {
4765 lp->ibn = 3;
4766 lp->active = *p++;
4767 if (MOTO_SROM_BUG) lp->active = 0;
4768 lp->phy[lp->active].gep = (*p ? p : NULL); p += (2 * (*p) + 1);
4769 lp->phy[lp->active].rst = (*p ? p : NULL); p += (2 * (*p) + 1);
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004770 lp->phy[lp->active].mc = get_unaligned_le16(p); p += 2;
4771 lp->phy[lp->active].ana = get_unaligned_le16(p); p += 2;
4772 lp->phy[lp->active].fdx = get_unaligned_le16(p); p += 2;
4773 lp->phy[lp->active].ttm = get_unaligned_le16(p); p += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774 lp->phy[lp->active].mci = *p;
4775 return 0;
4776 } else if ((lp->media == INIT) && (lp->timeout < 0)) {
4777 lp->ibn = 3;
4778 lp->active = *p;
4779 if (MOTO_SROM_BUG) lp->active = 0;
4780 lp->infoblock_csr6 = OMR_MII_100;
Richard Knutssoneb034a72007-05-19 22:18:10 +02004781 lp->useMII = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 lp->infoblock_media = ANS;
4783
4784 de4x5_switch_mac_port(dev);
4785 }
4786
4787 return dc2114x_autoconf(dev);
4788}
4789
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004790static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004791type4_infoblock(struct net_device *dev, u_char count, u_char *p)
4792{
4793 struct de4x5_private *lp = netdev_priv(dev);
4794 u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
4795
4796 /* Recursively figure out the info blocks */
4797 if (--count > lp->tcount) {
4798 if (*(p+len) < 128) {
4799 return dc_infoblock[COMPACT](dev, count, p+len);
4800 } else {
4801 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4802 }
4803 }
4804
4805 if ((lp->media == INIT) && (lp->timeout < 0)) {
4806 lp->ibn = 4;
4807 lp->active = 0;
4808 p+=2;
4809 lp->infoblock_media = (*p++) & MEDIA_CODE;
4810 lp->cache.csr13 = CSR13; /* Hard coded defaults */
4811 lp->cache.csr14 = CSR14;
4812 lp->cache.csr15 = CSR15;
Harvey Harrison6caf52a2008-04-29 01:03:36 -07004813 lp->cache.gepc = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
4814 lp->cache.gep = ((s32)(get_unaligned_le16(p)) << 16); p += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004815 csr6 = *p++;
4816 flags = *p++;
4817
4818 lp->asBitValid = (flags & 0x80) ? 0 : -1;
4819 lp->defMedium = (flags & 0x40) ? -1 : 0;
4820 lp->asBit = 1 << ((csr6 >> 1) & 0x07);
4821 lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
4822 lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
Richard Knutssoneb034a72007-05-19 22:18:10 +02004823 lp->useMII = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824
4825 de4x5_switch_mac_port(dev);
4826 }
4827
4828 return dc2114x_autoconf(dev);
4829}
4830
4831/*
4832** This block type provides information for resetting external devices
4833** (chips) through the General Purpose Register.
4834*/
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004835static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836type5_infoblock(struct net_device *dev, u_char count, u_char *p)
4837{
4838 struct de4x5_private *lp = netdev_priv(dev);
4839 u_char len = (*p & BLOCK_LEN)+1;
4840
4841 /* Recursively figure out the info blocks */
4842 if (--count > lp->tcount) {
4843 if (*(p+len) < 128) {
4844 return dc_infoblock[COMPACT](dev, count, p+len);
4845 } else {
4846 return dc_infoblock[*(p+len+1)](dev, count, p+len);
4847 }
4848 }
4849
4850 /* Must be initializing to run this code */
4851 if ((lp->state == INITIALISED) || (lp->media == INIT)) {
4852 p+=2;
4853 lp->rst = p;
4854 srom_exec(dev, lp->rst);
4855 }
4856
4857 return DE4X5_AUTOSENSE_MS;
4858}
4859
4860/*
4861** MII Read/Write
4862*/
4863
4864static int
4865mii_rd(u_char phyreg, u_char phyaddr, u_long ioaddr)
4866{
4867 mii_wdata(MII_PREAMBLE, 2, ioaddr); /* Start of 34 bit preamble... */
4868 mii_wdata(MII_PREAMBLE, 32, ioaddr); /* ...continued */
4869 mii_wdata(MII_STRD, 4, ioaddr); /* SFD and Read operation */
4870 mii_address(phyaddr, ioaddr); /* PHY address to be accessed */
4871 mii_address(phyreg, ioaddr); /* PHY Register to read */
4872 mii_ta(MII_STRD, ioaddr); /* Turn around time - 2 MDC */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004873
Linus Torvalds1da177e2005-04-16 15:20:36 -07004874 return mii_rdata(ioaddr); /* Read data */
4875}
4876
4877static void
4878mii_wr(int data, u_char phyreg, u_char phyaddr, u_long ioaddr)
4879{
4880 mii_wdata(MII_PREAMBLE, 2, ioaddr); /* Start of 34 bit preamble... */
4881 mii_wdata(MII_PREAMBLE, 32, ioaddr); /* ...continued */
4882 mii_wdata(MII_STWR, 4, ioaddr); /* SFD and Write operation */
4883 mii_address(phyaddr, ioaddr); /* PHY address to be accessed */
4884 mii_address(phyreg, ioaddr); /* PHY Register to write */
4885 mii_ta(MII_STWR, ioaddr); /* Turn around time - 2 MDC */
4886 data = mii_swap(data, 16); /* Swap data bit ordering */
4887 mii_wdata(data, 16, ioaddr); /* Write data */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004888
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889 return;
4890}
4891
4892static int
4893mii_rdata(u_long ioaddr)
4894{
4895 int i;
4896 s32 tmp = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004897
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898 for (i=0; i<16; i++) {
4899 tmp <<= 1;
4900 tmp |= getfrom_mii(MII_MRD | MII_RD, ioaddr);
4901 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004902
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 return tmp;
4904}
4905
4906static void
4907mii_wdata(int data, int len, u_long ioaddr)
4908{
4909 int i;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004910
Linus Torvalds1da177e2005-04-16 15:20:36 -07004911 for (i=0; i<len; i++) {
4912 sendto_mii(MII_MWR | MII_WR, data, ioaddr);
4913 data >>= 1;
4914 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004915
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916 return;
4917}
4918
4919static void
4920mii_address(u_char addr, u_long ioaddr)
4921{
4922 int i;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004923
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924 addr = mii_swap(addr, 5);
4925 for (i=0; i<5; i++) {
4926 sendto_mii(MII_MWR | MII_WR, addr, ioaddr);
4927 addr >>= 1;
4928 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004929
Linus Torvalds1da177e2005-04-16 15:20:36 -07004930 return;
4931}
4932
4933static void
4934mii_ta(u_long rw, u_long ioaddr)
4935{
4936 if (rw == MII_STWR) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004937 sendto_mii(MII_MWR | MII_WR, 1, ioaddr);
4938 sendto_mii(MII_MWR | MII_WR, 0, ioaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939 } else {
4940 getfrom_mii(MII_MRD | MII_RD, ioaddr); /* Tri-state MDIO */
4941 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004942
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 return;
4944}
4945
4946static int
4947mii_swap(int data, int len)
4948{
4949 int i, tmp = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004950
Linus Torvalds1da177e2005-04-16 15:20:36 -07004951 for (i=0; i<len; i++) {
4952 tmp <<= 1;
4953 tmp |= (data & 1);
4954 data >>= 1;
4955 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004956
Linus Torvalds1da177e2005-04-16 15:20:36 -07004957 return tmp;
4958}
4959
4960static void
4961sendto_mii(u32 command, int data, u_long ioaddr)
4962{
4963 u32 j;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004964
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965 j = (data & 1) << 17;
4966 outl(command | j, ioaddr);
4967 udelay(1);
4968 outl(command | MII_MDC | j, ioaddr);
4969 udelay(1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004970
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 return;
4972}
4973
4974static int
4975getfrom_mii(u32 command, u_long ioaddr)
4976{
4977 outl(command, ioaddr);
4978 udelay(1);
4979 outl(command | MII_MDC, ioaddr);
4980 udelay(1);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04004981
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982 return ((inl(ioaddr) >> 19) & 1);
4983}
4984
4985/*
4986** Here's 3 ways to calculate the OUI from the ID registers.
4987*/
4988static int
4989mii_get_oui(u_char phyaddr, u_long ioaddr)
4990{
4991/*
4992 union {
4993 u_short reg;
4994 u_char breg[2];
4995 } a;
4996 int i, r2, r3, ret=0;*/
4997 int r2, r3;
4998
4999 /* Read r2 and r3 */
5000 r2 = mii_rd(MII_ID0, phyaddr, ioaddr);
5001 r3 = mii_rd(MII_ID1, phyaddr, ioaddr);
5002 /* SEEQ and Cypress way * /
5003 / * Shuffle r2 and r3 * /
5004 a.reg=0;
5005 r3 = ((r3>>10)|(r2<<6))&0x0ff;
5006 r2 = ((r2>>2)&0x3fff);
5007
5008 / * Bit reverse r3 * /
5009 for (i=0;i<8;i++) {
5010 ret<<=1;
5011 ret |= (r3&1);
5012 r3>>=1;
5013 }
5014
5015 / * Bit reverse r2 * /
5016 for (i=0;i<16;i++) {
5017 a.reg<<=1;
5018 a.reg |= (r2&1);
5019 r2>>=1;
5020 }
5021
5022 / * Swap r2 bytes * /
5023 i=a.breg[0];
5024 a.breg[0]=a.breg[1];
5025 a.breg[1]=i;
5026
5027 return ((a.reg<<8)|ret); */ /* SEEQ and Cypress way */
5028/* return ((r2<<6)|(u_int)(r3>>10)); */ /* NATIONAL and BROADCOM way */
5029 return r2; /* (I did it) My way */
5030}
5031
5032/*
5033** The SROM spec forces us to search addresses [1-31 0]. Bummer.
5034*/
5035static int
5036mii_get_phy(struct net_device *dev)
5037{
5038 struct de4x5_private *lp = netdev_priv(dev);
5039 u_long iobase = dev->base_addr;
Denis Chengff8ac602007-09-02 18:30:18 +08005040 int i, j, k, n, limit=ARRAY_SIZE(phy_info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041 int id;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005042
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 lp->active = 0;
Richard Knutssoneb034a72007-05-19 22:18:10 +02005044 lp->useMII = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045
5046 /* Search the MII address space for possible PHY devices */
5047 for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(i+1)%DE4X5_MAX_MII) {
5048 lp->phy[lp->active].addr = i;
5049 if (i==0) n++; /* Count cycles */
5050 while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005051 id = mii_get_oui(i, DE4X5_MII);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052 if ((id == 0) || (id == 65535)) continue; /* Valid ID? */
5053 for (j=0; j<limit; j++) { /* Search PHY table */
5054 if (id != phy_info[j].id) continue; /* ID match? */
5055 for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
5056 if (k < DE4X5_MAX_PHY) {
5057 memcpy((char *)&lp->phy[k],
5058 (char *)&phy_info[j], sizeof(struct phy_table));
5059 lp->phy[k].addr = i;
5060 lp->mii_cnt++;
5061 lp->active++;
5062 } else {
5063 goto purgatory; /* Stop the search */
5064 }
5065 break;
5066 }
5067 if ((j == limit) && (i < DE4X5_MAX_MII)) {
5068 for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
5069 lp->phy[k].addr = i;
5070 lp->phy[k].id = id;
5071 lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */
5072 lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */
5073 lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */
5074 lp->mii_cnt++;
5075 lp->active++;
5076 printk("%s: Using generic MII device control. If the board doesn't operate, \nplease mail the following dump to the author:\n", dev->name);
5077 j = de4x5_debug;
5078 de4x5_debug |= DEBUG_MII;
5079 de4x5_dbg_mii(dev, k);
5080 de4x5_debug = j;
5081 printk("\n");
5082 }
5083 }
5084 purgatory:
5085 lp->active = 0;
5086 if (lp->phy[0].id) { /* Reset the PHY devices */
5087 for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
5088 mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
5089 while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005090
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091 de4x5_dbg_mii(dev, k);
5092 }
5093 }
Richard Knutssoneb034a72007-05-19 22:18:10 +02005094 if (!lp->mii_cnt) lp->useMII = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
5096 return lp->mii_cnt;
5097}
5098
5099static char *
5100build_setup_frame(struct net_device *dev, int mode)
5101{
5102 struct de4x5_private *lp = netdev_priv(dev);
5103 int i;
5104 char *pa = lp->setup_frame;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005105
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106 /* Initialise the setup frame */
5107 if (mode == ALL) {
5108 memset(lp->setup_frame, 0, SETUP_FRAME_LEN);
5109 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005110
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111 if (lp->setup_f == HASH_PERF) {
5112 for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; i<ETH_ALEN; i++) {
5113 *(pa + i) = dev->dev_addr[i]; /* Host address */
5114 if (i & 0x01) pa += 2;
5115 }
5116 *(lp->setup_frame + (HASH_TABLE_LEN >> 3) - 3) = 0x80;
5117 } else {
5118 for (i=0; i<ETH_ALEN; i++) { /* Host address */
5119 *(pa + (i&1)) = dev->dev_addr[i];
5120 if (i & 0x01) pa += 4;
5121 }
5122 for (i=0; i<ETH_ALEN; i++) { /* Broadcast address */
5123 *(pa + (i&1)) = (char) 0xff;
5124 if (i & 0x01) pa += 4;
5125 }
5126 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005127
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128 return pa; /* Points to the next entry */
5129}
5130
5131static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132disable_ast(struct net_device *dev)
5133{
Al Viro561b4fb2007-12-23 20:01:04 +00005134 struct de4x5_private *lp = netdev_priv(dev);
5135 del_timer_sync(&lp->timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136}
5137
5138static long
5139de4x5_switch_mac_port(struct net_device *dev)
5140{
5141 struct de4x5_private *lp = netdev_priv(dev);
5142 u_long iobase = dev->base_addr;
5143 s32 omr;
5144
5145 STOP_DE4X5;
5146
5147 /* Assert the OMR_PS bit in CSR6 */
5148 omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR |
5149 OMR_FDX));
5150 omr |= lp->infoblock_csr6;
5151 if (omr & OMR_PS) omr |= OMR_HBD;
5152 outl(omr, DE4X5_OMR);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005153
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154 /* Soft Reset */
5155 RESET_DE4X5;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005156
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157 /* Restore the GEP - especially for COMPACT and Type 0 Infoblocks */
5158 if (lp->chipset == DC21140) {
5159 gep_wr(lp->cache.gepc, dev);
5160 gep_wr(lp->cache.gep, dev);
5161 } else if ((lp->chipset & ~0x0ff) == DC2114x) {
5162 reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, lp->cache.csr15);
5163 }
5164
5165 /* Restore CSR6 */
5166 outl(omr, DE4X5_OMR);
5167
5168 /* Reset CSR8 */
5169 inl(DE4X5_MFC);
5170
5171 return omr;
5172}
5173
5174static void
5175gep_wr(s32 data, struct net_device *dev)
5176{
5177 struct de4x5_private *lp = netdev_priv(dev);
5178 u_long iobase = dev->base_addr;
5179
5180 if (lp->chipset == DC21140) {
5181 outl(data, DE4X5_GEP);
5182 } else if ((lp->chipset & ~0x00ff) == DC2114x) {
5183 outl((data<<16) | lp->cache.csr15, DE4X5_SIGR);
5184 }
5185
5186 return;
5187}
5188
5189static int
5190gep_rd(struct net_device *dev)
5191{
5192 struct de4x5_private *lp = netdev_priv(dev);
5193 u_long iobase = dev->base_addr;
5194
5195 if (lp->chipset == DC21140) {
5196 return inl(DE4X5_GEP);
5197 } else if ((lp->chipset & ~0x00ff) == DC2114x) {
5198 return (inl(DE4X5_SIGR) & 0x000fffff);
5199 }
5200
5201 return 0;
5202}
5203
5204static void
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205yawn(struct net_device *dev, int state)
5206{
5207 struct de4x5_private *lp = netdev_priv(dev);
5208 u_long iobase = dev->base_addr;
5209
5210 if ((lp->chipset == DC21040) || (lp->chipset == DC21140)) return;
5211
5212 if(lp->bus == EISA) {
5213 switch(state) {
5214 case WAKEUP:
5215 outb(WAKEUP, PCI_CFPM);
5216 mdelay(10);
5217 break;
5218
5219 case SNOOZE:
5220 outb(SNOOZE, PCI_CFPM);
5221 break;
5222
5223 case SLEEP:
5224 outl(0, DE4X5_SICR);
5225 outb(SLEEP, PCI_CFPM);
5226 break;
5227 }
5228 } else {
5229 struct pci_dev *pdev = to_pci_dev (lp->gendev);
5230 switch(state) {
5231 case WAKEUP:
5232 pci_write_config_byte(pdev, PCI_CFDA_PSM, WAKEUP);
5233 mdelay(10);
5234 break;
5235
5236 case SNOOZE:
5237 pci_write_config_byte(pdev, PCI_CFDA_PSM, SNOOZE);
5238 break;
5239
5240 case SLEEP:
5241 outl(0, DE4X5_SICR);
5242 pci_write_config_byte(pdev, PCI_CFDA_PSM, SLEEP);
5243 break;
5244 }
5245 }
5246
5247 return;
5248}
5249
5250static void
5251de4x5_parse_params(struct net_device *dev)
5252{
5253 struct de4x5_private *lp = netdev_priv(dev);
5254 char *p, *q, t;
5255
5256 lp->params.fdx = 0;
5257 lp->params.autosense = AUTO;
5258
5259 if (args == NULL) return;
5260
5261 if ((p = strstr(args, dev->name))) {
5262 if (!(q = strstr(p+strlen(dev->name), "eth"))) q = p + strlen(p);
5263 t = *q;
5264 *q = '\0';
5265
5266 if (strstr(p, "fdx") || strstr(p, "FDX")) lp->params.fdx = 1;
5267
5268 if (strstr(p, "autosense") || strstr(p, "AUTOSENSE")) {
5269 if (strstr(p, "TP")) {
5270 lp->params.autosense = TP;
5271 } else if (strstr(p, "TP_NW")) {
5272 lp->params.autosense = TP_NW;
5273 } else if (strstr(p, "BNC")) {
5274 lp->params.autosense = BNC;
5275 } else if (strstr(p, "AUI")) {
5276 lp->params.autosense = AUI;
5277 } else if (strstr(p, "BNC_AUI")) {
5278 lp->params.autosense = BNC;
5279 } else if (strstr(p, "10Mb")) {
5280 lp->params.autosense = _10Mb;
5281 } else if (strstr(p, "100Mb")) {
5282 lp->params.autosense = _100Mb;
5283 } else if (strstr(p, "AUTO")) {
5284 lp->params.autosense = AUTO;
5285 }
5286 }
5287 *q = t;
5288 }
5289
5290 return;
5291}
5292
5293static void
5294de4x5_dbg_open(struct net_device *dev)
5295{
5296 struct de4x5_private *lp = netdev_priv(dev);
5297 int i;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005298
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299 if (de4x5_debug & DEBUG_OPEN) {
5300 printk("%s: de4x5 opening with irq %d\n",dev->name,dev->irq);
5301 printk("\tphysical address: ");
5302 for (i=0;i<6;i++) {
5303 printk("%2.2x:",(short)dev->dev_addr[i]);
5304 }
5305 printk("\n");
5306 printk("Descriptor head addresses:\n");
5307 printk("\t0x%8.8lx 0x%8.8lx\n",(u_long)lp->rx_ring,(u_long)lp->tx_ring);
5308 printk("Descriptor addresses:\nRX: ");
5309 for (i=0;i<lp->rxRingSize-1;i++){
5310 if (i < 3) {
5311 printk("0x%8.8lx ",(u_long)&lp->rx_ring[i].status);
5312 }
5313 }
5314 printk("...0x%8.8lx\n",(u_long)&lp->rx_ring[i].status);
5315 printk("TX: ");
5316 for (i=0;i<lp->txRingSize-1;i++){
5317 if (i < 3) {
5318 printk("0x%8.8lx ", (u_long)&lp->tx_ring[i].status);
5319 }
5320 }
5321 printk("...0x%8.8lx\n", (u_long)&lp->tx_ring[i].status);
5322 printk("Descriptor buffers:\nRX: ");
5323 for (i=0;i<lp->rxRingSize-1;i++){
5324 if (i < 3) {
5325 printk("0x%8.8x ",le32_to_cpu(lp->rx_ring[i].buf));
5326 }
5327 }
5328 printk("...0x%8.8x\n",le32_to_cpu(lp->rx_ring[i].buf));
5329 printk("TX: ");
5330 for (i=0;i<lp->txRingSize-1;i++){
5331 if (i < 3) {
5332 printk("0x%8.8x ", le32_to_cpu(lp->tx_ring[i].buf));
5333 }
5334 }
5335 printk("...0x%8.8x\n", le32_to_cpu(lp->tx_ring[i].buf));
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005336 printk("Ring size: \nRX: %d\nTX: %d\n",
5337 (short)lp->rxRingSize,
5338 (short)lp->txRingSize);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005340
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341 return;
5342}
5343
5344static void
5345de4x5_dbg_mii(struct net_device *dev, int k)
5346{
5347 struct de4x5_private *lp = netdev_priv(dev);
5348 u_long iobase = dev->base_addr;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005349
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350 if (de4x5_debug & DEBUG_MII) {
5351 printk("\nMII device address: %d\n", lp->phy[k].addr);
5352 printk("MII CR: %x\n",mii_rd(MII_CR,lp->phy[k].addr,DE4X5_MII));
5353 printk("MII SR: %x\n",mii_rd(MII_SR,lp->phy[k].addr,DE4X5_MII));
5354 printk("MII ID0: %x\n",mii_rd(MII_ID0,lp->phy[k].addr,DE4X5_MII));
5355 printk("MII ID1: %x\n",mii_rd(MII_ID1,lp->phy[k].addr,DE4X5_MII));
5356 if (lp->phy[k].id != BROADCOM_T4) {
5357 printk("MII ANA: %x\n",mii_rd(0x04,lp->phy[k].addr,DE4X5_MII));
5358 printk("MII ANC: %x\n",mii_rd(0x05,lp->phy[k].addr,DE4X5_MII));
5359 }
5360 printk("MII 16: %x\n",mii_rd(0x10,lp->phy[k].addr,DE4X5_MII));
5361 if (lp->phy[k].id != BROADCOM_T4) {
5362 printk("MII 17: %x\n",mii_rd(0x11,lp->phy[k].addr,DE4X5_MII));
5363 printk("MII 18: %x\n",mii_rd(0x12,lp->phy[k].addr,DE4X5_MII));
5364 } else {
5365 printk("MII 20: %x\n",mii_rd(0x14,lp->phy[k].addr,DE4X5_MII));
5366 }
5367 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005368
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369 return;
5370}
5371
5372static void
5373de4x5_dbg_media(struct net_device *dev)
5374{
5375 struct de4x5_private *lp = netdev_priv(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005376
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377 if (lp->media != lp->c_media) {
5378 if (de4x5_debug & DEBUG_MEDIA) {
5379 printk("%s: media is %s%s\n", dev->name,
5380 (lp->media == NC ? "unconnected, link down or incompatible connection" :
5381 (lp->media == TP ? "TP" :
5382 (lp->media == ANS ? "TP/Nway" :
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005383 (lp->media == BNC ? "BNC" :
5384 (lp->media == AUI ? "AUI" :
5385 (lp->media == BNC_AUI ? "BNC/AUI" :
5386 (lp->media == EXT_SIA ? "EXT SIA" :
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387 (lp->media == _100Mb ? "100Mb/s" :
5388 (lp->media == _10Mb ? "10Mb/s" :
5389 "???"
5390 ))))))))), (lp->fdx?" full duplex.":"."));
5391 }
5392 lp->c_media = lp->media;
5393 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005394
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395 return;
5396}
5397
5398static void
5399de4x5_dbg_srom(struct de4x5_srom *p)
5400{
5401 int i;
5402
5403 if (de4x5_debug & DEBUG_SROM) {
5404 printk("Sub-system Vendor ID: %04x\n", *((u_short *)p->sub_vendor_id));
5405 printk("Sub-system ID: %04x\n", *((u_short *)p->sub_system_id));
5406 printk("ID Block CRC: %02x\n", (u_char)(p->id_block_crc));
5407 printk("SROM version: %02x\n", (u_char)(p->version));
Joe Perches0795af52007-10-03 17:59:30 -07005408 printk("# controllers: %02x\n", (u_char)(p->num_controllers));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409
Johannes Berge1749612008-10-27 15:59:26 -07005410 printk("Hardware Address: %pM\n", p->ieee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411 printk("CRC checksum: %04x\n", (u_short)(p->chksum));
5412 for (i=0; i<64; i++) {
5413 printk("%3d %04x\n", i<<1, (u_short)*((u_short *)p+i));
5414 }
5415 }
5416
5417 return;
5418}
5419
5420static void
5421de4x5_dbg_rx(struct sk_buff *skb, int len)
5422{
5423 int i, j;
5424
5425 if (de4x5_debug & DEBUG_RX) {
Johannes Berge1749612008-10-27 15:59:26 -07005426 printk("R: %pM <- %pM len/SAP:%02x%02x [%d]\n",
5427 skb->data, &skb->data[6],
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428 (u_char)skb->data[12],
5429 (u_char)skb->data[13],
5430 len);
5431 for (j=0; len>0;j+=16, len-=16) {
5432 printk(" %03x: ",j);
5433 for (i=0; i<16 && i<len; i++) {
5434 printk("%02x ",(u_char)skb->data[i+j]);
5435 }
5436 printk("\n");
5437 }
5438 }
5439
5440 return;
5441}
5442
5443/*
5444** Perform IOCTL call functions here. Some are privileged operations and the
5445** effective uid is checked in those cases. In the normal course of events
5446** this function is only used for my testing.
5447*/
5448static int
5449de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
5450{
5451 struct de4x5_private *lp = netdev_priv(dev);
5452 struct de4x5_ioctl *ioc = (struct de4x5_ioctl *) &rq->ifr_ifru;
5453 u_long iobase = dev->base_addr;
5454 int i, j, status = 0;
5455 s32 omr;
5456 union {
5457 u8 addr[144];
5458 u16 sval[72];
5459 u32 lval[36];
5460 } tmp;
5461 u_long flags = 0;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005462
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463 switch(ioc->cmd) {
5464 case DE4X5_GET_HWADDR: /* Get the hardware address */
5465 ioc->len = ETH_ALEN;
5466 for (i=0; i<ETH_ALEN; i++) {
5467 tmp.addr[i] = dev->dev_addr[i];
5468 }
5469 if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
5470 break;
5471
5472 case DE4X5_SET_HWADDR: /* Set the hardware address */
5473 if (!capable(CAP_NET_ADMIN)) return -EPERM;
5474 if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT;
5475 if (netif_queue_stopped(dev))
5476 return -EBUSY;
5477 netif_stop_queue(dev);
5478 for (i=0; i<ETH_ALEN; i++) {
5479 dev->dev_addr[i] = tmp.addr[i];
5480 }
5481 build_setup_frame(dev, PHYS_ADDR_ONLY);
5482 /* Set up the descriptor and give ownership to the card */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005483 load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484 SETUP_FRAME_LEN, (struct sk_buff *)1);
5485 lp->tx_new = (++lp->tx_new) % lp->txRingSize;
5486 outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
5487 netif_wake_queue(dev); /* Unlock the TX ring */
5488 break;
5489
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490 case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */
5491 if (!capable(CAP_NET_ADMIN)) return -EPERM;
5492 printk("%s: Boo!\n", dev->name);
5493 break;
5494
5495 case DE4X5_MCA_EN: /* Enable pass all multicast addressing */
5496 if (!capable(CAP_NET_ADMIN)) return -EPERM;
5497 omr = inl(DE4X5_OMR);
5498 omr |= OMR_PM;
5499 outl(omr, DE4X5_OMR);
5500 break;
5501
5502 case DE4X5_GET_STATS: /* Get the driver statistics */
5503 {
5504 struct pkt_stats statbuf;
5505 ioc->len = sizeof(statbuf);
5506 spin_lock_irqsave(&lp->lock, flags);
5507 memcpy(&statbuf, &lp->pktStats, ioc->len);
5508 spin_unlock_irqrestore(&lp->lock, flags);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005509 if (copy_to_user(ioc->data, &statbuf, ioc->len))
5510 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511 break;
5512 }
5513 case DE4X5_CLR_STATS: /* Zero out the driver statistics */
5514 if (!capable(CAP_NET_ADMIN)) return -EPERM;
5515 spin_lock_irqsave(&lp->lock, flags);
5516 memset(&lp->pktStats, 0, sizeof(lp->pktStats));
5517 spin_unlock_irqrestore(&lp->lock, flags);
5518 break;
5519
5520 case DE4X5_GET_OMR: /* Get the OMR Register contents */
5521 tmp.addr[0] = inl(DE4X5_OMR);
5522 if (copy_to_user(ioc->data, tmp.addr, 1)) return -EFAULT;
5523 break;
5524
5525 case DE4X5_SET_OMR: /* Set the OMR Register contents */
5526 if (!capable(CAP_NET_ADMIN)) return -EPERM;
5527 if (copy_from_user(tmp.addr, ioc->data, 1)) return -EFAULT;
5528 outl(tmp.addr[0], DE4X5_OMR);
5529 break;
5530
5531 case DE4X5_GET_REG: /* Get the DE4X5 Registers */
5532 j = 0;
5533 tmp.lval[0] = inl(DE4X5_STS); j+=4;
5534 tmp.lval[1] = inl(DE4X5_BMR); j+=4;
5535 tmp.lval[2] = inl(DE4X5_IMR); j+=4;
5536 tmp.lval[3] = inl(DE4X5_OMR); j+=4;
5537 tmp.lval[4] = inl(DE4X5_SISR); j+=4;
5538 tmp.lval[5] = inl(DE4X5_SICR); j+=4;
5539 tmp.lval[6] = inl(DE4X5_STRR); j+=4;
5540 tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
5541 ioc->len = j;
5542 if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
5543 break;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005544
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545#define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005546/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547 case DE4X5_DUMP:
5548 j = 0;
5549 tmp.addr[j++] = dev->irq;
5550 for (i=0; i<ETH_ALEN; i++) {
5551 tmp.addr[j++] = dev->dev_addr[i];
5552 }
5553 tmp.addr[j++] = lp->rxRingSize;
5554 tmp.lval[j>>2] = (long)lp->rx_ring; j+=4;
5555 tmp.lval[j>>2] = (long)lp->tx_ring; j+=4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005556
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557 for (i=0;i<lp->rxRingSize-1;i++){
5558 if (i < 3) {
5559 tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
5560 }
5561 }
5562 tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
5563 for (i=0;i<lp->txRingSize-1;i++){
5564 if (i < 3) {
5565 tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
5566 }
5567 }
5568 tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005569
Linus Torvalds1da177e2005-04-16 15:20:36 -07005570 for (i=0;i<lp->rxRingSize-1;i++){
5571 if (i < 3) {
5572 tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
5573 }
5574 }
5575 tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
5576 for (i=0;i<lp->txRingSize-1;i++){
5577 if (i < 3) {
5578 tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
5579 }
5580 }
5581 tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005582
Linus Torvalds1da177e2005-04-16 15:20:36 -07005583 for (i=0;i<lp->rxRingSize;i++){
5584 tmp.lval[j>>2] = le32_to_cpu(lp->rx_ring[i].status); j+=4;
5585 }
5586 for (i=0;i<lp->txRingSize;i++){
5587 tmp.lval[j>>2] = le32_to_cpu(lp->tx_ring[i].status); j+=4;
5588 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005589
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590 tmp.lval[j>>2] = inl(DE4X5_BMR); j+=4;
5591 tmp.lval[j>>2] = inl(DE4X5_TPD); j+=4;
5592 tmp.lval[j>>2] = inl(DE4X5_RPD); j+=4;
5593 tmp.lval[j>>2] = inl(DE4X5_RRBA); j+=4;
5594 tmp.lval[j>>2] = inl(DE4X5_TRBA); j+=4;
5595 tmp.lval[j>>2] = inl(DE4X5_STS); j+=4;
5596 tmp.lval[j>>2] = inl(DE4X5_OMR); j+=4;
5597 tmp.lval[j>>2] = inl(DE4X5_IMR); j+=4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005598 tmp.lval[j>>2] = lp->chipset; j+=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599 if (lp->chipset == DC21140) {
5600 tmp.lval[j>>2] = gep_rd(dev); j+=4;
5601 } else {
5602 tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4;
5603 tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4;
5604 tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4;
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005605 tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005606 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005607 tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005608 if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005609 tmp.lval[j>>2] = lp->active; j+=4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005610 tmp.lval[j>>2]=mii_rd(MII_CR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5611 tmp.lval[j>>2]=mii_rd(MII_SR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5612 tmp.lval[j>>2]=mii_rd(MII_ID0,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5613 tmp.lval[j>>2]=mii_rd(MII_ID1,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5614 if (lp->phy[lp->active].id != BROADCOM_T4) {
5615 tmp.lval[j>>2]=mii_rd(MII_ANA,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5616 tmp.lval[j>>2]=mii_rd(MII_ANLPA,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5617 }
5618 tmp.lval[j>>2]=mii_rd(0x10,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5619 if (lp->phy[lp->active].id != BROADCOM_T4) {
5620 tmp.lval[j>>2]=mii_rd(0x11,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5621 tmp.lval[j>>2]=mii_rd(0x12,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5622 } else {
5623 tmp.lval[j>>2]=mii_rd(0x14,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
5624 }
5625 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005626
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627 tmp.addr[j++] = lp->txRingSize;
5628 tmp.addr[j++] = netif_queue_stopped(dev);
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005629
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 ioc->len = j;
5631 if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
5632 break;
5633
5634*/
5635 default:
5636 return -EOPNOTSUPP;
5637 }
Jeff Garzikf3b197a2006-05-26 21:39:03 -04005638
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639 return status;
5640}
5641
5642static int __init de4x5_module_init (void)
5643{
5644 int err = 0;
5645
5646#ifdef CONFIG_PCI
Jeff Garzik29917622006-08-19 17:48:59 -04005647 err = pci_register_driver(&de4x5_pci_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648#endif
5649#ifdef CONFIG_EISA
5650 err |= eisa_driver_register (&de4x5_eisa_driver);
5651#endif
5652
5653 return err;
5654}
5655
5656static void __exit de4x5_module_exit (void)
5657{
5658#ifdef CONFIG_PCI
5659 pci_unregister_driver (&de4x5_pci_driver);
5660#endif
5661#ifdef CONFIG_EISA
5662 eisa_driver_unregister (&de4x5_eisa_driver);
5663#endif
5664}
5665
5666module_init (de4x5_module_init);
5667module_exit (de4x5_module_exit);