1 ; =============================================================================
2 ; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2011 Return Infinity -- see LICENSE.TXT
6 ; =============================================================================
13 ; -----------------------------------------------------------------------------
14 ; Initialize an Intel 8254x NIC
15 ; IN: BL = Bus number of the Intel device
16 ; CL = Device/Slot number of the Intel device
23 ; Read BAR4, If BAR4 is all 0'z then we are using 32-bit addresses
25 ; Grab the Base I/O Address of the device
29 ; jc os_net_i8254x_init_pio
31 ; jc os_net_i8253x_init_64_bit
32 and eax, 0xFFFFFFF0 ; EAX now holds the Base Memory IO Address (clear the low 4 bits)
34 mov dword [os_NetIOBaseMem
], eax
36 ; Grab the IRQ of the device
37 mov dl, 0x0F ; Get device's IRQ number from PCI Register 15 (IRQ is bits 7-0)
39 mov [os_NetIRQ
], al ; AL holds the IRQ
41 ; Grab the MAC address
42 mov rsi
, [os_NetIOBaseMem
]
43 mov eax, [rsi
+0x5400] ; RAL
45 je os_net_i8254x_init_get_MAC_via_EPROM
53 mov eax, [rsi
+0x5404] ; RAH
57 jmp os_net_i8254x_init_done_MAC
59 os_net_i8254x_init_get_MAC_via_EPROM:
60 mov rsi
, [os_NetIOBaseMem
]
82 os_net_i8254x_init_done_MAC:
84 ; Enable the Network IRQ in the PIC
89 call os_net_i8254x_reset
97 ;os_net_i8254x_init_pio:
99 ; -----------------------------------------------------------------------------
102 ; -----------------------------------------------------------------------------
103 ; os_net_i8254x_reset - Reset an Intel 8254x NIC
105 ; OUT: Nothing, all registers preserved
107 mov rsi
, [os_NetIOBaseMem
]
111 mov [rsi
+I8254X_REG_IMC
], eax ; Disable all interrupt causes
112 mov eax, [rsi
+I8254X_REG_ICR
] ; Clear any pending interrupts
114 mov [rsi
+I8254X_REG_ITR
], eax ; Disable interrupt throttling logic
117 mov [rsi
+I8254X_REG_PBA
], eax ; PBA: set the RX buffer size to 48KB (TX buffer is calculated as 64-RX buffer)
120 mov [rsi
+I8254X_REG_TXCW
], eax ; TXCW: set ANE, TxConfigWord (Half/Full duplex, Next Page Request)
122 mov eax, [rsi
+I8254X_REG_CTRL
]
129 mov [rsi
+I8254X_REG_CTRL
], eax ; CTRL: clear LRST, set SLU and ASDE, clear RSTPHY, VME, and ILOS
132 add rdi
, 0x5200 ; MTA: reset
140 mov rax
, os_eth_rx_buffer
141 mov [rsi
+I8254X_REG_RDBAL
], eax ; Receive Descriptor Base Address Low
143 mov [rsi
+I8254X_REG_RDBAH
], eax ; Receive Descriptor Base Address High
145 mov [rsi
+I8254X_REG_RDLEN
], eax ; Receive Descriptor Length
147 mov [rsi
+I8254X_REG_RDH
], eax ; Receive Descriptor Head
149 mov [rsi
+I8254X_REG_RDT
], eax ; Receive Descriptor Tail
150 mov eax, 0x04008006 ; Receiver Enable, Store Bad Packets, Broadcast Accept Mode, Strip Ethernet CRC from incoming packet
151 mov [rsi
+I8254X_REG_RCTL
], eax ; Receive Control Register
154 mov rdi
, os_eth_rx_buffer
159 mov rax
, os_eth_tx_buffer
160 mov [rsi
+I8254X_REG_TDBAL
], eax ; Transmit Descriptor Base Address Low
162 mov [rsi
+I8254X_REG_TDBAH
], eax ; Transmit Descriptor Base Address High
164 mov [rsi
+I8254X_REG_TDLEN
], eax ; Transmit Descriptor Length
166 mov [rsi
+I8254X_REG_TDH
], eax ; Transmit Descriptor Head
167 mov [rsi
+I8254X_REG_TDT
], eax ; Transmit Descriptor Tail
168 mov eax, 0x010400FA ; Enabled, Pad Short Packets, 15 retrys, 64-byte COLD, Re-transmit on Late Collision
169 mov [rsi
+I8254X_REG_TCTL
], eax ; Transmit Control Register
170 mov eax, 0x0060200A ; IPGT 10, IPGR1 8, IPGR2 6
171 mov [rsi
+I8254X_REG_TIPG
], eax ; Transmit IPG Register
174 mov [rsi
+I8254X_REG_RDTR
], eax ; Clear the Receive Delay Timer Register
175 mov [rsi
+I8254X_REG_RADV
], eax ; Clear the Receive Interrupt Absolute Delay Timer
176 mov [rsi
+I8254X_REG_RSRPD
], eax ; Clear the Receive Small Packet Detect Interrupt
179 ; mov eax, 0x1FFFF ; Temp enable all interrupt types
180 mov [rsi
+I8254X_REG_IMS
], eax ; Enable interrupt types
183 ; -----------------------------------------------------------------------------
186 ; -----------------------------------------------------------------------------
187 ; os_net_i8254x_transmit - Transmit a packet via an Intel 8254x NIC
188 ; IN: RSI = Location of packet
189 ; RCX = Length of packet
191 ; Uses RAX, RCX, RSI, RDI
192 os_net_i8254x_transmit:
193 mov rdi
, os_eth_tx_buffer
; Transmit Descriptor Base Address
195 stosq
; Store the data location
196 mov rax
, rcx
; The packet size is in CL
201 mov rdi
, [os_NetIOBaseMem
]
203 mov [rdi
+I8254X_REG_TDH
], eax ; TDH - Transmit Descriptor Head
205 mov [rdi
+I8254X_REG_TDT
], eax ; TDL - Transmit Descriptor Tail
207 ; -----------------------------------------------------------------------------
210 ; -----------------------------------------------------------------------------
211 ; os_net_i8254x_poll - Polls the Intel 8254x NIC for a received packet
212 ; IN: RDI = Location to store packet
213 ; OUT: RCX = Length of packet
214 ; Uses RAX, RCX, RDX, RSI, RDI
217 mov cx, [os_eth_rx_buffer
+8] ; Get the packet length
222 mov rsi
, [os_NetIOBaseMem
]
224 mov [rsi
+I8254X_REG_RDH
], eax ; Receive Descriptor Head
226 mov [rsi
+I8254X_REG_RDT
], eax ; Receive Descriptor Tail
228 ; -----------------------------------------------------------------------------
231 ; -----------------------------------------------------------------------------
232 ; os_net_i8254x_ack_int - Acknowledge an internal interrupt of the Intel 8254x NIC
233 os_net_i8254x_ack_int:
234 mov rdi
, [os_NetIOBaseMem
]
235 mov eax, [rdi
+I8254X_REG_ICR
]
237 ; -----------------------------------------------------------------------------
240 ; Maximum packet size
241 I8254X_MAX_PKT_SIZE
equ 16384
244 I8254X_REG_CTRL
equ 0x0000 ; Control Register
245 I8254X_REG_STATUS
equ 0x0008 ; Device Status Register
246 I8254X_REG_CTRLEXT
equ 0x0018 ; Extended Control Register
247 I8254X_REG_MDIC
equ 0x0020 ; MDI Control Register
248 I8254X_REG_FCAL
equ 0x0028 ; Flow Control Address Low
249 I8254X_REG_FCAH
equ 0x002C ; Flow Control Address High
250 I8254X_REG_FCT
equ 0x0030 ; Flow Control Type
251 I8254X_REG_VET
equ 0x0038 ; VLAN Ether Type
252 I8254X_REG_ICR
equ 0x00C0 ; Interrupt Cause Read
253 I8254X_REG_ITR
equ 0x00C4 ; Interrupt Throttling Register
254 I8254X_REG_ICS
equ 0x00C8 ; Interrupt Cause Set Register
255 I8254X_REG_IMS
equ 0x00D0 ; Interrupt Mask Set/Read Register
256 I8254X_REG_IMC
equ 0x00D8 ; Interrupt Mask Clear Register
257 I8254X_REG_RCTL
equ 0x0100 ; Receive Control Register
258 I8254X_REG_FCTTV
equ 0x0170 ; Flow Control Transmit Timer Value
259 I8254X_REG_TXCW
equ 0x0178 ; Transmit Configuration Word
260 I8254X_REG_RXCW
equ 0x0180 ; Receive Configuration Word
261 I8254X_REG_TCTL
equ 0x0400 ; Transmit Control Register
262 I8254X_REG_TIPG
equ 0x0410 ; Transmit Inter Packet Gap
264 I8254X_REG_LEDCTL
equ 0x0E00 ; LED Control
265 I8254X_REG_PBA
equ 0x1000 ; Packet Buffer Allocation
267 I8254X_REG_RDBAL
equ 0x2800 ; RX Descriptor Base Address Low
268 I8254X_REG_RDBAH
equ 0x2804 ; RX Descriptor Base Address High
269 I8254X_REG_RDLEN
equ 0x2808 ; RX Descriptor Length
270 I8254X_REG_RDH
equ 0x2810 ; RX Descriptor Head
271 I8254X_REG_RDT
equ 0x2818 ; RX Descriptor Tail
272 I8254X_REG_RDTR
equ 0x2820 ; RX Delay Timer Register
273 I8254X_REG_RXDCTL
equ 0x3828 ; RX Descriptor Control
274 I8254X_REG_RADV
equ 0x282C ; RX Int. Absolute Delay Timer
275 I8254X_REG_RSRPD
equ 0x2C00 ; RX Small Packet Detect Interrupt
277 I8254X_REG_TXDMAC
equ 0x3000 ; TX DMA Control
278 I8254X_REG_TDBAL
equ 0x3800 ; TX Descriptor Base Address Low
279 I8254X_REG_TDBAH
equ 0x3804 ; TX Descriptor Base Address High
280 I8254X_REG_TDLEN
equ 0x3808 ; TX Descriptor Length
281 I8254X_REG_TDH
equ 0x3810 ; TX Descriptor Head
282 I8254X_REG_TDT
equ 0x3818 ; TX Descriptor Tail
283 I8254X_REG_TIDV
equ 0x3820 ; TX Interrupt Delay Value
284 I8254X_REG_TXDCTL
equ 0x3828 ; TX Descriptor Control
285 I8254X_REG_TADV
equ 0x382C ; TX Absolute Interrupt Delay Value
286 I8254X_REG_TSPMT
equ 0x3830 ; TCP Segmentation Pad & Min Threshold
288 I8254X_REG_RXCSUM
equ 0x5000 ; RX Checksum Control
290 ; Register list for i8254x
291 I82542_REG_RDTR
equ 0x0108 ; RX Delay Timer Register
292 I82542_REG_RDBAL
equ 0x0110 ; RX Descriptor Base Address Low
293 I82542_REG_RDBAH
equ 0x0114 ; RX Descriptor Base Address High
294 I82542_REG_RDLEN
equ 0x0118 ; RX Descriptor Length
295 I82542_REG_RDH
equ 0x0120 ; RDH for i82542
296 I82542_REG_RDT
equ 0x0128 ; RDT for i82542
297 I82542_REG_TDBAL
equ 0x0420 ; TX Descriptor Base Address Low
298 I82542_REG_TDBAH
equ 0x0424 ; TX Descriptor Base Address Low
299 I82542_REG_TDLEN
equ 0x0428 ; TX Descriptor Length
300 I82542_REG_TDH
equ 0x0430 ; TDH for i82542
301 I82542_REG_TDT
equ 0x0438 ; TDT for i82542
303 ; CTRL - Control Register (0x0000)
304 I8254X_CTRL_FD
equ 0x00000001 ; Full Duplex
305 I8254X_CTRL_LRST
equ 0x00000008 ; Link Reset
306 I8254X_CTRL_ASDE
equ 0x00000020 ; Auto-speed detection
307 I8254X_CTRL_SLU
equ 0x00000040 ; Set Link Up
308 I8254X_CTRL_ILOS
equ 0x00000080 ; Invert Loss of Signal
309 I8254X_CTRL_SPEED_MASK
equ 0x00000300 ; Speed selection
310 I8254X_CTRL_SPEED_SHIFT
equ 8
311 I8254X_CTRL_FRCSPD
equ 0x00000800 ; Force Speed
312 I8254X_CTRL_FRCDPLX
equ 0x00001000 ; Force Duplex
313 I8254X_CTRL_SDP0_DATA
equ 0x00040000 ; SDP0 data
314 I8254X_CTRL_SDP1_DATA
equ 0x00080000 ; SDP1 data
315 I8254X_CTRL_SDP0_IODIR
equ 0x00400000 ; SDP0 direction
316 I8254X_CTRL_SDP1_IODIR
equ 0x00800000 ; SDP1 direction
317 I8254X_CTRL_RST
equ 0x04000000 ; Device Reset
318 I8254X_CTRL_RFCE
equ 0x08000000 ; RX Flow Ctrl Enable
319 I8254X_CTRL_TFCE
equ 0x10000000 ; TX Flow Ctrl Enable
320 I8254X_CTRL_VME
equ 0x40000000 ; VLAN Mode Enable
321 I8254X_CTRL_PHY_RST
equ 0x80000000 ; PHY reset
323 ; STATUS - Device Status Register (0x0008)
324 I8254X_STATUS_FD
equ 0x00000001 ; Full Duplex
325 I8254X_STATUS_LU
equ 0x00000002 ; Link Up
326 I8254X_STATUS_TXOFF
equ 0x00000010 ; Transmit paused
327 I8254X_STATUS_TBIMODE
equ 0x00000020 ; TBI Mode
328 I8254X_STATUS_SPEED_MASK
equ 0x000000C0 ; Link Speed setting
329 I8254X_STATUS_SPEED_SHIFT
equ 6
330 I8254X_STATUS_ASDV_MASK
equ 0x00000300 ; Auto Speed Detection
331 I8254X_STATUS_ASDV_SHIFT
equ 8
332 I8254X_STATUS_PCI66
equ 0x00000800 ; PCI bus speed
333 I8254X_STATUS_BUS64
equ 0x00001000 ; PCI bus width
334 I8254X_STATUS_PCIX_MODE
equ 0x00002000 ; PCI-X mode
335 I8254X_STATUS_PCIXSPD_MASK
equ 0x0000C000 ; PCI-X speed
336 I8254X_STATUS_PCIXSPD_SHIFT
equ 14
338 ; CTRL_EXT - Extended Device Control Register (0x0018)
339 I8254X_CTRLEXT_PHY_INT
equ 0x00000020 ; PHY interrupt
340 I8254X_CTRLEXT_SDP6_DATA
equ 0x00000040 ; SDP6 data
341 I8254X_CTRLEXT_SDP7_DATA
equ 0x00000080 ; SDP7 data
342 I8254X_CTRLEXT_SDP6_IODIR
equ 0x00000400 ; SDP6 direction
343 I8254X_CTRLEXT_SDP7_IODIR
equ 0x00000800 ; SDP7 direction
344 I8254X_CTRLEXT_ASDCHK
equ 0x00001000 ; Auto-Speed Detect Chk
345 I8254X_CTRLEXT_EE_RST
equ 0x00002000 ; EEPROM reset
346 I8254X_CTRLEXT_SPD_BYPS
equ 0x00008000 ; Speed Select Bypass
347 I8254X_CTRLEXT_RO_DIS
equ 0x00020000 ; Relaxed Ordering Dis.
348 I8254X_CTRLEXT_LNKMOD_MASK
equ 0x00C00000 ; Link Mode
349 I8254X_CTRLEXT_LNKMOD_SHIFT
equ 22
351 ; MDIC - MDI Control Register (0x0020)
352 I8254X_MDIC_DATA_MASK
equ 0x0000FFFF ; Data
353 I8254X_MDIC_REG_MASK
equ 0x001F0000 ; PHY Register
354 I8254X_MDIC_REG_SHIFT
equ 16
355 I8254X_MDIC_PHY_MASK
equ 0x03E00000 ; PHY Address
356 I8254X_MDIC_PHY_SHIFT
equ 21
357 I8254X_MDIC_OP_MASK
equ 0x0C000000 ; Opcode
358 I8254X_MDIC_OP_SHIFT
equ 26
359 I8254X_MDIC_R
equ 0x10000000 ; Ready
360 I8254X_MDIC_I
equ 0x20000000 ; Interrupt Enable
361 I8254X_MDIC_E
equ 0x40000000 ; Error
363 ; ICR - Interrupt Cause Read (0x00c0)
364 I8254X_ICR_TXDW
equ 0x00000001 ; TX Desc Written back
365 I8254X_ICR_TXQE
equ 0x00000002 ; TX Queue Empty
366 I8254X_ICR_LSC
equ 0x00000004 ; Link Status Change
367 I8254X_ICR_RXSEQ
equ 0x00000008 ; RX Sequence Error
368 I8254X_ICR_RXDMT0
equ 0x00000010 ; RX Desc min threshold reached
369 I8254X_ICR_RXO
equ 0x00000040 ; RX Overrun
370 I8254X_ICR_RXT0
equ 0x00000080 ; RX Timer Interrupt
371 I8254X_ICR_MDAC
equ 0x00000200 ; MDIO Access Complete
372 I8254X_ICR_RXCFG
equ 0x00000400
373 I8254X_ICR_PHY_INT
equ 0x00001000 ; PHY Interrupt
374 I8254X_ICR_GPI_SDP6
equ 0x00002000 ; GPI on SDP6
375 I8254X_ICR_GPI_SDP7
equ 0x00004000 ; GPI on SDP7
376 I8254X_ICR_TXD_LOW
equ 0x00008000 ; TX Desc low threshold hit
377 I8254X_ICR_SRPD
equ 0x00010000 ; Small RX packet detected
379 ; RCTL - Receive Control Register (0x0100)
380 I8254X_RCTL_EN
equ 0x00000002 ; Receiver Enable
381 I8254X_RCTL_SBP
equ 0x00000004 ; Store Bad Packets
382 I8254X_RCTL_UPE
equ 0x00000008 ; Unicast Promiscuous Enabled
383 I8254X_RCTL_MPE
equ 0x00000010 ; Xcast Promiscuous Enabled
384 I8254X_RCTL_LPE
equ 0x00000020 ; Long Packet Reception Enable
385 I8254X_RCTL_LBM_MASK
equ 0x000000C0 ; Loopback Mode
386 I8254X_RCTL_LBM_SHIFT
equ 6
387 I8254X_RCTL_RDMTS_MASK
equ 0x00000300 ; RX Desc Min Threshold Size
388 I8254X_RCTL_RDMTS_SHIFT
equ 8
389 I8254X_RCTL_MO_MASK
equ 0x00003000 ; Multicast Offset
390 I8254X_RCTL_MO_SHIFT
equ 12
391 I8254X_RCTL_BAM
equ 0x00008000 ; Broadcast Accept Mode
392 I8254X_RCTL_BSIZE_MASK
equ 0x00030000 ; RX Buffer Size
393 I8254X_RCTL_BSIZE_SHIFT
equ 16
394 I8254X_RCTL_VFE
equ 0x00040000 ; VLAN Filter Enable
395 I8254X_RCTL_CFIEN
equ 0x00080000 ; CFI Enable
396 I8254X_RCTL_CFI
equ 0x00100000 ; Canonical Form Indicator Bit
397 I8254X_RCTL_DPF
equ 0x00400000 ; Discard Pause Frames
398 I8254X_RCTL_PMCF
equ 0x00800000 ; Pass MAC Control Frames
399 I8254X_RCTL_BSEX
equ 0x02000000 ; Buffer Size Extension
400 I8254X_RCTL_SECRC
equ 0x04000000 ; Strip Ethernet CRC
402 ; TCTL - Transmit Control Register (0x0400)
403 I8254X_TCTL_EN
equ 0x00000002 ; Transmit Enable
404 I8254X_TCTL_PSP
equ 0x00000008 ; Pad short packets
405 I8254X_TCTL_SWXOFF
equ 0x00400000 ; Software XOFF Transmission
407 ; PBA - Packet Buffer Allocation (0x1000)
408 I8254X_PBA_RXA_MASK
equ 0x0000FFFF ; RX Packet Buffer
409 I8254X_PBA_RXA_SHIFT
equ 0
410 I8254X_PBA_TXA_MASK
equ 0xFFFF0000 ; TX Packet Buffer
411 I8254X_PBA_TXA_SHIFT
equ 16
414 I8254X_FCT_TYPE_DEFAULT
equ 0x8808
416 ; === TX Descriptor fields ===
418 ; TX Packet Length (word 2)
419 I8254X_TXDESC_LEN_MASK
equ 0x0000ffff
421 ; TX Descriptor CMD field (word 2)
422 I8254X_TXDESC_IDE
equ 0x80000000 ; Interrupt Delay Enable
423 I8254X_TXDESC_VLE
equ 0x40000000 ; VLAN Packet Enable
424 I8254X_TXDESC_DEXT
equ 0x20000000 ; Extension
425 I8254X_TXDESC_RPS
equ 0x10000000 ; Report Packet Sent
426 I8254X_TXDESC_RS
equ 0x08000000 ; Report Status
427 I8254X_TXDESC_IC
equ 0x04000000 ; Insert Checksum
428 I8254X_TXDESC_IFCS
equ 0x02000000 ; Insert FCS
429 I8254X_TXDESC_EOP
equ 0x01000000 ; End Of Packet
431 ; TX Descriptor STA field (word 3)
432 I8254X_TXDESC_TU
equ 0x00000008 ; Transmit Underrun
433 I8254X_TXDESC_LC
equ 0x00000004 ; Late Collision
434 I8254X_TXDESC_EC
equ 0x00000002 ; Excess Collisions
435 I8254X_TXDESC_DD
equ 0x00000001 ; Descriptor Done
437 ; === RX Descriptor fields ===
439 ; RX Packet Length (word 2)
440 I8254X_RXDESC_LEN_MASK
equ 0x0000ffff
442 ; RX Descriptor STA field (word 3)
443 I8254X_RXDESC_PIF
equ 0x00000080 ; Passed In-exact Filter
444 I8254X_RXDESC_IPCS
equ 0x00000040 ; IP cksum calculated
445 I8254X_RXDESC_TCPCS
equ 0x00000020 ; TCP cksum calculated
446 I8254X_RXDESC_VP
equ 0x00000008 ; Packet is 802.1Q
447 I8254X_RXDESC_IXSM
equ 0x00000004 ; Ignore cksum indication
448 I8254X_RXDESC_EOP
equ 0x00000002 ; End Of Packet
449 I8254X_RXDESC_DD
equ 0x00000001 ; Descriptor Done
451 ; =============================================================================