Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / drivers / net / rtl8139 / rtl8139.c
blob6ccefa56e7bc6f0bb940a89480664673aaa9623e
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
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 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU 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, see <http://www.gnu.org/licenses/>.
21 #include <config.h>
22 #include <build.h>
24 #ifndef ARCH_i386
25 #undef CONFIG_DRV_RTL8139
26 #endif
28 #ifdef CONFIG_DRV_RTL8139
30 #include <system.h>
31 #include <string.h>
32 #include <arch/io.h>
33 #include <pci.h>
34 #include <task.h>
35 #include <net/eth.h>
36 #include <net/net.h>
38 /* PCI probe IDs */
39 #define RTL8139_VENDORID 0x10ec
40 #define RTL8139_DEVICEID 0x8139
42 /* RTL8139C register definitions */
43 #define RTL8139_IDR0 0x00 /* Mac address */
44 #define RTL8139_MAR0 0x08 /* Multicast filter */
45 #define RTL8139_TXSTATUS0 0x10 /* Transmit status (4 32bit regs) */
46 #define RTL8139_TXSTATUS1 0x14 /* Transmit status (4 32bit regs) */
47 #define RTL8139_TXSTATUS2 0x18 /* Transmit status (4 32bit regs) */
48 #define RTL8139_TXSTATUS3 0x1c /* Transmit status (4 32bit regs) */
49 #define RTL8139_TXADDR0 0x20 /* Tx descriptors (also 4 32bit) */
50 #define RTL8139_TXADDR1 0x24 /* Tx descriptors (also 4 32bit) */
51 #define RTL8139_TXADDR2 0x28 /* Tx descriptors (also 4 32bit) */
52 #define RTL8139_TXADDR3 0x2c /* Tx descriptors (also 4 32bit) */
53 #define RTL8139_RXBUF 0x30 /* Receive buffer start address */
54 #define RTL8139_RXEARLYCNT 0x34 /* Early Rx byte count */
55 #define RTL8139_RXEARLYSTATUS 0x36 /* Early Rx status */
56 #define RTL8139_CHIPCMD 0x37 /* Command register */
57 #define RTL8139_RXBUFTAIL 0x38 /* Current address of packet read (queue tail) */
58 #define RTL8139_RXBUFHEAD 0x3A /* Current buffer address (queue head) */
59 #define RTL8139_INTRMASK 0x3C /* Interrupt mask */
60 #define RTL8139_INTRSTATUS 0x3E /* Interrupt status */
61 #define RTL8139_TXCONFIG 0x40 /* Tx config */
62 #define RTL8139_RXCONFIG 0x44 /* Rx config */
63 #define RTL8139_TIMER 0x48 /* A general purpose counter */
64 #define RTL8139_RXMISSED 0x4C /* 24 bits valid, write clears */
65 #define RTL8139_CFG9346 0x50 /* 93C46 command register */
66 #define RTL8139_CONFIG0 0x51 /* Configuration reg 0 */
67 #define RTL8139_CONFIG1 0x52 /* Configuration reg 1 */
68 #define RTL8139_TIMERINT 0x54 /* Timer interrupt register (32 bits) */
69 #define RTL8139_MEDIASTATUS 0x58 /* Media status register */
70 #define RTL8139_CONFIG3 0x59 /* Config register 3 */
71 #define RTL8139_CONFIG4 0x5A /* Config register 4 */
72 #define RTL8139_HLTCLK 0x5B /* Halted Clock */
73 #define RTL8139_MULTIINTR 0x5C /* Multiple interrupt select */
74 #define RTL8139_MII_TSAD 0x60 /* Transmit status of all descriptors (16 bits) */
75 #define RTL8139_MII_BMCR 0x62 /* Basic Mode Control Register (16 bits) */
76 #define RTL8139_MII_BMSR 0x64 /* Basic Mode Status Register (16 bits) */
77 #define RTL8139_AS_ADVERT 0x66 /* Auto-negotiation advertisement reg (16 bits) */
78 #define RTL8139_AS_LPAR 0x68 /* Auto-negotiation link partner reg (16 bits) */
79 #define RTL8139_AS_EXPANSION 0x6A /* Auto-negotiation expansion reg (16 bits) */
81 /* RTL8193C command bits; or these together and write teh resulting value
82 into CHIPCMD to execute it. */
83 #define RTL8139_CMD_RESET 0x10
84 #define RTL8139_CMD_RX_ENABLE 0x08
85 #define RTL8139_CMD_TX_ENABLE 0x04
86 #define RTL8139_CMD_RX_BUF_EMPTY 0x01
88 /* RTL8139C interrupt status bits */
89 #define RTL8139_INT_PCIERR 0x8000 /* PCI Bus error */
90 #define RTL8139_INT_TIMEOUT 0x4000 /* Set when TCTR reaches TimerInt value */
91 #define RTL8139_INT_RXFIFO_OVERFLOW 0x0040 /* Rx FIFO overflow */
92 #define RTL8139_INT_RXFIFO_UNDERRUN 0x0020 /* Packet underrun / link change */
93 #define RTL8139_INT_RXBUF_OVERFLOW 0x0010 /* Rx BUFFER overflow */
94 #define RTL8139_INT_TX_ERR 0x0008
95 #define RTL8139_INT_TX_OK 0x0004
96 #define RTL8139_INT_RX_ERR 0x0002
97 #define RTL8139_INT_RX_OK 0x0001
99 /* RTL8139C transmit status bits */
100 #define RTL8139_TX_CARRIER_LOST 0x80000000 /* Carrier sense lost */
101 #define RTL8139_TX_ABORTED 0x40000000 /* Transmission aborted */
102 #define RTL8139_TX_OUT_OF_WINDOW 0x20000000 /* Out of window collision */
103 #define RTL8139_TX_CARRIER_HBEAT 0x10000000 /* not sure */
104 #define RTL8139_TX_STATUS_OK 0x00008000 /* Status ok: a good packet was transmitted */
105 #define RTL8139_TX_UNDERRUN 0x00004000 /* Transmit FIFO underrun */
106 #define RTL8139_TX_HOST_OWNS 0x00002000 /* Set to 1 when DMA operation is completed */
107 #define RTL8139_TX_SIZE_MASK 0x00001fff /* Descriptor size mask */
109 #define RTL8139_TX_IFG0 0x1000000
110 #define RTL8139_TX_IFG1 0x2000000
111 #define RTL8139_TX_MXDMA2 0x400
112 #define RTL8139_TX_MXDMA1 0x200
114 /* RTL8139C receive status bits */
115 #define RTL8139_RX_MULTICAST 0x00008000 /* Multicast packet */
116 #define RTL8139_RX_PAM 0x00004000 /* Physical address matched */
117 #define RTL8139_RX_BROADCAST 0x00002000 /* Broadcast address matched */
118 #define RTL8139_RX_BAD_SYMBOL 0x00000020 /* Invalid symbol in 100TX packet */
119 #define RTL8139_RX_RUNT 0x00000010 /* Packet size is <64 bytes */
120 #define RTL8139_RX_TOO_LONG 0x00000008 /* Packet size is >4K bytes */
121 #define RTL8139_RX_CRC_ERR 0x00000004 /* CRC error */
122 #define RTL8139_RX_FRAME_ALIGN 0x00000002 /* Frame alignment error */
123 #define RTL8139_RX_STATUS_OK 0x00000001 /* Status ok: a good packet was received */
125 #define RTL8139_RX_RBLEN0 0x800
126 #define RTL8139_RX_MXDMA2 0x400
127 #define RTL8139_RX_MXDMA1 0x200
128 #define RTL8139_RX_AB 0x8
129 #define RTL8139_RX_AM 0x4
130 #define RTL8139_RX_APM 0x2
132 #define RTL8139_BMCR_FDUPLEX 0x0100
133 #define RTL8139_MSR_SPEED10 0x08
135 #define RTL8139_PM_ENABLE 0x01
136 #define RTL8139_PM_LWAKE 0x10
137 #define RTL8139_PM_LWPTN (1 << 2)
138 #define RTL8139_PM_SLEEP (1 << 1)
139 #define RTL8139_PM_PWRDN (1 << 0)
141 /* EEPROM_Ctrl bits. */
142 #define RTL8139_EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
143 #define RTL8139_EE_CS 0x08 /* EEPROM chip select. */
144 #define RTL8139_EE_DATA_WRITE 0x02 /* EEPROM chip data in. */
145 #define RTL8139_EE_WRITE_0 0x00
146 #define RTL8139_EE_WRITE_1 0x02
147 #define RTL8139_EE_DATA_READ 0x01 /* EEPROM chip data out. */
148 #define RTL8139_EE_ENB (0x80 | RTL8139_EE_CS)
150 /* The EEPROM commands include the alway-set leading bit. */
151 #define RTL8139_EE_WRITE_CMD (5 << 6)
152 #define RTL8139_EE_READ_CMD (6 << 6)
153 #define RTL8139_EE_ERASE_CMD (7 << 6)
155 #define TAILREG_TO_TAIL(in) \
156 (unsigned short)(((unsigned)(in) + 16) % 0x10000)
158 #define TAIL_TO_TAILREG(in) \
159 (unsigned short)((unsigned)(in) - 16)
161 #define MYRT_INTS (RTL8139_INT_PCIERR | RTL8139_INT_RX_ERR | RTL8139_INT_RX_OK | \
162 RTL8139_INT_TX_ERR | RTL8139_INT_TX_OK | RTL8139_INT_RXBUF_OVERFLOW)
164 #define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \
165 (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)
166 #define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)
168 enum chip_flags {
169 HasHltClk = (1 << 0),
170 HasLWake = (1 << 1),
173 typedef enum {
174 CH_8139 = 0,
175 CH_8139_K,
176 CH_8139A,
177 CH_8139A_G,
178 CH_8139B,
179 CH_8130,
180 CH_8139C,
181 CH_8100,
182 CH_8100B_8139D,
183 CH_8101,
184 } chip_t;
186 /* directly indexed by chip_t, above */
187 static const struct {
188 const char *name;
189 unsigned version; /* from RTL8139C/RTL8139D docs */
190 unsigned flags;
191 } rtl_chip_info[] = {
192 { "RTL-8139",
193 HW_REVID(1, 0, 0, 0, 0, 0, 0),
194 HasHltClk,
197 { "RTL-8139 rev K",
198 HW_REVID(1, 1, 0, 0, 0, 0, 0),
199 HasHltClk,
202 { "RTL-8139A",
203 HW_REVID(1, 1, 1, 0, 0, 0, 0),
204 HasHltClk, /* XXX undocumented? */
207 { "RTL-8139A rev G",
208 HW_REVID(1, 1, 1, 0, 0, 1, 0),
209 HasHltClk, /* XXX undocumented? */
212 { "RTL-8139B",
213 HW_REVID(1, 1, 1, 1, 0, 0, 0),
214 HasLWake,
217 { "RTL-8130",
218 HW_REVID(1, 1, 1, 1, 1, 0, 0),
219 HasLWake,
222 { "RTL-8139C",
223 HW_REVID(1, 1, 1, 0, 1, 0, 0),
224 HasLWake,
227 { "RTL-8100",
228 HW_REVID(1, 1, 1, 1, 0, 1, 0),
229 HasLWake,
232 { "RTL-8100B/8139D",
233 HW_REVID(1, 1, 1, 0, 1, 0, 1),
234 HasHltClk /* XXX undocumented? */
235 | HasLWake,
238 { "RTL-8101",
239 HW_REVID(1, 1, 1, 0, 1, 1, 1),
240 HasLWake,
244 /* rtl8139 device structure */
245 struct rtl8139_dev_t {
246 unsigned char irq;
247 pcidev_t *pcidev;
248 unsigned short addr_io;
249 mac_addr_t addr_mac;
250 char *txbuf;
251 char *rxbuf;
252 unsigned char txbn;
253 unsigned char txbn_last;
254 unsigned chipset;
257 struct rtl8139_dev_t *rtl8139_dev;
258 static netdev_t *ifdev;
260 /* prototypes */
261 unsigned rtl8139_start (struct rtl8139_dev_t *dev);
262 unsigned rtl8139_int_rx (struct rtl8139_dev_t *dev);
263 unsigned rtl8139_int_tx (struct rtl8139_dev_t *dev);
264 bool rtl8139_acthandler (unsigned act, char *block, unsigned block_len);
266 /* I/O operations */
267 unsigned char rtl8139_read8 (struct rtl8139_dev_t *dev, unsigned short port)
269 return inb (dev->addr_io + port);
272 void rtl8139_write8 (struct rtl8139_dev_t *dev, unsigned short port, unsigned char val)
274 outb (dev->addr_io + port, val);
277 unsigned short rtl8139_read16 (struct rtl8139_dev_t *dev, unsigned short port)
279 return inw (dev->addr_io + port);
282 void rtl8139_write16 (struct rtl8139_dev_t *dev, unsigned short port, unsigned short val)
284 outw (dev->addr_io + port, val);
287 unsigned rtl8139_read32 (struct rtl8139_dev_t *dev, unsigned short port)
289 return inl (dev->addr_io + port);
292 void rtl8139_write32 (struct rtl8139_dev_t *dev, unsigned short port, unsigned val)
294 outl (dev->addr_io + port, val);
297 /* READ/WRITE func */
298 unsigned rtl8139_read (char *buf, unsigned len)
300 return rtl8139_acthandler (DEV_ACT_READ, buf, len);
303 unsigned rtl8139_write (char *buf, unsigned len)
305 return rtl8139_acthandler (DEV_ACT_WRITE, buf, len);
309 /* Serial EEPROM section. */
310 static int rtl8139_eeprom_read (struct rtl8139_dev_t *dev, int location)
312 int i;
313 unsigned int retval = 0;
314 int read_cmd = location | RTL8139_EE_READ_CMD;
316 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB & ~RTL8139_EE_CS);
317 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
319 /* Shift the read command bits out. */
320 for (i = 10; i >= 0; i--) {
321 int dataval = (read_cmd & (1 << i)) ? RTL8139_EE_DATA_WRITE : 0;
323 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | dataval);
324 rtl8139_read8 (dev, RTL8139_CFG9346);
326 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | dataval | RTL8139_EE_SHIFT_CLK);
327 rtl8139_read8 (dev, RTL8139_CFG9346);
330 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
332 rtl8139_read8 (dev, RTL8139_CFG9346);
334 for (i = 16; i > 0; i --) {
335 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | RTL8139_EE_SHIFT_CLK);
336 rtl8139_read8 (dev, RTL8139_CFG9346);
338 retval = (retval << 1) | ((rtl8139_read8 (dev, RTL8139_CFG9346) & RTL8139_EE_DATA_READ) ? 1 : 0);
340 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
341 rtl8139_read8 (dev, RTL8139_CFG9346);
344 /* Terminate the EEPROM access. */
345 rtl8139_write8 (dev, RTL8139_CFG9346, ~RTL8139_EE_CS);
347 return retval;
350 /* detect rtl8139 device in PC */
351 pcidev_t *rtl8139_detect ()
353 /* First detect network card - is connected to PCI bus ?*/
354 pcidev_t *pcidev = pcidev_find (RTL8139_VENDORID, RTL8139_DEVICEID);
356 if (!pcidev)
357 return 0;
359 return pcidev;
362 /* reset rtl8139 device */
363 unsigned rtl8139_reset (struct rtl8139_dev_t *dev)
365 int i;
367 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RESET);
369 /* wait until chip is ready */
370 for (i = 0; i < 1000; i ++) {
371 if (!(rtl8139_read8 (dev, RTL8139_CHIPCMD) & RTL8139_CMD_RESET))
372 return 1;
374 /* 10ms timeout */
375 timer_wait (10);
378 kprintf ("ERROR -> waiting for rtl8139 reset\n");
380 return 0;
383 /* nic interrupt handler */
384 void rtl8139_int ()
386 //int_disable ();
388 struct rtl8139_dev_t *dev = rtl8139_dev;
390 unsigned short status = rtl8139_read16 (dev, RTL8139_INTRSTATUS);
392 // disable interrupts
393 rtl8139_write16 (dev, RTL8139_INTRMASK, 0);
395 rtl8139_write16 (dev, RTL8139_INTRSTATUS, status);
397 if (status & RTL8139_INT_RX_OK)
398 rtl8139_int_rx (dev);
400 if (status & RTL8139_INT_RX_ERR)
401 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> read error :(\n");
403 if(status & RTL8139_INT_RXBUF_OVERFLOW) {
404 rtl8139_write32 (dev, RTL8139_RXMISSED, 0);
405 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (rtl8139_read16 (dev, RTL8139_RXBUFHEAD)));
408 if (status & RTL8139_INT_TX_OK)
409 rtl8139_int_tx (dev);
411 if (status & RTL8139_INT_TX_ERR)
412 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> write error:(\n");
414 kprintf ("rtl8139 -> interrupt (0x%x)\n", status);
416 // reenable interrupts
417 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
419 //int_enable ();
422 /* rx descriptor structure */
423 typedef struct rx_entry {
424 volatile unsigned short status;
425 volatile unsigned short len;
426 volatile unsigned char data[1];
427 } rx_entry;
429 unsigned rtl8139_int_rx (struct rtl8139_dev_t *dev)
431 unsigned tail = TAILREG_TO_TAIL (rtl8139_read16 (dev, RTL8139_RXBUFTAIL));
433 rx_entry *entry = (rx_entry *)((unsigned char *) dev->rxbuf + tail);
435 if (!entry)
436 return 0;
438 unsigned len = 2048;
440 unsigned l = entry->len - 4; // minus the crc
442 if ((entry->status & RTL8139_RX_STATUS_OK) == 0) {
443 // error, lets reset the card
444 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139_rx () -> rx error");
446 // stop the rx and tx and mask all interrupts
447 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RESET);
448 rtl8139_write16 (dev, RTL8139_INTRMASK, 0x0);
450 // reset the rx pointers
451 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (0));
452 rtl8139_write16 (dev, RTL8139_RXBUFHEAD, 0x0);
454 // start it back up
455 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
457 // Enable RX/TX once more
458 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
459 return 0;
462 if (l > len) {
463 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139_rx () -> packet too large for buffer (len %d, buf_len %ld)\n", l, len);
464 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAILREG_TO_TAIL (rtl8139_read16 (dev, RTL8139_RXBUFHEAD)));
465 return 0;
468 if(tail + len > 0xffff) {
469 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> packet wraps around\n");
470 //netdev_rx_add_queue (ifdev, (char *) &entry->data[0], 0x10000 - (tail + 4));
471 //netdev_rx_add_queue (ifdev, (char *) dev->rxbuf, l - (0x10000 - (tail + 4)));
473 //memcpy (buf, (const void *) &entry->data[0], l - (0x10000 - (tail + 4)));
474 //memcpy ((unsigned char *) buf + 0x10000 - (tail + 4), (const void *) dev->rxbuf, len - (0x10000 - (tail + 4)));
475 } else {
476 netdev_rx_add_queue (ifdev, (char *) &entry->data[0], entry->len);
477 //memcpy (buf, (const void *) &entry->data[0], l);
480 // calculate the new tail
481 tail = ((tail + entry->len + 4 + 3) & ~3) % 0x10000;
483 //kprintf ("new tail at 0x%x, tailreg will say 0x%x\n", tail, TAIL_TO_TAILREG(tail));
485 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (tail));
487 if(tail != rtl8139_read16 (dev, RTL8139_RXBUFHEAD)) {
488 // we're at last one more packet behind
491 return l;
494 unsigned rtl8139_tx (struct rtl8139_dev_t *dev, char *buf, unsigned len)
496 /* copy our buffer to txbuf */
497 memcpy ((char *) (dev->txbuf + dev->txbn * 0x800), buf, len);
499 /* we need send crc too */
500 //len += 4;
502 /* ethernet min. packet length is 64 with crc */
503 if(len < 64)
504 len = 64;
506 rtl8139_write32 (dev, RTL8139_TXSTATUS0 + dev->txbn * 4, len | 0x80000);
508 if (++ dev->txbn >= 4)
509 dev->txbn = 0;
511 return 1;
514 unsigned rtl8139_int_tx (struct rtl8139_dev_t *dev)
516 unsigned i;
517 unsigned txstat;
519 for (i = 0; i < 4; i ++) {
520 if (i > 0 && dev->txbn_last == dev->txbn)
521 break;
523 txstat = rtl8139_read32 (dev, RTL8139_TXSTATUS0 + dev->txbn_last * 4);
525 kprintf ("txstat[%d] = 0x%x %u %u %u\n", dev->txbn_last, txstat, (txstat & RTL8139_TX_STATUS_OK) ? 1 : 0, (txstat & RTL8139_TX_UNDERRUN) ? 1 : 0, (txstat & RTL8139_TX_ABORTED) ? 1 : 0);
527 if((txstat & (RTL8139_TX_STATUS_OK | RTL8139_TX_UNDERRUN | RTL8139_TX_ABORTED)) == 0)
528 break;
530 if(++ dev->txbn_last >= 4)
531 dev->txbn_last = 0;
534 return 1;
537 /* INIT sequence */
538 unsigned init_rtl8139 ()
540 unsigned i = 0;
542 pcidev_t *pcidev = rtl8139_detect ();
544 if (!pcidev)
545 return 0;
547 struct rtl8139_dev_t *dev = (struct rtl8139_dev_t *) kmalloc (sizeof (struct rtl8139_dev_t));
549 if (!dev)
550 return 0;
552 /* get irq id */
553 dev->irq = pcidev->u.h0.interrupt_line;
554 dev->addr_io = pcidev->u.h0.base_registers[0] & ~3;
556 dev->txbn = 0;
557 dev->txbn_last = 0;
559 pci_device_enable (pcidev);
561 pci_device_adjust (pcidev);
563 /* reset device now */
564 //rtl8139_reset (dev);
566 // reset config1
567 rtl8139_write8 (dev, RTL8139_CONFIG1, 0x0);
569 /* go out from low-power mode */
570 rtl8139_write8 (dev, RTL8139_HLTCLK, 'R');
572 // check for broken hardware
573 unsigned respond = rtl8139_read32 (dev, RTL8139_TXCONFIG);
575 if (respond == 0xffffffff) {
576 kprintf ("rtl8139 -> Chip not respond, probably it's broken\n");
577 return 0;
580 /* get mac address from ethernet */
581 if (rtl8139_eeprom_read (dev, 0) != 0xffff) {
582 unsigned short m[3];
583 for (i = 0; i < 3; i ++)
584 m[i] = rtl8139_eeprom_read (dev, i + 7);
586 memcpy (dev->addr_mac, &m, sizeof (mac_addr_t));
587 } else {
588 for (i = 0; i < 6; i ++)
589 dev->addr_mac[i] = rtl8139_read8 (dev, RTL8139_IDR0 + i);
592 unsigned char speed10 = rtl8139_read8 (dev, RTL8139_MEDIASTATUS) & RTL8139_MSR_SPEED10;
593 unsigned short fullduplex = rtl8139_read16 (dev, RTL8139_MII_BMCR) & RTL8139_BMCR_FDUPLEX;
595 kprintf ("rtl8139 -> ethernet speed %sMbps %s-duplex\n", speed10 ? "10" : "100", fullduplex ? "full" : "half");
597 /* identify chip attached to board */
598 unsigned version = respond & HW_REVID_MASK;
599 for (i = 0; i < 10; i ++)
600 if (version == rtl_chip_info[i].version) {
601 dev->chipset = i;
602 break;
605 kprintf ("rtl8139 -> identified chip type as '%s'\n", rtl_chip_info[i].name);
607 rtl8139_dev = dev;
609 unsigned char r;
610 if (dev->chipset >= CH_8139B) {
611 unsigned char r2 = r = rtl8139_read8 (dev, RTL8139_CONFIG1);
613 if ((rtl_chip_info[dev->chipset].flags & HasLWake) && (r & RTL8139_PM_LWAKE))
614 r2 &= ~RTL8139_PM_LWAKE;
616 r2 |= RTL8139_PM_ENABLE;
618 if (r != r2) {
619 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
620 rtl8139_write8 (dev, RTL8139_CONFIG1, r);
621 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
624 if (rtl_chip_info[dev->chipset].flags & HasLWake) {
625 r = rtl8139_read8 (dev, RTL8139_CONFIG4);
626 if (r & RTL8139_PM_LWPTN) {
627 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
628 rtl8139_write8 (dev, RTL8139_CONFIG4, r & ~RTL8139_PM_LWPTN);
629 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
632 } else {
633 r = rtl8139_read8 (dev, RTL8139_CONFIG1);
634 r &= ~(RTL8139_PM_SLEEP | RTL8139_PM_PWRDN);
635 rtl8139_write8 (dev, RTL8139_CONFIG1, r);
638 /* reset device now */
639 rtl8139_reset (dev);
640 timer_wait (4000);
641 /* set interrupt vector */
642 irq_install_handler (dev->irq, rtl8139_int);
644 return rtl8139_start (dev);
647 unsigned rtl8139_start (struct rtl8139_dev_t *dev)
649 /* Put the chip into low-power mode. */
650 if (rtl_chip_info[dev->chipset].flags & HasHltClk)
651 rtl8139_write8 (dev, RTL8139_HLTCLK, 'R'); /* 'R' would leave the clock running. */
653 /* reset device now */
654 rtl8139_reset (dev);
656 // enable writing to the config registers
657 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
659 // reset config1
660 rtl8139_write8 (dev, RTL8139_CONFIG1, 0x0);
662 unsigned i;
663 for (i = 0; i < 6; i ++)
664 rtl8139_write8 (dev, RTL8139_IDR0 + i, dev->addr_mac[i]);
666 // enable rx and tx functions
667 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
669 // set rx fifo threashold to 256bytes
670 rtl8139_write32 (dev, RTL8139_RXCONFIG, 0x00009c00);/*RTL8139_RX_RBLEN0 | RTL8139_RX_MXDMA2 | RTL8139_RX_MXDMA1 |
671 RTL8139_RX_AB | RTL8139_RX_AM | RTL8139_RX_APM);*/
673 // set tx fifo threashold to 256bytes
674 rtl8139_write32 (dev, RTL8139_TXCONFIG, 0x03000400);/*RTL8139_TX_IFG0 | RTL8139_TX_IFG1 | RTL8139_TX_MXDMA2 |
675 RTL8139_TX_MXDMA1);*/
677 // disable lan-wake and set the driver-loaded bit
678 rtl8139_write8 (dev, RTL8139_CONFIG1, (rtl8139_read8 (dev, RTL8139_CONFIG1) & ~0x30) | 0x20);
680 // enable fifo auto-clear
681 rtl8139_write8 (dev, RTL8139_CONFIG4, rtl8139_read8 (dev, RTL8139_CONFIG4) | 0x80);
683 // enable receiving broadcast and physical packets
684 rtl8139_write32 (dev, RTL8139_RXCONFIG, rtl8139_read32 (dev, RTL8139_RXCONFIG) | 0x0000000f);
686 // go back to normal mode
687 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
689 // setup rx buffer
690 dev->rxbuf = (char *) 0x51000;
692 rtl8139_write32 (dev, RTL8139_RXBUF, (unsigned) dev->rxbuf);
694 // setup tx buffer
695 dev->txbuf = (char *) 0x59000;
697 rtl8139_write32 (dev, RTL8139_TXADDR0, (unsigned) dev->txbuf);
698 rtl8139_write32 (dev, RTL8139_TXADDR1, (unsigned) dev->txbuf + 2*1024);
699 rtl8139_write32 (dev, RTL8139_TXADDR2, (unsigned) dev->txbuf + 4*1024);
700 rtl8139_write32 (dev, RTL8139_TXADDR3, (unsigned) dev->txbuf + 6*1024);
702 // reset rx missed counter
703 rtl8139_write32 (dev, RTL8139_RXMISSED, 0x0);
705 // filter all multicast packets
706 rtl8139_write32 (dev, RTL8139_MAR0, 0x0);
707 rtl8139_write32 (dev, RTL8139_MAR0 + 4, 0x0);
709 // disable all multi-interrupts
710 rtl8139_write16 (dev, RTL8139_MULTIINTR, 0x0);
712 // enable rx and tx
713 unsigned char chipstatus = rtl8139_read8 (dev, RTL8139_CHIPCMD);
715 if (chipstatus & RTL8139_CMD_TX_ENABLE || chipstatus & RTL8139_CMD_RX_ENABLE)
716 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
718 //rtl8139_write8 (dev, RTL8139_CFG9346, 0);
720 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
722 /* create new network device */
723 ifdev = netdev_create (dev->addr_mac, &rtl8139_read, &rtl8139_write, dev->addr_io);
725 if (!ifdev)
726 return 0;
728 return 1;
731 bool rtl8139_acthandler (unsigned act, char *block, unsigned block_len)
733 switch (act) {
734 case DEV_ACT_INIT:
736 return init_rtl8139 ();
738 break;
739 case DEV_ACT_READ:
742 return 1;
744 break;
745 case DEV_ACT_WRITE:
747 return rtl8139_tx (rtl8139_dev, block, block_len);
749 break;
752 return 0;
754 #endif