1 ; =============================================================================
2 ; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2012 Return Infinity -- see LICENSE.TXT
5 ; Realtek 8169 NIC. http://wiki.osdev.org/RTL8169
6 ; =============================================================================
13 ; -----------------------------------------------------------------------------
14 ; Initialize a Realtek 8169 NIC
15 ; IN: BL = Bus number of the Realtek device
16 ; CL = Device/Slot number of the Realtek device
23 ; Grab the Base I/O Address of the device
26 and eax, 0xFFFFFFFC ; EAX now holds the Base IO Address (clear the low 2 bits)
27 mov word [os_NetIOAddress
], ax
29 ; Grab the IRQ of the device
30 mov dl, 0x0F ; Get device's IRQ number from PCI Register 15 (IRQ is bits 7-0)
32 mov [os_NetIRQ
], al ; AL holds the IRQ
34 ; Grab the MAC address
35 mov dx, word [os_NetIOAddress
]
54 ; Enable the Network IRQ in the PIC
55 ; IRQ value 0-7 set to zero bit 0-7 in 0x21 and value 8-15 set to zero bit 0-7 in 0xa1
56 ; in al, 0x21 ; low byte target 0x21
59 ; mov dx, 0x21 ; Use the low byte pic
61 ; jl os_net_rtl8169_init_low
62 ; sub al, 8 ; IRQ 8-16
64 ; in al, 0xA1 ; High byte target 0xA1
67 ; mov dx, 0xA1 ; Use the high byte pic
68 ;os_net_rtl8169_init_low:
77 call os_net_rtl8169_reset
84 ; -----------------------------------------------------------------------------
87 ; -----------------------------------------------------------------------------
88 ; os_net_rtl8136_reset - Reset a Realtek 8169 NIC
90 ; OUT: Nothing, all registers preserved
96 mov dx, word [os_NetIOAddress
]
97 add dx, RTL8169_REG_COMMAND
98 mov al, 0x10 ; Bit 4 set for Reset
100 mov cx, 1000 ; Wait no longer for the reset to complete
104 jz reset_8169_completed
; RST remains 1 during reset, Reset complete when 0
106 jns wait_for_8169_reset
107 reset_8169_completed:
109 ; Unlock config registers
110 mov dx, word [os_NetIOAddress
]
111 add dx, RTL8169_REG_9346CR
112 mov al, 0xC0 ; Unlock
116 mov dx, word [os_NetIOAddress
]
117 add dx, RTL8169_REG_CCR
119 bts ax, 3 ; Enable PCI Multiple Read/Write
120 btc ax, 9 ; Little-endian mode
125 ; Recieve configuration
126 mov dx, word [os_NetIOAddress
]
127 add edx, RTL8169_REG_RCR
128 mov eax, 0x0000E70A ; Set bits 1 (APM), 3 (AB), 8-10 (Unlimited), 13-15 (No limit)
132 mov dx, word [os_NetIOAddress
]
133 add dx, RTL8169_REG_TCR
138 mov dx, word [os_NetIOAddress
]
139 add dx, RTL8169_REG_MAXRX
140 mov ax, 0x3FFF ; 16384 - 1
144 mov dx, word [os_NetIOAddress
]
145 add dx, RTL8169_REG_MAXTX
149 ; Set the Transmit Normal Priority Descriptor Start Address
150 mov dx, word [os_NetIOAddress
]
151 add dx, RTL8169_REG_TNPDS
152 mov rax
, os_eth_tx_buffer
153 out dx, eax ; Write the low bits
156 out dx, eax ; Write the high bits
157 mov eax, 0x70000000 ; Set bit 30 (End of Descriptor Ring), 29 (FS), and 28 (LS)
158 mov [os_eth_tx_buffer
], eax
160 ; Set the Receive Descriptor Start Address
161 mov dx, word [os_NetIOAddress
]
162 add dx, RTL8169_REG_RDSAR
163 mov rax
, os_eth_rx_buffer
164 out dx, eax ; Write the low bits
167 out dx, eax ; Write the high bits
168 mov eax, 0x80001FF8 ; Set bits 31 (Ownership), also buffer size (Max 0x1FF8)
169 mov [os_eth_rx_buffer
], eax
170 mov rax
, os_ethernet_rx_buffer
171 mov [os_eth_rx_buffer
+8], rax
172 mov eax, 0xC0001FF8 ; Set bits 31 (Ownership) and 30 (End of Descriptor Ring), also buffer size (Max 0x1FF8)
173 mov [os_eth_rx_buffer
+16], eax
174 mov rax
, os_ethernet_rx_buffer
175 mov [os_eth_rx_buffer
+24], rax
177 ; Initialize multicast registers (no filtering)
179 mov dx, word [os_NetIOAddress
]
180 add dx, RTL8169_REG_MAR0
185 ; Enable Rx/Tx in the Command register
186 mov dx, word [os_NetIOAddress
]
187 add dx, RTL8169_REG_COMMAND
188 mov al, (1 << RTL8169_BIT_RE
) |
(1 << RTL8169_BIT_TE
) ;0x0C ; Set bits 2 (TE) and 3 (RE)
191 ; Enable Receive and Transmit interrupts
192 mov dx, word [os_NetIOAddress
]
193 add dx, RTL8169_REG_IMR
194 mov ax, 0x0005 ; Set bits 0 (RX OK) and 2 (TX OK)
197 ; Lock config register
198 mov dx, word [os_NetIOAddress
]
199 add dx, RTL8169_REG_9346CR
207 ; -----------------------------------------------------------------------------
210 ; -----------------------------------------------------------------------------
211 ; os_net_rtl8169_transmit - Transmit a packet via a Realtek 8169 NIC
212 ; IN: RSI = Location of packet
213 ; RCX = Length of packet
215 ; Uses RAX, RCX, RDX, RSI, RDI
216 ; ToDo: Check for proper timeout
217 os_net_rtl8169_transmit:
218 mov rdi
, os_eth_tx_buffer
220 stosw ; Store the frame length
221 add rdi
, 6 ; Should the other data be cleared here?
223 stosq
; Store the packet location
224 or dword [os_eth_tx_buffer
], 0xF0000000 ; Set bit 31 (OWN), 30 (EOR), 29 (FS), and 28 (LS)
225 mov dx, word [os_NetIOAddress
]
226 add dx, RTL8169_REG_TPPOLL
228 out dx, al ; Set up TX Polling
229 os_net_rtl8169_transmit_sendloop:
230 mov eax, [os_eth_tx_buffer
]
231 and eax, 0x80000000 ; Check the ownership bit (BT command instead?)
232 cmp eax, 0x80000000 ; If the ownership bit is clear then the NIC sent the packet
233 je os_net_rtl8169_transmit_sendloop
235 ; -----------------------------------------------------------------------------
238 ; -----------------------------------------------------------------------------
239 ; os_net_rtl8169_poll - Polls the Realtek 8169 NIC for a received packet
240 ; IN: RDI = Location to store packet
241 ; OUT: RCX = Length of packet
242 ; Uses RAX, RCX, RDX, RSI, RDI
245 mov cx, [os_eth_rx_buffer
]
246 and cx, 0x3FFF ; Clear the two high bits as length is bits 13-0
248 jne os_net_rtl8169_poll_first_descriptor
249 mov cx, [os_eth_rx_buffer
+16]
250 and cx, 0x3FFF ; Clear the two high bits as length is bits 13-0
251 os_net_rtl8169_poll_first_descriptor:
252 mov rsi
, os_ethernet_rx_buffer
254 rep movsb ; Copy the packet to the lacation stored in RDI
256 mov eax, 0x80001FF8 ; Set bits 31 (Ownership), also buffer size (Max 0x1FF8)
257 mov [os_eth_rx_buffer
], eax
258 mov rax
, os_ethernet_rx_buffer
259 mov [os_eth_rx_buffer
+8], rax
260 mov eax, 0xC0001FF8 ; Set bits 31 (Ownership) and 30 (End of Descriptor Ring), also buffer size (Max 0x1FF8)
261 mov [os_eth_rx_buffer
+16], eax
262 mov rax
, os_ethernet_rx_buffer
263 mov [os_eth_rx_buffer
+24], rax
265 ; -----------------------------------------------------------------------------
268 ; -----------------------------------------------------------------------------
269 ; os_net_rtl8169_ack_int - Acknowledge an internal interrupt of the Realtek 8169 NIC
270 os_net_rtl8169_ack_int:
271 mov dx, word [os_NetIOAddress
] ; Clear active interrupt sources
272 add dx, RTL8169_REG_ISR
274 ; call os_debug_dump_ax ; Display the interrupt type
278 ; -----------------------------------------------------------------------------
281 ; Register Descriptors
282 RTL8169_REG_IDR0
equ 0x00 ; ID Register 0
283 RTL8169_REG_IDR1
equ 0x01 ; ID Register 1
284 RTL8169_REG_IDR2
equ 0x02 ; ID Register 2
285 RTL8169_REG_IDR3
equ 0x03 ; ID Register 3
286 RTL8169_REG_IDR4
equ 0x04 ; ID Register 4
287 RTL8169_REG_IDR5
equ 0x05 ; ID Register 5
288 RTL8169_REG_MAR0
equ 0x08 ; Multicast Register 0
289 RTL8169_REG_MAR1
equ 0x09 ; Multicast Register 1
290 RTL8169_REG_MAR2
equ 0x0A ; Multicast Register 2
291 RTL8169_REG_MAR3
equ 0x0B ; Multicast Register 3
292 RTL8169_REG_MAR4
equ 0x0C ; Multicast Register 4
293 RTL8169_REG_MAR5
equ 0x0D ; Multicast Register 5
294 RTL8169_REG_MAR6
equ 0x0E ; Multicast Register 6
295 RTL8169_REG_MAR7
equ 0x0F ; Multicast Register 7
296 RTL8169_REG_TNPDS
equ 0x20 ; Transmit Normal Priority Descriptors: Start address (64-bit). (256-byte alignment)
297 RTL8169_REG_COMMAND
equ 0x37 ; Command Register
298 RTL8169_REG_TPPOLL
equ 0x38 ; Transmit Priority Polling Register
299 RTL8169_REG_IMR
equ 0x3C ; Interrupt Mask Register
300 RTL8169_REG_ISR
equ 0x3E ; Interrupt Status Register
301 RTL8169_REG_TCR
equ 0x40 ; Transmit (Tx) Configuration Register
302 RTL8169_REG_RCR
equ 0x44 ; Receive (Rx) Configuration Register
303 RTL8169_REG_9346CR
equ 0x50 ; 93C46 (93C56) Command Register
304 RTL8169_REG_CONFIG0
equ 0x51 ; Configuration Register 0
305 RTL8169_REG_CONFIG1
equ 0x52 ; Configuration Register 1
306 RTL8169_REG_CONFIG2
equ 0x53 ; Configuration Register 2
307 RTL8169_REG_CONFIG3
equ 0x54 ; Configuration Register 3
308 RTL8169_REG_CONFIG4
equ 0x55 ; Configuration Register 4
309 RTL8169_REG_CONFIG5
equ 0x56 ; Configuration Register 5
310 RTL8169_REG_PHYAR
equ 0x60 ; PHY Access Register
311 RTL8169_REG_PHYStatus
equ 0x6C ; PHY(GMII, MII, or TBI) Status Register
312 RTL8169_REG_MAXRX
equ 0xDA ; Mac Receive Packet Size Register
313 RTL8169_REG_CCR
equ 0xE0 ; C+ Command Register
314 RTL8169_REG_RDSAR
equ 0xE4 ; Receive Descriptor Start Address Register (256-byte alignment)
315 RTL8169_REG_MAXTX
equ 0xEC ; Max Transmit Packet Size Register
317 ; Command Register (Offset 0037h, R/W)
318 RTL8169_BIT_RST
equ 4 ; Reset
319 RTL8169_BIT_RE
equ 3 ; Receiver Enable
320 RTL8169_BIT_TE
equ 2 ; Transmitter Enable
322 ; Receive Configuration (Offset 0044h-0047h, R/W)
323 RTL8169_BIT_AER
equ 5 ; Accept Error
324 RTL8169_BIT_AR
equ 4 ; Accept Runt
325 RTL8169_BIT_AB
equ 3 ; Accept Broadcast Packets
326 RTL8169_BIT_AM
equ 2 ; Accept Multicast Packets
327 RTL8169_BIT_APM
equ 1 ; Accept Physical Match Packets
328 RTL8169_BIT_AAP
equ 0 ; Accept All Packets with Destination Address
331 ; BMCR (address 0x00)
332 RTL8169_BIT_ANE
equ 12 ; Auto-Negotiation Enable
335 dd 0x801f0001, 0x80151000, 0x801865c7, 0x80040000, 0x800300a1, 0x80020008, 0x80011020, 0x80001000
336 dd 0x80040800, 0x80040000, 0x80047000, 0x8003ff41, 0x8002de60, 0x80010140, 0x80000077, 0x80047800
337 dd 0x80047000, 0x8004a000, 0x8003df01, 0x8002df20, 0x8001ff95, 0x8000fa00, 0x8004a800, 0x8004a000
338 dd 0x8004b000, 0x8003ff41, 0x8002de20, 0x80010140, 0x800000bb, 0x8004b800, 0x8004b000, 0x8004f000
339 dd 0x8003df01, 0x8002df20, 0x8001ff95, 0x8000bf00, 0x8004f800, 0x8004f000, 0x80040000, 0x801f0000
342 ; =============================================================================