Working on ethernet.
Includes a prototype E1000 driver.
This commit is contained in:
parent
98f3786e8b
commit
2c95714d2f
|
@ -20,6 +20,8 @@
|
||||||
#include <kernel/system/pci.h>
|
#include <kernel/system/pci.h>
|
||||||
#include <kernel/system/stack.h>
|
#include <kernel/system/stack.h>
|
||||||
|
|
||||||
|
#include <lainlib/ethernet/e1000/e1000.h>
|
||||||
|
|
||||||
//Removed cause "wacky copyrighted stuff"
|
//Removed cause "wacky copyrighted stuff"
|
||||||
//#include <kernel/system/screen.h>
|
//#include <kernel/system/screen.h>
|
||||||
|
|
||||||
|
@ -32,6 +34,8 @@ extern volatile size_t* _kernel_text_start;
|
||||||
|
|
||||||
extern address_space_t KernelAddressSpace;
|
extern address_space_t KernelAddressSpace;
|
||||||
|
|
||||||
|
extern e1000_device_t* E1000NIC;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
|
@ -31,6 +31,8 @@ typedef void (*IRQHandler)(INTERRUPT_FRAME* Frame);
|
||||||
|
|
||||||
extern IRQHandler IRQ_Handlers[16];
|
extern IRQHandler IRQ_Handlers[16];
|
||||||
|
|
||||||
|
void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame));
|
||||||
|
|
||||||
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
|
void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt);
|
||||||
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
|
void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt);
|
||||||
void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception);
|
void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception);
|
||||||
|
|
|
@ -17,100 +17,100 @@
|
||||||
#define PCI_CONFIG_DATA 0xCFC
|
#define PCI_CONFIG_DATA 0xCFC
|
||||||
|
|
||||||
|
|
||||||
const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_t progif);
|
const char* PCIGetDeviceName_Subclass(uint8_t DeviceClass, uint8_t Subclass, uint8_t ProgrammableInterface);
|
||||||
|
|
||||||
const char* PCIGetClassName(uint8_t devclass);
|
const char* PCIGetClassName(uint8_t DeviceClass);
|
||||||
|
|
||||||
void PCIEnumerate();
|
void PCIEnumerate();
|
||||||
|
|
||||||
uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
|
uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
typedef struct __attribute__((packed)) {
|
||||||
uint8_t io_space : 1; // Device can respond to I/O access
|
uint8_t IOMapped : 1; // Device can respond to I/O access
|
||||||
uint8_t memory_space : 1; // Device can respond to memory access (device is MMIO mapped)
|
uint8_t MMIOMapped : 1; // Device can respond to memory access (device is MMIO mapped)
|
||||||
uint8_t bus_master : 1; // Device is Bus Master; can generate PCI addresses
|
uint8_t IsBusMaster : 1; // Device is Bus Master; can generate PCI addresses
|
||||||
uint8_t special_cycle : 1; // Device can monitor Special Cycle
|
uint8_t MonitorSpecialCycle : 1; // Device can monitor Special Cycle
|
||||||
uint8_t memory_write_and_invalidate : 1; // Device can generate Memory Write And Invalidate commands; else Memory Write must be used
|
uint8_t AllowMemWriteInvalidate : 1; // Device can generate Memory Write And Invalidate commands; else Memory Write must be used
|
||||||
uint8_t vga_palette : 1; // Device snoops the VGA palette on write; else is treated like a normal access
|
uint8_t SnoopVGA : 1; // Device snoops the VGA palette on write; else is treated like a normal access
|
||||||
uint8_t parity_error_response : 1; // Device responds to Parity Errors by setting PERR#; else will set pci_status#parity_error and continue.
|
uint8_t RespondsParityError : 1; // Device responds to Parity Errors by setting PERR#; else will set pci_status#ParityError and continue.
|
||||||
uint8_t _reserved : 1; // Hardwired to 0
|
uint8_t _reserved : 1; // Hardwired to 0
|
||||||
uint8_t serr : 1; // Enable SERR# driver; System ERRor
|
uint8_t SystemErr : 1; // Enable SERR# driver; System ERRor
|
||||||
uint8_t fast_back_back : 1; // Device is allowed to generate fast back-to-back transactions to other agents.
|
uint8_t FastBack2Back : 1; // Device is allowed to generate fast back-to-back transactions to other agents.
|
||||||
uint8_t disable_interrupt : 1; // Disable assertion of INTx# signal; else enable.
|
uint8_t DisableInterrupt : 1; // Disable assertion of INTx# signal; else enable.
|
||||||
} pci_command_t;
|
} pci_command_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
typedef struct __attribute__((packed)) {
|
||||||
uint8_t _reserved : 3; // 3 bits hardwired to 0
|
uint8_t _reserved : 3; // 3 bits hardwired to 0
|
||||||
uint8_t interrupt : 1; // State of device's INTx# signal. If pci_command#disable_interrupt is 0 and this is 1, the signal will be asserted.
|
uint8_t InterruptActive : 1; // State of device's INTx# signal. If pci_command#DisableInterrupt is 0 and this is 1, the signal will be asserted.
|
||||||
uint8_t capability_list : 1; // If set, device will implement New Capabilities list at 0x34 offset.
|
uint8_t Capabilities : 1; // If set, device will implement New Capabilities list at 0x34 offset.
|
||||||
uint8_t freq_66_capable : 1; // Device can run at 66MHz. Else, device will run at 33MHz.
|
uint8_t Mhz66Capable : 1; // Device can run at 66MHz. Else, device will run at 33MHz.
|
||||||
uint8_t _reserved1 : 1; // Reserved as of 3.0, Used in 2.1 as "Supports User Definable Features"
|
uint8_t _reserved1 : 1; // Reserved as of 3.0, Used in 2.1 as "Supports User Definable Features"
|
||||||
uint8_t fast_back_back : 1; // Device is allowed to accept fast back-to-back transactions from other agents.
|
uint8_t FastBack2Back : 1; // Device is allowed to accept fast back-to-back transactions from other agents.
|
||||||
uint8_t master_parity_error : 1; // Only set when PERR# is asserted by the Bus Master while pci_command#parity_error_response is set.
|
uint8_t MasterParityError : 1; // Only set when PERR# is asserted by the Bus Master while pci_command#RespondsParityError is set.
|
||||||
uint8_t devsel_timing : 2; // Read-Only; represents the slowest time a device will assert DEVSEL#. 00 = fast, 01 = medium, 11 = slow.
|
uint8_t DEVSELTiming : 2; // Read-Only; represents the slowest time a device will assert DEVSEL#. 00 = fast, 01 = medium, 11 = slow.
|
||||||
uint8_t target_signalled_abort : 1; // Target device terminated transaction via Target-Abort
|
uint8_t TargetAborted : 1; // Target device terminated transaction via Target-Abort
|
||||||
uint8_t received_target_abort : 1; // Master's connection was terminated by Target-Abort
|
uint8_t ReceivedTargetAbort : 1; // Master's connection was terminated by Target-Abort
|
||||||
uint8_t received_master_abort : 1; // Master's connection was terminated by Master-Abort
|
uint8_t ReceivedMasterAbort : 1; // Master's connection was terminated by Master-Abort
|
||||||
uint8_t system_error_asserted : 1; // Device asserted SERR#
|
uint8_t SystemAssertedError : 1; // Device asserted SERR#
|
||||||
uint8_t parity_error : 1; // Device detected parity error. Parity error may not be handled.
|
uint8_t ParityError : 1; // Device detected parity error. Parity error may not be handled.
|
||||||
} pci_status_t;
|
} pci_status_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
typedef struct __attribute__((packed)) {
|
||||||
uint16_t vendor_id; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid.
|
uint16_t VendorID; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid.
|
||||||
uint16_t device_id; // 16 bit Device ID allocated by the vendor.
|
uint16_t DeviceID; // 16 bit Device ID allocated by the vendor.
|
||||||
pci_command_t command; // 16 bit PCI_COMMAND register.
|
pci_command_t Command; // 16 bit PCI_COMMAND register.
|
||||||
pci_status_t status; // 16 bit PCI_STATUS register.
|
pci_status_t Status; // 16 bit PCI_STATUS register.
|
||||||
uint8_t revision_id; // 8 bit register, revision identifier specified by vendor.
|
uint8_t RevisionID; // 8 bit register, revision identifier specified by vendor.
|
||||||
uint8_t progIF; // 8 bit register, identifies any programming interface the device may have.
|
uint8_t ProgrammingInterface; // 8 bit register, identifies any programming interface the device may have.
|
||||||
uint8_t subclass; // 8 bit Subclass code; identifies the specific function of the device
|
uint8_t Subclass; // 8 bit Subclass code; identifies the specific function of the device
|
||||||
uint8_t class_code; // 8 bit Class Code; identifies the function of the device
|
uint8_t ClassCode; // 8 bit Class Code; identifies the function of the device
|
||||||
uint8_t cache_line_size; // 8 bit; specifies system cache line size in 32-bit blocks. Devices can limit this. Unsupported values are treated as 0.
|
uint8_t CacheLine; // 8 bit; specifies system cache line size in 32-bit blocks. Devices can limit this. Unsupported values are treated as 0.
|
||||||
uint8_t latency_timer; // 8 bit; specifies latency timer in (bus clock) units.
|
uint8_t LatencyTimer; // 8 bit; specifies latency timer in (bus clock) units.
|
||||||
uint8_t header_type; // 8 bit; identifies the layout of the header and the type of device; 00 = device, 01 = pci-pci bridge, 11 = CardBus bridge. Multi-function defined by bit 7.
|
uint8_t HeaderType; // 8 bit; identifies the layout of the header and the type of device; 00 = device, 01 = pci-pci bridge, 11 = CardBus bridge. Multi-function defined by bit 7.
|
||||||
uint8_t bist; // 8 bit; status and control of a device's built-in self-test (BIST)
|
uint8_t BuiltInSelfTest; // 8 bit; status and control of a device's built-in self-test (BIST)
|
||||||
} pci_header_common_t;
|
} pci_header_common_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
typedef struct __attribute__((packed)) {
|
||||||
// pci_header_common_t first, then..
|
// pci_header_common_t first, then..
|
||||||
uint32_t bar[6]; // 6 x 32 bit Base Address Registers (BARs)
|
uint32_t BARs[6]; // 6 x 32 bit Base Address Registers (BARs)
|
||||||
uint32_t cis_pointer; // Points to Card Information Structure for PCI devices that share silicon with CardBus
|
uint32_t CISPtr; // Points to Card Information Structure for PCI devices that share silicon with CardBus
|
||||||
uint16_t subsystem_vendor_id;
|
uint16_t SubsysVendor;
|
||||||
uint16_t subsystem_id;
|
uint16_t SubsysID;
|
||||||
uint32_t expansion_bar; // Points to the base of an Expansion ROM.
|
uint32_t ExpansionBAR; // Points to the base of an Expansion ROM.
|
||||||
uint8_t capabilities; // The pointer generated by pci_status#capabilities_list
|
uint8_t Capabilities; // The pointer generated by pci_status#capabilities_list
|
||||||
uint8_t _reserved[3]; // 24 bit reserved at top end of register.
|
uint8_t _reserved[3]; // 24 bit reserved at top end of register.
|
||||||
uint32_t _reserved2;
|
uint32_t _reserved2;
|
||||||
uint8_t interrupt_line; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
uint8_t InterruptPin; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
||||||
uint8_t interrupt; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
uint8_t InterruptActive; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
||||||
uint8_t min_grant; // Specifies the length of the burst period, in quarter-microsecond units
|
uint8_t MinimumTimeshare; // Specifies the length of the burst period, in quarter-microsecond units
|
||||||
uint8_t max_latency; // Specifies how often the device accesses the PCI bus - in quarter-microseconds
|
uint8_t MaxmimumTimeshare; // Specifies how often the device accesses the PCI bus - in quarter-microseconds
|
||||||
} pci_header_device_t;
|
} pci_header_device_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) {
|
typedef struct __attribute__((packed)) {
|
||||||
// pci_header_common_t first
|
// pci_header_common_t first
|
||||||
uint32_t bar[2];
|
uint32_t BARs[2];
|
||||||
uint8_t pri_bus; // Primary Bus Number.
|
uint8_t PrimaryBus; // Primary Bus Number.
|
||||||
uint8_t sec_bus; // Secondary Bus Number.
|
uint8_t SecondaryBus; // Secondary Bus Number.
|
||||||
uint8_t sub_bus; // Subordinate Bus Number.
|
uint8_t SubordinateBus; // Subordinate Bus Number.
|
||||||
uint8_t sec_latency_timer; // Secondary Latency Timer.
|
uint8_t LatencyTimer; // Secondary Latency Timer.
|
||||||
uint8_t io_base; // IO Base is 24 bits. This is lower 8.
|
uint8_t IOBaseLow; // IO Base is 24 bits. This is lower 8.
|
||||||
uint8_t io_limit; // IO Limit is 24 bits. This is lower 8.
|
uint8_t IOLimitLow; // IO Limit is 24 bits. This is lower 8.
|
||||||
pci_status_t sec_status; // Secondary Status.
|
pci_status_t SecondaryStatus; // Secondary Status.
|
||||||
uint16_t mem_base;
|
uint16_t MemoryBase;
|
||||||
uint16_t mem_limit;
|
uint16_t MemoryLimit;
|
||||||
uint16_t mem_base_prefetch; // Prefetchable Memory Base is 48 bits. This is lower 16.
|
uint16_t PrefetchBaseLow; // Prefetchable Memory Base is 48 bits. This is lower 16.
|
||||||
uint16_t mem_limit_prefetch; // Prefetchable Memory Limit is 48 bits. This is lower 16.
|
uint16_t PrefetchLimitLow; // Prefetchable Memory Limit is 48 bits. This is lower 16.
|
||||||
uint32_t mem_base_prefetch_upper; // Prefetchable Memory Base is 48 bits. This is upper 32.
|
uint32_t PrefetchBaseHigh; // Prefetchable Memory Base is 48 bits. This is upper 32.
|
||||||
uint32_t mem_limit_prefetch_upper; // Prefetchable Memory Limit is 48 bits. This is upper 32.
|
uint32_t PrefetchLimitHigh; // Prefetchable Memory Limit is 48 bits. This is upper 32.
|
||||||
uint16_t io_base_upper; // IO Base is 24 bits. This is upper 16.
|
uint16_t IOBaseHigh; // IO Base is 24 bits. This is upper 16.
|
||||||
uint16_t io_limit_upper; // IO Limit is 24 bits. This is upper 16.
|
uint16_t IOLimitHigh; // IO Limit is 24 bits. This is upper 16.
|
||||||
uint8_t capabilities; // Pointer generated by pci_status#capabilities_list
|
uint8_t Capabilities; // Pointer generated by pci_status#capabilities_list
|
||||||
uint8_t _reserved[3]; // 24 reserved bits.
|
uint8_t _reserved[3]; // 24 reserved bits.
|
||||||
uint32_t expansion_bar; // Base of Expansion ROM.
|
uint32_t ExpansionBAR; // Base of Expansion ROM.
|
||||||
uint8_t interrupt_line; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
uint8_t InterruptPin; // Specifies the PIC pin that INTx# is connected to. Can be 0-15 because x86 PICs have 16 IRQs. 0xFF is no connection.
|
||||||
uint8_t interrupt; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
uint8_t InterruptActive; // Specifies the interrupt pin the device uses. 0x1 is INTA#, 0x2 is INTB#, 0x3 is INTC#, 0x4 is INTD#, 0x0 is no interrupt.
|
||||||
uint16_t bridge_control;
|
uint16_t BridgeControl;
|
||||||
} pci_header_bridge_t;
|
} pci_header_bridge_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,52 +122,53 @@ typedef struct {
|
||||||
} pci_address_t;
|
} pci_address_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t present : 1;
|
uint8_t Present : 1;
|
||||||
uint8_t mmio : 1;
|
uint8_t MMIO : 1;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
size_t addr;
|
size_t Address;
|
||||||
uint16_t port;
|
uint16_t Port;
|
||||||
};
|
};
|
||||||
size_t length;
|
|
||||||
|
size_t Length;
|
||||||
} pci_bar_t;
|
} pci_bar_t;
|
||||||
|
|
||||||
typedef struct pci_dev{
|
typedef struct pci_device {
|
||||||
|
|
||||||
struct pci_dev* parent; // Parent of the device (for PCI hubs / splitters)
|
struct pci_dev* Parent; // Parent of the device (for PCI hubs / splitters)
|
||||||
|
|
||||||
uint16_t device_id;
|
uint16_t DeviceID;
|
||||||
uint16_t vendor_id;
|
uint16_t VendorID;
|
||||||
|
|
||||||
uint8_t devclass;
|
uint8_t DeviceClass;
|
||||||
uint8_t subclass;
|
uint8_t Subclass;
|
||||||
|
|
||||||
uint8_t progif;
|
uint8_t ProgrammableInterface;
|
||||||
|
|
||||||
pci_address_t address;
|
pci_address_t address;
|
||||||
|
|
||||||
pci_bar_t bars[6];
|
pci_bar_t BARs[6];
|
||||||
|
|
||||||
int irq; // The IRQ of the device if already handled
|
int IRQ; // The IRQ of the device if already handled
|
||||||
|
|
||||||
// The headers!
|
// The headers!
|
||||||
volatile pci_header_common_t* header;
|
volatile pci_header_common_t* Header;
|
||||||
|
|
||||||
union { // The device can only be one of these at a time, but they both form part of the config space.
|
union { // The device can only be one of these at a time, but they both form part of the config space.
|
||||||
volatile pci_header_bridge_t* bridge;
|
volatile pci_header_bridge_t* bridge;
|
||||||
volatile pci_header_device_t* device;
|
volatile pci_header_device_t* device;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pci_dev** children; // If this device is a hub, it has children...
|
struct pci_dev** Children; // If this device is a hub, it has children...
|
||||||
|
|
||||||
// acpi_node_t acpi;
|
// acpi_node_t acpi;
|
||||||
} pci_dev_t;
|
} pci_device_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
pci_address_t key;
|
pci_address_t key;
|
||||||
pci_dev_t* value;
|
pci_device_t* value;
|
||||||
} pci_entry_t;
|
} pci_entry_t;
|
||||||
|
|
||||||
|
|
||||||
extern pci_dev_t** pci_root_devices;
|
extern pci_device_t** pci_root_devices;
|
||||||
extern pci_entry_t* pci_map;
|
extern pci_entry_t* pci_map;
|
181
chroma/inc/lainlib/ethernet/e1000/e1000.h
Normal file
181
chroma/inc/lainlib/ethernet/e1000/e1000.h
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2021 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <kernel/system/pci.h>
|
||||||
|
#include <kernel/system/interrupts.h>
|
||||||
|
#include <kernel/system/io.h>
|
||||||
|
|
||||||
|
#define INTEL_VEND 0x8086 // Vendor ID for Intel
|
||||||
|
#define E1000_DEV 0x100E // Device ID for the e1000 Qemu, Bochs, and VirtualBox emmulated NICs
|
||||||
|
#define E1000_I217 0x153A // Device ID for Intel I217
|
||||||
|
#define E1000_82577LM 0x10EA // Device ID for Intel 82577LM
|
||||||
|
|
||||||
|
#define REG_CTRL 0x0000
|
||||||
|
#define REG_STATUS 0x0008
|
||||||
|
#define REG_EEPROM 0x0014
|
||||||
|
#define REG_CTRL_EXT 0x0018
|
||||||
|
#define REG_IMASK 0x00D0
|
||||||
|
#define REG_RCTRL 0x0100
|
||||||
|
#define REG_RXDESCLO 0x2800
|
||||||
|
#define REG_RXDESCHI 0x2804
|
||||||
|
#define REG_RXDESCLEN 0x2808
|
||||||
|
#define REG_RXDESCHEAD 0x2810
|
||||||
|
#define REG_RXDESCTAIL 0x2818
|
||||||
|
|
||||||
|
#define REG_TCTRL 0x0400
|
||||||
|
#define REG_TXDESCLO 0x3800
|
||||||
|
#define REG_TXDESCHI 0x3804
|
||||||
|
#define REG_TXDESCLEN 0x3808
|
||||||
|
#define REG_TXDESCHEAD 0x3810
|
||||||
|
#define REG_TXDESCTAIL 0x3818
|
||||||
|
|
||||||
|
|
||||||
|
#define REG_RDTR 0x2820 // RX Delay Timer Register
|
||||||
|
#define REG_RXDCTL 0x3828 // RX Descriptor Control
|
||||||
|
#define REG_RADV 0x282C // RX Int. Absolute Delay Timer
|
||||||
|
#define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt
|
||||||
|
|
||||||
|
#define REG_MAC 0x5400 // MAC address base
|
||||||
|
|
||||||
|
#define REG_TIPG 0x0410 // Transmit Inter Packet Gap
|
||||||
|
#define ECTRL_SLU 0x40 // set-link-up
|
||||||
|
|
||||||
|
|
||||||
|
#define RCTL_EN (1 << 1) // Receiver Enable
|
||||||
|
#define RCTL_SBP (1 << 2) // Store Bad Packets
|
||||||
|
#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled
|
||||||
|
#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled
|
||||||
|
#define RCTL_LPE (1 << 5) // Long Packet Reception Enable
|
||||||
|
#define RCTL_LBM_NONE (0 << 6) // No Loopback
|
||||||
|
#define RCTL_LBM_PHY (3 << 6) // PHY or external SerDesc loopback
|
||||||
|
#define RCTL_RDMTS_HALF (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN
|
||||||
|
#define RCTL_RDMTS_QUARTER (1 << 8) // Free Buffer Threshold is 1/4 of RDLEN
|
||||||
|
#define RCTL_RDMTS_EIGHTH (2 << 8) // Free Buffer Threshold is 1/8 of RDLEN
|
||||||
|
#define RCTL_MO_36 (0 << 12) // Multicast Offset - bits 47:36
|
||||||
|
#define RCTL_MO_35 (1 << 12) // Multicast Offset - bits 46:35
|
||||||
|
#define RCTL_MO_34 (2 << 12) // Multicast Offset - bits 45:34
|
||||||
|
#define RCTL_MO_32 (3 << 12) // Multicast Offset - bits 43:32
|
||||||
|
#define RCTL_BAM (1 << 15) // Broadcast Accept Mode
|
||||||
|
#define RCTL_VFE (1 << 18) // VLAN Filter Enable
|
||||||
|
#define RCTL_CFIEN (1 << 19) // Canonical Form Indicator Enable
|
||||||
|
#define RCTL_CFI (1 << 20) // Canonical Form Indicator Bit Value
|
||||||
|
#define RCTL_DPF (1 << 22) // Discard Pause Frames
|
||||||
|
#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames
|
||||||
|
#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC
|
||||||
|
|
||||||
|
// Buffer Sizes
|
||||||
|
#define RCTL_BSIZE_256 (3 << 16)
|
||||||
|
#define RCTL_BSIZE_512 (2 << 16)
|
||||||
|
#define RCTL_BSIZE_1024 (1 << 16)
|
||||||
|
#define RCTL_BSIZE_2048 (0 << 16)
|
||||||
|
#define RCTL_BSIZE_4096 ((3 << 16) | (1 << 25))
|
||||||
|
#define RCTL_BSIZE_8192 ((2 << 16) | (1 << 25))
|
||||||
|
#define RCTL_BSIZE_16384 ((1 << 16) | (1 << 25))
|
||||||
|
|
||||||
|
|
||||||
|
// Transmit Command
|
||||||
|
|
||||||
|
#define CMD_EOP (1 << 0) // End of Packet
|
||||||
|
#define CMD_IFCS (1 << 1) // Insert FCS
|
||||||
|
#define CMD_IC (1 << 2) // Insert Checksum
|
||||||
|
#define CMD_RS (1 << 3) // Report Status
|
||||||
|
#define CMD_RPS (1 << 4) // Report Packet Sent
|
||||||
|
#define CMD_VLE (1 << 6) // VLAN Packet Enable
|
||||||
|
#define CMD_IDE (1 << 7) // Interrupt Delay Enable
|
||||||
|
|
||||||
|
|
||||||
|
// TCTL Register
|
||||||
|
|
||||||
|
#define TCTL_EN (1 << 1) // Transmit Enable
|
||||||
|
#define TCTL_PSP (1 << 3) // Pad Short Packets
|
||||||
|
#define TCTL_CT_SHIFT 4 // Collision Threshold
|
||||||
|
#define TCTL_COLD_SHIFT 12 // Collision Distance
|
||||||
|
#define TCTL_RRTHRES_SHIFT 29 // Read Request Threshold
|
||||||
|
#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission
|
||||||
|
#define TCTL_RTLC (1 << 24) // Re-transmit on Late Collision
|
||||||
|
|
||||||
|
#define TSTA_DD (1 << 0) // Descriptor Done
|
||||||
|
#define TSTA_EC (1 << 1) // Excess Collisions
|
||||||
|
#define TSTA_LC (1 << 2) // Late Collision
|
||||||
|
#define LSTA_TU (1 << 3) // Transmit Underrun
|
||||||
|
|
||||||
|
#define E1000_NUM_RX_DESC 32
|
||||||
|
#define E1000_NUM_TX_DESC 8
|
||||||
|
|
||||||
|
struct e1000_receive_packet {
|
||||||
|
volatile uint64_t Address;
|
||||||
|
volatile uint16_t Length;
|
||||||
|
volatile uint16_t checksum;
|
||||||
|
volatile uint8_t Status;
|
||||||
|
volatile uint8_t errors;
|
||||||
|
volatile uint16_t Special;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct e1000_transmit_packet {
|
||||||
|
volatile uint64_t Address;
|
||||||
|
volatile uint16_t Length;
|
||||||
|
volatile uint8_t CSO;
|
||||||
|
volatile uint8_t Command;
|
||||||
|
volatile uint8_t Status;
|
||||||
|
volatile uint8_t CSS;
|
||||||
|
volatile uint16_t Special;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef struct e1000_device {
|
||||||
|
// BAR0's type
|
||||||
|
uint8_t BARType;
|
||||||
|
// The base IO address
|
||||||
|
uint16_t IOBase;
|
||||||
|
// The base MMIO address
|
||||||
|
uint64_t MemoryBase; // MMIO Base Address
|
||||||
|
// Does this card use an EEPROM?
|
||||||
|
bool HasEEPROM;
|
||||||
|
// The MAC address
|
||||||
|
uint8_t MAC[6];
|
||||||
|
// Receive circular buffer.
|
||||||
|
struct e1000_receive_packet* ReceivePackets[E1000_NUM_RX_DESC];
|
||||||
|
// Transmit circular buffer.
|
||||||
|
struct e1000_transmit_packet* TransmitPackets[E1000_NUM_TX_DESC];
|
||||||
|
// Current receive packet index
|
||||||
|
uint16_t CurrentReceivePacket;
|
||||||
|
// Current transmit packet index
|
||||||
|
uint16_t CurrentTransmitPacket;
|
||||||
|
} e1000_device_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Write a command to the E1000's registers
|
||||||
|
void E1000WriteCommandRegister(e1000_device_t* Device, uint16_t Address, uint32_t Data);
|
||||||
|
// Read the E1000's command registers
|
||||||
|
uint32_t E1000ReadCommandRegister(e1000_device_t* Device, uint16_t Address);
|
||||||
|
|
||||||
|
// Does this card use an EEPROM?
|
||||||
|
bool E1000DetectEEPROM(e1000_device_t* Device);
|
||||||
|
// Read 4 bytes from an EEPROM address
|
||||||
|
uint32_t E1000ReadEEPROM(e1000_device_t* Device, uint8_t Address);
|
||||||
|
// Read this NIC's MAC address
|
||||||
|
bool E1000ReadMAC(e1000_device_t* Device);
|
||||||
|
// Connect to a network, if there is one
|
||||||
|
void E1000Uplink(e1000_device_t* Device);
|
||||||
|
// Prepare for receiving packets
|
||||||
|
void E1000InitRX(e1000_device_t* Device);
|
||||||
|
// Prepare for sending packets
|
||||||
|
void E1000InitTX(e1000_device_t* Device);
|
||||||
|
// Prepare for receiving interrupts
|
||||||
|
void E1000InitInt(e1000_device_t* Device);
|
||||||
|
// Handle a received packet
|
||||||
|
void E1000Receive(e1000_device_t* Device);
|
||||||
|
|
||||||
|
// Handle constructing meta information about this device.
|
||||||
|
void E1000Init(e1000_device_t* Device, pci_device_t* PCIHeader);
|
||||||
|
// Initialise and start the driver
|
||||||
|
void E1000Startup(e1000_device_t* Device);
|
||||||
|
// Handle an interrupt received from the card
|
||||||
|
void E1000InterruptFired(INTERRUPT_FRAME* InterruptContext);
|
||||||
|
// Get the E1000's MAC address
|
||||||
|
uint8_t* E1000GetMAC(e1000_device_t* Device);
|
||||||
|
// Send a packet
|
||||||
|
int E1000Send(e1000_device_t* Device, const void* Data, uint16_t Length);
|
352
chroma/lainlib/ethernet/e1000/E1000Driver.c
Normal file
352
chroma/lainlib/ethernet/e1000/E1000Driver.c
Normal file
|
@ -0,0 +1,352 @@
|
||||||
|
/*************************
|
||||||
|
*** Team Kitty, 2021 ***
|
||||||
|
*** Lainlib ***
|
||||||
|
************************/
|
||||||
|
#include <lainlib/ethernet/e1000/e1000.h>
|
||||||
|
#include <kernel/chroma.h>
|
||||||
|
#include <kernel/system/memory.h>
|
||||||
|
#include <kernel/system/interrupts.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This file handles all the logic for interfacing with the E1000 networking device.
|
||||||
|
* This card is labelled either the Intel I217, or Intel Gigabit 82577LM.
|
||||||
|
* These cards are identical, and this driver will work identically for both of them.
|
||||||
|
*
|
||||||
|
* To use this driver, allocate an e1000_device struct and pass it to the E1000Init() function,
|
||||||
|
* along with its' PCI device header.
|
||||||
|
*
|
||||||
|
* TODO: usage information
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to the device's command registers.
|
||||||
|
* If we use BAR type 0, we use MMIO, otherwise ports.
|
||||||
|
*
|
||||||
|
* @param Device The device to which we write the data.
|
||||||
|
* @param Address The address to write the data at. For MMIO, the offset from base.
|
||||||
|
* @param Data The data to write into the register.
|
||||||
|
*/
|
||||||
|
void E1000WriteCommandRegister(e1000_device_t* Device, uint16_t Address, uint32_t Data) {
|
||||||
|
if(Device->BARType == 0)
|
||||||
|
WriteMMIO(Device->MemoryBase + Address, Data, 4);
|
||||||
|
else {
|
||||||
|
WritePort(Device->IOBase, Address, 4);
|
||||||
|
WritePort(Device->IOBase + 4, Data, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the device's command registers.
|
||||||
|
* If we use BAR type 0, we read from MMIO. Otherwise, ports.
|
||||||
|
*
|
||||||
|
* @param Device The device to read the data from
|
||||||
|
* @param Address The address we expect the data to be at. For MMIO, the offset from base.
|
||||||
|
* @return uint32_t The data contained in the register.
|
||||||
|
*/
|
||||||
|
uint32_t E1000ReadCommandRegister(e1000_device_t* Device, uint16_t Address) {
|
||||||
|
if(Device->BARType == 0)
|
||||||
|
return ReadMMIO(Device->MemoryBase + Address, 4);
|
||||||
|
else {
|
||||||
|
WritePort(Device->IOBase, Address, 4);
|
||||||
|
return ReadPort(Device->IOBase + 4, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to detect the presence of an EEPROM in the E1000.
|
||||||
|
* It sometimes doesn't like revealing its secrets, so we try it around 1000 times.
|
||||||
|
*
|
||||||
|
* @param Device The device to attempt to detect an EEPROM inside.
|
||||||
|
* @return true The given device has an EEPROM
|
||||||
|
* @return false The given device does not have an EEPROM
|
||||||
|
*/
|
||||||
|
bool E1000DetectEEPROM(e1000_device_t* Device) {
|
||||||
|
uint32_t Res = 0;
|
||||||
|
E1000WriteCommandRegister(Device, REG_EEPROM, 0x1);
|
||||||
|
Device->HasEEPROM = false;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < 1000 && !Device->HasEEPROM; i++) {
|
||||||
|
Res = E1000ReadCommandRegister(Device, REG_EEPROM);
|
||||||
|
if(Res & 0x10)
|
||||||
|
Device->HasEEPROM = true;
|
||||||
|
}
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read data from the E1000's EEPROM, if it has one.
|
||||||
|
* TODO: Unify
|
||||||
|
* @param Device The device to read
|
||||||
|
* @param Address The address we expect the data to be at
|
||||||
|
* @return uint32_t 32 bits of data in the given address of the EEPROM. 0 if not.
|
||||||
|
*/
|
||||||
|
uint32_t E1000ReadEEPROM(e1000_device_t* Device, uint8_t Address) {
|
||||||
|
uint32_t Temp = 0;
|
||||||
|
|
||||||
|
if(Device->HasEEPROM) {
|
||||||
|
// Tell the device we want the data at given address.
|
||||||
|
E1000WriteCommandRegister(Device, REG_EEPROM, (((uint32_t) Address) << 8) | 1);
|
||||||
|
// Spinlock until we get the result we expect
|
||||||
|
// TODO: Timeout?
|
||||||
|
while(!((Temp = E1000ReadCommandRegister(Device, REG_EEPROM)) & (1 << 4)));
|
||||||
|
} else {
|
||||||
|
// The E1000, if it does not have an EEPROM, instead stores it in internal ROM.
|
||||||
|
// So the same thing applies, but with different bits.
|
||||||
|
E1000WriteCommandRegister(Device, REG_EEPROM, (((uint32_t) Address) << 2) | 1);
|
||||||
|
while(!((Temp = E1000ReadCommandRegister(Device, REG_EEPROM)) & (1 << 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint16_t)((Temp >> 16) & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the E1000's MAC address into the internal buffer.
|
||||||
|
*
|
||||||
|
* @param Device The device to read from.
|
||||||
|
* @return true The read finished successfully
|
||||||
|
* @return false The MMIO base address is non-zero - this is invalid.
|
||||||
|
*/
|
||||||
|
bool E1000ReadMAC(e1000_device_t* Device) {
|
||||||
|
if(Device->HasEEPROM) {
|
||||||
|
uint32_t Temp;
|
||||||
|
Temp = E1000ReadEEPROM(Device, 0);
|
||||||
|
Device->MAC[0] = Temp & 0xff;
|
||||||
|
Device->MAC[1] = Temp >> 8;
|
||||||
|
Temp = E1000ReadEEPROM(Device, 1);
|
||||||
|
Device->MAC[2] = Temp & 0xff;
|
||||||
|
Device->MAC[3] = Temp >> 8;
|
||||||
|
Temp = E1000ReadEEPROM(Device, 2);
|
||||||
|
Device->MAC[4] = Temp & 0xff;
|
||||||
|
Device->MAC[5] = Temp >> 8;
|
||||||
|
} else {
|
||||||
|
uint8_t* MACBaseChar = (uint8_t*) (Device->MemoryBase + REG_MAC);
|
||||||
|
uint32_t* MACBaseLong = (uint32_t*) (Device->MemoryBase + REG_MAC);
|
||||||
|
|
||||||
|
if(MACBaseLong[0] != 0)
|
||||||
|
for(size_t i = 0; i < 6; i++)
|
||||||
|
Device->MAC[i] = MACBaseChar[i];
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the receive buffers, tell the device how to handle incoming packets.
|
||||||
|
*
|
||||||
|
* @param Device The device to prepare
|
||||||
|
*/
|
||||||
|
void E1000InitRX(e1000_device_t* Device) {
|
||||||
|
uint8_t* Ptr;
|
||||||
|
struct e1000_receive_packet* Packets;
|
||||||
|
|
||||||
|
Ptr = (uint8_t*) (kmalloc(sizeof(struct e1000_receive_packet) * E1000_NUM_RX_DESC + 16));
|
||||||
|
|
||||||
|
Packets = (struct e1000_receive_packet*) Ptr;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < E1000_NUM_RX_DESC; i++) {
|
||||||
|
Device->ReceivePackets[i] = (struct e1000_receive_packet*) ((uint8_t*)Packets + i*16);
|
||||||
|
Device->ReceivePackets[i]->address = (size_t) ((uint8_t*) kmalloc((PAGE_SIZE * 2) + 16));
|
||||||
|
Device->ReceivePackets[i]->Status = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCLO, (uint32_t) ((size_t)Ptr >> 32));
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCHI, (uint32_t) ((size_t)Ptr & 0xFFFFFFFF));
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCLO, (size_t) Ptr);
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCHI, 0);
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCLEN, E1000_NUM_RX_DESC * 16);
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCHEAD, 0);
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCTAIL, E1000_NUM_RX_DESC - 1);
|
||||||
|
|
||||||
|
Device->CurrentReceivePacket = 0;
|
||||||
|
E1000WriteCommandRegister(Device, REG_RCTRL,
|
||||||
|
RCTL_EN | // ENable
|
||||||
|
RCTL_SBP | // Store Bad Packets
|
||||||
|
RCTL_UPE | // Unicast Promiscuous Enable
|
||||||
|
RCTL_MPE | // Multicast Promiscuous Enable
|
||||||
|
RCTL_LBM_NONE | // LoopBack Mode
|
||||||
|
RCTL_RDMTS_HALF | // Receive Descriptor Minimum Threshold Size - throw interrupts when the buffer gets half filled
|
||||||
|
RCTL_BAM | // Broadcast Accept Mode
|
||||||
|
RCTL_SECRC | // Strip Ethernet CRC
|
||||||
|
RCTL_BSIZE_8192 // 8192 byte long buffer.
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the transmit buffers, tell the device how to handle outgoing packets.
|
||||||
|
*
|
||||||
|
* @param Device The device to prepare
|
||||||
|
*/
|
||||||
|
void E1000InitTX(e1000_device_t* Device) {
|
||||||
|
uint8_t* Ptr;
|
||||||
|
struct e1000_transmit_packet* Packets;
|
||||||
|
|
||||||
|
Ptr = (uint8_t*) (kmalloc(sizeof(struct e1000_transmit_packet) * E1000_NUM_TX_DESC + 16));
|
||||||
|
Packets = (struct e1000_transmit_packet*) Ptr;
|
||||||
|
|
||||||
|
for(int i = 0; i < E1000_NUM_TX_DESC; i++) {
|
||||||
|
Device->TransmitPackets[i] = (struct e1000_transmit_packet*) ((uint8_t*) Packets + (i * 16));
|
||||||
|
Device->TransmitPackets[i]->Address = 0;
|
||||||
|
Device->TransmitPackets[i]->Command = 0;
|
||||||
|
Device->TransmitPackets[i]->Status = TSTA_DD;
|
||||||
|
}
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCHI, (uint32_t) ((size_t)Ptr >> 32));
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCLO, (uint32_t) ((size_t)Ptr & 0xFFFFFFFF));
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCLEN, E1000_NUM_TX_DESC * 16);
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCHEAD, 0);
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCTAIL, 0);
|
||||||
|
|
||||||
|
Device->CurrentTransmitPacket = 0;
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TCTRL,
|
||||||
|
TCTL_EN | // ENable
|
||||||
|
TCTL_PSP | // Pad Short Packets
|
||||||
|
(15 << TCTL_CT_SHIFT) | // Collision Threshold - Attempt to re-send the packet 15 times.
|
||||||
|
(0x3F << TCTL_COLD_SHIFT) | // Collision Distance
|
||||||
|
(0x3 << TCTL_RRTHRES_SHIFT) // Read Request Threshold - infinity.
|
||||||
|
);
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_TIPG,
|
||||||
|
0x0060200A);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the device that it may send interrupts to inform us of what's going on
|
||||||
|
*
|
||||||
|
* @param Device The device to notify
|
||||||
|
*/
|
||||||
|
void E1000InitInt(e1000_device_t* Device) {
|
||||||
|
E1000WriteCommandRegister(Device, REG_IMASK, 0x1F6DC);
|
||||||
|
E1000WriteCommandRegister(Device, REG_IMASK, 0xFF & ~4);
|
||||||
|
E1000ReadCommandRegister(Device, 0xC0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle interrupts fired by the E1000.
|
||||||
|
* It will either:
|
||||||
|
* - Help initialise the device
|
||||||
|
* - Handle an incoming packet
|
||||||
|
*
|
||||||
|
* @param InterruptContext The interrupt metadata.
|
||||||
|
*/
|
||||||
|
void E1000InterruptFired(INTERRUPT_FRAME* InterruptContext) {
|
||||||
|
e1000_device_t* NIC = E1000NIC; // TODO: Find device from interrupt frame?
|
||||||
|
E1000WriteCommandRegister(NIC, REG_IMASK, 1);
|
||||||
|
uint32_t NICStatus = E1000ReadCommandRegister(NIC, 0xC0);
|
||||||
|
|
||||||
|
if(NICStatus & 0x4)
|
||||||
|
E1000Uplink(NIC);
|
||||||
|
else if(NICStatus & 0x80)
|
||||||
|
E1000Receive(NIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the state of the device, prepare it for further initialization steps.
|
||||||
|
*
|
||||||
|
* @param Device The device to initialise
|
||||||
|
* @param PCIHeader The device's PCI headers.
|
||||||
|
*/
|
||||||
|
void E1000Init(e1000_device_t* Device, pci_device_t* PCIHeader) {
|
||||||
|
pci_bar_t BAR = PCIHeader->BARs[0];
|
||||||
|
|
||||||
|
InstallIRQ(11, E1000InterruptFired);
|
||||||
|
|
||||||
|
if(BAR.MMIO) {
|
||||||
|
Device->BARType = 0;
|
||||||
|
Device->MemoryBase = DecodeVirtualAddress(&KernelAddressSpace, BAR.Address);
|
||||||
|
SerialPrintf("[E1000] Device is memory mapped - 0x%p x 0x%d\r\n", Device->MemoryBase, BAR.Length);
|
||||||
|
// UpdatePaging
|
||||||
|
} else {
|
||||||
|
Device->BARType = 1;
|
||||||
|
Device->IOBase = BAR.Port;
|
||||||
|
SerialPrintf("[E1000] Device is port mapped - 0x%p\r\n", Device->IOBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(E1000DetectEEPROM(Device))
|
||||||
|
SerialPrintf("[E1000] Device has EEPROM\r\n");
|
||||||
|
|
||||||
|
E1000ReadMAC(Device);
|
||||||
|
|
||||||
|
SerialPrintf("[E1000] Device's MAC is %d:%d:%d:%d:%d:%d\r\n", Device->MAC[0], Device->MAC[1], Device->MAC[2], Device->MAC[3], Device->MAC[4], Device->MAC[5]);
|
||||||
|
|
||||||
|
// Setup multicast
|
||||||
|
for(size_t i = 0; i < 0x80; i++)
|
||||||
|
WritePort(0x5200 + i * 4, 0, 4);
|
||||||
|
|
||||||
|
E1000InitRX(Device);
|
||||||
|
E1000InitTX(Device);
|
||||||
|
E1000InitInt(Device);
|
||||||
|
|
||||||
|
SerialPrintf("[E1000] Device ready.\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the device that it may connect itself to any networks it finds itself on.
|
||||||
|
*
|
||||||
|
* @param Device The device to notify
|
||||||
|
*/
|
||||||
|
void E1000Uplink(e1000_device_t* Device) {
|
||||||
|
uint32_t Flags = E1000ReadCommandRegister(Device, 0);
|
||||||
|
E1000WriteCommandRegister(Device, 0, Flags | 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a received packet, placing it in the buffer for other apps to consume.
|
||||||
|
*
|
||||||
|
* @param Device The device which received this packet.
|
||||||
|
*/
|
||||||
|
void E1000Receive(e1000_device_t* Device) {
|
||||||
|
uint16_t Temp;
|
||||||
|
|
||||||
|
while(Device->ReceivePackets[Device->CurrentReceivePacket]->Status & 0x1) {
|
||||||
|
Device->ReceivePackets[Device->CurrentReceivePacket]->Status = 0;
|
||||||
|
Temp = Device->CurrentReceivePacket;
|
||||||
|
Device->CurrentReceivePacket = (Device->CurrentReceivePacket + 1) % E1000_NUM_RX_DESC;
|
||||||
|
|
||||||
|
E1000WriteCommandRegister(Device, REG_RXDESCTAIL, Temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the E1000's MAC address.
|
||||||
|
* Only valid after E1000ReadMAC is called.
|
||||||
|
*
|
||||||
|
* @param Device The device to read
|
||||||
|
* @return uint8_t* A pointer to the MAC data.
|
||||||
|
*/
|
||||||
|
uint8_t* E1000GetMAC(e1000_device_t* Device) {
|
||||||
|
return (uint8_t*) Device->MAC;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a packet of specified length, via the given Device.
|
||||||
|
*
|
||||||
|
* @param Device The NIC to send the packet from
|
||||||
|
* @param Data The data to send
|
||||||
|
* @param Length The length of the data
|
||||||
|
* @return int 0 if successful. No other returns.
|
||||||
|
*/
|
||||||
|
int E1000Send(e1000_device_t* Device, const void* Data, uint16_t Length) {
|
||||||
|
struct e1000_transmit_packet* Target = Device->TransmitPackets[Device->CurrentTransmitPacket];
|
||||||
|
|
||||||
|
Target->Address = (size_t) Data;
|
||||||
|
Target->Length = Length;
|
||||||
|
Target->Command = CMD_EOP | CMD_IFCS | CMD_RS;
|
||||||
|
Target->Status = 0;
|
||||||
|
|
||||||
|
uint8_t temp = Device->CurrentTransmitPacket;
|
||||||
|
Device->CurrentTransmitPacket = (Device->CurrentTransmitPacket + 1) % E1000_NUM_TX_DESC;
|
||||||
|
E1000WriteCommandRegister(Device, REG_TXDESCTAIL, Device->CurrentTransmitPacket);
|
||||||
|
|
||||||
|
while(!(Device->TransmitPackets[temp]->Status & 0xFF));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
23
chroma/lainlib/ethernet/ethernet.h
Normal file
23
chroma/lainlib/ethernet/ethernet.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/************************
|
||||||
|
*** Team Kitty, 2021 ***
|
||||||
|
*** Chroma ***
|
||||||
|
***********************/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct mac_address {
|
||||||
|
uint8_t MAC[6];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
enum packet_types {
|
||||||
|
ET_ARP = 0x0806,
|
||||||
|
ET_IP4 = 0x0800,
|
||||||
|
ET_IP6 = 0x86DD,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ethernet_packet {
|
||||||
|
mac_address Dest;
|
||||||
|
mac_address Source;
|
||||||
|
uint16_t Type;
|
||||||
|
uint8_t Payload[];
|
||||||
|
};
|
|
@ -178,7 +178,7 @@ void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame)) {
|
||||||
/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */
|
/* A simple wrapper that unlinks a function pointer, rendering the IRQ unused. */
|
||||||
void UninstallIRQHandler(int IRQ) {
|
void UninstallIRQHandler(int IRQ) {
|
||||||
IRQ_Handlers[IRQ] = NULL; // 0 is used in the common check to make sure that the function is callable.
|
IRQ_Handlers[IRQ] = NULL; // 0 is used in the common check to make sure that the function is callable.
|
||||||
// This removes this irq from that check, ergo the function will no longer be called.
|
// This removes this IRQ from that check, ergo the function will no longer be called.
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyIRQ(INTERRUPT_FRAME* frame) {
|
void EmptyIRQ(INTERRUPT_FRAME* frame) {
|
||||||
|
|
|
@ -12,14 +12,14 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pci_dev_t** pci_root_devices = NULL;
|
pci_device_t** pci_root_devices = NULL;
|
||||||
pci_entry_t* pci_map = NULL;
|
pci_entry_t* pci_map = NULL;
|
||||||
|
|
||||||
//static uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
|
//static uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset);
|
||||||
|
|
||||||
//static const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_t progif);
|
//static const char* PCIGetDeviceName_Subclass(uint8_t DeviceClass, uint8_t Subclass, uint8_t ProgrammableInterface);
|
||||||
|
|
||||||
//static const char* PCIGetClassName(uint8_t devclass);
|
//static const char* PCIGetClassName(uint8_t DeviceClass);
|
||||||
|
|
||||||
void PCIEnumerate() {
|
void PCIEnumerate() {
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ void PCIEnumerate() {
|
||||||
|
|
||||||
uint32_t registerData;
|
uint32_t registerData;
|
||||||
|
|
||||||
uint16_t device_id, vendor_id;
|
uint16_t DeviceID, VendorID;
|
||||||
|
|
||||||
uint8_t class_code, subclass_code;
|
uint8_t ClassCode, subclass_code;
|
||||||
|
|
||||||
SerialPrintf("[ PCI] Started PCI Enumeration.");
|
SerialPrintf("[ PCI] Started PCI Enumeration.");
|
||||||
|
|
||||||
|
@ -42,11 +42,11 @@ void PCIEnumerate() {
|
||||||
uint8_t multifunction_bit = header & 0x80; // The multifunction bit is the highest bit of the header
|
uint8_t multifunction_bit = header & 0x80; // The multifunction bit is the highest bit of the header
|
||||||
|
|
||||||
registerData = PCIReadConfig(bus, device, function, 0); // Read the Vendor/Device ID register
|
registerData = PCIReadConfig(bus, device, function, 0); // Read the Vendor/Device ID register
|
||||||
vendor_id = (uint16_t) (registerData & 0x0000FFFF); // Vendor ID is bottom word
|
VendorID = (uint16_t) (registerData & 0x0000FFFF); // Vendor ID is bottom word
|
||||||
device_id = (uint16_t) (registerData >> 16); // Device ID is top word
|
DeviceID = (uint16_t) (registerData >> 16); // Device ID is top word
|
||||||
|
|
||||||
registerData = PCIReadConfig(bus, device, function, 8); // Read the Device Info register
|
registerData = PCIReadConfig(bus, device, function, 8); // Read the Device Info register
|
||||||
class_code = (uint16_t)( registerData >> 24); // Device class is top byte, so shift them down
|
ClassCode = (uint16_t)( registerData >> 24); // Device class is top byte, so shift them down
|
||||||
subclass_code = (uint16_t) ((registerData >> 16) & 0x00FF); // Device subclass is same as header - lower byte of higher word. Shift down and mask just like before.
|
subclass_code = (uint16_t) ((registerData >> 16) & 0x00FF); // Device subclass is same as header - lower byte of higher word. Shift down and mask just like before.
|
||||||
uint8_t device_progif = (uint16_t) ((registerData & 0x0000FF00) >> 8); // Device Programming Interface is higher byte of lower word, so mask and shift
|
uint8_t device_progif = (uint16_t) ((registerData & 0x0000FF00) >> 8); // Device Programming Interface is higher byte of lower word, so mask and shift
|
||||||
uint8_t device_revision = (uint16_t) (registerData & 0x000000FF); // Device revision is lower byte of whole double word. Just mask it.
|
uint8_t device_revision = (uint16_t) (registerData & 0x000000FF); // Device revision is lower byte of whole double word. Just mask it.
|
||||||
|
@ -55,9 +55,9 @@ void PCIEnumerate() {
|
||||||
/* 0xFFFF is not a valid Vendor ID. This serves as a sanity check.
|
/* 0xFFFF is not a valid Vendor ID. This serves as a sanity check.
|
||||||
* If this check is true, then nothing is logged and we continue for the next loop.
|
* If this check is true, then nothing is logged and we continue for the next loop.
|
||||||
*/
|
*/
|
||||||
if(vendor_id != 0xFFFF) {
|
if(VendorID != 0xFFFF) {
|
||||||
SerialPrintf("[ PCI]\n[ PCI]\t%x:%x:\n[ PCI]\t\tVendor: %x\n[ PCI]\t\tDevice: %x", bus, device, vendor_id, device_id);
|
SerialPrintf("[ PCI]\n[ PCI]\t%x:%x:\n[ PCI]\t\tVendor: %x\n[ PCI]\t\tDevice: %x", bus, device, VendorID, DeviceID);
|
||||||
SerialPrintf("\n[ PCI]\t\tClass: %s\n[ PCI]\t\tDevice Type: %s\n[ PCI]\t\tRevision: %d\n", PCIGetClassName(class_code), PCIGetDeviceName_Subclass(class_code, subclass_code, device_progif), device_revision);
|
SerialPrintf("\n[ PCI]\t\tClass: %s\n[ PCI]\t\tDevice Type: %s\n[ PCI]\t\tRevision: %d\n", PCIGetClassName(ClassCode), PCIGetDeviceName_Subclass(ClassCode, subclass_code, device_progif), device_revision);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the PCI Device header tells us that this is not a multifunction device,
|
/* If the PCI Device header tells us that this is not a multifunction device,
|
||||||
|
@ -102,11 +102,11 @@ uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offs
|
||||||
return ReadPort(0xCFC, 4);
|
return ReadPort(0xCFC, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_t progif) {
|
const char* PCIGetDeviceName_Subclass(uint8_t DeviceClass, uint8_t Subclass, uint8_t ProgrammableInterface) {
|
||||||
switch(devclass) {
|
switch(DeviceClass) {
|
||||||
|
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Non-VGA-Compatible device";
|
case 0x00: return "Non-VGA-Compatible device";
|
||||||
case 0x01: return "VGA-Compatible device";
|
case 0x01: return "VGA-Compatible device";
|
||||||
default: return "Unknown Unclassified";
|
default: return "Unknown Unclassified";
|
||||||
|
@ -114,10 +114,10 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "SCSI Bus Controller";
|
case 0x00: return "SCSI Bus Controller";
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "ISA Compatibility Mode-only IDE Controller";
|
case 0x00: return "ISA Compatibility Mode-only IDE Controller";
|
||||||
case 0x05: return "PCI Native Mode-only IDE Controller";
|
case 0x05: return "PCI Native Mode-only IDE Controller";
|
||||||
case 0x0A: return "ISA Compatibility Mode IDE Controller (supports PCI Native Mode)";
|
case 0x0A: return "ISA Compatibility Mode IDE Controller (supports PCI Native Mode)";
|
||||||
|
@ -133,7 +133,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
case 0x03: return "IPI Bus Controller";
|
case 0x03: return "IPI Bus Controller";
|
||||||
case 0x04: return "RAID Controller";
|
case 0x04: return "RAID Controller";
|
||||||
case 0x05: {
|
case 0x05: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x20: return "Single-DMA ATA Controller";
|
case 0x20: return "Single-DMA ATA Controller";
|
||||||
case 0x30: return "Chained-DMA ATA Controller";
|
case 0x30: return "Chained-DMA ATA Controller";
|
||||||
default: return "ATA Controller";
|
default: return "ATA Controller";
|
||||||
|
@ -142,7 +142,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
|
|
||||||
|
|
||||||
case 0x06: {
|
case 0x06: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Vendor-Specific Interface SATA Controller";
|
case 0x00: return "Vendor-Specific Interface SATA Controller";
|
||||||
case 0x01: return "AHCI 1.0 SATA Controller";
|
case 0x01: return "AHCI 1.0 SATA Controller";
|
||||||
case 0x02: return "Serial Storage Bus SATA Controller";
|
case 0x02: return "Serial Storage Bus SATA Controller";
|
||||||
|
@ -152,7 +152,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
case 0x07: return "Serial Attached SCSI (SAS)";
|
case 0x07: return "Serial Attached SCSI (SAS)";
|
||||||
|
|
||||||
case 0x08:{
|
case 0x08:{
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x01: return "NVMHCI Memory Controller";
|
case 0x01: return "NVMHCI Memory Controller";
|
||||||
case 0x02: return "NVMe Memory Controller";
|
case 0x02: return "NVMe Memory Controller";
|
||||||
default: return "Non-Volatile Memory Controller";
|
default: return "Non-Volatile Memory Controller";
|
||||||
|
@ -166,7 +166,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x02: {
|
case 0x02: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Ethernet Controller";
|
case 0x00: return "Ethernet Controller";
|
||||||
case 0x01: return "Token Ring Controller";
|
case 0x01: return "Token Ring Controller";
|
||||||
case 0x02: return "FDDI Controller";
|
case 0x02: return "FDDI Controller";
|
||||||
|
@ -182,9 +182,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "VGA Controller";
|
case 0x00: return "VGA Controller";
|
||||||
case 0x01: return "8514 VGA Controller";
|
case 0x01: return "8514 VGA Controller";
|
||||||
default: return "VGA Compatible Controller";
|
default: return "VGA Compatible Controller";
|
||||||
|
@ -199,7 +199,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x04: {
|
case 0x04: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Multimedia Video Controller";
|
case 0x00: return "Multimedia Video Controller";
|
||||||
case 0x01: return "Multimedia Audio Controller";
|
case 0x01: return "Multimedia Audio Controller";
|
||||||
case 0x02: return "Computer Telephony Device";
|
case 0x02: return "Computer Telephony Device";
|
||||||
|
@ -210,7 +210,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x05: {
|
case 0x05: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "RAM Controller";
|
case 0x00: return "RAM Controller";
|
||||||
case 0x01: return "Flash Controller";
|
case 0x01: return "Flash Controller";
|
||||||
case 0x80: return "Other";
|
case 0x80: return "Other";
|
||||||
|
@ -219,7 +219,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x06: {
|
case 0x06: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Host Bridge";
|
case 0x00: return "Host Bridge";
|
||||||
case 0x01: return "ISA Bridge";
|
case 0x01: return "ISA Bridge";
|
||||||
case 0x02: return "EISA Bridge";
|
case 0x02: return "EISA Bridge";
|
||||||
|
@ -238,10 +238,10 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x07: {
|
case 0x07: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
|
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Serial Controller <8250>";
|
case 0x00: return "Serial Controller <8250>";
|
||||||
case 0x01: return "Serial controller <16450>";
|
case 0x01: return "Serial controller <16450>";
|
||||||
case 0x02: return "Serial controller <16550>";
|
case 0x02: return "Serial controller <16550>";
|
||||||
|
@ -255,7 +255,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Standard Parallel Port";
|
case 0x00: return "Standard Parallel Port";
|
||||||
case 0x01: return "Bi-Directional Parallel Port";
|
case 0x01: return "Bi-Directional Parallel Port";
|
||||||
case 0x02: return "ECP 1.X Compliant Parallel Port";
|
case 0x02: return "ECP 1.X Compliant Parallel Port";
|
||||||
|
@ -267,7 +267,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
case 0x02: return "Multiport Serial Controller";
|
case 0x02: return "Multiport Serial Controller";
|
||||||
|
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic Modem";
|
case 0x00: return "Generic Modem";
|
||||||
case 0x01: return "Hayes 16450 Compatible Modem";
|
case 0x01: return "Hayes 16450 Compatible Modem";
|
||||||
case 0x02: return "Hayes 16550 Compatible Modem";
|
case 0x02: return "Hayes 16550 Compatible Modem";
|
||||||
|
@ -285,9 +285,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x08: {
|
case 0x08: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic 8259-Compatible PIC";
|
case 0x00: return "Generic 8259-Compatible PIC";
|
||||||
case 0x01: return "ISA-Compatible PIC";
|
case 0x01: return "ISA-Compatible PIC";
|
||||||
case 0x02: return "EISA-Compatible PIC";
|
case 0x02: return "EISA-Compatible PIC";
|
||||||
|
@ -298,7 +298,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x01: {
|
case 0x01: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic 8237-Compatible DMA Controller";
|
case 0x00: return "Generic 8237-Compatible DMA Controller";
|
||||||
case 0x01: return "ISA-Compatible DMA Controller";
|
case 0x01: return "ISA-Compatible DMA Controller";
|
||||||
case 0x02: return "EISA-Compatible DMA Controller";
|
case 0x02: return "EISA-Compatible DMA Controller";
|
||||||
|
@ -307,7 +307,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x02: {
|
case 0x02: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic 8254-Compatible Timer";
|
case 0x00: return "Generic 8254-Compatible Timer";
|
||||||
case 0x01: return "ISA-Compatible Timer";
|
case 0x01: return "ISA-Compatible Timer";
|
||||||
case 0x02: return "EISA-Compatible Timer";
|
case 0x02: return "EISA-Compatible Timer";
|
||||||
|
@ -317,7 +317,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic RTC Controller";
|
case 0x00: return "Generic RTC Controller";
|
||||||
case 0x01: return "ISA-Compatible RTC Controller";
|
case 0x01: return "ISA-Compatible RTC Controller";
|
||||||
default: return "RTC Controller";
|
default: return "RTC Controller";
|
||||||
|
@ -334,14 +334,14 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x09: {
|
case 0x09: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Keyboard Controller";
|
case 0x00: return "Keyboard Controller";
|
||||||
case 0x01: return "Digitiser Pen";
|
case 0x01: return "Digitiser Pen";
|
||||||
case 0x02: return "Mouse Controller";
|
case 0x02: return "Mouse Controller";
|
||||||
case 0x03: return "Scanner Controller";
|
case 0x03: return "Scanner Controller";
|
||||||
|
|
||||||
case 0x04: {
|
case 0x04: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic Gameport Controller";
|
case 0x00: return "Generic Gameport Controller";
|
||||||
case 0x10: return "Extended Gameport Controller";
|
case 0x10: return "Extended Gameport Controller";
|
||||||
default: return "Gameport Controller";
|
default: return "Gameport Controller";
|
||||||
|
@ -355,7 +355,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0A: {
|
case 0x0A: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Generic Docking Station";
|
case 0x00: return "Generic Docking Station";
|
||||||
case 0x80: return "Other";
|
case 0x80: return "Other";
|
||||||
default: return "Unknown Docking Station";
|
default: return "Unknown Docking Station";
|
||||||
|
@ -363,7 +363,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0B: {
|
case 0x0B: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "386 Processor";
|
case 0x00: return "386 Processor";
|
||||||
case 0x01: return "486 Processor";
|
case 0x01: return "486 Processor";
|
||||||
case 0x02: return "Pentium Processor";
|
case 0x02: return "Pentium Processor";
|
||||||
|
@ -378,9 +378,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0C: {
|
case 0x0C: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: {
|
case 0x00: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "Generic Firewire Controller";
|
case 0x00: return "Generic Firewire Controller";
|
||||||
case 0x10: return "OHCI Firewire Controller";
|
case 0x10: return "OHCI Firewire Controller";
|
||||||
default: return "FireWire (IEEE 1394) Controller";
|
default: return "FireWire (IEEE 1394) Controller";
|
||||||
|
@ -391,7 +391,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
case 0x02: return "SSA";
|
case 0x02: return "SSA";
|
||||||
|
|
||||||
case 0x03: {
|
case 0x03: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "UHCI USB Controller";
|
case 0x00: return "UHCI USB Controller";
|
||||||
case 0x10: return "OHCI USB Controller";
|
case 0x10: return "OHCI USB Controller";
|
||||||
case 0x20: return "EHCI USB (2.0) Controller";
|
case 0x20: return "EHCI USB (2.0) Controller";
|
||||||
|
@ -407,7 +407,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
case 0x06: return "InfiniBand";
|
case 0x06: return "InfiniBand";
|
||||||
|
|
||||||
case 0x07: {
|
case 0x07: {
|
||||||
switch(progif) {
|
switch(ProgrammableInterface) {
|
||||||
case 0x00: return "SMIC IPMI Interface";
|
case 0x00: return "SMIC IPMI Interface";
|
||||||
case 0x01: return "Keyboard Controller-Style IPMI Interface";
|
case 0x01: return "Keyboard Controller-Style IPMI Interface";
|
||||||
case 0x02: return "Block Transfer IPMI Interface";
|
case 0x02: return "Block Transfer IPMI Interface";
|
||||||
|
@ -423,7 +423,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0D: {
|
case 0x0D: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "IRDA Compatible Controller";
|
case 0x00: return "IRDA Compatible Controller";
|
||||||
case 0x01: return "Consumer IR Controller";
|
case 0x01: return "Consumer IR Controller";
|
||||||
case 0x10: return "RF Controller";
|
case 0x10: return "RF Controller";
|
||||||
|
@ -437,14 +437,14 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0E: {
|
case 0x0E: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "I20";
|
case 0x00: return "I20";
|
||||||
default: return "Unknown Intelligent Controller";
|
default: return "Unknown Intelligent Controller";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0F: {
|
case 0x0F: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x01: return "Satellite TV Controller";
|
case 0x01: return "Satellite TV Controller";
|
||||||
case 0x02: return "Satellite Audio Controller";
|
case 0x02: return "Satellite Audio Controller";
|
||||||
case 0x03: return "Satellite Voice Controller";
|
case 0x03: return "Satellite Voice Controller";
|
||||||
|
@ -454,7 +454,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x10: {
|
case 0x10: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "Network & Computing Codec";
|
case 0x00: return "Network & Computing Codec";
|
||||||
case 0x10: return "Entertainment Codec";
|
case 0x10: return "Entertainment Codec";
|
||||||
case 0x80: return "Other Codec";
|
case 0x80: return "Other Codec";
|
||||||
|
@ -463,7 +463,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x11: {
|
case 0x11: {
|
||||||
switch(subclass) {
|
switch(Subclass) {
|
||||||
case 0x00: return "DPIO Modules";
|
case 0x00: return "DPIO Modules";
|
||||||
case 0x01: return "Performance Counters";
|
case 0x01: return "Performance Counters";
|
||||||
case 0x10: return "Communication Synchronizer";
|
case 0x10: return "Communication Synchronizer";
|
||||||
|
@ -489,9 +489,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_
|
||||||
return "Invalid Device!";
|
return "Invalid Device!";
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* PCIGetClassName(uint8_t devclass) {
|
const char* PCIGetClassName(uint8_t DeviceClass) {
|
||||||
|
|
||||||
switch(devclass) {
|
switch(DeviceClass) {
|
||||||
case 0x00: return "Unclassified";
|
case 0x00: return "Unclassified";
|
||||||
case 0x01: return "Mass Storage Controller";
|
case 0x01: return "Mass Storage Controller";
|
||||||
case 0x02: return "Network Controller";
|
case 0x02: return "Network Controller";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user