1 ; =============================================================================
2 ; BareMetal -- a 64-bit OS written in Assembly for x86-64 systems
3 ; Copyright (C) 2008-2012 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
86 ; call interrupt_enable
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
218 mov cx, [os_eth_rx_buffer
+8] ; Get the packet length
223 mov rsi
, [os_NetIOBaseMem
]
225 mov [rsi
+I8254X_REG_RDH
], eax ; Receive Descriptor Head
227 mov [rsi
+I8254X_REG_RDT
], eax ; Receive Descriptor Tail
230 mov rdi
, os_eth_rx_buffer
236 ; -----------------------------------------------------------------------------
239 ; -----------------------------------------------------------------------------
240 ; os_net_i8254x_ack_int - Acknowledge an internal interrupt of the Intel 8254x NIC
241 os_net_i8254x_ack_int:
243 mov rdi
, [os_NetIOBaseMem
]
244 mov eax, [rdi
+I8254X_REG_ICR
]
246 ; -----------------------------------------------------------------------------
249 ; Maximum packet size
250 I8254X_MAX_PKT_SIZE
equ 16384
253 I8254X_REG_CTRL
equ 0x0000 ; Control Register
254 I8254X_REG_STATUS
equ 0x0008 ; Device Status Register
255 I8254X_REG_CTRLEXT
equ 0x0018 ; Extended Control Register
256 I8254X_REG_MDIC
equ 0x0020 ; MDI Control Register
257 I8254X_REG_FCAL
equ 0x0028 ; Flow Control Address Low
258 I8254X_REG_FCAH
equ 0x002C ; Flow Control Address High
259 I8254X_REG_FCT
equ 0x0030 ; Flow Control Type
260 I8254X_REG_VET
equ 0x0038 ; VLAN Ether Type
261 I8254X_REG_ICR
equ 0x00C0 ; Interrupt Cause Read
262 I8254X_REG_ITR
equ 0x00C4 ; Interrupt Throttling Register
263 I8254X_REG_ICS
equ 0x00C8 ; Interrupt Cause Set Register
264 I8254X_REG_IMS
equ 0x00D0 ; Interrupt Mask Set/Read Register
265 I8254X_REG_IMC
equ 0x00D8 ; Interrupt Mask Clear Register
266 I8254X_REG_RCTL
equ 0x0100 ; Receive Control Register
267 I8254X_REG_FCTTV
equ 0x0170 ; Flow Control Transmit Timer Value
268 I8254X_REG_TXCW
equ 0x0178 ; Transmit Configuration Word
269 I8254X_REG_RXCW
equ 0x0180 ; Receive Configuration Word
270 I8254X_REG_TCTL
equ 0x0400 ; Transmit Control Register
271 I8254X_REG_TIPG
equ 0x0410 ; Transmit Inter Packet Gap
273 I8254X_REG_LEDCTL
equ 0x0E00 ; LED Control
274 I8254X_REG_PBA
equ 0x1000 ; Packet Buffer Allocation
276 I8254X_REG_RDBAL
equ 0x2800 ; RX Descriptor Base Address Low
277 I8254X_REG_RDBAH
equ 0x2804 ; RX Descriptor Base Address High
278 I8254X_REG_RDLEN
equ 0x2808 ; RX Descriptor Length
279 I8254X_REG_RDH
equ 0x2810 ; RX Descriptor Head
280 I8254X_REG_RDT
equ 0x2818 ; RX Descriptor Tail
281 I8254X_REG_RDTR
equ 0x2820 ; RX Delay Timer Register
282 I8254X_REG_RXDCTL
equ 0x3828 ; RX Descriptor Control
283 I8254X_REG_RADV
equ 0x282C ; RX Int. Absolute Delay Timer
284 I8254X_REG_RSRPD
equ 0x2C00 ; RX Small Packet Detect Interrupt
286 I8254X_REG_TXDMAC
equ 0x3000 ; TX DMA Control
287 I8254X_REG_TDBAL
equ 0x3800 ; TX Descriptor Base Address Low
288 I8254X_REG_TDBAH
equ 0x3804 ; TX Descriptor Base Address High
289 I8254X_REG_TDLEN
equ 0x3808 ; TX Descriptor Length
290 I8254X_REG_TDH
equ 0x3810 ; TX Descriptor Head
291 I8254X_REG_TDT
equ 0x3818 ; TX Descriptor Tail
292 I8254X_REG_TIDV
equ 0x3820 ; TX Interrupt Delay Value
293 I8254X_REG_TXDCTL
equ 0x3828 ; TX Descriptor Control
294 I8254X_REG_TADV
equ 0x382C ; TX Absolute Interrupt Delay Value
295 I8254X_REG_TSPMT
equ 0x3830 ; TCP Segmentation Pad & Min Threshold
297 I8254X_REG_RXCSUM
equ 0x5000 ; RX Checksum Control
299 ; Register list for i8254x
300 I82542_REG_RDTR
equ 0x0108 ; RX Delay Timer Register
301 I82542_REG_RDBAL
equ 0x0110 ; RX Descriptor Base Address Low
302 I82542_REG_RDBAH
equ 0x0114 ; RX Descriptor Base Address High
303 I82542_REG_RDLEN
equ 0x0118 ; RX Descriptor Length
304 I82542_REG_RDH
equ 0x0120 ; RDH for i82542
305 I82542_REG_RDT
equ 0x0128 ; RDT for i82542
306 I82542_REG_TDBAL
equ 0x0420 ; TX Descriptor Base Address Low
307 I82542_REG_TDBAH
equ 0x0424 ; TX Descriptor Base Address Low
308 I82542_REG_TDLEN
equ 0x0428 ; TX Descriptor Length
309 I82542_REG_TDH
equ 0x0430 ; TDH for i82542
310 I82542_REG_TDT
equ 0x0438 ; TDT for i82542
312 ; CTRL - Control Register (0x0000)
313 I8254X_CTRL_FD
equ 0x00000001 ; Full Duplex
314 I8254X_CTRL_LRST
equ 0x00000008 ; Link Reset
315 I8254X_CTRL_ASDE
equ 0x00000020 ; Auto-speed detection
316 I8254X_CTRL_SLU
equ 0x00000040 ; Set Link Up
317 I8254X_CTRL_ILOS
equ 0x00000080 ; Invert Loss of Signal
318 I8254X_CTRL_SPEED_MASK
equ 0x00000300 ; Speed selection
319 I8254X_CTRL_SPEED_SHIFT
equ 8
320 I8254X_CTRL_FRCSPD
equ 0x00000800 ; Force Speed
321 I8254X_CTRL_FRCDPLX
equ 0x00001000 ; Force Duplex
322 I8254X_CTRL_SDP0_DATA
equ 0x00040000 ; SDP0 data
323 I8254X_CTRL_SDP1_DATA
equ 0x00080000 ; SDP1 data
324 I8254X_CTRL_SDP0_IODIR
equ 0x00400000 ; SDP0 direction
325 I8254X_CTRL_SDP1_IODIR
equ 0x00800000 ; SDP1 direction
326 I8254X_CTRL_RST
equ 0x04000000 ; Device Reset
327 I8254X_CTRL_RFCE
equ 0x08000000 ; RX Flow Ctrl Enable
328 I8254X_CTRL_TFCE
equ 0x10000000 ; TX Flow Ctrl Enable
329 I8254X_CTRL_VME
equ 0x40000000 ; VLAN Mode Enable
330 I8254X_CTRL_PHY_RST
equ 0x80000000 ; PHY reset
332 ; STATUS - Device Status Register (0x0008)
333 I8254X_STATUS_FD
equ 0x00000001 ; Full Duplex
334 I8254X_STATUS_LU
equ 0x00000002 ; Link Up
335 I8254X_STATUS_TXOFF
equ 0x00000010 ; Transmit paused
336 I8254X_STATUS_TBIMODE
equ 0x00000020 ; TBI Mode
337 I8254X_STATUS_SPEED_MASK
equ 0x000000C0 ; Link Speed setting
338 I8254X_STATUS_SPEED_SHIFT
equ 6
339 I8254X_STATUS_ASDV_MASK
equ 0x00000300 ; Auto Speed Detection
340 I8254X_STATUS_ASDV_SHIFT
equ 8
341 I8254X_STATUS_PCI66
equ 0x00000800 ; PCI bus speed
342 I8254X_STATUS_BUS64
equ 0x00001000 ; PCI bus width
343 I8254X_STATUS_PCIX_MODE
equ 0x00002000 ; PCI-X mode
344 I8254X_STATUS_PCIXSPD_MASK
equ 0x0000C000 ; PCI-X speed
345 I8254X_STATUS_PCIXSPD_SHIFT
equ 14
347 ; CTRL_EXT - Extended Device Control Register (0x0018)
348 I8254X_CTRLEXT_PHY_INT
equ 0x00000020 ; PHY interrupt
349 I8254X_CTRLEXT_SDP6_DATA
equ 0x00000040 ; SDP6 data
350 I8254X_CTRLEXT_SDP7_DATA
equ 0x00000080 ; SDP7 data
351 I8254X_CTRLEXT_SDP6_IODIR
equ 0x00000400 ; SDP6 direction
352 I8254X_CTRLEXT_SDP7_IODIR
equ 0x00000800 ; SDP7 direction
353 I8254X_CTRLEXT_ASDCHK
equ 0x00001000 ; Auto-Speed Detect Chk
354 I8254X_CTRLEXT_EE_RST
equ 0x00002000 ; EEPROM reset
355 I8254X_CTRLEXT_SPD_BYPS
equ 0x00008000 ; Speed Select Bypass
356 I8254X_CTRLEXT_RO_DIS
equ 0x00020000 ; Relaxed Ordering Dis.
357 I8254X_CTRLEXT_LNKMOD_MASK
equ 0x00C00000 ; Link Mode
358 I8254X_CTRLEXT_LNKMOD_SHIFT
equ 22
360 ; MDIC - MDI Control Register (0x0020)
361 I8254X_MDIC_DATA_MASK
equ 0x0000FFFF ; Data
362 I8254X_MDIC_REG_MASK
equ 0x001F0000 ; PHY Register
363 I8254X_MDIC_REG_SHIFT
equ 16
364 I8254X_MDIC_PHY_MASK
equ 0x03E00000 ; PHY Address
365 I8254X_MDIC_PHY_SHIFT
equ 21
366 I8254X_MDIC_OP_MASK
equ 0x0C000000 ; Opcode
367 I8254X_MDIC_OP_SHIFT
equ 26
368 I8254X_MDIC_R
equ 0x10000000 ; Ready
369 I8254X_MDIC_I
equ 0x20000000 ; Interrupt Enable
370 I8254X_MDIC_E
equ 0x40000000 ; Error
372 ; ICR - Interrupt Cause Read (0x00c0)
373 I8254X_ICR_TXDW
equ 0x00000001 ; TX Desc Written back
374 I8254X_ICR_TXQE
equ 0x00000002 ; TX Queue Empty
375 I8254X_ICR_LSC
equ 0x00000004 ; Link Status Change
376 I8254X_ICR_RXSEQ
equ 0x00000008 ; RX Sequence Error
377 I8254X_ICR_RXDMT0
equ 0x00000010 ; RX Desc min threshold reached
378 I8254X_ICR_RXO
equ 0x00000040 ; RX Overrun
379 I8254X_ICR_RXT0
equ 0x00000080 ; RX Timer Interrupt
380 I8254X_ICR_MDAC
equ 0x00000200 ; MDIO Access Complete
381 I8254X_ICR_RXCFG
equ 0x00000400
382 I8254X_ICR_PHY_INT
equ 0x00001000 ; PHY Interrupt
383 I8254X_ICR_GPI_SDP6
equ 0x00002000 ; GPI on SDP6
384 I8254X_ICR_GPI_SDP7
equ 0x00004000 ; GPI on SDP7
385 I8254X_ICR_TXD_LOW
equ 0x00008000 ; TX Desc low threshold hit
386 I8254X_ICR_SRPD
equ 0x00010000 ; Small RX packet detected
388 ; RCTL - Receive Control Register (0x0100)
389 I8254X_RCTL_EN
equ 0x00000002 ; Receiver Enable
390 I8254X_RCTL_SBP
equ 0x00000004 ; Store Bad Packets
391 I8254X_RCTL_UPE
equ 0x00000008 ; Unicast Promiscuous Enabled
392 I8254X_RCTL_MPE
equ 0x00000010 ; Xcast Promiscuous Enabled
393 I8254X_RCTL_LPE
equ 0x00000020 ; Long Packet Reception Enable
394 I8254X_RCTL_LBM_MASK
equ 0x000000C0 ; Loopback Mode
395 I8254X_RCTL_LBM_SHIFT
equ 6
396 I8254X_RCTL_RDMTS_MASK
equ 0x00000300 ; RX Desc Min Threshold Size
397 I8254X_RCTL_RDMTS_SHIFT
equ 8
398 I8254X_RCTL_MO_MASK
equ 0x00003000 ; Multicast Offset
399 I8254X_RCTL_MO_SHIFT
equ 12
400 I8254X_RCTL_BAM
equ 0x00008000 ; Broadcast Accept Mode
401 I8254X_RCTL_BSIZE_MASK
equ 0x00030000 ; RX Buffer Size
402 I8254X_RCTL_BSIZE_SHIFT
equ 16
403 I8254X_RCTL_VFE
equ 0x00040000 ; VLAN Filter Enable
404 I8254X_RCTL_CFIEN
equ 0x00080000 ; CFI Enable
405 I8254X_RCTL_CFI
equ 0x00100000 ; Canonical Form Indicator Bit
406 I8254X_RCTL_DPF
equ 0x00400000 ; Discard Pause Frames
407 I8254X_RCTL_PMCF
equ 0x00800000 ; Pass MAC Control Frames
408 I8254X_RCTL_BSEX
equ 0x02000000 ; Buffer Size Extension
409 I8254X_RCTL_SECRC
equ 0x04000000 ; Strip Ethernet CRC
411 ; TCTL - Transmit Control Register (0x0400)
412 I8254X_TCTL_EN
equ 0x00000002 ; Transmit Enable
413 I8254X_TCTL_PSP
equ 0x00000008 ; Pad short packets
414 I8254X_TCTL_SWXOFF
equ 0x00400000 ; Software XOFF Transmission
416 ; PBA - Packet Buffer Allocation (0x1000)
417 I8254X_PBA_RXA_MASK
equ 0x0000FFFF ; RX Packet Buffer
418 I8254X_PBA_RXA_SHIFT
equ 0
419 I8254X_PBA_TXA_MASK
equ 0xFFFF0000 ; TX Packet Buffer
420 I8254X_PBA_TXA_SHIFT
equ 16
423 I8254X_FCT_TYPE_DEFAULT
equ 0x8808
425 ; === TX Descriptor fields ===
427 ; TX Packet Length (word 2)
428 I8254X_TXDESC_LEN_MASK
equ 0x0000ffff
430 ; TX Descriptor CMD field (word 2)
431 I8254X_TXDESC_IDE
equ 0x80000000 ; Interrupt Delay Enable
432 I8254X_TXDESC_VLE
equ 0x40000000 ; VLAN Packet Enable
433 I8254X_TXDESC_DEXT
equ 0x20000000 ; Extension
434 I8254X_TXDESC_RPS
equ 0x10000000 ; Report Packet Sent
435 I8254X_TXDESC_RS
equ 0x08000000 ; Report Status
436 I8254X_TXDESC_IC
equ 0x04000000 ; Insert Checksum
437 I8254X_TXDESC_IFCS
equ 0x02000000 ; Insert FCS
438 I8254X_TXDESC_EOP
equ 0x01000000 ; End Of Packet
440 ; TX Descriptor STA field (word 3)
441 I8254X_TXDESC_TU
equ 0x00000008 ; Transmit Underrun
442 I8254X_TXDESC_LC
equ 0x00000004 ; Late Collision
443 I8254X_TXDESC_EC
equ 0x00000002 ; Excess Collisions
444 I8254X_TXDESC_DD
equ 0x00000001 ; Descriptor Done
446 ; === RX Descriptor fields ===
448 ; RX Packet Length (word 2)
449 I8254X_RXDESC_LEN_MASK
equ 0x0000ffff
451 ; RX Descriptor STA field (word 3)
452 I8254X_RXDESC_PIF
equ 0x00000080 ; Passed In-exact Filter
453 I8254X_RXDESC_IPCS
equ 0x00000040 ; IP cksum calculated
454 I8254X_RXDESC_TCPCS
equ 0x00000020 ; TCP cksum calculated
455 I8254X_RXDESC_VP
equ 0x00000008 ; Packet is 802.1Q
456 I8254X_RXDESC_IXSM
equ 0x00000004 ; Ignore cksum indication
457 I8254X_RXDESC_EOP
equ 0x00000002 ; End Of Packet
458 I8254X_RXDESC_DD
equ 0x00000001 ; Descriptor Done
460 ; =============================================================================