diff --git a/chroma/inc/kernel/chroma.h b/chroma/inc/kernel/chroma.h index 551248b..6e5beff 100644 --- a/chroma/inc/kernel/chroma.h +++ b/chroma/inc/kernel/chroma.h @@ -20,6 +20,8 @@ #include #include +#include + //Removed cause "wacky copyrighted stuff" //#include @@ -32,6 +34,8 @@ extern volatile size_t* _kernel_text_start; extern address_space_t KernelAddressSpace; +extern e1000_device_t* E1000NIC; + typedef struct { uint32_t magic; uint32_t version; diff --git a/chroma/inc/kernel/system/interrupts.h b/chroma/inc/kernel/system/interrupts.h index 30c2ec5..186402e 100644 --- a/chroma/inc/kernel/system/interrupts.h +++ b/chroma/inc/kernel/system/interrupts.h @@ -31,6 +31,8 @@ typedef void (*IRQHandler)(INTERRUPT_FRAME* Frame); extern IRQHandler IRQ_Handlers[16]; +void InstallIRQ(int IRQ, void (*Handler)(INTERRUPT_FRAME* Frame)); + void IRQ_Common(INTERRUPT_FRAME* Frame, size_t Interupt); void ISR_Common(INTERRUPT_FRAME* Frame, size_t Interrupt); void ISR_Error_Common(INTERRUPT_FRAME* Frame, size_t ErrorCode, size_t Exception); diff --git a/chroma/inc/kernel/system/pci.h b/chroma/inc/kernel/system/pci.h index dc87c27..d5c9665 100644 --- a/chroma/inc/kernel/system/pci.h +++ b/chroma/inc/kernel/system/pci.h @@ -17,100 +17,100 @@ #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(); uint32_t PCIReadConfig(uint8_t bus, uint8_t slot, uint8_t function, uint8_t offset); typedef struct __attribute__((packed)) { - uint8_t io_space : 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 bus_master : 1; // Device is Bus Master; can generate PCI addresses - uint8_t special_cycle : 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 vga_palette : 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 IOMapped : 1; // Device can respond to I/O access + uint8_t MMIOMapped : 1; // Device can respond to memory access (device is MMIO mapped) + uint8_t IsBusMaster : 1; // Device is Bus Master; can generate PCI addresses + uint8_t MonitorSpecialCycle : 1; // Device can monitor Special Cycle + uint8_t AllowMemWriteInvalidate : 1; // Device can generate Memory Write And Invalidate commands; else Memory Write must be used + uint8_t SnoopVGA : 1; // Device snoops the VGA palette on write; else is treated like a normal access + 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 serr : 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 disable_interrupt : 1; // Disable assertion of INTx# signal; else enable. + uint8_t SystemErr : 1; // Enable SERR# driver; System ERRor + uint8_t FastBack2Back : 1; // Device is allowed to generate fast back-to-back transactions to other agents. + uint8_t DisableInterrupt : 1; // Disable assertion of INTx# signal; else enable. } pci_command_t; typedef struct __attribute__((packed)) { 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 capability_list : 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 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 Capabilities : 1; // If set, device will implement New Capabilities list at 0x34 offset. + 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 fast_back_back : 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 devsel_timing : 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 received_target_abort : 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 system_error_asserted : 1; // Device asserted SERR# - uint8_t parity_error : 1; // Device detected parity error. Parity error may not be handled. + uint8_t FastBack2Back : 1; // Device is allowed to accept fast back-to-back transactions from other agents. + uint8_t MasterParityError : 1; // Only set when PERR# is asserted by the Bus Master while pci_command#RespondsParityError is set. + uint8_t DEVSELTiming : 2; // Read-Only; represents the slowest time a device will assert DEVSEL#. 00 = fast, 01 = medium, 11 = slow. + uint8_t TargetAborted : 1; // Target device terminated transaction via Target-Abort + uint8_t ReceivedTargetAbort : 1; // Master's connection was terminated by Target-Abort + uint8_t ReceivedMasterAbort : 1; // Master's connection was terminated by Master-Abort + uint8_t SystemAssertedError : 1; // Device asserted SERR# + uint8_t ParityError : 1; // Device detected parity error. Parity error may not be handled. } pci_status_t; typedef struct __attribute__((packed)) { - uint16_t vendor_id; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid. - uint16_t device_id; // 16 bit Device ID allocated by the vendor. - pci_command_t command; // 16 bit PCI_COMMAND register. - pci_status_t status; // 16 bit PCI_STATUS register. - uint8_t revision_id; // 8 bit register, revision identifier specified by vendor. - uint8_t progIF; // 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 class_code; // 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 latency_timer; // 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 bist; // 8 bit; status and control of a device's built-in self-test (BIST) + uint16_t VendorID; // 16 bit Vendor ID allocated by PCI-SIG. 0xFFFF is invalid. + uint16_t DeviceID; // 16 bit Device ID allocated by the vendor. + pci_command_t Command; // 16 bit PCI_COMMAND register. + pci_status_t Status; // 16 bit PCI_STATUS register. + uint8_t RevisionID; // 8 bit register, revision identifier specified by vendor. + 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 ClassCode; // 8 bit Class Code; identifies the function of the device + 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 LatencyTimer; // 8 bit; specifies latency timer in (bus clock) units. + 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 BuiltInSelfTest; // 8 bit; status and control of a device's built-in self-test (BIST) } pci_header_common_t; typedef struct __attribute__((packed)) { // pci_header_common_t first, then.. - uint32_t bar[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 - uint16_t subsystem_vendor_id; - uint16_t subsystem_id; - uint32_t expansion_bar; // Points to the base of an Expansion ROM. - uint8_t capabilities; // The pointer generated by pci_status#capabilities_list + uint32_t BARs[6]; // 6 x 32 bit Base Address Registers (BARs) + uint32_t CISPtr; // Points to Card Information Structure for PCI devices that share silicon with CardBus + uint16_t SubsysVendor; + uint16_t SubsysID; + uint32_t ExpansionBAR; // Points to the base of an Expansion ROM. + uint8_t Capabilities; // The pointer generated by pci_status#capabilities_list uint8_t _reserved[3]; // 24 bit reserved at top end of register. 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 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 min_grant; // 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 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 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 MinimumTimeshare; // Specifies the length of the burst period, in quarter-microsecond units + uint8_t MaxmimumTimeshare; // Specifies how often the device accesses the PCI bus - in quarter-microseconds } pci_header_device_t; typedef struct __attribute__((packed)) { // pci_header_common_t first - uint32_t bar[2]; - uint8_t pri_bus; // Primary Bus Number. - uint8_t sec_bus; // Secondary Bus Number. - uint8_t sub_bus; // Subordinate Bus Number. - uint8_t sec_latency_timer; // Secondary Latency Timer. - uint8_t io_base; // IO Base is 24 bits. This is lower 8. - uint8_t io_limit; // IO Limit is 24 bits. This is lower 8. - pci_status_t sec_status; // Secondary Status. - uint16_t mem_base; - uint16_t mem_limit; - uint16_t mem_base_prefetch; // 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. - uint32_t mem_base_prefetch_upper; // 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. - uint16_t io_base_upper; // IO Base is 24 bits. This is upper 16. - uint16_t io_limit_upper; // IO Limit is 24 bits. This is upper 16. - uint8_t capabilities; // Pointer generated by pci_status#capabilities_list + uint32_t BARs[2]; + uint8_t PrimaryBus; // Primary Bus Number. + uint8_t SecondaryBus; // Secondary Bus Number. + uint8_t SubordinateBus; // Subordinate Bus Number. + uint8_t LatencyTimer; // Secondary Latency Timer. + uint8_t IOBaseLow; // IO Base is 24 bits. This is lower 8. + uint8_t IOLimitLow; // IO Limit is 24 bits. This is lower 8. + pci_status_t SecondaryStatus; // Secondary Status. + uint16_t MemoryBase; + uint16_t MemoryLimit; + uint16_t PrefetchBaseLow; // Prefetchable Memory Base is 48 bits. This is lower 16. + uint16_t PrefetchLimitLow; // Prefetchable Memory Limit is 48 bits. This is lower 16. + uint32_t PrefetchBaseHigh; // Prefetchable Memory Base is 48 bits. This is upper 32. + uint32_t PrefetchLimitHigh; // Prefetchable Memory Limit is 48 bits. This is upper 32. + uint16_t IOBaseHigh; // IO Base 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 _reserved[3]; // 24 reserved bits. - uint32_t expansion_bar; // 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 interrupt; // 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; + uint32_t ExpansionBAR; // Base of Expansion ROM. + 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 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 BridgeControl; } pci_header_bridge_t; @@ -122,52 +122,53 @@ typedef struct { } pci_address_t; typedef struct { - uint8_t present : 1; - uint8_t mmio : 1; + uint8_t Present : 1; + uint8_t MMIO : 1; union { - size_t addr; - uint16_t port; + size_t Address; + uint16_t Port; }; - size_t length; + + size_t Length; } 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 vendor_id; + uint16_t DeviceID; + uint16_t VendorID; - uint8_t devclass; - uint8_t subclass; + uint8_t DeviceClass; + uint8_t Subclass; - uint8_t progif; + uint8_t ProgrammableInterface; 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! - 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. volatile pci_header_bridge_t* bridge; 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; -} pci_dev_t; +} pci_device_t; typedef struct { pci_address_t key; - pci_dev_t* value; + pci_device_t* value; } pci_entry_t; -extern pci_dev_t** pci_root_devices; +extern pci_device_t** pci_root_devices; extern pci_entry_t* pci_map; \ No newline at end of file diff --git a/chroma/inc/lainlib/ethernet/e1000/e1000.h b/chroma/inc/lainlib/ethernet/e1000/e1000.h new file mode 100644 index 0000000..dcabf21 --- /dev/null +++ b/chroma/inc/lainlib/ethernet/e1000/e1000.h @@ -0,0 +1,181 @@ +/************************ + *** Team Kitty, 2021 *** + *** Chroma *** + ***********************/ + +#include +#include +#include +#include +#include + +#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); diff --git a/chroma/lainlib/ethernet/e1000/E1000Driver.c b/chroma/lainlib/ethernet/e1000/E1000Driver.c new file mode 100644 index 0000000..d45ecce --- /dev/null +++ b/chroma/lainlib/ethernet/e1000/E1000Driver.c @@ -0,0 +1,352 @@ +/************************* + *** Team Kitty, 2021 *** + *** Lainlib *** + ************************/ +#include +#include +#include +#include + +/** + * 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; +} \ No newline at end of file diff --git a/chroma/lainlib/ethernet/ethernet.h b/chroma/lainlib/ethernet/ethernet.h new file mode 100644 index 0000000..7a9a095 --- /dev/null +++ b/chroma/lainlib/ethernet/ethernet.h @@ -0,0 +1,23 @@ +/************************ + *** Team Kitty, 2021 *** + *** Chroma *** + ***********************/ + +#include + +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[]; +}; \ No newline at end of file diff --git a/chroma/system/interrupts.c b/chroma/system/interrupts.c index 8ae348e..3548a2a 100644 --- a/chroma/system/interrupts.c +++ b/chroma/system/interrupts.c @@ -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. */ void UninstallIRQHandler(int IRQ) { 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) { diff --git a/chroma/system/pci.c b/chroma/system/pci.c index 52cbd4c..f8fc482 100644 --- a/chroma/system/pci.c +++ b/chroma/system/pci.c @@ -12,14 +12,14 @@ * */ -pci_dev_t** pci_root_devices = NULL; +pci_device_t** pci_root_devices = NULL; pci_entry_t* pci_map = NULL; //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() { @@ -27,9 +27,9 @@ void PCIEnumerate() { 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."); @@ -42,11 +42,11 @@ void PCIEnumerate() { 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 - vendor_id = (uint16_t) (registerData & 0x0000FFFF); // Vendor ID is bottom word - device_id = (uint16_t) (registerData >> 16); // Device ID is top word + VendorID = (uint16_t) (registerData & 0x0000FFFF); // Vendor ID is bottom word + DeviceID = (uint16_t) (registerData >> 16); // Device ID is top word 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. 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. @@ -55,9 +55,9 @@ void PCIEnumerate() { /* 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(vendor_id != 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("\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); + if(VendorID != 0xFFFF) { + 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(ClassCode), PCIGetDeviceName_Subclass(ClassCode, subclass_code, device_progif), device_revision); } /* 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); } -const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_t progif) { - switch(devclass) { +const char* PCIGetDeviceName_Subclass(uint8_t DeviceClass, uint8_t Subclass, uint8_t ProgrammableInterface) { + switch(DeviceClass) { case 0x00: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Non-VGA-Compatible device"; case 0x01: return "VGA-Compatible device"; default: return "Unknown Unclassified"; @@ -114,10 +114,10 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x01: { - switch(subclass) { + switch(Subclass) { case 0x00: return "SCSI Bus Controller"; case 0x01: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "ISA Compatibility 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)"; @@ -133,7 +133,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ case 0x03: return "IPI Bus Controller"; case 0x04: return "RAID Controller"; case 0x05: { - switch(progif) { + switch(ProgrammableInterface) { case 0x20: return "Single-DMA ATA Controller"; case 0x30: return "Chained-DMA ATA Controller"; default: return "ATA Controller"; @@ -142,7 +142,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ case 0x06: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Vendor-Specific Interface SATA Controller"; case 0x01: return "AHCI 1.0 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 0x08:{ - switch(progif) { + switch(ProgrammableInterface) { case 0x01: return "NVMHCI Memory Controller"; case 0x02: return "NVMe 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: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Ethernet Controller"; case 0x01: return "Token Ring Controller"; case 0x02: return "FDDI Controller"; @@ -182,9 +182,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x03: { - switch(subclass) { + switch(Subclass) { case 0x00: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "VGA Controller"; case 0x01: return "8514 VGA Controller"; default: return "VGA Compatible Controller"; @@ -199,7 +199,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x04: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Multimedia Video Controller"; case 0x01: return "Multimedia Audio Controller"; case 0x02: return "Computer Telephony Device"; @@ -210,7 +210,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x05: { - switch(subclass) { + switch(Subclass) { case 0x00: return "RAM Controller"; case 0x01: return "Flash Controller"; case 0x80: return "Other"; @@ -219,7 +219,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x06: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Host Bridge"; case 0x01: return "ISA Bridge"; case 0x02: return "EISA Bridge"; @@ -238,10 +238,10 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x07: { - switch(subclass) { + switch(Subclass) { case 0x00: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Serial Controller <8250>"; case 0x01: return "Serial controller <16450>"; case 0x02: return "Serial controller <16550>"; @@ -255,7 +255,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x01: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Standard Parallel Port"; case 0x01: return "Bi-Directional 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 0x03: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic Modem"; case 0x01: return "Hayes 16450 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: { - switch(subclass) { + switch(Subclass) { case 0x00: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic 8259-Compatible PIC"; case 0x01: return "ISA-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: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic 8237-Compatible DMA Controller"; case 0x01: return "ISA-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: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic 8254-Compatible Timer"; case 0x01: return "ISA-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: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic RTC Controller"; case 0x01: return "ISA-Compatible RTC Controller"; default: return "RTC Controller"; @@ -334,14 +334,14 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x09: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Keyboard Controller"; case 0x01: return "Digitiser Pen"; case 0x02: return "Mouse Controller"; case 0x03: return "Scanner Controller"; case 0x04: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic Gameport Controller"; case 0x10: return "Extended Gameport Controller"; default: return "Gameport Controller"; @@ -355,7 +355,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x0A: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Generic Docking Station"; case 0x80: return "Other"; default: return "Unknown Docking Station"; @@ -363,7 +363,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x0B: { - switch(subclass) { + switch(Subclass) { case 0x00: return "386 Processor"; case 0x01: return "486 Processor"; case 0x02: return "Pentium Processor"; @@ -378,9 +378,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x0C: { - switch(subclass) { + switch(Subclass) { case 0x00: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "Generic Firewire Controller"; case 0x10: return "OHCI Firewire 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 0x03: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "UHCI USB Controller"; case 0x10: return "OHCI USB 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 0x07: { - switch(progif) { + switch(ProgrammableInterface) { case 0x00: return "SMIC IPMI Interface"; case 0x01: return "Keyboard Controller-Style 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: { - switch(subclass) { + switch(Subclass) { case 0x00: return "IRDA Compatible Controller"; case 0x01: return "Consumer IR Controller"; case 0x10: return "RF Controller"; @@ -437,14 +437,14 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x0E: { - switch(subclass) { + switch(Subclass) { case 0x00: return "I20"; default: return "Unknown Intelligent Controller"; } } case 0x0F: { - switch(subclass) { + switch(Subclass) { case 0x01: return "Satellite TV Controller"; case 0x02: return "Satellite Audio Controller"; case 0x03: return "Satellite Voice Controller"; @@ -454,7 +454,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x10: { - switch(subclass) { + switch(Subclass) { case 0x00: return "Network & Computing Codec"; case 0x10: return "Entertainment Codec"; case 0x80: return "Other Codec"; @@ -463,7 +463,7 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ } case 0x11: { - switch(subclass) { + switch(Subclass) { case 0x00: return "DPIO Modules"; case 0x01: return "Performance Counters"; case 0x10: return "Communication Synchronizer"; @@ -489,9 +489,9 @@ const char* PCIGetDeviceName_Subclass(uint8_t devclass, uint8_t subclass, uint8_ return "Invalid Device!"; } -const char* PCIGetClassName(uint8_t devclass) { +const char* PCIGetClassName(uint8_t DeviceClass) { - switch(devclass) { + switch(DeviceClass) { case 0x00: return "Unclassified"; case 0x01: return "Mass Storage Controller"; case 0x02: return "Network Controller";