grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / devs / networks / rtl8139 / rtl8139.c
blobbee3096a8ff9df79f2128d790b59aaaf3da21cd0
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)
297 int i;
298 UBYTE *base = get_hwbase(unit);
300 WORDOUT(base + RTLr_IntrMask, 0);
301 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) | CmdReset);
302 udelay(100);
303 for (i = 1000; i > 0; i--)
305 if ((BYTEIN(base + RTLr_ChipCmd) & CmdReset) == 0)
307 break;
312 static void rtl8139nic_get_mac(struct net_device *unit, char * addr, BOOL fromROM)
314 UBYTE *base = get_hwbase(unit);
315 int i;
317 RTLD(bug("[%s] rtl8139nic_get_mac()\n",unit->rtl8139u_name))
318 if (fromROM)
320 int addr_len = read_eeprom((IPTR)base, 0, 8) == 0x8129 ? 8 : 6;
321 int mac_add = 0;
322 for (i = 0; i < 3; i++)
324 UWORD mac_curr = read_eeprom((IPTR)base, i + 7, addr_len);
325 addr[mac_add++] = mac_curr & 0xff;
326 addr[mac_add++] = (mac_curr >> 8) & 0xff;
329 else
331 ULONG mac_cur = 0;
332 mac_cur = LONGIN(base + RTLr_MAC0 + 0);
333 addr[0] = mac_cur & 0xFF;
334 addr[1] = (mac_cur >> 8) & 0xFF;
335 addr[2] = (mac_cur >> 16) & 0xFF;
336 addr[3] = (mac_cur >> 24) & 0xFF;
337 mac_cur = LONGIN(base + RTLr_MAC0 + 4);
338 addr[4] = mac_cur & 0xFF;
339 addr[5] = (mac_cur >> 8) & 0xFF;
343 static void rtl8139nic_set_mac(struct net_device *unit)
345 UBYTE *base = get_hwbase(unit);
346 // int i,j;
348 RTLD(bug("[%s] rtl8139nic_set_mac()\n",unit->rtl8139u_name))
350 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
352 LONGOUT(base + RTLr_MAC0 + 0,
353 unit->rtl8139u_dev_addr[0] |
354 (unit->rtl8139u_dev_addr[1] << 8) |
355 (unit->rtl8139u_dev_addr[2] << 16) |
356 (unit->rtl8139u_dev_addr[3] << 24));
357 LONGOUT(base + RTLr_MAC0 + 4,
358 unit->rtl8139u_dev_addr[4] |
359 (unit->rtl8139u_dev_addr[5] << 8));
361 BYTEOUT(base + RTLr_Cfg9346, 0x00);
363 RTLD(
364 /* Read it back to be certain! */
365 TEXT newmac[6];
366 rtl8139nic_get_mac(unit, newmac, FALSE);
368 bug("[%s] rtl8139nic_set_mac: New MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
369 newmac[0], newmac[1], newmac[2],
370 newmac[3], newmac[4], newmac[5]))
373 static void rtl8139nic_initialize(struct net_device *unit)
375 struct fe_priv *np = unit->rtl8139u_fe_priv;
376 UBYTE *base = get_hwbase(unit);
377 int config1;
378 // int i;
380 config1 = BYTEIN(base + RTLr_Config1);
381 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
383 // 8129
384 BYTEOUT(base + RTLr_Config1, config1 & ~0x03);
386 RTLD(bug("[%s] Chipset brought out of low power mode.\n", unit->rtl8139u_name))
388 rtl8139nic_get_mac(unit, np->orig_mac, TRUE);
390 int phy, phy_idx = 0;
391 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
393 for (phy = 0; phy < 32 && phy_idx < sizeof(np->mii_phys); phy++)
395 int mii_status = mdio_read(unit, phy, 1);
396 if (mii_status != 0xffff && mii_status != 0x0000)
398 np->mii_phys[phy_idx++] = phy;
399 np->advertising = mdio_read(unit, phy, 4);
400 RTLD(bug("[%s] MII transceiver %d status 0x%4.4x advertising %4.4x\n", unit->rtl8139u_name,
401 phy, mii_status, np->advertising))
406 if (phy_idx == 0)
408 RTLD(bug("[%s] No MII transceiver found, Assuming SYM transceiver\n", unit->rtl8139u_name))
409 np->mii_phys[0] = 32;
412 unit->rtl8139u_dev_addr[0] = unit->rtl8139u_org_addr[0] = np->orig_mac[0];
413 unit->rtl8139u_dev_addr[1] = unit->rtl8139u_org_addr[1] = np->orig_mac[1];
414 unit->rtl8139u_dev_addr[2] = unit->rtl8139u_org_addr[2] = np->orig_mac[2];
415 unit->rtl8139u_dev_addr[3] = unit->rtl8139u_org_addr[3] = np->orig_mac[3];
416 unit->rtl8139u_dev_addr[4] = unit->rtl8139u_org_addr[4] = np->orig_mac[4];
417 unit->rtl8139u_dev_addr[5] = unit->rtl8139u_org_addr[5] = np->orig_mac[5];
419 RTLD(bug("[%s] MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->rtl8139u_name,
420 unit->rtl8139u_dev_addr[0], unit->rtl8139u_dev_addr[1], unit->rtl8139u_dev_addr[2],
421 unit->rtl8139u_dev_addr[3], unit->rtl8139u_dev_addr[4], unit->rtl8139u_dev_addr[5]))
423 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
424 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
426 // 8129
427 BYTEOUT(base + RTLr_Config1, 0x03);
429 BYTEOUT(base + RTLr_HltClk, 'H'); //Disable the chips clock ('R' enables)
430 RTLD(bug("[%s] Chipset put into low power mode.\n", unit->rtl8139u_name))
433 static void rtl8139nic_drain_tx(struct net_device *unit)
435 // struct fe_priv *np = get_pcnpriv(unit);
436 // int i;
438 // for (i = 0; i < NUM_TX_DESC; i++)
439 // {
440 /* TODO: rtl8139nic_drain_tx does nothing atm. */
441 // }
444 static void rtl8139nic_drain_rx(struct net_device *unit)
446 // struct fe_priv *np = get_pcnpriv(unit);
447 // int i;
449 // for (i = 0; i < RX_RING_SIZE; i++)
450 // {
451 /* TODO: rtl8139nic_drain_rx does nothing atm. */
452 // }
456 static void drain_ring(struct net_device *unit)
458 rtl8139nic_drain_tx(unit);
459 rtl8139nic_drain_rx(unit);
462 static int request_irq(struct net_device *unit)
464 RTLD(bug("[%s] request_irq()\n", unit->rtl8139u_name))
466 if (!unit->rtl8139u_IntsAdded)
468 AddIntServer(INTB_KERNEL + unit->rtl8139u_IRQ,
469 &unit->rtl8139u_irqhandler);
470 AddIntServer(INTB_VERTB, &unit->rtl8139u_touthandler);
471 unit->rtl8139u_IntsAdded = TRUE;
473 RTLD(bug("[%s] request_irq: IRQ Handlers configured\n", unit->rtl8139u_name))
475 return 0;
478 static void free_irq(struct net_device *unit)
480 if (unit->rtl8139u_IntsAdded)
482 RemIntServer(INTB_KERNEL + unit->rtl8139u_IRQ,
483 &unit->rtl8139u_irqhandler);
484 RemIntServer(INTB_VERTB, &unit->rtl8139u_touthandler);
485 unit->rtl8139u_IntsAdded = FALSE;
489 int rtl8139nic_set_rxmode(struct net_device *unit)
491 struct fe_priv *np = get_pcnpriv(unit);
492 UBYTE *base = get_hwbase(unit);
493 ULONG mc_filter[2]; //Multicast hash filter.
494 ULONG rx_mode;
496 RTLD(bug("[%s] rtl8139nic_set_rxmode(flags %x)\n", unit->rtl8139u_name, unit->rtl8139u_flags))
498 /* TODO: Fix set_rxmode.. doesnt load multicast list atm .. */
499 if (unit->rtl8139u_flags & IFF_PROMISC)
501 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: PROMISC\n",unit->rtl8139u_name))
502 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys;
503 mc_filter[1] = mc_filter[0] = 0xffffffff;
505 else if (unit->rtl8139u_flags & IFF_ALLMULTI)
507 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: ALLMULTI\n",unit->rtl8139u_name))
508 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
509 mc_filter[1] = mc_filter[0] = 0xffffffff;
511 else
513 // struct mclist *mclist;
514 // int i;
515 RTLD(bug("[%s] rtl8139nic_set_rxmode: Mode: DEFAULT\n",unit->rtl8139u_name))
517 rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
518 /*if (unit->mc_count < multicast_filter_limit)
520 mc_filter[1] = mc_filter[0] = 0;
521 /*for (i = 0, mclist = dev->netif->mclist; mclist && i < dev->netif->mccount; i++, mclist = mclist->next)
523 set_bit(mc_filter, ether_crc(6, (unsigned char *) &mclist->hwaddr) >> 26);
526 else
528 mc_filter[1] = mc_filter[0] = 0xffffffff;
532 LONGOUT(base + RTLr_RxConfig, np->rx_config | rx_mode);
533 LONGOUT(base + RTLr_MAR0 + 0, mc_filter[0]);
534 LONGOUT(base + RTLr_MAR0 + 4, mc_filter[1]);
536 return 0;
539 static int rtl8139nic_open(struct net_device *unit)
541 struct fe_priv *np = get_pcnpriv(unit);
542 UBYTE *base = get_hwbase(unit);
543 int ret, i, rx_buf_len_idx;
545 rx_buf_len_idx = RX_BUF_LEN_IDX;
547 ret = request_irq(unit);
548 if (ret)
550 goto out_drain;
553 np->rx_buf_len = 8192 << rx_buf_len_idx;
555 np->rx_buffer = HIDD_PCIDriver_AllocPCIMem(
556 unit->rtl8139u_PCIDriver,
557 (np->rx_buf_len + 16 + (TX_BUF_SIZE * NUM_TX_DESC))
560 if (np->rx_buffer != NULL)
562 np->tx_buffer = HIDD_PCIDriver_AllocPCIMem(
563 unit->rtl8139u_PCIDriver,
564 (np->rx_buf_len + 16 + (TX_BUF_SIZE * NUM_TX_DESC))
568 if ((np->rx_buffer != NULL) && (np->tx_buffer != NULL))
570 RTLD(bug("[%s] rtl8139nic_open: Allocated IO Buffers [ %d x Tx @ %x] [ Rx @ %x, %d bytes]\n",
571 unit->rtl8139u_name,
572 NUM_TX_DESC, np->tx_buffer,
573 np->rx_buffer, np->rx_buf_len))
575 np->tx_dirty = np->tx_current = 0;
577 for (i = 0; i < NUM_TX_DESC; i++)
579 np->tx_pbuf[i] = NULL;
580 np->tx_buf[i] = np->tx_buffer + (i * TX_BUF_SIZE);
582 RTLD(bug("[%s] rtl8139nic_open: TX Buffers initialised\n",unit->rtl8139u_name))
584 // Early Tx threshold: 256 bytes
585 np->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
586 np->rx_config = (RX_FIFO_THRESH << 13) | (rx_buf_len_idx << 11) | (RX_DMA_BURST << 8);
588 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) | CmdReset);
589 udelay(100);
590 for (i = 1000; i > 0; i--)
592 if ((BYTEIN(base + RTLr_ChipCmd) & CmdReset) == 0)
594 break;
597 RTLD(bug("[%s] rtl8139nic_open: NIC Reset\n",unit->rtl8139u_name))
599 rtl8139nic_set_mac(unit);
600 RTLD(bug("[%s] rtl8139nic_open: copied MAC address\n",unit->rtl8139u_name))
602 np->rx_current = 0;
604 // Unlock
605 BYTEOUT(base + RTLr_Cfg9346, 0xc0);
607 //Enable Tx/Rx so we can set the config(s)
608 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) |
609 CmdRxEnb | CmdTxEnb);
610 LONGOUT(base + RTLr_RxConfig, np->rx_config);
611 LONGOUT(base + RTLr_TxConfig, TX_DMA_BURST << 8);
613 RTLD(bug("[%s] rtl8139nic_open: Enabled Tx/Rx\n",unit->rtl8139u_name))
615 /* check_duplex */
616 if (np->mii_phys[0] >= 0 || (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR))
618 UWORD mii_reg5 = mdio_read(unit, np->mii_phys[0], 5);
619 if (mii_reg5 != 0xffff)
621 if (((mii_reg5 & 0x0100) == 0x0100) || ((mii_reg5 & 0x00c0) == 0x0040))
623 np->full_duplex = 1;
627 if ((mii_reg5 == 0 ) || !(mii_reg5 & 0x0180))
629 unit->rtl8139u_rtl_LinkSpeed = 10000000;
631 else
633 unit->rtl8139u_rtl_LinkSpeed = 100000000;
636 RTLD(bug("[%s] rtl8139nic_open: Setting %s%s-duplex based on auto-neg partner ability %4.4x\n",unit->rtl8139u_name,
637 mii_reg5 == 0 ? "" : (mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
638 np->full_duplex ? "full" : "half", mii_reg5))
641 if (unit->rtl8139u_rtl_chipcapabilities & RTLc_HAS_MII_XCVR)
643 // 8129
644 BYTEOUT(base + RTLr_Config1, np->full_duplex ? 0x60 : 0x20);
646 // Lock
647 BYTEOUT(base + RTLr_Cfg9346, 0x00);
648 udelay(10);
649 LONGOUT(base + RTLr_RxBuf, (IPTR)np->rx_buffer);
651 //Start the chips Tx/Rx processes
652 LONGOUT(base + RTLr_RxMissed, 0);
654 rtl8139nic_set_rxmode(unit);
656 WORDOUT(base + RTLr_MultiIntr, WORDIN(RTLr_MultiIntr) & MultiIntrClear);
658 BYTEOUT(base + RTLr_ChipCmd, (BYTEIN(base + RTLr_ChipCmd) & CmdClear) |
659 CmdRxEnb | CmdTxEnb);
661 // Enable all known interrupts by setting the interrupt mask ..
662 WORDOUT(base + RTLr_IntrMask, PCIErr |
663 PCSTimeout |
664 RxUnderrun |
665 RxOverflow |
666 RxFIFOOver |
667 TxErr |
668 TxOK |
669 RxErr |
670 RxOK);
672 unit->rtl8139u_flags |= IFF_UP;
673 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
674 RTLD(bug("[%s] rtl8139nic_open: Device set as ONLINE\n",unit->rtl8139u_name))
676 return 0;
678 out_drain:
679 drain_ring(unit);
680 return ret;
683 static int rtl8139nic_close(struct net_device *unit)
685 struct fe_priv *np = get_pcnpriv(unit);
687 unit->rtl8139u_flags &= ~IFF_UP;
689 ObtainSemaphore(&np->lock);
690 np->in_shutdown = 1;
691 ReleaseSemaphore(&np->lock);
693 unit->rtl8139u_toutNEED = FALSE;
695 ObtainSemaphore(&np->lock);
697 rtl8139nic_deinitialize(unit); // Stop the chipset and set it in 16bit-mode
699 ReleaseSemaphore(&np->lock);
701 free_irq(unit);
703 drain_ring(unit);
705 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->rx_buffer);
706 HIDD_PCIDriver_FreePCIMem(unit->rtl8139u_PCIDriver, np->tx_buffer);
708 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
710 return 0;
714 void rtl8139nic_get_functions(struct net_device *Unit)
716 Unit->initialize = rtl8139nic_initialize;
717 Unit->deinitialize = rtl8139nic_deinitialize;
718 Unit->start = rtl8139nic_open;
719 Unit->stop = rtl8139nic_close;
720 Unit->set_mac_address = rtl8139nic_set_mac;
721 Unit->set_multicast = rtl8139nic_set_multicast;