diff --git a/src/drivers.asm b/src/drivers.asm index 7c535c9..570e09c 100644 --- a/src/drivers.asm +++ b/src/drivers.asm @@ -29,7 +29,7 @@ %include "drivers/net/i8254x.asm" %include "drivers/net/i8257x.asm" %include "drivers/net/i8259x.asm" -%include "drivers/net/r8169.asm" +; %include "drivers/net/r8169.asm" %include "drivers/net/virtio-net.asm" ; Video @@ -129,13 +129,13 @@ dw 0x1572 ; X710 (SFP+) dw 0x0000 ; Realtek 816x/811x Gigabit Ethernet -dw 0x8169 ; Driver ID -dw 0x10EC ; Vendor ID -dw 0x8161 ; 8111/8168/8411 PCI Express -dw 0x8167 ; 8110SC/8169SC -dw 0x8168 ; 8111/8168/8211/8411 PCI Express -dw 0x8169 ; 8169 -dw 0x0000 +;dw 0x8169 ; Driver ID +;dw 0x10EC ; Vendor ID +;dw 0x8161 ; 8111/8168/8411 PCI Express +;dw 0x8167 ; 8110SC/8169SC +;dw 0x8168 ; 8111/8168/8211/8411 PCI Express +;dw 0x8169 ; 8169 +;dw 0x0000 ; End of list dw 0x0000 diff --git a/src/drivers/lfb/fonts/baremetal.fnt b/src/drivers/lfb/fonts/baremetal.fnt index 5b9a00f..911192f 100644 --- a/src/drivers/lfb/fonts/baremetal.fnt +++ b/src/drivers/lfb/fonts/baremetal.fnt @@ -192,11 +192,11 @@ db 00000000b db 00000000b db 00000000b db 00000000b +db 00000000b db 01000000b db 01000000b db 10000000b db 00000000b -db 00000000b ; - db 00000000b diff --git a/src/drivers/net/i8254x.asm b/src/drivers/net/i8254x.asm index f8f04d7..71b9041 100644 --- a/src/drivers/net/i8254x.asm +++ b/src/drivers/net/i8254x.asm @@ -10,16 +10,29 @@ ; Initialize an Intel 8254x NIC ; IN: RDX = Packed Bus address (as per syscalls/bus.asm) net_i8254x_init: + push rdi push rsi push rdx push rcx push rax + mov rdi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rdi, rax + + mov ax, 0x8254 ; Driver tag for i8254x + stosw + add rdi, 14 + ; Get the Base Memory Address of the device mov al, 0 ; Read BAR0 call os_bus_read_bar - mov [os_NetIOBaseMem], rax ; Save it as the base - mov [os_NetIOLength], rcx ; Save the length + stosq ; Save the base + push rax ; Save the base for gathering the MAC later + mov rax, rcx + stosq ; Save the length ; Set PCI Status/Command values mov dl, 0x01 ; Read Status/Command @@ -30,43 +43,74 @@ net_i8254x_init: call os_bus_write ; Write updated Status/Command ; Get the MAC address - mov rsi, [os_NetIOBaseMem] + pop rsi ; Restore the base + sub rdi, 24 ; 8 bytes into net table entry mov eax, [rsi+i8254x_RAL] ; RAL - mov [os_NetMAC], al + stosb shr eax, 8 - mov [os_NetMAC+1], al + stosb shr eax, 8 - mov [os_NetMAC+2], al + stosb shr eax, 8 - mov [os_NetMAC+3], al + stosb mov eax, [rsi+i8254x_RAH] ; RAH - mov [os_NetMAC+4], al + stosb shr eax, 8 - mov [os_NetMAC+5], al + stosb + + ; Set base addresses for TX and RX descriptors + xor ecx, ecx + mov cl, byte [os_net_icount] + shl ecx, 15 + + add rdi, 0x22 + mov rax, os_tx_desc + add rax, rcx + stosq + mov rax, os_rx_desc + add rax, rcx + stosq ; Reset the device + xor edx, edx + mov dl, [os_net_icount] call net_i8254x_reset + ; Store call addresses + sub rdi, 0x20 + mov rax, net_i8254x_transmit + stosq + mov rax, net_i8254x_poll + stosq + net_i8254x_init_error: pop rax pop rcx pop rdx pop rsi + pop rdi ret ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- ; net_i8254x_reset - Reset an Intel 8254x NIC -; IN: Nothing +; IN: RDX = Interface ID ; OUT: Nothing, all registers preserved net_i8254x_reset: push rdi push rsi push rax - mov rsi, [os_NetIOBaseMem] + ; Gather Base Address from net_table + mov rsi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rsi, rax + add rsi, 16 + mov rsi, [rsi] mov rdi, rsi ; Disable Interrupts @@ -110,8 +154,12 @@ net_i8254x_reset: ; Create RX descriptors push rdi mov ecx, i8254x_MAX_DESC + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 mov rdi, os_rx_desc -net_i8254x_reset_nextdesc: + add rdi, rax +net_i8254x_reset_nextdesc: mov rax, os_PacketBuffers ; Default packet will go here stosq xor eax, eax @@ -121,7 +169,10 @@ net_i8254x_reset_nextdesc: pop rdi ; Initialize receive - mov rax, os_rx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_rx_desc mov [rsi+i8254x_RDBAL], eax ; Receive Descriptor Base Address Low shr rax, 32 mov [rsi+i8254x_RDBAH], eax ; Receive Descriptor Base Address High @@ -135,7 +186,10 @@ net_i8254x_reset_nextdesc: mov [rsi+i8254x_RCTL], eax ; Receive Control Register ; Initialize transmit - mov rax, os_tx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_tx_desc mov [rsi+i8254x_TDBAL], eax ; Transmit Descriptor Base Address Low shr rax, 32 mov [rsi+i8254x_TDBAH], eax ; Transmit Descriptor Base Address High @@ -164,6 +218,7 @@ net_i8254x_reset_nextdesc: ; ----------------------------------------------------------------------------- ; net_i8254x_transmit - Transmit a packet via an Intel 8254x NIC ; IN: RSI = Location of packet +; RDX = Interface ID ; RCX = Length of packet ; OUT: Nothing ; Note: This driver uses the "legacy format" so TDESC.CMD.DEXT (5) is cleared to 0 @@ -182,10 +237,10 @@ net_i8254x_transmit: push rdi push rax - mov rdi, os_tx_desc ; Transmit Descriptor Base Address + mov rdi, [rdx+nt_tx_desc] ; Transmit Descriptor Base Address ; Calculate the descriptor to write to - mov eax, [i8254x_tx_lasttail] + mov eax, [rdx+nt_tx_tail] ; Get tx_lasttail push rax ; Save lasttail shl eax, 4 ; Quick multiply by 16 add rdi, rax ; Add offset to RDI @@ -203,8 +258,8 @@ net_i8254x_transmit: pop rax ; Restore lasttail add eax, 1 and eax, i8254x_MAX_DESC - 1 - mov [i8254x_tx_lasttail], eax - mov rdi, [os_NetIOBaseMem] + mov [rdx+nt_tx_tail], eax ; Set tx_lasttail + mov rdi, [rdx+nt_base] ; Load the base MMIO of the NIC mov [rdi+i8254x_TDT], eax ; TDL - Transmit Descriptor Tail pop rax @@ -216,6 +271,7 @@ net_i8254x_transmit: ; ----------------------------------------------------------------------------- ; net_i8254x_poll - Polls the Intel 8254x NIC for a received packet ; IN: RDI = Location to store packet +; RDX = Interface ID ; OUT: RCX = Length of packet ; Note: RDESC Descriptor Format: ; First Qword: @@ -231,11 +287,11 @@ net_i8254x_poll: push rsi ; Used for the base MMIO of the NIC push rax - mov rdi, os_rx_desc - mov rsi, [os_NetIOBaseMem] ; Load the base MMIO of the NIC + mov rdi, [rdx+nt_rx_desc] + mov rsi, [rdx+nt_base] ; Load the base MMIO of the NIC ; Calculate the descriptor to read from - mov eax, [i8254x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead shl eax, 4 ; Quick multiply by 16 add eax, 8 ; Offset to bytes received add rdi, rax ; Add offset to RDI @@ -249,10 +305,11 @@ net_i8254x_poll: stosq ; Clear the descriptor length and status ; Increment i8254x_rx_lasthead and the Receive Descriptor Tail - mov eax, [i8254x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead add eax, 1 and eax, i8254x_MAX_DESC - 1 - mov [i8254x_rx_lasthead], eax + mov [rdx+nt_rx_head], eax ; Set rx_lasthead + mov eax, [rsi+i8254x_RDT] ; Read the current Receive Descriptor Tail add eax, 1 ; Add 1 to the Receive Descriptor Tail and eax, i8254x_MAX_DESC - 1 @@ -288,10 +345,6 @@ net_i8254x_poll_end: ; ----------------------------------------------------------------------------- -; Variables -i8254x_tx_lasttail: dd 0 -i8254x_rx_lasthead: dd 0 - ; Constants i8254x_MAX_PKT_SIZE equ 16384 i8254x_MAX_DESC equ 16 ; Must be 16, 32, 64, 128, etc. diff --git a/src/drivers/net/i8257x.asm b/src/drivers/net/i8257x.asm index 4a4ac96..6b003fd 100644 --- a/src/drivers/net/i8257x.asm +++ b/src/drivers/net/i8257x.asm @@ -13,16 +13,29 @@ ; Initialize an Intel 8257x NIC ; IN: RDX = Packed Bus address (as per syscalls/bus.asm) net_i8257x_init: + push rdi push rsi push rdx push rcx push rax + mov rdi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rdi, rax + + mov ax, 0x8257 ; Driver tag for i8257x + stosw + add rdi, 14 + ; Get the Base Memory Address of the device mov al, 0 ; Read BAR0 call os_bus_read_bar - mov [os_NetIOBaseMem], rax ; Save it as the base - mov [os_NetIOLength], rcx ; Save the length + stosq ; Save the base + push rax ; Save the base for gathering the MAC later + mov rax, rcx + stosq ; Save the length ; Set PCI Status/Command values mov dl, 0x01 ; Read Status/Command @@ -33,29 +46,53 @@ net_i8257x_init: call os_bus_write ; Write updated Status/Command ; Get the MAC address - mov rsi, [os_NetIOBaseMem] + pop rsi ; Restore the base + sub rdi, 24 ; 8 bytes into net table entry mov eax, [rsi+i8257x_RAL] ; RAL - mov [os_NetMAC], al + stosb shr eax, 8 - mov [os_NetMAC+1], al + stosb shr eax, 8 - mov [os_NetMAC+2], al + stosb shr eax, 8 - mov [os_NetMAC+3], al + stosb mov eax, [rsi+i8257x_RAH] ; RAH - mov [os_NetMAC+4], al + stosb shr eax, 8 - mov [os_NetMAC+5], al + stosb + + ; Set base addresses for TX and RX descriptors + xor ecx, ecx + mov cl, byte [os_net_icount] + shl ecx, 15 + + add rdi, 0x22 + mov rax, os_tx_desc + add rax, rcx + stosq + mov rax, os_rx_desc + add rax, rcx + stosq ; Reset the device + xor edx, edx + mov dl, [os_net_icount] call net_i8257x_reset + ; Store call addresses + sub rdi, 0x20 + mov rax, net_i8257x_transmit + stosq + mov rax, net_i8257x_poll + stosq + net_i8257x_init_error: pop rax pop rcx pop rdx pop rsi + pop rdi ret ; ----------------------------------------------------------------------------- @@ -69,7 +106,14 @@ net_i8257x_reset: push rsi push rax - mov rsi, [os_NetIOBaseMem] + ; Gather Base Address from net_table + mov rsi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rsi, rax + add rsi, 16 + mov rsi, [rsi] mov rdi, rsi ; Disable Interrupts (14.4) @@ -114,7 +158,11 @@ net_i8257x_init_reset_wait: ; Create RX descriptors push rdi mov ecx, i8257x_MAX_DESC + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 mov rdi, os_rx_desc + add rdi, rax net_i8257x_reset_nextdesc: mov rax, os_PacketBuffers ; Default packet will go here stosq @@ -125,7 +173,10 @@ net_i8257x_reset_nextdesc: pop rdi ; Initialize receive (14.6) - mov rax, os_rx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_rx_desc mov [rsi+i8257x_RDBAL], eax ; Receive Descriptor Base Address Low shr rax, 32 mov [rsi+i8257x_RDBAH], eax ; Receive Descriptor Base Address High @@ -139,7 +190,10 @@ net_i8257x_reset_nextdesc: mov [rsi+i8257x_RCTL], eax ; Receive Control Register ; Initialize transmit (14.7) - mov rax, os_tx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_tx_desc mov [rsi+i8257x_TDBAL], eax ; Transmit Descriptor Base Address Low shr rax, 32 mov [rsi+i8257x_TDBAH], eax ; Transmit Descriptor Base Address High @@ -166,6 +220,7 @@ net_i8257x_reset_nextdesc: ; ----------------------------------------------------------------------------- ; net_i8257x_transmit - Transmit a packet via an Intel 8257x NIC ; IN: RSI = Location of packet +; RDX = Interface ID ; RCX = Length of packet ; OUT: Nothing ; Note: This driver uses the "legacy format" so TDESC.CMD.DEXT (5) is cleared to 0 @@ -184,10 +239,10 @@ net_i8257x_transmit: push rdi push rax - mov rdi, os_tx_desc ; Transmit Descriptor Base Address + mov rdi, [rdx+nt_tx_desc] ; Transmit Descriptor Base Address ; Calculate the descriptor to write to - mov eax, [i8257x_tx_lasttail] + mov eax, [rdx+nt_tx_tail] ; Get tx_lasttail push rax ; Save lasttail shl eax, 4 ; Quick multiply by 16 add rdi, rax ; Add offset to RDI @@ -205,8 +260,8 @@ net_i8257x_transmit: pop rax ; Restore lasttail add eax, 1 and eax, i8257x_MAX_DESC - 1 - mov [i8257x_tx_lasttail], eax - mov rdi, [os_NetIOBaseMem] + mov [rdx+nt_tx_tail], eax ; Set tx_lasttail + mov rdi, [rdx+nt_base] ; Load the base MMIO of the NIC mov [rdi+i8257x_TDT], eax ; TDL - Transmit Descriptor Tail pop rax @@ -218,6 +273,7 @@ net_i8257x_transmit: ; ----------------------------------------------------------------------------- ; net_i8257x_poll - Polls the Intel 8257x NIC for a received packet ; IN: RDI = Location to store packet +; RDX = Interface ID ; OUT: RCX = Length of packet ; Note: RDESC Descriptor Format: ; First Qword: @@ -233,11 +289,11 @@ net_i8257x_poll: push rsi ; Used for the base MMIO of the NIC push rax - mov rdi, os_rx_desc - mov rsi, [os_NetIOBaseMem] ; Load the base MMIO of the NIC + mov rdi, [rdx+nt_rx_desc] + mov rsi, [rdx+nt_base] ; Load the base MMIO of the NIC ; Calculate the descriptor to read from - mov eax, [i8257x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead shl eax, 4 ; Quick multiply by 16 add eax, 8 ; Offset to bytes received add rdi, rax ; Add offset to RDI @@ -251,10 +307,11 @@ net_i8257x_poll: stosq ; Clear the descriptor length and status ; Increment i8257x_rx_lasthead and the Receive Descriptor Tail - mov eax, [i8257x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead add eax, 1 and eax, i8257x_MAX_DESC - 1 - mov [i8257x_rx_lasthead], eax + mov [rdx+nt_rx_head], eax ; Set rx_lasthead + mov eax, [rsi+i8257x_RDT] ; Read the current Receive Descriptor Tail add eax, 1 ; Add 1 to the Receive Descriptor Tail and eax, i8257x_MAX_DESC - 1 @@ -274,10 +331,6 @@ net_i8257x_poll_end: ; ----------------------------------------------------------------------------- -; Variables -i8257x_tx_lasttail: dd 0 -i8257x_rx_lasthead: dd 0 - ; Constants i8257x_MAX_PKT_SIZE equ 16384 i8257x_MAX_DESC equ 16 ; Must be 16, 32, 64, 128, etc. diff --git a/src/drivers/net/i8259x.asm b/src/drivers/net/i8259x.asm index ad00a7e..c1b2c1f 100644 --- a/src/drivers/net/i8259x.asm +++ b/src/drivers/net/i8259x.asm @@ -10,16 +10,29 @@ ; Initialize an Intel 8259x NIC ; IN: RDX = Packed Bus address (as per syscalls/bus.asm) net_i8259x_init: + push rdi push rsi push rdx push rcx push rax + mov rdi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rdi, rax + + mov ax, 0x8259 ; Driver tag for i8259x + stosw + add rdi, 14 + ; Get the Base Memory Address of the device mov al, 0 ; Read BAR0 call os_bus_read_bar - mov [os_NetIOBaseMem], rax ; Save it as the base - mov [os_NetIOLength], rcx ; Save the length + stosq ; Save the base + push rax ; Save the base for gathering the MAC later + mov rax, rcx + stosq ; Save the length ; Set PCI Status/Command values mov dl, 0x01 ; Read Status/Command @@ -30,29 +43,53 @@ net_i8259x_init: call os_bus_write ; Write updated Status/Command ; Get the MAC address - mov rsi, [os_NetIOBaseMem] + pop rsi ; Restore the base + sub rdi, 24 ; 8 bytes into net table entry mov eax, [rsi+i8259x_RAL] ; RAL - mov [os_NetMAC], al + stosb shr eax, 8 - mov [os_NetMAC+1], al + stosb shr eax, 8 - mov [os_NetMAC+2], al + stosb shr eax, 8 - mov [os_NetMAC+3], al + stosb mov eax, [rsi+i8259x_RAH] ; RAH - mov [os_NetMAC+4], al + stosb shr eax, 8 - mov [os_NetMAC+5], al + stosb + + ; Set base addresses for TX and RX descriptors + xor ecx, ecx + mov cl, byte [os_net_icount] + shl ecx, 15 + + add rdi, 0x22 + mov rax, os_tx_desc + add rax, rcx + stosq + mov rax, os_rx_desc + add rax, rcx + stosq ; Reset the device + xor edx, edx + mov dl, [os_net_icount] call net_i8259x_reset + ; Store call addresses + sub rdi, 0x20 + mov rax, net_i8259x_transmit + stosq + mov rax, net_i8259x_poll + stosq + net_i8259x_init_error: pop rax pop rcx pop rdx pop rsi + pop rdi ret ; ----------------------------------------------------------------------------- @@ -62,10 +99,19 @@ net_i8259x_init_error: ; IN: Nothing ; OUT: Nothing, all registers preserved net_i8259x_reset: + push rdi push rsi push rax - mov rsi, [os_NetIOBaseMem] + ; Gather Base Address from net_table + mov rsi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rsi, rax + add rsi, 16 + mov rsi, [rsi] + mov rdi, rsi ; Disable Interrupts (4.6.3.1) xor eax, eax @@ -138,7 +184,11 @@ net_i8259x_reset_dma_wait: ; Create RX descriptors push rdi mov ecx, i8259x_MAX_DESC + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 mov rdi, os_rx_desc + add rdi, rax net_i8259x_reset_nextdesc: mov rax, os_PacketBuffers ; Default packet will go here stosq @@ -181,7 +231,10 @@ net_i8259x_reset_nextdesc: bts eax, 28 ; i8259x_SRRCTL_DROP_EN mov [rsi+i8259x_SRRCTL], eax ; Set up RX descriptor ring 0 - mov rax, os_rx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_rx_desc mov [rsi+i8259x_RDBAL], eax shr rax, 32 mov [rsi+i8259x_RDBAH], eax @@ -254,7 +307,10 @@ net_i8259x_init_rx_enable_wait: btc eax, i8259x_RTTDCS_ARBDIS mov [rsi+i8259x_RTTDCS], eax ; Set up TX descriptor ring 0 - mov rax, os_tx_desc + xor eax, eax + mov al, byte [os_net_icount] + shl eax, 15 + add rax, os_tx_desc mov [rsi+i8259x_TDBAL], eax ; Bits 6:0 are ignored, memory alignment at 128bytes shr rax, 32 mov [rsi+i8259x_TDBAH], eax @@ -288,21 +344,21 @@ net_i8259x_init_tx_enable_wait: ; or eax, 0x80000000 ; GPIE_PBA_SUPPORT ; or eax, 0x40000000 ; GPIE_EIAME ; mov [rsi+0x00898], eax ; Set Ixgbe_GPIE - + ; ; Step 2:- We don't use the minimum threshold interrupt - + ; ; Step 3:- ; mov eax, 0x0000FFFF ; mov [rsi+i8259x_EIAC], eax ; ; Step 4:- In our case we prefer to not auto-mask the interrupts ; ; TODO- Set EITR - + ; ; Step 5:- ; mov eax, [rsi+i8259x_EIMS] ; or eax, 0x00000001 ; mov [rsi+i8259x_EIMS], eax - + ; DEBUG - Enable Promiscuous mode mov eax, [rsi+i8259x_FCTRL] @@ -316,6 +372,7 @@ net_i8259x_init_tx_enable_wait: pop rax pop rsi + pop rdi ret ; ----------------------------------------------------------------------------- @@ -323,6 +380,7 @@ net_i8259x_init_tx_enable_wait: ; ----------------------------------------------------------------------------- ; net_i8259x_transmit - Transmit a packet via an Intel 8259x NIC ; IN: RSI = Location of packet +; RDX = Interface ID ; RCX = Length of packet ; OUT: Nothing ; Note: Transmit Descriptor (TDESC) Layout - Legacy Mode (7.2.3.2.2): @@ -333,10 +391,10 @@ net_i8259x_transmit: push rdi push rax - mov rdi, os_tx_desc ; Transmit Descriptor Base Address + mov rdi, [rdx+nt_tx_desc] ; Transmit Descriptor Base Address ; Calculate the descriptor to write to - mov eax, [i8259x_tx_lasttail] + mov eax, [rdx+nt_tx_tail] ; Get tx_lasttail push rax ; Save lasttail shl eax, 4 ; Quick multiply by 16 add rdi, rax ; Add offset to RDI @@ -354,8 +412,8 @@ net_i8259x_transmit: pop rax ; Restore lasttail add eax, 1 and eax, i8259x_MAX_DESC - 1 - mov [i8259x_tx_lasttail], eax - mov rdi, [os_NetIOBaseMem] + mov [rdx+nt_tx_tail], eax ; Set tx_lasttail + mov rdi, [rdx+nt_base] ; Load the base MMIO of the NIC mov [rdi+i8259x_TDT], eax ; TDL - Transmit Descriptor Tail ; TDESC.STA.DD (bit 32) should be 1 once the hardware has sent the packet @@ -369,6 +427,7 @@ net_i8259x_transmit: ; ----------------------------------------------------------------------------- ; net_i8259x_poll - Polls the Intel 8259x NIC for a received packet ; IN: RDI = Location to store packet +; RDX = Interface ID ; OUT: RCX = Length of packet ; Note: Receive Descriptor (RDESC) Layout - Legacy Mode (7.1.5): ; Bits 63:0 - Buffer Address @@ -379,11 +438,11 @@ net_i8259x_poll: push rsi ; Used for the base MMIO of the NIC push rax - mov rdi, os_rx_desc - mov rsi, [os_NetIOBaseMem] ; Load the base MMIO of the NIC + mov rdi, [rdx+nt_rx_desc] + mov rsi, [rdx+nt_base] ; Load the base MMIO of the NIC ; Calculate the descriptor to read from - mov eax, [i8259x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead shl eax, 4 ; Quick multiply by 16 add eax, 8 ; Offset to bytes received add rdi, rax ; Add offset to RDI @@ -397,10 +456,11 @@ net_i8259x_poll: stosq ; Clear the descriptor length and status ; Increment i8259x_rx_lasthead and the Receive Descriptor Tail - mov eax, [i8259x_rx_lasthead] + mov eax, [rdx+nt_rx_head] ; Get rx_lasthead add eax, 1 and eax, i8259x_MAX_DESC - 1 - mov [i8259x_rx_lasthead], eax + mov [rdx+nt_rx_head], eax ; Set rx_lasthead + mov eax, [rsi+i8259x_RDT] ; Read the current Receive Descriptor Tail add eax, 1 ; Add 1 to the Receive Descriptor Tail and eax, i8259x_MAX_DESC - 1 @@ -420,10 +480,6 @@ net_i8259x_poll_end: ; ----------------------------------------------------------------------------- -; Variables -i8259x_tx_lasttail: dd 0 -i8259x_rx_lasthead: dd 0 - ; Constants i8259x_MAX_PKT_SIZE equ 16384 i8259x_MAX_DESC equ 4096 ; Must be 16, 32, 64, 128, etc. diff --git a/src/drivers/net/r8169.asm b/src/drivers/net/r8169.asm index 8ed7f94..618af4c 100644 --- a/src/drivers/net/r8169.asm +++ b/src/drivers/net/r8169.asm @@ -15,11 +15,22 @@ net_r8169_init: push rcx push rax + mov rdi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rdi, rax + + mov ax, 0x8169 ; Driver tag for r8169 + stosw + add rdi, 14 + ; Get the Base I/O Address of the device mov dl, 0x04 ; BAR0 call os_bus_read and eax, 0xFFFFFFFC ; EAX now holds the Base IO Address (clear the low 2 bits) - mov word [os_NetIOAddress], ax + stosq ; Save the base + push rdx ; Set PCI Status/Command values mov dl, 0x01 ; Read Status/Command @@ -30,28 +41,51 @@ net_r8169_init: call os_bus_write ; Write updated Status/Command ; Get the MAC address - mov dx, word [os_NetIOAddress] + pop rdx + sub rdi, 16 in al, dx - mov [os_NetMAC], al + stosb inc dx in al, dx - mov [os_NetMAC+1], al + stosb inc dx in al, dx - mov [os_NetMAC+2], al + stosb inc dx in al, dx - mov [os_NetMAC+3], al + stosb inc dx in al, dx - mov [os_NetMAC+4], al + stosb inc dx in al, dx - mov [os_NetMAC+5], al + stosb + + ; Set base addresses for TX and RX descriptors + xor ecx, ecx + mov cl, byte [os_net_icount] + shl ecx, 15 + + add rdi, 0x22 + mov rax, os_tx_desc + add rax, rcx + stosq + mov rax, os_rx_desc + add rax, rcx + stosq ; Reset the device + xor edx, edx + mov dl, [os_net_icount] call net_r8169_reset + ; Store call addresses + sub rdi, 0x20 + mov rax, net_r8169_transmit + stosq + mov rax, net_r8169_poll + stosq + pop rax pop rcx pop rdx @@ -61,7 +95,7 @@ net_r8169_init: ; ----------------------------------------------------------------------------- -; os_net_rtl8136_reset - Reset a Realtek 8169 NIC +; os_net_r8169_reset - Reset a Realtek 8169 NIC ; IN: Nothing ; OUT: Nothing, all registers preserved net_r8169_reset: diff --git a/src/drivers/net/virtio-net.asm b/src/drivers/net/virtio-net.asm index dc8e250..99cc951 100644 --- a/src/drivers/net/virtio-net.asm +++ b/src/drivers/net/virtio-net.asm @@ -10,17 +10,31 @@ ; Initialize a Virtio NIC ; IN: RDX = Packed Bus address (as per syscalls/bus.asm) net_virtio_init: + push rdi push rsi push rdx push rcx push rbx push rax + mov rdi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rdi, rax + + mov ax, 0x1AF4 ; Driver tag for virtio-net + stosw + push rdi ; Used in msi-x init + add rdi, 14 + ; Get the Base Memory Address of the device mov al, 4 ; Read BAR4 call os_bus_read_bar - mov [os_NetIOBaseMem], rax ; Save it as the base - mov [os_NetIOLength], rcx ; Save the length + stosq ; Save the base + push rax ; Save the base for gathering the MAC later + mov rax, rcx + stosq ; Save the length ; Set PCI Status/Command values mov dl, 0x01 ; Read Status/Command @@ -159,36 +173,51 @@ virtio_net_init_cap_next_offset: virtio_net_init_cap_end: ; Get the MAC address - mov rsi, [os_NetIOBaseMem] + pop rsi ; Pushed as RAX + pop rdi + add rdi, 6 ; nt_MAC add rsi, [virtio_net_device_offset] - lodsb - mov [os_NetMAC], al - lodsb - mov [os_NetMAC+1], al - lodsb - mov [os_NetMAC+2], al - lodsb - mov [os_NetMAC+3], al - lodsb - mov [os_NetMAC+4], al - lodsb - mov [os_NetMAC+5], al + mov ecx, 6 + rep movsb + + ; Set base addresses for TX and RX descriptors + xor ecx, ecx + mov cl, byte [os_net_icount] + shl ecx, 15 + add rdi, 0x22 + mov rax, os_tx_desc + add rax, rcx + stosq + mov rax, os_rx_desc + add rax, rcx + stosq + ; Reset the device + xor edx, edx + mov dl, [os_net_icount] call net_virtio_reset + ; Store call addresses + sub rdi, 0x20 + mov rax, net_virtio_transmit + stosq + mov rax, net_virtio_poll + stosq + virtio_net_init_error: pop rax pop rbx pop rcx pop rdx pop rsi + pop rdi ret ; ----------------------------------------------------------------------------- ; ----------------------------------------------------------------------------- ; net_virtio_reset - Reset a Virtio NIC -; IN: Nothing +; IN: RDX = Interface ID ; OUT: Nothing, all registers preserved net_virtio_reset: push rdi @@ -198,7 +227,15 @@ net_virtio_reset: ; Device Initialization (section 3.1) - mov rsi, [os_NetIOBaseMem] + ; Gather Base Address from net_table + mov rsi, net_table + xor eax, eax + mov al, [os_net_icount] + shl eax, 7 ; Quick multiply by 128 + add rsi, rax + add rsi, 16 + mov rsi, [rsi] + mov rdi, rsi ; 3.1.1 - Step 1 - Reset the device (section 2.4) mov al, 0x00 @@ -211,7 +248,7 @@ virtio_net_init_reset_wait: ; 3.1.1 - Step 2 - Tell the device we see it mov al, VIRTIO_STATUS_ACKNOWLEDGE mov [rsi+VIRTIO_DEVICE_STATUS], al - + ; 3.1.1 - Step 3 - Tell the device we support it mov al, VIRTIO_STATUS_ACKNOWLEDGE | VIRTIO_STATUS_DRIVER mov [rsi+VIRTIO_DEVICE_STATUS], al @@ -244,7 +281,7 @@ virtio_net_init_reset_wait: ; 3.1.1 - Step 5 mov al, VIRTIO_STATUS_ACKNOWLEDGE | VIRTIO_STATUS_DRIVER | VIRTIO_STATUS_FEATURES_OK mov [rsi+VIRTIO_DEVICE_STATUS], al - + ; 3.1.1 - Step 6 - Re-read device status to make sure FEATURES_OK is still set mov al, [rsi+VIRTIO_DEVICE_STATUS] bt ax, 3 ; VIRTIO_STATUS_FEATURES_OK @@ -260,7 +297,7 @@ virtio_net_init_reset_wait: mov ax, 0x0000 mov [rsi+VIRTIO_CONFIG_MSIX_VECTOR], ax - ; Set up Queue 0 + ; Set up Queue 0 (Receive) xor eax, eax mov [rsi+VIRTIO_QUEUE_SELECT], ax mov ax, [rsi+VIRTIO_QUEUE_SIZE] ; Return the size of the queue @@ -286,7 +323,7 @@ virtio_net_init_reset_wait: mov ax, 1 mov [rsi+VIRTIO_QUEUE_ENABLE], ax - ; Set up Queue 1 + ; Set up Queue 1 (Transmit) mov eax, 1 mov [rsi+VIRTIO_QUEUE_SELECT], ax mov ax, [rsi+VIRTIO_QUEUE_SIZE] ; Return the size of the queue @@ -360,6 +397,7 @@ virtio_net_init_pop: ; ----------------------------------------------------------------------------- ; net_virtio_transmit - Transmit a packet via a Virtio NIC ; IN: RSI = Location of packet +; RDX = Interface ID ; RCX = Length of packet ; OUT: Nothing net_virtio_transmit: @@ -394,7 +432,7 @@ net_virtio_transmit: stosw ; 16-bit ring ; Notify the queue - mov rdi, [os_NetIOBaseMem] + mov rdi, [rdx+nt_base] ; Transmit Descriptor Base Address add rdi, [virtio_net_notify_offset] add rdi, 4 xor eax, eax @@ -422,6 +460,7 @@ net_virtio_transmit_wait: ; ----------------------------------------------------------------------------- ; net_virtio_poll - Polls the Virtio NIC for a received packet ; IN: RDI = Location to store packet +; RDX = Interface ID ; OUT: RCX = Length of packet net_virtio_poll: push rdi diff --git a/src/init/64.asm b/src/init/64.asm index 6c95f12..d6516a0 100644 --- a/src/init/64.asm +++ b/src/init/64.asm @@ -100,10 +100,10 @@ make_interrupt_gate_stubs: mov rdi, os_nvs_io stosq stosq - mov rdi, os_net_transmit - stosq - stosq - stosq +; mov rdi, os_net_transmit +; stosq +; stosq +; stosq ; Configure the Stack base mov rax, 0x200000 ; Stacks start at 2MiB diff --git a/src/init/net.asm b/src/init/net.asm index 4017d6e..b7bc9e3 100644 --- a/src/init/net.asm +++ b/src/init/net.asm @@ -11,8 +11,7 @@ init_net: ; Check Bus Table for a Ethernet device mov rsi, bus_table ; Load Bus Table address to RSI - sub rsi, 16 - add rsi, 8 ; Add offset to Class Code + sub rsi, 8 ; Subtract offset for Class Code init_net_check_bus: add rsi, 16 ; Increment to next record in memory mov ax, [rsi] ; Load Class Code / Subclass Code @@ -29,6 +28,8 @@ init_net_probe_find_driver: mov edx, [rsi] ; Load value for os_bus_read/write mov r8d, [rsi+4] ; Save the Device ID / Vendor ID in R8D rol r8d, 16 ; Swap the Device ID / Vendor ID + add rsi, 8 ; Move RSI back to Class Code + push rsi mov rsi, NIC_DeviceVendor_ID init_net_probe_find_next_driver: lodsw ; Load a driver ID @@ -44,8 +45,8 @@ init_net_probe_find_next_device: cmp eax, r8d je init_net_probe_found ; If Carry is clear then we found a supported NIC jmp init_net_probe_find_next_device ; Check the next device - init_net_probe_found: + pop rsi cmp bx, 0x1AF4 je init_net_probe_found_virtio cmp bx, 0x8254 @@ -54,62 +55,42 @@ init_net_probe_found: je init_net_probe_found_i8257x cmp bx, 0x8259 je init_net_probe_found_i8259x - cmp bx, 0x8169 - je init_net_probe_found_r8169 +; cmp bx, 0x8169 +; je init_net_probe_found_r8169 jmp init_net_probe_not_found init_net_probe_found_virtio: call net_virtio_init - mov rdi, os_net_transmit - mov rax, net_virtio_transmit - stosq - mov rax, net_virtio_poll - stosq jmp init_net_probe_found_finish init_net_probe_found_i8254x: call net_i8254x_init - mov rdi, os_net_transmit - mov rax, net_i8254x_transmit - stosq - mov rax, net_i8254x_poll - stosq jmp init_net_probe_found_finish init_net_probe_found_i8257x: call net_i8257x_init - mov rdi, os_net_transmit - mov rax, net_i8257x_transmit - stosq - mov rax, net_i8257x_poll - stosq jmp init_net_probe_found_finish init_net_probe_found_i8259x: call net_i8259x_init - mov rdi, os_net_transmit - mov rax, net_i8259x_transmit - stosq - mov rax, net_i8259x_poll - stosq jmp init_net_probe_found_finish -init_net_probe_found_r8169: - call net_r8169_init - mov rdi, os_net_transmit - mov rax, net_r8169_transmit - stosq - mov rax, net_r8169_poll - stosq - jmp init_net_probe_found_finish +;init_net_probe_found_r8169: +; call net_r8169_init +; jmp init_net_probe_found_finish init_net_probe_found_finish: - add byte [os_net_icount], 1 mov byte [os_NetEnabled], 1 ; A supported NIC was found. Signal to the OS that networking is enabled add r9, 15 ; Add offset to driver enabled byte mov byte [r9], 1 ; Mark device as having a driver + add byte [os_net_icount], 1 + cmp byte [os_net_icount], 2 ; Have 2 NIC's been activated? + je init_net_end ; If so, bail out as 2 is the max at the moment + jmp init_net_check_bus ; Check for another network device init_net_probe_not_found: + +init_net_end: ; Output block to screen (4/4) mov ebx, 6 call os_debug_block diff --git a/src/syscalls/net.asm b/src/syscalls/net.asm index 3b33ef2..3c8d0d6 100644 --- a/src/syscalls/net.asm +++ b/src/syscalls/net.asm @@ -20,7 +20,12 @@ b_net_status: je b_net_status_end mov ecx, 6 - mov rsi, os_NetMAC + + mov rsi, rdx + shl esi, 7 ; Quick multiply by 128 + add esi, net_table ; Add offset to net_table + add esi, 8 + b_net_status_loadMAC: shl rax, 8 lodsb @@ -42,17 +47,23 @@ b_net_status_end: ; RDX = Interface ID ; OUT: Nothing. All registers preserved b_net_tx: + push rdx push rcx push rax cmp byte [os_NetEnabled], 1 ; Check if networking is enabled jne b_net_tx_fail + shl edx, 7 ; Quick multiply by 128 + add edx, net_table ; Add offset to net_table + b_net_tx_maxcheck: cmp rcx, 1522 ; Fail if more than 1522 bytes ja b_net_tx_fail - mov rax, os_NetLock ; Lock the net so only one send can happen at a time + ; Lock the network interface so only one send can happen at a time + mov rax, rdx + add rax, nt_lock call b_smp_lock ; Calculate where in physical memory the data should be read from @@ -60,16 +71,22 @@ b_net_tx_maxcheck: call os_virt_to_phys xchg rax, rsi - inc qword [os_net_TXPackets] - add qword [os_net_TXBytes], rcx - call qword [os_net_transmit] ; Call the driver + ; Call the driver transmit function + call [rdx+nt_transmit] ; Call driver transmit function passing RDX as interface + + ; Increment interface counters + inc qword [rdx+nt_tx_packets] ; Increment TXPackets + add qword [rdx+nt_tx_bytes], rcx ; Increment TXBytes - mov rax, os_NetLock + ; Unlock the network interface + mov rax, rdx + add rax, nt_lock call b_smp_unlock b_net_tx_fail: pop rax pop rcx + pop rdx ret ; ----------------------------------------------------------------------------- @@ -83,6 +100,7 @@ b_net_tx_fail: b_net_rx: push rdi push rsi + push rdx push rax xor ecx, ecx @@ -90,18 +108,28 @@ b_net_rx: cmp byte [os_NetEnabled], 1 ; Check if networking is enabled jne b_net_rx_nodata - call qword [os_net_poll] ; Call the driver + shl edx, 7 ; Quick multiply by 128 + add edx, net_table ; Add offset to net_table + + ; Call the driver poll function + call [rdx+nt_poll] ; Call driver poll function passing RDX as interface + cmp cx, 0 je b_net_rx_nodata - inc qword [os_net_RXPackets] - add qword [os_net_RXBytes], rcx + + ; Increment interface counters + inc qword [rdx+nt_rx_packets] ; Increment RXPackets + add qword [rdx+nt_rx_bytes], rcx ; Increment RXBytes mov rsi, os_PacketBuffers ; Packet exists here push rcx rep movsb ; Copy packet to requested address pop rcx +; TODO is b_net_rx_nodata needed if CX is already set +b_net_rx_end: pop rax + pop rdx pop rsi pop rdi ret @@ -109,6 +137,7 @@ b_net_rx: b_net_rx_nodata: xor ecx, ecx pop rax + pop rdx pop rsi pop rdi ret diff --git a/src/sysvar.asm b/src/sysvar.asm index 1b6a2bf..c28a88f 100644 --- a/src/sysvar.asm +++ b/src/sysvar.asm @@ -43,10 +43,11 @@ os_nvs_mem: equ 0x0000000000130000 ; 0x130000 -> 0x15FFFF 192K NVS structures/b os_usb_mem: equ 0x0000000000160000 ; 0x160000 -> 0x19FFFF 256K USB structures/buffers ; Network memory -os_net_mem: equ 0x00000000001A0000 ; 0x1A0000 -> 0x1CFFFF 192K Network descriptors/buffers +os_net_mem: equ 0x00000000001A0000 ; 0x1A0000 -> 0x1BFFFF 128K Network descriptors/buffers os_rx_desc: equ 0x00000000001A0000 ; 0x1A0000 -> 0x1AFFFF 64K Ethernet receive descriptors os_tx_desc: equ 0x00000000001B0000 ; 0x1B0000 -> 0x1BFFFF 64K Ethernet transmit descriptors -os_PacketBuffers: equ 0x00000000001C0000 ; 0x1C0000 -> 0x1CFFFF 64K Ethernet packet buffers + + ; 0x1C0000 -> 0x1CFFFF 64K Free ; LFB font data os_font: equ 0x00000000001D0000 ; 0x1D0000 -> 0x1DFFFF 64K Font video data @@ -58,34 +59,23 @@ os_SMP: equ 0x00000000001FF800 ; SMP table. Each item is 8 bytes. (2KiB before app_start: equ 0xFFFF800000000000 ; Location of application memory +; System Variables + ; DQ - Starting at offset 0, increments by 8 os_LocalAPICAddress: equ os_SystemVariables + 0x0000 os_IOAPICAddress: equ os_SystemVariables + 0x0008 os_SysConfEn: equ os_SystemVariables + 0x0010 ; Enabled bits: 0=PS/2 Keyboard, 1=PS/2 Mouse, 2=Serial, 4=HPET, 5=xHCI -os_PacketAddress: equ os_SystemVariables + 0x0018 os_StackBase: equ os_SystemVariables + 0x0020 -os_net_transmit: equ os_SystemVariables + 0x0028 -os_net_poll: equ os_SystemVariables + 0x0030 -os_net_ackint: equ os_SystemVariables + 0x0038 -os_NetIOBaseMem: equ os_SystemVariables + 0x0040 -os_NetMAC: equ os_SystemVariables + 0x0048 os_HPET_Address: equ os_SystemVariables + 0x0050 os_AHCI_Base: equ os_SystemVariables + 0x0058 os_NetworkCallback: equ os_SystemVariables + 0x0060 os_KeyboardCallback: equ os_SystemVariables + 0x0068 os_ClockCallback: equ os_SystemVariables + 0x0070 -os_net_TXBytes: equ os_SystemVariables + 0x0078 -os_net_TXPackets: equ os_SystemVariables + 0x0080 -os_net_RXBytes: equ os_SystemVariables + 0x0088 -os_net_RXPackets: equ os_SystemVariables + 0x0090 -;os_hdd_BytesRead: equ os_SystemVariables + 0x0098 -;os_hdd_BytesWrite: equ os_SystemVariables + 0x00A0 os_NVMe_Base: equ os_SystemVariables + 0x00A8 os_nvs_io: equ os_SystemVariables + 0x00B0 os_nvs_id: equ os_SystemVariables + 0x00B8 os_screen_lfb: equ os_SystemVariables + 0x00C0 os_virtioblk_base: equ os_SystemVariables + 0x00C8 -os_NetIOLength: equ os_SystemVariables + 0x00D0 os_MouseCallback: equ os_SystemVariables + 0x00D8 os_xHCI_Base: equ os_SystemVariables + 0x00E0 os_usb_evtoken: equ os_SystemVariables + 0x00E8 @@ -105,8 +95,6 @@ os_xhci_int0_count: equ os_SystemVariables + 0x011C ; Incremented on xHCI Interr ; DW - Starting at offset 512, increments by 2 os_NumCores: equ os_SystemVariables + 0x0200 os_CoreSpeed: equ os_SystemVariables + 0x0202 -os_NetIOAddress: equ os_SystemVariables + 0x0204 -os_NetLock: equ os_SystemVariables + 0x0206 os_nvsVar: equ os_SystemVariables + 0x0208 ; Bit 0 for NVMe, 1 for AHCI, 2 for ATA, 3 for Virtio Block os_screen_x: equ os_SystemVariables + 0x020A os_screen_y: equ os_SystemVariables + 0x020C @@ -128,7 +116,7 @@ key: equ os_SystemVariables + 0x0301 key_shift: equ os_SystemVariables + 0x0302 os_BusEnabled: equ os_SystemVariables + 0x0303 ; 1 if PCI is enabled, 2 if PCIe is enabled os_NetEnabled: equ os_SystemVariables + 0x0304 ; 1 if a supported network card was enabled -os_NetIRQ: equ os_SystemVariables + 0x0305 ; Set to Interrupt line that NIC is connected to +;os_NetIRQ: equ os_SystemVariables + 0x0305 ; Set to Interrupt line that NIC is connected to ;os_NetActivity_TX: equ os_SystemVariables + 0x0306 ;os_NetActivity_RX: equ os_SystemVariables + 0x0307 ;os_EthernetBuffer_C1: equ os_SystemVariables + 0x0308 ; Counter 1 for the Ethernet RX Ring Buffer @@ -152,20 +140,32 @@ os_BSP: equ os_SystemVariables + 0x0319 os_HPET_IRQ: equ os_SystemVariables + 0x031A os_net_icount: equ os_SystemVariables + 0x031B -; Network Device Table Base -os_net_table: equ os_SystemVariables + 0x2000 - -; Network Devices Entries - each entry is 64 bytes -os_net_entry_base: equ os_SystemVariables + 0x2000 -os_net_entry_transmit: equ os_SystemVariables + 0x2008 -os_net_entry_poll: equ os_SystemVariables + 0x2010 -os_net_entry_stats: equ os_SystemVariables + 0x2018 -os_net_entry_MAC: equ os_SystemVariables + 0x2020 -os_net_entry_tx_tail: equ os_SystemVariables + 0x2028 -os_net_entry_rx_tail: equ os_SystemVariables + 0x202C -; Next Device starts at 0x8040 +; System tables bus_table: equ os_SystemVariables + 0x8000 +net_table: equ os_SystemVariables + 0xA000 + +; Buffers +os_PacketBuffers: equ os_SystemVariables + 0xC000 ; 16KiB + +; net_table values (per device - 128 bytes) +nt_ID: equ 0x00 ; 16-bit +nt_lock: equ 0x02 ; 16-bit +nt_MAC: equ 0x08 ; 48-bit +nt_base: equ 0x10 ; 64-bit +nt_len: equ 0x18 ; 64-bit +nt_transmit: equ 0x20 ; 64-bit +nt_poll: equ 0x28 ; 64-bit +nt_tx_desc: equ 0x30 ; 64-bit +nt_rx_desc: equ 0x38 ; 64-bit +nt_tx_tail: equ 0x40 ; 64-bit +nt_rx_head: equ 0x44 ; 64-bit +nt_tx_packets: equ 0x50 ; 64-bit +nt_tx_bytes: equ 0x58 ; 64-bit +nt_rx_packets: equ 0x60 ; 64-bit +nt_rx_bytes: equ 0x68 ; 64-bit +; bytes 70-7F for future use + ; Misc tchar: db 0, 0