App inst fixed on invalid image file; App zinstall for ZDE works - we've got GUI...
[ZeXOS.git] / kernel / drivers / net / rtl8139 / rtl8139.c
blob61c384c051cbbce57e56839c8f628b9d01e8b512
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include <config.h>
23 #include <build.h>
25 #ifndef ARCH_i386
26 #undef CONFIG_DRV_RTL8139
27 #endif
29 #ifdef CONFIG_DRV_RTL8139
31 #include <system.h>
32 #include <string.h>
33 #include <arch/io.h>
34 #include <pci.h>
35 #include <task.h>
36 #include <net/eth.h>
37 #include <net/net.h>
39 /* PCI probe IDs */
40 #define RTL8139_VENDORID 0x10ec
41 #define RTL8139_DEVICEID 0x8139
43 /* RTL8139C register definitions */
44 #define RTL8139_IDR0 0x00 /* Mac address */
45 #define RTL8139_MAR0 0x08 /* Multicast filter */
46 #define RTL8139_TXSTATUS0 0x10 /* Transmit status (4 32bit regs) */
47 #define RTL8139_TXSTATUS1 0x14 /* Transmit status (4 32bit regs) */
48 #define RTL8139_TXSTATUS2 0x18 /* Transmit status (4 32bit regs) */
49 #define RTL8139_TXSTATUS3 0x1c /* Transmit status (4 32bit regs) */
50 #define RTL8139_TXADDR0 0x20 /* Tx descriptors (also 4 32bit) */
51 #define RTL8139_TXADDR1 0x24 /* Tx descriptors (also 4 32bit) */
52 #define RTL8139_TXADDR2 0x28 /* Tx descriptors (also 4 32bit) */
53 #define RTL8139_TXADDR3 0x2c /* Tx descriptors (also 4 32bit) */
54 #define RTL8139_RXBUF 0x30 /* Receive buffer start address */
55 #define RTL8139_RXEARLYCNT 0x34 /* Early Rx byte count */
56 #define RTL8139_RXEARLYSTATUS 0x36 /* Early Rx status */
57 #define RTL8139_CHIPCMD 0x37 /* Command register */
58 #define RTL8139_RXBUFTAIL 0x38 /* Current address of packet read (queue tail) */
59 #define RTL8139_RXBUFHEAD 0x3A /* Current buffer address (queue head) */
60 #define RTL8139_INTRMASK 0x3C /* Interrupt mask */
61 #define RTL8139_INTRSTATUS 0x3E /* Interrupt status */
62 #define RTL8139_TXCONFIG 0x40 /* Tx config */
63 #define RTL8139_RXCONFIG 0x44 /* Rx config */
64 #define RTL8139_TIMER 0x48 /* A general purpose counter */
65 #define RTL8139_RXMISSED 0x4C /* 24 bits valid, write clears */
66 #define RTL8139_CFG9346 0x50 /* 93C46 command register */
67 #define RTL8139_CONFIG0 0x51 /* Configuration reg 0 */
68 #define RTL8139_CONFIG1 0x52 /* Configuration reg 1 */
69 #define RTL8139_TIMERINT 0x54 /* Timer interrupt register (32 bits) */
70 #define RTL8139_MEDIASTATUS 0x58 /* Media status register */
71 #define RTL8139_CONFIG3 0x59 /* Config register 3 */
72 #define RTL8139_CONFIG4 0x5A /* Config register 4 */
73 #define RTL8139_HLTCLK 0x5B /* Halted Clock */
74 #define RTL8139_MULTIINTR 0x5C /* Multiple interrupt select */
75 #define RTL8139_MII_TSAD 0x60 /* Transmit status of all descriptors (16 bits) */
76 #define RTL8139_MII_BMCR 0x62 /* Basic Mode Control Register (16 bits) */
77 #define RTL8139_MII_BMSR 0x64 /* Basic Mode Status Register (16 bits) */
78 #define RTL8139_AS_ADVERT 0x66 /* Auto-negotiation advertisement reg (16 bits) */
79 #define RTL8139_AS_LPAR 0x68 /* Auto-negotiation link partner reg (16 bits) */
80 #define RTL8139_AS_EXPANSION 0x6A /* Auto-negotiation expansion reg (16 bits) */
82 /* RTL8193C command bits; or these together and write teh resulting value
83 into CHIPCMD to execute it. */
84 #define RTL8139_CMD_RESET 0x10
85 #define RTL8139_CMD_RX_ENABLE 0x08
86 #define RTL8139_CMD_TX_ENABLE 0x04
87 #define RTL8139_CMD_RX_BUF_EMPTY 0x01
89 /* RTL8139C interrupt status bits */
90 #define RTL8139_INT_PCIERR 0x8000 /* PCI Bus error */
91 #define RTL8139_INT_TIMEOUT 0x4000 /* Set when TCTR reaches TimerInt value */
92 #define RTL8139_INT_RXFIFO_OVERFLOW 0x0040 /* Rx FIFO overflow */
93 #define RTL8139_INT_RXFIFO_UNDERRUN 0x0020 /* Packet underrun / link change */
94 #define RTL8139_INT_RXBUF_OVERFLOW 0x0010 /* Rx BUFFER overflow */
95 #define RTL8139_INT_TX_ERR 0x0008
96 #define RTL8139_INT_TX_OK 0x0004
97 #define RTL8139_INT_RX_ERR 0x0002
98 #define RTL8139_INT_RX_OK 0x0001
100 /* RTL8139C transmit status bits */
101 #define RTL8139_TX_CARRIER_LOST 0x80000000 /* Carrier sense lost */
102 #define RTL8139_TX_ABORTED 0x40000000 /* Transmission aborted */
103 #define RTL8139_TX_OUT_OF_WINDOW 0x20000000 /* Out of window collision */
104 #define RTL8139_TX_CARRIER_HBEAT 0x10000000 /* not sure */
105 #define RTL8139_TX_STATUS_OK 0x00008000 /* Status ok: a good packet was transmitted */
106 #define RTL8139_TX_UNDERRUN 0x00004000 /* Transmit FIFO underrun */
107 #define RTL8139_TX_HOST_OWNS 0x00002000 /* Set to 1 when DMA operation is completed */
108 #define RTL8139_TX_SIZE_MASK 0x00001fff /* Descriptor size mask */
110 #define RTL8139_TX_IFG0 0x1000000
111 #define RTL8139_TX_IFG1 0x2000000
112 #define RTL8139_TX_MXDMA2 0x400
113 #define RTL8139_TX_MXDMA1 0x200
115 /* RTL8139C receive status bits */
116 #define RTL8139_RX_MULTICAST 0x00008000 /* Multicast packet */
117 #define RTL8139_RX_PAM 0x00004000 /* Physical address matched */
118 #define RTL8139_RX_BROADCAST 0x00002000 /* Broadcast address matched */
119 #define RTL8139_RX_BAD_SYMBOL 0x00000020 /* Invalid symbol in 100TX packet */
120 #define RTL8139_RX_RUNT 0x00000010 /* Packet size is <64 bytes */
121 #define RTL8139_RX_TOO_LONG 0x00000008 /* Packet size is >4K bytes */
122 #define RTL8139_RX_CRC_ERR 0x00000004 /* CRC error */
123 #define RTL8139_RX_FRAME_ALIGN 0x00000002 /* Frame alignment error */
124 #define RTL8139_RX_STATUS_OK 0x00000001 /* Status ok: a good packet was received */
126 #define RTL8139_RX_RBLEN0 0x800
127 #define RTL8139_RX_MXDMA2 0x400
128 #define RTL8139_RX_MXDMA1 0x200
129 #define RTL8139_RX_AB 0x8
130 #define RTL8139_RX_AM 0x4
131 #define RTL8139_RX_APM 0x2
133 #define RTL8139_BMCR_FDUPLEX 0x0100
134 #define RTL8139_MSR_SPEED10 0x08
136 #define RTL8139_PM_ENABLE 0x01
137 #define RTL8139_PM_LWAKE 0x10
138 #define RTL8139_PM_LWPTN (1 << 2)
139 #define RTL8139_PM_SLEEP (1 << 1)
140 #define RTL8139_PM_PWRDN (1 << 0)
142 /* EEPROM_Ctrl bits. */
143 #define RTL8139_EE_SHIFT_CLK 0x04 /* EEPROM shift clock. */
144 #define RTL8139_EE_CS 0x08 /* EEPROM chip select. */
145 #define RTL8139_EE_DATA_WRITE 0x02 /* EEPROM chip data in. */
146 #define RTL8139_EE_WRITE_0 0x00
147 #define RTL8139_EE_WRITE_1 0x02
148 #define RTL8139_EE_DATA_READ 0x01 /* EEPROM chip data out. */
149 #define RTL8139_EE_ENB (0x80 | RTL8139_EE_CS)
151 /* The EEPROM commands include the alway-set leading bit. */
152 #define RTL8139_EE_WRITE_CMD (5 << 6)
153 #define RTL8139_EE_READ_CMD (6 << 6)
154 #define RTL8139_EE_ERASE_CMD (7 << 6)
156 #define TAILREG_TO_TAIL(in) \
157 (unsigned short)(((unsigned)(in) + 16) % 0x10000)
159 #define TAIL_TO_TAILREG(in) \
160 (unsigned short)((unsigned)(in) - 16)
162 #define MYRT_INTS (RTL8139_INT_PCIERR | RTL8139_INT_RX_ERR | RTL8139_INT_RX_OK | \
163 RTL8139_INT_TX_ERR | RTL8139_INT_TX_OK | RTL8139_INT_RXBUF_OVERFLOW)
165 #define HW_REVID(b30, b29, b28, b27, b26, b23, b22) \
166 (b30<<30 | b29<<29 | b28<<28 | b27<<27 | b26<<26 | b23<<23 | b22<<22)
167 #define HW_REVID_MASK HW_REVID(1, 1, 1, 1, 1, 1, 1)
169 #define RTL8139_CONFIG3_MAGIC (1 << 5)
171 #define RTL8139_MULTIINTR_CLEAR 0xf000
173 enum chip_flags {
174 HasHltClk = (1 << 0),
175 HasLWake = (1 << 1),
178 typedef enum {
179 CH_8139 = 0,
180 CH_8139_K,
181 CH_8139A,
182 CH_8139A_G,
183 CH_8139B,
184 CH_8130,
185 CH_8139C,
186 CH_8100,
187 CH_8100B_8139D,
188 CH_8101,
189 } chip_t;
191 /* directly indexed by chip_t, above */
192 static const struct {
193 const char *name;
194 unsigned version; /* from RTL8139C/RTL8139D docs */
195 unsigned flags;
196 } rtl_chip_info[] = {
197 { "RTL-8139",
198 HW_REVID(1, 0, 0, 0, 0, 0, 0),
199 HasHltClk,
202 { "RTL-8139 rev K",
203 HW_REVID(1, 1, 0, 0, 0, 0, 0),
204 HasHltClk,
207 { "RTL-8139A",
208 HW_REVID(1, 1, 1, 0, 0, 0, 0),
209 HasHltClk, /* XXX undocumented? */
212 { "RTL-8139A rev G",
213 HW_REVID(1, 1, 1, 0, 0, 1, 0),
214 HasHltClk, /* XXX undocumented? */
217 { "RTL-8139B",
218 HW_REVID(1, 1, 1, 1, 0, 0, 0),
219 HasLWake,
222 { "RTL-8130",
223 HW_REVID(1, 1, 1, 1, 1, 0, 0),
224 HasLWake,
227 { "RTL-8139C",
228 HW_REVID(1, 1, 1, 0, 1, 0, 0),
229 HasLWake,
232 { "RTL-8100",
233 HW_REVID(1, 1, 1, 1, 0, 1, 0),
234 HasLWake,
237 { "RTL-8100B/8139D",
238 HW_REVID(1, 1, 1, 0, 1, 0, 1),
239 HasHltClk /* XXX undocumented? */
240 | HasLWake,
243 { "RTL-8101",
244 HW_REVID(1, 1, 1, 0, 1, 1, 1),
245 HasLWake,
249 /* rtl8139 device structure */
250 struct rtl8139_dev_t {
251 unsigned char irq;
252 pcidev_t *pcidev;
253 unsigned short addr_io;
254 mac_addr_t addr_mac;
255 char *txbuf;
256 char *rxbuf;
257 unsigned char txbn;
258 unsigned char txbn_last;
259 unsigned chipset;
262 struct rtl8139_dev_t *rtl8139_dev;
263 static netdev_t *ifdev;
265 /* prototypes */
266 unsigned rtl8139_start (struct rtl8139_dev_t *dev);
267 unsigned rtl8139_int_rx (struct rtl8139_dev_t *dev);
268 unsigned rtl8139_int_tx (struct rtl8139_dev_t *dev);
269 bool rtl8139_acthandler (unsigned act, char *block, unsigned block_len);
271 /* I/O operations */
272 unsigned char rtl8139_read8 (struct rtl8139_dev_t *dev, unsigned short port)
274 return inb (dev->addr_io + port);
277 void rtl8139_write8 (struct rtl8139_dev_t *dev, unsigned short port, unsigned char val)
279 outb (dev->addr_io + port, val);
282 unsigned short rtl8139_read16 (struct rtl8139_dev_t *dev, unsigned short port)
284 return inw (dev->addr_io + port);
287 void rtl8139_write16 (struct rtl8139_dev_t *dev, unsigned short port, unsigned short val)
289 outw (dev->addr_io + port, val);
292 unsigned rtl8139_read32 (struct rtl8139_dev_t *dev, unsigned short port)
294 return inl (dev->addr_io + port);
297 void rtl8139_write32 (struct rtl8139_dev_t *dev, unsigned short port, unsigned val)
299 outl (dev->addr_io + port, val);
302 /* READ/WRITE func */
303 unsigned rtl8139_read (char *buf, unsigned len)
305 return rtl8139_acthandler (DEV_ACT_READ, buf, len);
308 unsigned rtl8139_write (char *buf, unsigned len)
310 return rtl8139_acthandler (DEV_ACT_WRITE, buf, len);
314 /* Serial EEPROM section. */
315 static int rtl8139_eeprom_read (struct rtl8139_dev_t *dev, int location)
317 int i;
318 unsigned int retval = 0;
319 int read_cmd = location | RTL8139_EE_READ_CMD;
321 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB & ~RTL8139_EE_CS);
322 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
324 /* Shift the read command bits out. */
325 for (i = 10; i >= 0; i--) {
326 int dataval = (read_cmd & (1 << i)) ? RTL8139_EE_DATA_WRITE : 0;
328 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | dataval);
329 rtl8139_read8 (dev, RTL8139_CFG9346);
331 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | dataval | RTL8139_EE_SHIFT_CLK);
332 rtl8139_read8 (dev, RTL8139_CFG9346);
335 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
337 rtl8139_read8 (dev, RTL8139_CFG9346);
339 for (i = 16; i > 0; i --) {
340 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB | RTL8139_EE_SHIFT_CLK);
341 rtl8139_read8 (dev, RTL8139_CFG9346);
343 retval = (retval << 1) | ((rtl8139_read8 (dev, RTL8139_CFG9346) & RTL8139_EE_DATA_READ) ? 1 : 0);
345 rtl8139_write8 (dev, RTL8139_CFG9346, RTL8139_EE_ENB);
346 rtl8139_read8 (dev, RTL8139_CFG9346);
349 /* Terminate the EEPROM access. */
350 rtl8139_write8 (dev, RTL8139_CFG9346, ~RTL8139_EE_CS);
352 return retval;
355 /* detect rtl8139 device in PC */
356 pcidev_t *rtl8139_detect ()
358 /* First detect network card - is connected to PCI bus ?*/
359 pcidev_t *pcidev = pcidev_find (RTL8139_VENDORID, RTL8139_DEVICEID);
361 if (!pcidev)
362 return 0;
364 return pcidev;
367 /* reset rtl8139 device */
368 unsigned rtl8139_reset (struct rtl8139_dev_t *dev)
370 int i;
372 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RESET);
374 /* wait until chip is ready */
375 for (i = 0; i < 1000; i ++) {
376 if (!(rtl8139_read8 (dev, RTL8139_CHIPCMD) & RTL8139_CMD_RESET))
377 return 1;
379 /* 10ms timeout */
380 timer_wait (10);
383 kprintf ("ERROR -> waiting for rtl8139 reset\n");
385 return 0;
388 /* nic interrupt handler */
389 void rtl8139_int ()
391 //int_disable ();
393 struct rtl8139_dev_t *dev = rtl8139_dev;
395 unsigned short status = rtl8139_read16 (dev, RTL8139_INTRSTATUS);
397 // disable interrupts
398 rtl8139_write16 (dev, RTL8139_INTRMASK, 0);
400 rtl8139_write16 (dev, RTL8139_INTRSTATUS, status);
402 if (status & RTL8139_INT_RX_OK)
403 rtl8139_int_rx (dev);
405 if (status & RTL8139_INT_RX_ERR)
406 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> read error :(\n");
408 if(status & RTL8139_INT_RXBUF_OVERFLOW) {
409 rtl8139_write32 (dev, RTL8139_RXMISSED, 0);
410 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (rtl8139_read16 (dev, RTL8139_RXBUFHEAD)));
413 if (status & RTL8139_INT_TX_OK)
414 rtl8139_int_tx (dev);
416 if (status & RTL8139_INT_TX_ERR)
417 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> write error:(\n");
419 //kprintf ("rtl8139 -> interrupt (0x%x)\n", status);
421 // reenable interrupts
422 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
424 //int_enable ();
427 /* rx descriptor structure */
428 typedef struct rx_entry {
429 volatile unsigned short status;
430 volatile unsigned short len;
431 volatile unsigned char data[1];
432 } rx_entry;
434 unsigned rtl8139_int_rx (struct rtl8139_dev_t *dev)
436 unsigned tail = TAILREG_TO_TAIL (rtl8139_read16 (dev, RTL8139_RXBUFTAIL));
438 rx_entry *entry = (rx_entry *)((unsigned char *) dev->rxbuf + tail);
440 if (!entry)
441 return 0;
443 unsigned len = 2048;
445 unsigned l = entry->len - 4; // minus the crc
447 if ((entry->status & RTL8139_RX_STATUS_OK) == 0) {
448 // error, lets reset the card
449 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139_rx () -> rx error");
451 // stop the rx and tx and mask all interrupts
452 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RESET);
453 rtl8139_write16 (dev, RTL8139_INTRMASK, 0x0);
455 // reset the rx pointers
456 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (0));
457 rtl8139_write16 (dev, RTL8139_RXBUFHEAD, 0x0);
459 // start it back up
460 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
462 // Enable RX/TX once more
463 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
464 return 0;
467 if (l > len) {
468 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139_rx () -> packet too large for buffer (len %d, buf_len %ld)\n", l, len);
469 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAILREG_TO_TAIL (rtl8139_read16 (dev, RTL8139_RXBUFHEAD)));
470 return 0;
473 if(tail + len > 0xffff) {
474 DPRINT (DBG_DRIVER | DBG_ETH, "rtl8139 -> packet wraps around\n");
475 //netdev_rx_add_queue (ifdev, (char *) &entry->data[0], 0x10000 - (tail + 4));
476 //netdev_rx_add_queue (ifdev, (char *) dev->rxbuf, l - (0x10000 - (tail + 4)));
478 //memcpy (buf, (const void *) &entry->data[0], l - (0x10000 - (tail + 4)));
479 //memcpy ((unsigned char *) buf + 0x10000 - (tail + 4), (const void *) dev->rxbuf, len - (0x10000 - (tail + 4)));
480 } else {
481 netdev_rx_add_queue (ifdev, (char *) &entry->data[0], entry->len);
482 //memcpy (buf, (const void *) &entry->data[0], l);
485 // calculate the new tail
486 tail = ((tail + entry->len + 4 + 3) & ~3) % 0x10000;
488 //kprintf ("new tail at 0x%x, tailreg will say 0x%x\n", tail, TAIL_TO_TAILREG(tail));
490 rtl8139_write16 (dev, RTL8139_RXBUFTAIL, TAIL_TO_TAILREG (tail));
492 if(tail != rtl8139_read16 (dev, RTL8139_RXBUFHEAD)) {
493 // we're at last one more packet behind
496 return l;
499 unsigned rtl8139_tx (struct rtl8139_dev_t *dev, char *buf, unsigned len)
501 /* copy our buffer to txbuf */
502 memcpy ((char *) (dev->txbuf + dev->txbn * 0x800), buf, len);
504 /* we need send crc too */
505 //len += 4;
507 /* ethernet min. packet length is 64 with crc */
508 if(len < 64)
509 len = 64;
511 rtl8139_write32 (dev, RTL8139_TXSTATUS0 + dev->txbn * 4, len | 0x80000);
513 if (++ dev->txbn >= 4)
514 dev->txbn = 0;
516 return 1;
519 unsigned rtl8139_int_tx (struct rtl8139_dev_t *dev)
521 unsigned i;
522 unsigned txstat;
524 for (i = 0; i < 4; i ++) {
525 if (i > 0 && dev->txbn_last == dev->txbn)
526 break;
528 txstat = rtl8139_read32 (dev, RTL8139_TXSTATUS0 + dev->txbn_last * 4);
530 //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);
532 if((txstat & (RTL8139_TX_STATUS_OK | RTL8139_TX_UNDERRUN | RTL8139_TX_ABORTED)) == 0)
533 break;
535 if(++ dev->txbn_last >= 4)
536 dev->txbn_last = 0;
539 return 1;
542 /* INIT sequence */
543 unsigned init_rtl8139 ()
545 unsigned i = 0;
547 pcidev_t *pcidev = rtl8139_detect ();
549 if (!pcidev)
550 return 0;
552 struct rtl8139_dev_t *dev = (struct rtl8139_dev_t *) kmalloc (sizeof (struct rtl8139_dev_t));
554 if (!dev)
555 return 0;
557 /* get irq id */
558 dev->irq = pcidev->u.h0.interrupt_line;
559 dev->addr_io = pcidev->u.h0.base_registers[0] & ~3;
561 dev->txbn = 0;
562 dev->txbn_last = 0;
564 pci_device_enable (pcidev);
566 pci_device_adjust (pcidev);
568 /* reset device now */
569 //rtl8139_reset (dev);
571 // reset config1
572 //rtl8139_write8 (dev, RTL8139_CONFIG1, 0x0);
574 /* go out from low-power mode */
575 rtl8139_write8 (dev, RTL8139_HLTCLK, 'R');
577 // check for broken hardware
578 unsigned respond = rtl8139_read32 (dev, RTL8139_TXCONFIG);
580 if (respond == 0xffffffff) {
581 kprintf ("rtl8139 -> Chip not respond, probably it's broken\n");
582 return 0;
585 /* get mac address from ethernet */
586 if (rtl8139_eeprom_read (dev, 0) != 0xffff) {
587 unsigned short m[3];
588 for (i = 0; i < 3; i ++)
589 m[i] = rtl8139_eeprom_read (dev, i + 7);
591 memcpy (dev->addr_mac, &m, sizeof (mac_addr_t));
592 } else {
593 for (i = 0; i < 6; i ++)
594 dev->addr_mac[i] = rtl8139_read8 (dev, RTL8139_IDR0 + i);
597 unsigned char speed10 = rtl8139_read8 (dev, RTL8139_MEDIASTATUS) & RTL8139_MSR_SPEED10;
598 unsigned short fullduplex = rtl8139_read16 (dev, RTL8139_MII_BMCR) & RTL8139_BMCR_FDUPLEX;
600 kprintf ("rtl8139 -> ethernet speed %sMbps %s-duplex\n", speed10 ? "10" : "100", fullduplex ? "full" : "half");
602 /* identify chip attached to board */
603 unsigned version = respond & HW_REVID_MASK;
604 for (i = 0; i < 10; i ++)
605 if (version == rtl_chip_info[i].version) {
606 dev->chipset = i;
607 break;
610 kprintf ("rtl8139 -> identified chip type as '%s'\n", rtl_chip_info[i].name);
612 rtl8139_dev = dev;
614 unsigned char r;
615 if (dev->chipset >= CH_8139B) {
616 unsigned char r2 = r = rtl8139_read8 (dev, RTL8139_CONFIG1);
618 if ((rtl_chip_info[dev->chipset].flags & HasLWake) && (r & RTL8139_PM_LWAKE))
619 r2 &= ~RTL8139_PM_LWAKE;
621 r2 |= RTL8139_PM_ENABLE;
623 if (r != r2) {
624 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
625 rtl8139_write8 (dev, RTL8139_CONFIG1, r);
626 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
629 if (rtl_chip_info[dev->chipset].flags & HasLWake) {
630 r = rtl8139_read8 (dev, RTL8139_CONFIG4);
631 if (r & RTL8139_PM_LWPTN) {
632 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
633 rtl8139_write8 (dev, RTL8139_CONFIG4, r & ~RTL8139_PM_LWPTN);
634 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
637 } else {
638 r = rtl8139_read8 (dev, RTL8139_CONFIG1);
639 r &= ~(RTL8139_PM_SLEEP | RTL8139_PM_PWRDN);
640 rtl8139_write8 (dev, RTL8139_CONFIG1, r);
643 /* reset device now */
644 rtl8139_reset (dev);
646 /* Put the chip into low-power mode. */
647 if (rtl_chip_info[dev->chipset].flags & HasHltClk)
648 rtl8139_write8 (dev, RTL8139_HLTCLK, 'H'); /* 'R' would leave the clock running. */
650 /* set interrupt vector */
651 irq_install_handler (dev->irq, rtl8139_int);
653 return rtl8139_start (dev);
656 unsigned rtl8139_init_ring (struct rtl8139_dev_t *dev)
658 memset (dev->rxbuf, 0, 2048);
659 memset (dev->txbuf, 0, 4*2048);
661 return 1;
664 unsigned rtl8139_start (struct rtl8139_dev_t *dev)
666 dev->rxbuf = (char *) 0x63000;
667 dev->txbuf = (char *) 0x66000;
669 rtl8139_init_ring (dev);
671 /* Bring old chips out of low-power mode. */
672 if (rtl_chip_info[dev->chipset].flags & HasHltClk)
673 rtl8139_write8 (dev, RTL8139_HLTCLK, 'R');
675 /* reset device now */
676 rtl8139_reset (dev);
678 // enable writing to the config registers
679 rtl8139_write8 (dev, RTL8139_CFG9346, 0xc0);
681 // reset config1
682 //rtl8139_write8 (dev, RTL8139_CONFIG1, 0x0);
684 unsigned i;
685 for (i = 0; i < 6; i ++)
686 rtl8139_write8 (dev, RTL8139_IDR0 + i, dev->addr_mac[i]);
688 // enable rx and tx functions
689 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
691 // set rx fifo threashold to 256bytes
692 rtl8139_write32 (dev, RTL8139_RXCONFIG, 0x00009c00);/*RTL8139_RX_RBLEN0 | RTL8139_RX_MXDMA2 | RTL8139_RX_MXDMA1 |
693 RTL8139_RX_AB | RTL8139_RX_AM | RTL8139_RX_APM);*/
695 // set tx fifo threashold to 256bytes
696 rtl8139_write32 (dev, RTL8139_TXCONFIG, 0x03000400);/*RTL8139_TX_IFG0 | RTL8139_TX_IFG1 | RTL8139_TX_MXDMA2 |
697 RTL8139_TX_MXDMA1);*/
699 // disable lan-wake and set the driver-loaded bit
700 rtl8139_write8 (dev, RTL8139_CONFIG1, (rtl8139_read8 (dev, RTL8139_CONFIG1) & ~0x30) | 0x20);
702 // enable fifo auto-clear
703 rtl8139_write8 (dev, RTL8139_CONFIG4, rtl8139_read8 (dev, RTL8139_CONFIG4) | 0x80);
705 // enable receiving broadcast and physical packets
706 rtl8139_write32 (dev, RTL8139_RXCONFIG, rtl8139_read32 (dev, RTL8139_RXCONFIG) | 0x0000000f);
708 // setup rx buffer
709 rtl8139_write32 (dev, RTL8139_RXBUF, (unsigned) dev->rxbuf);
711 // go back to normal mode
712 rtl8139_write8 (dev, RTL8139_CFG9346, 0x0);
714 // setup tx buffer
715 rtl8139_write32 (dev, RTL8139_TXADDR0, (unsigned) dev->txbuf);
716 rtl8139_write32 (dev, RTL8139_TXADDR1, (unsigned) dev->txbuf + 2*1024);
717 rtl8139_write32 (dev, RTL8139_TXADDR2, (unsigned) dev->txbuf + 4*1024);
718 rtl8139_write32 (dev, RTL8139_TXADDR3, (unsigned) dev->txbuf + 6*1024);
720 // reset rx missed counter
721 rtl8139_write32 (dev, RTL8139_RXMISSED, 0x0);
723 // filter all multicast packets
724 rtl8139_write32 (dev, RTL8139_MAR0, 0x0);
725 rtl8139_write32 (dev, RTL8139_MAR0 + 4, 0x0);
727 // no early-rx interrupts
728 rtl8139_write16 (dev, RTL8139_MULTIINTR, rtl8139_read16 (dev, RTL8139_MULTIINTR) & RTL8139_MULTIINTR_CLEAR);
730 // enable rx and tx
731 unsigned char chipstatus = rtl8139_read8 (dev, RTL8139_CHIPCMD);
733 if (chipstatus & RTL8139_CMD_TX_ENABLE || chipstatus & RTL8139_CMD_RX_ENABLE)
734 rtl8139_write8 (dev, RTL8139_CHIPCMD, RTL8139_CMD_RX_ENABLE | RTL8139_CMD_TX_ENABLE);
736 if (dev->chipset >= CH_8139B) {
737 /* Disable magic packet scanning, which is enabled
738 * when PM is enabled in Config1. */
739 rtl8139_write8 (dev, RTL8139_CONFIG3, rtl8139_read8 (dev, RTL8139_CONFIG3) & ~RTL8139_CONFIG3_MAGIC);
742 rtl8139_write16 (dev, RTL8139_INTRMASK, MYRT_INTS);
744 /* create new network device */
745 ifdev = netdev_create (dev->addr_mac, &rtl8139_read, &rtl8139_write, dev->addr_io);
747 if (!ifdev)
748 return 0;
750 return 1;
753 bool rtl8139_acthandler (unsigned act, char *block, unsigned block_len)
755 switch (act) {
756 case DEV_ACT_INIT:
758 return init_rtl8139 ();
760 break;
761 case DEV_ACT_READ:
764 return 1;
766 break;
767 case DEV_ACT_WRITE:
769 return rtl8139_tx (rtl8139_dev, block, block_len);
771 break;
774 return 0;
776 #endif