Fixed return values that got inverted during conversion from using
[AROS.git] / workbench / devs / networks / rtl8139 / rtl8139.c
blob68fbbd77b7586a7ee5190ea381c3001837260d44
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/timer.h>
36 #include <devices/sana2.h>
37 #include <devices/sana2specialstats.h>
39 #include <utility/utility.h>
40 #include <utility/tagitem.h>
41 #include <utility/hooks.h>
43 #include <hidd/pci.h>
45 #include <proto/oop.h>
46 #include <proto/exec.h>
47 #include <proto/dos.h>
48 #include <proto/battclock.h>
50 #include <hardware/intbits.h>
52 #include <stdlib.h>
54 #include "unit.h"
55 #include LC_LIBDEFS_FILE
57 /* A bit fixed linux stuff here :) */
59 #undef LIBBASE
60 #define LIBBASE (unit->rtl8139u_device)
62 #if defined(__i386__) || defined(__x86_64__)
63 #define TIMER_RPROK 3599597124UL
65 static ULONG usec2tick(ULONG usec)
67 ULONG ret, timer_rpr = TIMER_RPROK;
68 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
69 return ret;
72 void udelay(LONG usec)
74 int oldtick, tick;
75 usec = usec2tick(usec);
77 BYTEOUT(0x43, 0x80);
78 oldtick = BYTEIN(0x42);
79 oldtick += BYTEIN(0x42) << 8;
81 while (usec > 0)
83 BYTEOUT(0x43, 0x80);
84 tick = BYTEIN(0x42);
85 tick += BYTEIN(0x42) << 8;
87 usec -= (oldtick - tick);
88 if (tick > oldtick) usec -= 0x10000;
89 oldtick = tick;
92 #else
94 struct timerequest timerio;
95 struct MsgPort *timermp;
97 void udelay(LONG usec)
99 timerio.tr_node.io_Command = TR_ADDREQUEST;
100 timerio.tr_time.tv_secs = usec / 1000000;
101 timerio.tr_time.tv_micro = usec % 1000000;
102 DoIO(&timerio.tr_node);
105 int init_timer(void)
107 if ((timermp = CreateMsgPort())) {
108 timerio.tr_node.io_Message.mn_Node.ln_Type=NT_MESSAGE;
109 timerio.tr_node.io_Message.mn_ReplyPort = timermp;
110 timerio.tr_node.io_Message.mn_Length=sizeof(timerio);
111 if (0 == OpenDevice("timer.device", UNIT_MICROHZ, &timerio.tr_node, 0)) {
112 return TRUE;
115 return FALSE;
117 ADD2INIT(init_timer, 10);
119 void exit_timer(void)
121 CloseDevice(&timerio.tr_node);
122 DeleteMsgPort(timermp);
124 ADD2EXIT(exit_timer, 10);
125 #endif
127 static inline struct fe_priv *get_pcnpriv(struct net_device *unit)
129 return unit->rtl8139u_fe_priv;
132 static inline UBYTE *get_hwbase(struct net_device *unit)
134 return (UBYTE *)unit->rtl8139u_BaseMem;
137 static int read_eeprom(long base, int location, int addr_len)
139 int i;
140 unsigned retval = 0;
141 long rtlprom_addr = base + RTLr_Cfg9346;
142 int read_cmd = location | (EE_READ_CMD << addr_len);
144 BYTEOUT(rtlprom_addr, EE_ENB & ~EE_CS);
145 BYTEOUT(rtlprom_addr, EE_ENB);
147 // Shift the read command bits out
148 for (i = 4 + addr_len; i >= 0; i--)
150 int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
151 BYTEOUT(rtlprom_addr, EE_ENB | dataval);
152 eeprom_delay(rtlprom_addr);
153 BYTEOUT(rtlprom_addr, EE_ENB | dataval | EE_SHIFT_CLK);
154 eeprom_delay(rtlprom_addr);
156 BYTEOUT(rtlprom_addr, EE_ENB);
157 eeprom_delay(rtlprom_addr);
159 for (i = 16; i > 0; i--)
161 BYTEOUT(rtlprom_addr, EE_ENB | EE_SHIFT_CLK);
162 eeprom_delay(rtlprom_addr);
163 retval = (retval << 1) | ((BYTEIN(rtlprom_addr) & EE_DATA_READ) ? 1 : 0);
164 BYTEOUT(rtlprom_addr, EE_ENB);
165 eeprom_delay(rtlprom_addr);
168 // Terminate EEPROM access
169 BYTEOUT(rtlprom_addr, ~EE_CS);
170 eeprom_delay(rtlprom_addr);
171 return retval;
174 // Syncronize the MII management interface by shifting 32 one bits out
175 static char mii_2_8139_map[8] =
177 RTLr_MII_BMCR, RTLr_MII_BMSR, 0, 0, RTLr_NWayAdvert, RTLr_NWayLPAR, RTLr_NWayExpansion, 0
180 static void mdio_sync(long base)
182 int i;
184 for (i = 32; i >= 0; i--)
186 BYTEOUT(base, MDIO_WRITE1);
187 mdio_delay(base);
188 BYTEOUT(base, MDIO_WRITE1 | MDIO_CLK);
189 mdio_delay(base);
193 static int mdio_read(struct net_device *unit, int phy_id, int location)
195 // struct fe_priv *np = get_pcnpriv(unit);
196 UBYTE *base = get_hwbase(unit);
197 int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
198 int retval = 0;
199 int i;
201 if (phy_id > 31)
203 // Really a 8139. Use internal registers
204 return location < 8 && mii_2_8139_map[location] ? WORDIN(base + mii_2_8139_map[location]) : 0;
207 mdio_sync((IPTR)base + RTLr_MII_SMI);
209 // Shift the read command bits out
210 for (i = 15; i >= 0; i--)
212 int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
214 BYTEOUT(base + RTLr_MII_SMI, MDIO_DIR | dataval);
215 mdio_delay(base + RTLr_MII_SMI);
216 BYTEOUT(base + RTLr_MII_SMI, MDIO_DIR | dataval | MDIO_CLK);
217 mdio_delay(base + RTLr_MII_SMI);
220 // Read the two transition, 16 data, and wire-idle bits
221 for (i = 19; i > 0; i--)
223 BYTEOUT(base + RTLr_MII_SMI, 0);
224 mdio_delay(base + RTLr_MII_SMI);
225 retval = (retval << 1) | ((BYTEIN(base + RTLr_MII_SMI) & MDIO_DATA_IN) ? 1 : 0);
226 BYTEOUT(base + RTLr_MII_SMI, MDIO_CLK);
227 mdio_delay(base + RTLr_MII_SMI);
230 return (retval >> 1) & 0xffff;
233 #if 0
234 static void rtl8139nic_start_rx(struct net_device *unit)
236 // struct fe_priv *np = get_pcnpriv(unit);
237 // UBYTE *base = get_hwbase(unit);
239 RTLD(bug("[%s] rtl8139nic_start_rx\n", unit->rtl8139u_name))
240 // Already running? Stop it.
241 /* TODO: Handle starting/stopping Rx */
244 static void rtl8139nic_stop_rx(struct net_device *unit)
246 // UBYTE *base = get_hwbase(unit);
248 RTLD(bug("[%s] rtl8139nic_stop_rx\n", unit->rtl8139u_name))
249 /* TODO: Handle starting/stopping Rx */
252 static void rtl8139nic_start_tx(struct net_device *unit)
254 // UBYTE *base = get_hwbase(unit);
256 RTLD(bug("[%s] rtl8139nic_start_tx()\n", unit->rtl8139u_name))
257 /* TODO: Handle starting/stopping Tx */
260 static void rtl8139nic_stop_tx(struct net_device *unit)
262 // UBYTE *base = get_hwbase(unit);
264 RTLD(bug("[%s] rtl8139nic_stop_tx()\n", unit->rtl8139u_name))
265 /* TODO: Handle starting/stopping Tx */
268 static void rtl8139nic_txrx_reset(struct net_device *unit)
270 // struct fe_priv *np = get_pcnpriv(unit);
271 // UBYTE *base = get_hwbase(unit);
273 RTLD(bug("[%s] rtl8139nic_txrx_reset()\n", unit->rtl8139u_name))
275 #endif
278 * rtl8139nic_set_multicast: unit->set_multicast function
279 * Called with unit->xmit_lock held.
281 static void rtl8139nic_set_multicast(struct net_device *unit)
283 // struct fe_priv *np = get_pcnpriv(unit);
284 // UBYTE *base = get_hwbase(unit);
285 ULONG addr[2];
286 ULONG mask[2];
287 // ULONG pff;
289 RTLD(bug("[%s] rtl8139nic_set_multicast()\n", unit->rtl8139u_name))
291 memset(addr, 0, sizeof(addr));
292 memset(mask, 0, sizeof(mask));
295 static void rtl8139nic_deinitialize(struct net_device *unit)
300 static void rtl8139nic_get_mac(struct net_device *unit, char * addr, BOOL fromROM)
302 UBYTE *base = get_hwbase(unit);
303 int i;
305 RTLD(bug("[%s] rtl8139nic_get_mac()\n",unit->rtl8139u_name))
306 if (fromROM)
308 int addr_len = read_eeprom((IPTR)base, 0, 8) == 0x8129 ? 8 : 6;
309 int mac_add = 0;
310 for (i = 0; i < 3; i++)
312 UWORD mac_curr = read_eeprom((IPTR)base, i + 7, addr_len);
313 addr[mac_add++] = mac_curr & 0xff;
314 addr[mac_add++] = (mac_curr >> 8) & 0xff;
317 else
319 ULONG mac_cur = 0;
320 mac_cur = LONGIN(base + RTLr_MAC0 + 0);
321 addr[0] = mac_cur & 0xFF;
322 addr[1] = (mac_cur >> 8) & 0xFF;
323 addr[2] = (mac_cur >> 16) & 0xFF;
324 addr[3] = (mac_cur >> 24) & 0xFF;
325 mac_cur = LONGIN(base + RTLr_MAC0 + 4);
326 addr[4] = mac_cur & 0xFF;
327 addr[5] = (mac_cur >> 8) & 0xFF;
331 static void rtl8139nic_set_mac(struct net_device *unit)
333 UBYTE *base = get_hwbase(unit);
334 // int i,j;
336 RTLD(bug("[%s] rtl8139nic_set_mac()\n",unit->rtl8139u_name))
338 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
340 LONGOUT(base + RTLr_MAC0 + 0,
341 unit->rtl8139u_dev_addr[0] |
342 (unit->rtl8139u_dev_addr[1] << 8) |
343 (unit->rtl8139u_dev_addr[2] << 16) |
344 (unit->rtl8139u_dev_addr[3] << 24));
345 LONGOUT(base + RTLr_MAC0 + 4,
346 unit->rtl8139u_dev_addr[4] |
347 (unit->rtl8139u_dev_addr[5] << 8));
349 BYTEOUT(base + RTLr_Cfg9346, 0x00);
351 RTLD(
352 /* Read it back to be certain! */
353 TEXT newmac[6];
354 rtl8139nic_get_mac(unit, newmac, FALSE);
356 bug("[%s] rtl8139nic_set_mac: New MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
357 newmac[0], newmac[1], newmac[2],
358 newmac[3], newmac[4], newmac[5]))
361 static void rtl8139nic_initialize(struct net_device *unit)
363 struct fe_priv *np = unit->rtl8139u_fe_priv;
364 UBYTE *base = get_hwbase(unit);
365 int config1;
366 // int i;
368 config1 = BYTEIN(base + RTLr_Config1);
369 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
371 // 8129
372 BYTEOUT(base + RTLr_Config1, config1 & ~0x03);
374 RTLD(bug("[%s] Chipset brought out of low power mode.\n", unit->rtl8139u_name))
376 rtl8139nic_get_mac(unit, np->orig_mac, TRUE);
378 int phy, phy_idx = 0;
379 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
381 for (phy = 0; phy < 32 && phy_idx < sizeof(np->mii_phys); phy++)
383 int mii_status = mdio_read(unit, phy, 1);
384 if (mii_status != 0xffff && mii_status != 0x0000)
386 np->mii_phys[phy_idx++] = phy;
387 np->advertising = mdio_read(unit, phy, 4);
388 RTLD(bug("[%s] MII transceiver %d status 0x%4.4x advertising %4.4x\n", unit->rtl8139u_name,
389 phy, mii_status, np->advertising))
394 if (phy_idx == 0)
396 RTLD(bug("[%s] No MII transceiver found, Assuming SYM transceiver\n", unit->rtl8139u_name))
397 np->mii_phys[0] = 32;
400 unit->rtl8139u_dev_addr[0] = unit->rtl8139u_org_addr[0] = np->orig_mac[0];
401 unit->rtl8139u_dev_addr[1] = unit->rtl8139u_org_addr[1] = np->orig_mac[1];
402 unit->rtl8139u_dev_addr[2] = unit->rtl8139u_org_addr[2] = np->orig_mac[2];
403 unit->rtl8139u_dev_addr[3] = unit->rtl8139u_org_addr[3] = np->orig_mac[3];
404 unit->rtl8139u_dev_addr[4] = unit->rtl8139u_org_addr[4] = np->orig_mac[4];
405 unit->rtl8139u_dev_addr[5] = unit->rtl8139u_org_addr[5] = np->orig_mac[5];
407 RTLD(bug("[%s] MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
408 unit->rtl8139u_dev_addr[0], unit->rtl8139u_dev_addr[1], unit->rtl8139u_dev_addr[2],
409 unit->rtl8139u_dev_addr[3], unit->rtl8139u_dev_addr[4], unit->rtl8139u_dev_addr[5]))
411 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
412 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
414 // 8129
415 BYTEOUT(base + RTLr_Config1, 0x03);
417 BYTEOUT(base + RTLr_HltClk, 'H'); //Disable the chips clock ('R' enables)
418 RTLD(bug("[%s] Chipset put into low power mode.\n", unit->rtl8139u_name))
421 static void rtl8139nic_drain_tx(struct net_device *unit)
423 // struct fe_priv *np = get_pcnpriv(unit);
424 // int i;
426 // for (i = 0; i < NUM_TX_DESC; i++)
427 // {
428 /* TODO: rtl8139nic_drain_tx does nothing atm. */
429 // }
432 static void rtl8139nic_drain_rx(struct net_device *unit)
434 // struct fe_priv *np = get_pcnpriv(unit);
435 // int i;
437 // for (i = 0; i < RX_RING_SIZE; i++)
438 // {
439 /* TODO: rtl8139nic_drain_rx does nothing atm. */
440 // }
444 static void drain_ring(struct net_device *unit)
446 rtl8139nic_drain_tx(unit);
447 rtl8139nic_drain_rx(unit);
450 static int request_irq(struct net_device *unit)
452 RTLD(bug("[%s] request_irq()\n", unit->rtl8139u_name))
454 if (!unit->rtl8139u_IntsAdded)
456 AddIntServer(INTB_KERNEL + unit->rtl8139u_IRQ,
457 &unit->rtl8139u_irqhandler);
458 AddIntServer(INTB_VERTB, &unit->rtl8139u_touthandler);
459 unit->rtl8139u_IntsAdded = TRUE;
461 RTLD(bug("[%s] request_irq: IRQ Handlers configured\n", unit->rtl8139u_name))
463 return 0;
466 static void free_irq(struct net_device *unit)
468 if (unit->rtl8139u_IntsAdded)
470 RemIntServer(INTB_KERNEL + unit->rtl8139u_IRQ,
471 &unit->rtl8139u_irqhandler);
472 RemIntServer(INTB_VERTB, &unit->rtl8139u_touthandler);
473 unit->rtl8139u_IntsAdded = FALSE;
477 int rtl8139nic_set_rxmode(struct net_device *unit)
479 struct fe_priv *np = get_pcnpriv(unit);
480 UBYTE *base = get_hwbase(unit);
481 ULONG mc_filter[2]; //Multicast hash filter.
482 ULONG rx_mode;
484 RTLD(bug("[%s] rtl8139nic_set_rxmode(flags %x)\n", unit->rtl8139u_name, unit->rtl8139u_flags))
486 /* TODO: Fix set_rxmode.. doesnt load multicast list atm .. */
487 if (unit->rtl8139u_flags & IFF_PROMISC)
489 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: PROMISC\n",unit->rtl8139u_name))
490 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys;
491 mc_filter[1] = mc_filter[0] = 0xffffffff;
493 else if (unit->rtl8139u_flags & IFF_ALLMULTI)
495 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: ALLMULTI\n",unit->rtl8139u_name))
496 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
497 mc_filter[1] = mc_filter[0] = 0xffffffff;
499 else
501 // struct mclist *mclist;
502 // int i;
503 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: DEFAULT\n",unit->rtl8139u_name))
505 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
506 /*if (unit->mc_count < multicast_filter_limit)
508 mc_filter[1] = mc_filter[0] = 0;
509 /*for (i = 0, mclist = dev->netif->mclist; mclist && i < dev->netif->mccount; i++, mclist = mclist->next)
511 set_bit(mc_filter, ether_crc(6, (unsigned char *) &mclist->hwaddr) >> 26);
514 else
516 mc_filter[1] = mc_filter[0] = 0xffffffff;
520 LONGOUT(base + RTLr_RxConfig, np->rx_config | rx_mode);
521 LONGOUT(base + RTLr_MAR0 + 0, mc_filter[0]);
522 LONGOUT(base + RTLr_MAR0 + 4, mc_filter[1]);
524 return 0;
527 static int rtl8139nic_open(struct net_device *unit)
529 struct fe_priv *np = get_pcnpriv(unit);
530 UBYTE *base = get_hwbase(unit);
531 int ret, i, rx_buf_len_idx;
533 rx_buf_len_idx = RX_BUF_LEN_IDX;
535 ret = request_irq(unit);
536 if (ret)
538 goto out_drain;
541 np->rx_buf_len = 8192 << rx_buf_len_idx;
543 np->rx_buffer = HIDD_PCIDriver_AllocPCIMem(
544 unit->rtl8139u_PCIDriver,
545 (np->rx_buf_len + 16 + (TX_BUF_SIZE * NUM_TX_DESC))
548 if (np->rx_buffer != NULL)
550 np->tx_buffer = HIDD_PCIDriver_AllocPCIMem(
551 unit->rtl8139u_PCIDriver,
552 (np->rx_buf_len + 16 + (TX_BUF_SIZE * NUM_TX_DESC))
556 if ((np->rx_buffer != NULL) && (np->tx_buffer != NULL))
558 RTLD(bug("[%s] rtl8139nic_open: Allocated IO Buffers [ %d x Tx @ %x] [ Rx @ %x, %d bytes]\n",
559 unit->rtl8139u_name,
560 NUM_TX_DESC, np->tx_buffer,
561 np->rx_buffer, np->rx_buf_len))
563 np->tx_dirty = np->tx_current = 0;
565 for (i = 0; i < NUM_TX_DESC; i++)
567 np->tx_pbuf[i] = NULL;
568 np->tx_buf[i] = np->tx_buffer + (i * TX_BUF_SIZE);
570 RTLD(bug("[%s] rtl8139nic_open: TX Buffers initialised\n",unit->rtl8139u_name))
572 // Early Tx threshold: 256 bytes
573 np->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
574 np->rx_config = (RX_FIFO_THRESH << 13) | (rx_buf_len_idx << 11) | (RX_DMA_BURST << 8);
576 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) | CmdReset);
577 udelay(100);
578 for (i = 1000; i > 0; i--)
580 if ((BYTEIN(base + RTLr_ChipCmd) & CmdReset) == 0)
582 break;
585 RTLD(bug("[%s] rtl8139nic_open: NIC Reset\n",unit->rtl8139u_name))
587 rtl8139nic_set_mac(unit);
588 RTLD(bug("[%s] rtl8139nic_open: copied MAC address\n",unit->rtl8139u_name))
590 np->rx_current = 0;
592 // Unlock
593 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
595 //Enable Tx/Rx so we can set the config(s)
596 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) |
597 CmdRxEnb | CmdTxEnb);
598 LONGOUT(base + RTLr_RxConfig, np->rx_config);
599 LONGOUT(base + RTLr_TxConfig, TX_DMA_BURST << 8);
601 RTLD(bug("[%s] rtl8139nic_open: Enabled Tx/Rx\n",unit->rtl8139u_name))
603 /* check_duplex */
604 if (np->mii_phys[0] >= 0 || (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR))
606 UWORD mii_reg5 = mdio_read(unit, np->mii_phys[0], 5);
607 if (mii_reg5 != 0xffff)
609 if (((mii_reg5 & 0x0100) == 0x0100) || ((mii_reg5 & 0x00c0) == 0x0040))
611 np->full_duplex = 1;
615 if ((mii_reg5 == 0 ) || !(mii_reg5 & 0x0180))
617 unit->rtl8139u_rtl_LinkSpeed = 10000000;
619 else
621 unit->rtl8139u_rtl_LinkSpeed = 100000000;
624 RTLD(bug("[%s] rtl8139nic_open: Setting %s%s-duplex based on auto-neg partner ability %4.4x\n",unit->rtl8139u_name,
625 mii_reg5 == 0 ? "" : (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
626 np->full_duplex ? "full" : "half", mii_reg5))
629 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
631 // 8129
632 BYTEOUT(base + RTLr_Config1, np->full_duplex ? 0x60 : 0x20);
634 // Lock
635 BYTEOUT(base + RTLr_Cfg9346, 0x00);
636 udelay(10);
637 LONGOUT(base + RTLr_RxBuf, (IPTR)np->rx_buffer);
639 //Start the chips Tx/Rx processes
640 LONGOUT(base + RTLr_RxMissed, 0);
642 rtl8139nic_set_rxmode(unit);
644 WORDOUT(base + RTLr_MultiIntr, WORDIN(RTLr_MultiIntr) & MultiIntrClear);
646 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) |
647 CmdRxEnb | CmdTxEnb);
649 // Enable all known interrupts by setting the interrupt mask ..
650 WORDOUT(base + RTLr_IntrMask, PCIErr |
651 PCSTimeout |
652 RxUnderrun |
653 RxOverflow |
654 RxFIFOOver |
655 TxErr |
656 TxOK |
657 RxErr |
658 RxOK);
660 unit->rtl8139u_flags |= IFF_UP;
661 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
662 RTLD(bug("[%s] rtl8139nic_open: Device set as ONLINE\n",unit->rtl8139u_name))
664 return 0;
666 out_drain:
667 drain_ring(unit);
668 return ret;
671 static int rtl8139nic_close(struct net_device *unit)
673 struct fe_priv *np = get_pcnpriv(unit);
675 unit->rtl8139u_flags &= ~IFF_UP;
677 ObtainSemaphore(&np->lock);
678 np->in_shutdown = 1;
679 ReleaseSemaphore(&np->lock);
681 unit->rtl8139u_toutNEED = FALSE;
683 ObtainSemaphore(&np->lock);
685 rtl8139nic_deinitialize(unit); // Stop the chipset and set it in 16bit-mode
687 ReleaseSemaphore(&np->lock);
689 free_irq(unit);
691 drain_ring(unit);
693 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->rx_buffer);
694 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->tx_buffer);
696 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
698 return 0;
702 void rtl8139nic_get_functions(struct net_device *Unit)
704 Unit->initialize = rtl8139nic_initialize;
705 Unit->deinitialize = rtl8139nic_deinitialize;
706 Unit->start = rtl8139nic_open;
707 Unit->stop = rtl8139nic_close;
708 Unit->set_mac_address = rtl8139nic_set_mac;
709 Unit->set_multicast = rtl8139nic_set_multicast;