* add p cc
[mascara-docs.git] / amd64 / bareMetalOS-0.5.3 / os / drivers / net / rtl8169.asm
blobc900fc3b84d1b27fe9e6494378d840f925e6fee1
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 ; =============================================================================
8 align 16
9 db 'DEBUG: RTL8169 '
10 align 16
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
17 os_net_rtl8169_init:
18 push rsi
19 push rdx
20 push rcx
21 push rax
23 ; Grab the Base I/O Address of the device
24 mov dl, 0x04 ; BAR0
25 call os_pci_read_reg
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)
31 call os_pci_read_reg
32 mov [os_NetIRQ], al ; AL holds the IRQ
34 ; Grab the MAC address
35 mov dx, word [os_NetIOAddress]
36 in al, dx
37 mov [os_NetMAC], al
38 add dx, 1
39 in al, dx
40 mov [os_NetMAC+1], al
41 add dx, 1
42 in al, dx
43 mov [os_NetMAC+2], al
44 add dx, 1
45 in al, dx
46 mov [os_NetMAC+3], al
47 add dx, 1
48 in al, dx
49 mov [os_NetMAC+4], al
50 add dx, 1
51 in al, dx
52 mov [os_NetMAC+5], al
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
57 ; mov bl, al
58 ; mov al, [os_NetIRQ]
59 ; mov dx, 0x21 ; Use the low byte pic
60 ; cmp al, 8
61 ; jl os_net_rtl8169_init_low
62 ; sub al, 8 ; IRQ 8-16
63 ; push ax
64 ; in al, 0xA1 ; High byte target 0xA1
65 ; mov bl, al
66 ; pop ax
67 ; mov dx, 0xA1 ; Use the high byte pic
68 ;os_net_rtl8169_init_low:
69 ; mov cl, al
70 ; mov al, 1
71 ; shl al, cl
72 ; not al
73 ; and al, bl
74 ; out dx, al
76 ; Reset the device
77 call os_net_rtl8169_reset
79 pop rax
80 pop rcx
81 pop rdx
82 pop rsi
83 ret
84 ; -----------------------------------------------------------------------------
87 ; -----------------------------------------------------------------------------
88 ; os_net_rtl8136_reset - Reset a Realtek 8169 NIC
89 ; IN: Nothing
90 ; OUT: Nothing, all registers preserved
91 os_net_rtl8169_reset:
92 push rdx
93 push rcx
94 push rax
96 mov dx, word [os_NetIOAddress]
97 add dx, RTL8169_REG_COMMAND
98 mov al, 0x10 ; Bit 4 set for Reset
99 out dx, al
100 mov cx, 1000 ; Wait no longer for the reset to complete
101 wait_for_8169_reset:
102 in al, dx
103 test al, 0x10
104 jz reset_8169_completed ; RST remains 1 during reset, Reset complete when 0
105 dec cx
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
113 out dx, al
115 ; Set the C+ Command
116 mov dx, word [os_NetIOAddress]
117 add dx, RTL8169_REG_CCR
118 in ax, dx
119 bts ax, 3 ; Enable PCI Multiple Read/Write
120 btc ax, 9 ; Little-endian mode
121 out dx, ax
123 ; Power management?
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)
129 out dx, eax
131 ; Set up TCR
132 mov dx, word [os_NetIOAddress]
133 add dx, RTL8169_REG_TCR
134 mov eax, 0x03000700
135 out dx, eax
137 ; Setup max RX size
138 mov dx, word [os_NetIOAddress]
139 add dx, RTL8169_REG_MAXRX
140 mov ax, 0x3FFF ; 16384 - 1
141 out dx, ax
143 ; Setup max TX size
144 mov dx, word [os_NetIOAddress]
145 add dx, RTL8169_REG_MAXTX
146 mov al, 0x3B
147 out dx, al
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
154 shr rax, 32
155 add dx, 4
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
165 shr rax, 32
166 add dx, 4
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)
178 mov eax, 0xFFFFFFFF
179 mov dx, word [os_NetIOAddress]
180 add dx, RTL8169_REG_MAR0
181 out dx, eax
182 add dx, 4 ; MAR4
183 out dx, eax
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)
189 out dx, al
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)
195 out dx, ax
197 ; Lock config register
198 mov dx, word [os_NetIOAddress]
199 add dx, RTL8169_REG_9346CR
200 mov al, 0x00 ; Lock
201 out dx, al
203 pop rax
204 pop rcx
205 pop rdx
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
214 ; OUT: Nothing
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
219 mov rax, rcx
220 stosw ; Store the frame length
221 add rdi, 6 ; Should the other data be cleared here?
222 mov rax, rsi
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
227 mov al, 0x40
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
243 os_net_rtl8169_poll:
244 xor ecx, ecx
245 mov cx, [os_eth_rx_buffer]
246 and cx, 0x3FFF ; Clear the two high bits as length is bits 13-0
247 cmp cx, 0x1FF8
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
253 push rcx
254 rep movsb ; Copy the packet to the lacation stored in RDI
255 pop rcx
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
273 in ax, dx
274 ; call os_debug_dump_ax ; Display the interrupt type
275 out dx, ax
276 shr eax, 2
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
330 ; PHY Register Table
331 ; BMCR (address 0x00)
332 RTL8169_BIT_ANE equ 12 ; Auto-Negotiation Enable
334 PHYConfig:
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
340 dd 0x800b0000
342 ; =============================================================================
343 ; EOF