Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / devs / networks / rtl8139 / rtl8139.c
blob1b071fa3a4b47d84be89f081cd6d4775c43b61e5
1 /*
2 * $Id$
3 */
5 /*
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA.
22 #include "rtl8139.h"
24 #include <exec/types.h>
25 #include <exec/resident.h>
26 #include <exec/io.h>
27 #include <exec/ports.h>
29 #include <aros/libcall.h>
30 #include <aros/macros.h>
31 #include <aros/io.h>
33 #include <oop/oop.h>
35 #include <devices/sana2.h>
36 #include <devices/sana2specialstats.h>
38 #include <utility/utility.h>
39 #include <utility/tagitem.h>
40 #include <utility/hooks.h>
42 #include <hidd/pci.h>
43 #include <hidd/irq.h>
45 #include <proto/oop.h>
46 #include <proto/exec.h>
47 #include <proto/dos.h>
48 #include <proto/battclock.h>
50 #include <stdlib.h>
52 #include "unit.h"
53 #include LC_LIBDEFS_FILE
55 /* A bit fixed linux stuff here :) */
57 #undef LIBBASE
58 #define LIBBASE (unit->rtl8139u_device)
60 #define TIMER_RPROK 3599597124UL
62 static ULONG usec2tick(ULONG usec)
64 ULONG ret, timer_rpr = TIMER_RPROK;
65 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
66 return ret;
69 void udelay(LONG usec)
71 int oldtick, tick;
72 usec = usec2tick(usec);
74 BYTEOUT(0x43, 0x80);
75 oldtick = BYTEIN(0x42);
76 oldtick += BYTEIN(0x42) << 8;
78 while (usec > 0)
80 BYTEOUT(0x43, 0x80);
81 tick = BYTEIN(0x42);
82 tick += BYTEIN(0x42) << 8;
84 usec -= (oldtick - tick);
85 if (tick > oldtick) usec -= 0x10000;
86 oldtick = tick;
90 static inline struct fe_priv *get_pcnpriv(struct net_device *unit)
92 return unit->rtl8139u_fe_priv;
95 static inline UBYTE *get_hwbase(struct net_device *unit)
97 return (UBYTE *)unit->rtl8139u_BaseMem;
100 static int read_eeprom(long base, int location, int addr_len)
102 int i;
103 unsigned retval = 0;
104 long rtlprom_addr = base + RTLr_Cfg9346;
105 int read_cmd = location | (EE_READ_CMD << addr_len);
107 BYTEOUT(rtlprom_addr, EE_ENB & ~EE_CS);
108 BYTEOUT(rtlprom_addr, EE_ENB);
110 // Shift the read command bits out
111 for (i = 4 + addr_len; i >= 0; i--)
113 int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
114 BYTEOUT(rtlprom_addr, EE_ENB | dataval);
115 eeprom_delay(rtlprom_addr);
116 BYTEOUT(rtlprom_addr, EE_ENB | dataval | EE_SHIFT_CLK);
117 eeprom_delay(rtlprom_addr);
119 BYTEOUT(rtlprom_addr, EE_ENB);
120 eeprom_delay(rtlprom_addr);
122 for (i = 16; i > 0; i--)
124 BYTEOUT(rtlprom_addr, EE_ENB | EE_SHIFT_CLK);
125 eeprom_delay(rtlprom_addr);
126 retval = (retval << 1) | ((BYTEIN(rtlprom_addr) & EE_DATA_READ) ? 1 : 0);
127 BYTEOUT(rtlprom_addr, EE_ENB);
128 eeprom_delay(rtlprom_addr);
131 // Terminate EEPROM access
132 BYTEOUT(rtlprom_addr, ~EE_CS);
133 return retval;
136 // Syncronize the MII management interface by shifting 32 one bits out
137 static char mii_2_8139_map[8] =
139 RTLr_MII_BMCR, RTLr_MII_BMSR, 0, 0, RTLr_NWayAdvert, RTLr_NWayLPAR, RTLr_NWayExpansion, 0
142 static void mdio_sync(long base)
144 int i;
146 for (i = 32; i >= 0; i--)
148 BYTEOUT(base, MDIO_WRITE1);
149 mdio_delay(base);
150 BYTEOUT(base, MDIO_WRITE1 | MDIO_CLK);
151 mdio_delay(base);
155 static int mdio_read(struct net_device *unit, int phy_id, int location)
157 struct fe_priv *np = get_pcnpriv(unit);
158 UBYTE *base = get_hwbase(unit);
159 int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
160 int retval = 0;
161 int i;
163 if (phy_id > 31)
165 // Really a 8139. Use internal registers
166 return location < 8 && mii_2_8139_map[location] ? WORDIN(base + mii_2_8139_map[location]) : 0;
169 mdio_sync(base + RTLr_MII_SMI);
171 // Shift the read command bits out
172 for (i = 15; i >= 0; i--)
174 int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
176 BYTEOUT(base + RTLr_MII_SMI, MDIO_DIR | dataval);
177 mdio_delay(base + RTLr_MII_SMI);
178 BYTEOUT(base + RTLr_MII_SMI, MDIO_DIR | dataval | MDIO_CLK);
179 mdio_delay(base + RTLr_MII_SMI);
182 // Read the two transition, 16 data, and wire-idle bits
183 for (i = 19; i > 0; i--)
185 BYTEOUT(base + RTLr_MII_SMI, 0);
186 mdio_delay(base + RTLr_MII_SMI);
187 retval = (retval << 1) | ((BYTEIN(base + RTLr_MII_SMI) & MDIO_DATA_IN) ? 1 : 0);
188 BYTEOUT(base + RTLr_MII_SMI, MDIO_CLK);
189 mdio_delay(base + RTLr_MII_SMI);
192 return (retval >> 1) & 0xffff;
195 static void rtl8139nic_start_rx(struct net_device *unit)
197 struct fe_priv *np = get_pcnpriv(unit);
198 UBYTE *base = get_hwbase(unit);
200 RTLD(bug("[%s] rtl8139nic_start_rx\n", unit->rtl8139u_name))
201 // Already running? Stop it.
202 #warning "TODO: Handle starting/stopping Rx"
205 static void rtl8139nic_stop_rx(struct net_device *unit)
207 UBYTE *base = get_hwbase(unit);
209 RTLD(bug("[%s] rtl8139nic_stop_rx\n", unit->rtl8139u_name))
210 #warning "TODO: Handle starting/stopping Rx"
213 static void rtl8139nic_start_tx(struct net_device *unit)
215 UBYTE *base = get_hwbase(unit);
217 RTLD(bug("[%s] rtl8139nic_start_tx()\n", unit->rtl8139u_name))
218 #warning "TODO: Handle starting/stopping Tx"
221 static void rtl8139nic_stop_tx(struct net_device *unit)
223 UBYTE *base = get_hwbase(unit);
225 RTLD(bug("[%s] rtl8139nic_stop_tx()\n", unit->rtl8139u_name))
226 #warning "TODO: Handle starting/stopping Tx"
229 static void rtl8139nic_txrx_reset(struct net_device *unit)
231 struct fe_priv *np = get_pcnpriv(unit);
232 UBYTE *base = get_hwbase(unit);
234 RTLD(bug("[%s] rtl8139nic_txrx_reset()\n", unit->rtl8139u_name))
238 * rtl8139nic_set_multicast: unit->set_multicast function
239 * Called with unit->xmit_lock held.
241 static void rtl8139nic_set_multicast(struct net_device *unit)
243 struct fe_priv *np = get_pcnpriv(unit);
244 UBYTE *base = get_hwbase(unit);
245 ULONG addr[2];
246 ULONG mask[2];
247 ULONG pff;
249 RTLD(bug("[%s] rtl8139nic_set_multicast()\n", unit->rtl8139u_name))
251 memset(addr, 0, sizeof(addr));
252 memset(mask, 0, sizeof(mask));
255 static void rtl8139nic_deinitialize(struct net_device *unit)
260 static void rtl8139nic_get_mac(struct net_device *unit, char * addr, BOOL fromROM)
262 UBYTE *base = get_hwbase(unit);
263 int i;
265 RTLD(bug("[%s] rtl8139nic_get_mac()\n",unit->rtl8139u_name))
266 if (fromROM)
268 int addr_len = read_eeprom(base, 0, 8) == 0x8129 ? 8 : 6;
269 int mac_add = 0;
270 for (i = 0; i < 3; i++)
272 UWORD mac_curr = read_eeprom(base, i + 7, addr_len);
273 addr[mac_add++] = mac_curr & 0xff;
274 addr[mac_add++] = (mac_curr >> 8) & 0xff;
277 else
279 ULONG mac_cur = 0;
280 mac_cur = LONGIN(base + RTLr_MAC0 + 0);
281 addr[0] = mac_cur & 0xFF;
282 addr[1] = (mac_cur >> 8) & 0xFF;
283 addr[2] = (mac_cur >> 16) & 0xFF;
284 addr[3] = (mac_cur >> 24) & 0xFF;
285 mac_cur = LONGIN(base + RTLr_MAC0 + 4);
286 addr[4] = mac_cur & 0xFF;
287 addr[5] = (mac_cur >> 8) & 0xFF;
291 static void rtl8139nic_set_mac(struct net_device *unit)
293 UBYTE *base = get_hwbase(unit);
294 int i,j;
296 RTLD(bug("[%s] rtl8139nic_set_mac()\n",unit->rtl8139u_name))
298 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
300 LONGOUT(base + RTLr_MAC0 + 0,
301 unit->rtl8139u_dev_addr[0] |
302 (unit->rtl8139u_dev_addr[1] << 8) |
303 (unit->rtl8139u_dev_addr[2] << 16) |
304 (unit->rtl8139u_dev_addr[3] << 24));
305 LONGOUT(base + RTLr_MAC0 + 4,
306 unit->rtl8139u_dev_addr[4] |
307 (unit->rtl8139u_dev_addr[5] << 8));
309 BYTEOUT(base + RTLr_Cfg9346, 0x00);
311 RTLD(
312 /* Read it back to be certain! */
313 TEXT newmac[6];
314 rtl8139nic_get_mac(unit, newmac, FALSE);
316 bug("[%s] rtl8139nic_set_mac: New MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
317 newmac[0], newmac[1], newmac[2],
318 newmac[3], newmac[4], newmac[5]))
321 static void rtl8139nic_initialize(struct net_device *unit)
323 struct fe_priv *np = unit->rtl8139u_fe_priv;
324 UBYTE *base = get_hwbase(unit);
325 int i, config1;
327 config1 = BYTEIN(base + RTLr_Config1);
328 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
330 BYTEOUT(base + RTLr_Config1, config1 & ~0x03);
332 RTLD(bug("[%s] Chipset brought out of low power mode.\n", unit->rtl8139u_name))
334 rtl8139nic_get_mac(unit, np->orig_mac, TRUE);
336 int phy, phy_idx = 0;
337 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
339 for (phy = 0; phy < 32 && phy_idx < sizeof(np->mii_phys); phy++)
341 int mii_status = mdio_read(unit, phy, 1);
342 if (mii_status != 0xffff && mii_status != 0x0000)
344 np->mii_phys[phy_idx++] = phy;
345 np->advertising = mdio_read(unit, phy, 4);
346 RTLD(bug("[%s] MII transceiver %d status 0x%4.4x advertising %4.4x\n", unit->rtl8139u_name,
347 phy, mii_status, np->advertising))
352 if (phy_idx == 0)
354 RTLD(bug("[%s] No MII transceiver found, Assuming SYM transceiver\n", unit->rtl8139u_name))
355 np->mii_phys[0] = 32;
358 unit->rtl8139u_dev_addr[0] = unit->rtl8139u_org_addr[0] = np->orig_mac[0];
359 unit->rtl8139u_dev_addr[1] = unit->rtl8139u_org_addr[1] = np->orig_mac[1];
360 unit->rtl8139u_dev_addr[2] = unit->rtl8139u_org_addr[2] = np->orig_mac[2];
361 unit->rtl8139u_dev_addr[3] = unit->rtl8139u_org_addr[3] = np->orig_mac[3];
362 unit->rtl8139u_dev_addr[4] = unit->rtl8139u_org_addr[4] = np->orig_mac[4];
363 unit->rtl8139u_dev_addr[5] = unit->rtl8139u_org_addr[5] = np->orig_mac[5];
365 RTLD(bug("[%s] MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
366 unit->rtl8139u_dev_addr[0], unit->rtl8139u_dev_addr[1], unit->rtl8139u_dev_addr[2],
367 unit->rtl8139u_dev_addr[3], unit->rtl8139u_dev_addr[4], unit->rtl8139u_dev_addr[5]))
369 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
370 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
372 BYTEOUT(base + RTLr_Config1, 0x03);
374 BYTEOUT(base + RTLr_HltClk, 'H'); //Disable the chips clock ('R' enables)
375 RTLD(bug("[%s] Chipset put into low power mode.\n", unit->rtl8139u_name))
378 static void rtl8139nic_drain_tx(struct net_device *unit)
380 struct fe_priv *np = get_pcnpriv(unit);
381 int i;
382 for (i = 0; i < NUM_TX_DESC; i++) {
383 #warning "TODO: rtl8139nic_drain_tx does nothing atm."
387 static void rtl8139nic_drain_rx(struct net_device *unit)
389 struct fe_priv *np = get_pcnpriv(unit);
390 int i;
391 // for (i = 0; i < RX_RING_SIZE; i++) {
392 #warning "TODO: rtl8139nic_drain_rx does nothing atm."
393 // }
397 static void drain_ring(struct net_device *unit)
399 rtl8139nic_drain_tx(unit);
400 rtl8139nic_drain_rx(unit);
403 static int request_irq(struct net_device *unit)
405 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
406 BOOL ret;
408 RTLD(bug("[%s] request_irq()\n", unit->rtl8139u_name))
410 if (irq)
412 ret = HIDD_IRQ_AddHandler(irq, unit->rtl8139u_irqhandler, unit->rtl8139u_IRQ);
413 HIDD_IRQ_AddHandler(irq, unit->rtl8139u_touthandler, vHidd_IRQ_Timer);
415 RTLD(bug("[%s] request_irq: IRQ Handlers configured\n", unit->rtl8139u_name))
417 OOP_DisposeObject(irq);
419 if (ret)
421 return 0;
424 return 1;
427 static void free_irq(struct net_device *unit)
429 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
430 if (irq)
432 HIDD_IRQ_RemHandler(irq, unit->rtl8139u_irqhandler);
433 HIDD_IRQ_RemHandler(irq, unit->rtl8139u_touthandler);
434 OOP_DisposeObject(irq);
438 int rtl8139nic_set_rxmode(struct net_device *unit)
440 struct fe_priv *np = get_pcnpriv(unit);
441 UBYTE *base = get_hwbase(unit);
442 ULONG mc_filter[2]; //Multicast hash filter.
443 ULONG rx_mode;
445 RTLD(bug("[%s] rtl8139nic_set_rxmode(flags %x)\n", unit->rtl8139u_name, unit->rtl8139u_flags))
447 #warning "TODO: Fix set_rxmode.. doesnt load multicast list atm .."
448 if (unit->rtl8139u_flags & IFF_PROMISC)
450 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: PROMISC\n",unit->rtl8139u_name))
451 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys;
452 mc_filter[1] = mc_filter[0] = 0xffffffff;
454 else if (unit->rtl8139u_flags & IFF_ALLMULTI)
456 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: ALLMULTI\n",unit->rtl8139u_name))
457 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
458 mc_filter[1] = mc_filter[0] = 0xffffffff;
460 else
462 // struct mclist *mclist;
463 // int i;
464 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: DEFAULT\n",unit->rtl8139u_name))
466 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
467 /*if (unit->mc_count < multicast_filter_limit)
469 mc_filter[1] = mc_filter[0] = 0;
470 /*for (i = 0, mclist = dev->netif->mclist; mclist && i < dev->netif->mccount; i++, mclist = mclist->next)
472 set_bit(mc_filter, ether_crc(6, (unsigned char *) &mclist->hwaddr) >> 26);
475 else
477 mc_filter[1] = mc_filter[0] = 0xffffffff;
481 LONGOUT(base + RTLr_RxConfig, np->rx_config | rx_mode);
482 LONGOUT(base + RTLr_MAR0 + 0, mc_filter[0]);
483 LONGOUT(base + RTLr_MAR0 + 4, mc_filter[1]);
485 return 0;
488 static int rtl8139nic_open(struct net_device *unit)
490 struct fe_priv *np = get_pcnpriv(unit);
491 UBYTE *base = get_hwbase(unit);
492 int ret, i, rx_buf_len_idx;
494 rx_buf_len_idx = RX_BUF_LEN_IDX;
496 ret = request_irq(unit);
497 if (ret)
498 goto out_drain;
502 np->rx_buf_len = 8192 << rx_buf_len_idx;
504 np->rx_buffer = HIDD_PCIDriver_AllocPCIMem(
505 unit->rtl8139u_PCIDriver,
506 (np->rx_buf_len + 16 + (TX_BUF_SIZE * NUM_TX_DESC)));
508 if (np->rx_buffer != NULL)
510 np->tx_buffer = (struct eth_frame *) (np->rx_buffer + np->rx_buf_len + 16);
512 } while (np->rx_buffer == NULL && (--rx_buf_len_idx >= 0));
514 if ((np->rx_buffer != NULL) && (np->tx_buffer != NULL))
516 RTLD(bug("[%s] rtl8139nic_open: Allocated IO Buffers [ %d x Tx @ %x] [ Rx @ %x, %d bytes]\n",unit->rtl8139u_name,
517 NUM_TX_DESC, np->tx_buffer,
518 np->rx_buffer, np->rx_buf_len))
520 np->tx_dirty = np->tx_current = 0;
522 for (i = 0; i < NUM_TX_DESC; i++)
524 np->tx_pbuf[i] = NULL;
525 np->tx_buf[i] = np->tx_buffer + (i * TX_BUF_SIZE);
527 RTLD(bug("[%s] rtl8139nic_open: TX Buffers initialised\n",unit->rtl8139u_name))
529 np->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
530 np->rx_config = (RX_FIFO_THRESH << 13) | (rx_buf_len_idx << 11) | (RX_DMA_BURST << 8);
532 BYTEOUT(base + RTLr_ChipCmd, CmdReset);
533 for (i = 1000; i > 0; i--)
535 if ((BYTEIN(base + RTLr_ChipCmd) & CmdReset) ==0) break;
537 RTLD(bug("[%s] rtl8139nic_open: NIC Reset\n",unit->rtl8139u_name))
539 rtl8139nic_set_mac(unit);
540 RTLD(bug("[%s] rtl8139nic_open: copied MAC address\n",unit->rtl8139u_name))
542 np->rx_current = 0;
544 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
546 //Enable Tx/Rx so we can set the config(s)
547 BYTEOUT(base + RTLr_ChipCmd, CmdRxEnb | CmdTxEnb);
548 LONGOUT(base + RTLr_RxConfig, np->rx_config);
549 LONGOUT(base + RTLr_TxConfig, TX_DMA_BURST << 8);
551 RTLD(bug("[%s] rtl8139nic_open: Enabled Tx/Rx\n",unit->rtl8139u_name))
553 /* check_duplex */
554 if (np->mii_phys[0] >= 0 || (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR))
556 UBYTE mii_reg5 = mdio_read(unit, np->mii_phys[0], 5);
557 if (mii_reg5 != 0xffff)
559 if (((mii_reg5 & 0x0100) == 0x0100) || ((mii_reg5 & 0x00c0) == 0x0040))
561 np->full_duplex = 1;
565 if ((mii_reg5 == 0 ) || !(mii_reg5 & 0x0180))
567 unit->rtl8139u_rtl_LinkSpeed = 10000000;
569 else
571 unit->rtl8139u_rtl_LinkSpeed = 100000000;
574 RTLD(bug("[%s] rtl8139nic_open: Setting %s%s-duplex based on auto-neg partner ability %4.4x\n",unit->rtl8139u_name,
575 mii_reg5 == 0 ? "" : (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
576 np->full_duplex ? "full" : "half", mii_reg5))
579 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
581 BYTEOUT(base + RTLr_Config1, np->full_duplex ? 0x60 : 0x20);
583 BYTEOUT(base + RTLr_Cfg9346, 0x00);
584 LONGOUT(base + RTLr_RxBuf, np->rx_buffer);
586 //Start the chips Tx/Rx processes
587 LONGOUT(base + RTLr_RxMissed, 0);
589 rtl8139nic_set_rxmode(unit);
590 BYTEOUT(base + RTLr_ChipCmd, CmdRxEnb | CmdTxEnb);
592 //Enable all known interrupts by setting the interrupt mask ..
593 WORDOUT(base + RTLr_IntrMask, PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver | TxErr | TxOK | RxErr | RxOK);
595 unit->rtl8139u_flags |= IFF_UP;
596 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
597 RTLD(bug("[%s] rtl8139nic_open: Device set as ONLINE\n",unit->rtl8139u_name))
599 return 0;
601 out_drain:
602 drain_ring(unit);
603 return ret;
606 static int rtl8139nic_close(struct net_device *unit)
608 struct fe_priv *np = get_pcnpriv(unit);
609 UBYTE *base;
611 unit->rtl8139u_flags &= ~IFF_UP;
613 ObtainSemaphore(&np->lock);
614 np->in_shutdown = 1;
615 ReleaseSemaphore(&np->lock);
617 unit->rtl8139u_toutNEED = FALSE;
619 netif_stop_queue(unit);
620 ObtainSemaphore(&np->lock);
622 rtl8139nic_deinitialize(unit); // Stop the chipset and set it in 16bit-mode
624 base = get_hwbase(unit);
626 ReleaseSemaphore(&np->lock);
628 free_irq(unit);
630 drain_ring(unit);
632 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->rx_buffer);
633 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->tx_buffer);
635 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
637 return 0;
641 void rtl8139nic_get_functions(struct net_device *Unit)
643 Unit->initialize = rtl8139nic_initialize;
644 Unit->deinitialize = rtl8139nic_deinitialize;
645 Unit->start = rtl8139nic_open;
646 Unit->stop = rtl8139nic_close;
647 Unit->set_mac_address = rtl8139nic_set_mac;
648 Unit->set_multicast = rtl8139nic_set_multicast;