1+ #include <stddef.h>
2+ #include <kernel/arch/x86_64/lapic.h>
3+ #include <kernel/arch/x86_64/idt.h>
4+ #include <kernel/arch/x86_64/io.h>
5+ #include <kernel/module.h>
6+ #include <kernel/printf.h>
7+ #include <kernel/mmu.h>
8+ #include <kernel/pci.h>
9+
10+ #define MAC (x ) (0x00 + x)
11+ #define RBSTART 0x30
12+ #define CMD 0x37
13+ #define IMR 0x3C
14+ #define TCR 0x44
15+ #define CONFIG_1 0x52
16+
17+ #define CR_RESET (1 << 4)
18+ #define CR_RE (1 << 2)
19+ #define CR_TE (1 << 3)
20+ #define CR_BUFE (1 << 5)
21+ #define CR_STA (1 << 6)
22+ #define CR_LOOPBACK (1 << 7)
23+
24+ #define ISR_ROK (1 << 0)
25+ #define ISR_TOK (1 << 2)
26+ #define ISR_RXERR (1 << 1)
27+ #define ISR_TXERR (1 << 3)
28+ #define ISR_RER (1 << 6)
29+ #define ISR_PUN (1 << 7)
30+ #define ISR_TER (1 << 8)
31+ #define ISR_RXOVW (1 << 9)
32+ #define ISR_CNT (1 << 10)
33+
34+ #define TCR_CRC_ENABLE (1 << 0)
35+ #define TCR_PAD_SHORT_FRAMES (1 << 1)
36+ #define TCR_COLLISION_TEST (1 << 2)
37+ #define TCR_AUTO_DEFER (1 << 3)
38+ #define TCR_LOOPBACK (1 << 7)
39+
40+ uint32_t ioaddr = 0 ;
41+ uint8_t mac [6 ] = {0 };
42+ void * rx_buffer = NULL ;
43+
44+ void rtl8139_irq_handler (struct registers * r ) {
45+ dprintf (LOG_INFO , "rtl8139 irq\n" );
46+ lapic_eoi ();
47+ }
48+
49+ int init () {
50+ struct pci_device * rtl_dev = pci_get_device_from_vendor (0x10ec , 0x8139 );
51+ if (!rtl_dev ) {
52+ dprintf (LOG_ERR , "%s:%d: No RTL8139 NIC found!\n" , __FILE__ , __LINE__ );
53+ return 1 ;
54+ }
55+
56+ pci_write (rtl_dev -> bus , rtl_dev -> device , rtl_dev -> function , 0x04 ,
57+ pci_read (rtl_dev -> bus , rtl_dev -> device , rtl_dev -> function , 0x04 ) | PCI_BUS_MASTER );
58+
59+ ioaddr = pci_read (rtl_dev -> bus , rtl_dev -> device , rtl_dev -> function , 0x10 ) & 0xFFFFFFFC ;
60+
61+ outb (ioaddr + CONFIG_1 , 0x00 );
62+ outb (ioaddr + CMD , 0x10 );
63+ while (inb (ioaddr + CMD ) & 0x10 );
64+ rx_buffer = mmu_alloc (ALIGN_UP (8192 + 16 + 1500 , PAGE_SIZE ) / PAGE_SIZE );
65+ outl (ioaddr + RBSTART , (uint32_t )(uintptr_t )rx_buffer );
66+ outw (ioaddr + 0x3C , ISR_TOK | ISR_ROK );
67+ outl (ioaddr + TCR , TCR_CRC_ENABLE | TCR_PAD_SHORT_FRAMES | TCR_COLLISION_TEST | TCR_AUTO_DEFER | TCR_LOOPBACK );
68+ outb (ioaddr + CMD , CR_RE | CR_TE );
69+
70+ mac [0 ] = inb (ioaddr + MAC (0 ));
71+ mac [1 ] = inb (ioaddr + MAC (1 ));
72+ mac [2 ] = inb (ioaddr + MAC (2 ));
73+ mac [3 ] = inb (ioaddr + MAC (3 ));
74+ mac [4 ] = inb (ioaddr + MAC (4 ));
75+ mac [5 ] = inb (ioaddr + MAC (5 ));
76+
77+ dprintf (LOG_INFO , "%s:%d: MAC address: %02x:%02x:%02x:%02x:%02x:%02x\n" , __FILE__ , __LINE__ , mac [0 ], mac [1 ], mac [2 ], mac [3 ], mac [4 ], mac [5 ]);
78+
79+ uint8_t irq = pci_read (rtl_dev -> bus , rtl_dev -> device , rtl_dev -> function , 0x3C ) & 0xFF ;
80+ dprintf (LOG_INFO , "%s:%d: registering handler for IRQ %u\n" , __FILE__ , __LINE__ , irq );
81+ irq_register (irq , rtl8139_irq_handler );
82+ return 0 ;
83+ }
84+
85+ int fini () {
86+ dprintf (LOG_INFO , "%s:%d: Goodbye!\n" , __FILE__ , __LINE__ );
87+ return 0 ;
88+ }
89+
90+ struct Module metadata = {
91+ .name = "RTL8139 driver" ,
92+ .init = init ,
93+ .fini = fini
94+ };
0 commit comments