first version of ide controller
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
//
|
||||
// Created by rick on 02-02-21.
|
||||
//
|
||||
// https://wiki.osdev.org/PCI
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
@@ -17,42 +18,17 @@
|
||||
#define PCI_CONFIG_SHIFT_FUNC_NUMBER 8
|
||||
|
||||
#define PCI_CONFIG_LINE_0 0x00
|
||||
#define PCI_CONFIG_VENDOR_ID 0x00
|
||||
#define PCI_CONFIG_DEVICE_ID 0x02
|
||||
#define PCI_CONFIG_LINE_1 0x01
|
||||
#define PCI_CONFIG_COMMAND 0x04
|
||||
#define PCI_CONFIG_STATUS 0x06
|
||||
#define PCI_CONFIG_LINE_2 0x08
|
||||
#define PCI_CONFIG_REVISION_ID 0x08
|
||||
#define PCI_CONFIG_PROG_IF 0x09
|
||||
#define PCI_CONFIG_SUBCLASS 0x0A
|
||||
#define PCI_CONFIG_CLASS_CODE 0x0B
|
||||
#define PCI_CONFIG_LINE_3 0x0C
|
||||
#define PCI_CONFIG_CACHE_LINE_SIZE 0x0C
|
||||
#define PCI_CONFIG_LATENCY_TIMER 0x0D
|
||||
#define PCI_CONFIG_HEADER_TYPE 0x0E
|
||||
#define PCI_CONFIG_BIST 0x0F
|
||||
#define PCI_CONFIG_BAR0 0x10
|
||||
#define PCI_CONFIG_BAR1 0x14
|
||||
#define PCI_CONFIG_BAR2 0x18
|
||||
#define PCI_CONFIG_BAR3 0x1C
|
||||
#define PCI_CONFIG_BAR4 0x20
|
||||
#define PCI_CONFIG_BAR5 0x24
|
||||
#define PCI_CONFIG_CARDBUS_CIS_P 0x28
|
||||
#define PCI_CONFIG_SUBSYSTEM_VENDOR_ID 0x2C
|
||||
#define PCI_CONFIG_SUBSYSTEM_ID 0x2E
|
||||
#define PCI_CONFIG_EXPANSION_ROM_ADDR 0x30
|
||||
#define PCI_CONFIG_CAP_POINTER 0x34
|
||||
#define PCI_CONFIG_INTERRUPT_LINE 0x3C
|
||||
#define PCI_CONFIG_INTERRUPT_PIN 0x3D
|
||||
#define PCI_CONFIG_MAX_GRANT 0x3E
|
||||
#define PCI_CONFIG_MAX_LATENCY 0x3F
|
||||
|
||||
#define PCI_HEADER_TYPE_MULTI_FUNC 0x80
|
||||
|
||||
#define MAX_PCI_DRIVERS 64
|
||||
#define MAX_PCI_DEVICES 64
|
||||
|
||||
#define MASK_BAR_IOSPACE 0xFFFFFFFC
|
||||
#define MASK_BAR_MEMSPACE 0xFFFFFFF0
|
||||
|
||||
const pci_driver *pci_drivers[MAX_PCI_DRIVERS];
|
||||
int last_pci_device_index = 0;
|
||||
pci_device pci_devices[MAX_PCI_DEVICES];
|
||||
@@ -68,61 +44,58 @@ u32 pci_register_driver(const pci_driver *pci_driver) {
|
||||
return PCI_REGISTER_ERR_FULL;
|
||||
}
|
||||
|
||||
u32 pci_config_address(u8 bus, u8 slot, u8 func, u8 offset) {
|
||||
return PCI_CONFIG_ENABLE
|
||||
| ((u32) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
||||
| ((u32) slot << PCI_CONFIG_SHIFT_DEV_NUMBER)
|
||||
| ((u32) func << PCI_CONFIG_SHIFT_FUNC_NUMBER)
|
||||
| (offset & 0xFC);
|
||||
}
|
||||
|
||||
u32 pci_config_read_double_word(u8 bus, u8 slot, u8 func, u8 offset) {
|
||||
u32 address = PCI_CONFIG_ENABLE
|
||||
| ((u32) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
||||
| ((u32) slot << PCI_CONFIG_SHIFT_DEV_NUMBER)
|
||||
| ((u32) func << PCI_CONFIG_SHIFT_FUNC_NUMBER)
|
||||
| (offset & 0xFC);
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
return port_double_word_in(PORT_PCI_CONFIG_DATA);
|
||||
}
|
||||
|
||||
u16 pci_config_read_word(u8 bus, u8 slot, u8 func, u8 offset) {
|
||||
u32 address = PCI_CONFIG_ENABLE
|
||||
| ((u32) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
||||
| ((u32) slot << PCI_CONFIG_SHIFT_DEV_NUMBER)
|
||||
| ((u32) func << PCI_CONFIG_SHIFT_FUNC_NUMBER)
|
||||
| (offset & 0xFC);
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
return port_double_word_in(PORT_PCI_CONFIG_DATA) >> ((offset & 2) * 8) & 0xFFFF;
|
||||
}
|
||||
|
||||
u8 pci_config_read_byte(u8 bus, u8 slot, u8 func, u8 offset) {
|
||||
u32 address = PCI_CONFIG_ENABLE
|
||||
| ((u32) bus << PCI_CONFIG_SHIFT_BUS_NUMBER)
|
||||
| ((u32) slot << PCI_CONFIG_SHIFT_DEV_NUMBER)
|
||||
| ((u32) func << PCI_CONFIG_SHIFT_FUNC_NUMBER)
|
||||
| (offset & 0xFC);
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
return port_double_word_in(PORT_PCI_CONFIG_DATA) >> ((offset & 0b11) * 8) & 0xFF;
|
||||
}
|
||||
|
||||
void pci_config_write_double_word(u8 bus, u8 slot, u8 func, u8 offset, u32 value) {
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
port_double_word_out(PORT_PCI_CONFIG_DATA, value);
|
||||
}
|
||||
|
||||
void pci_config_write_word(u8 bus, u8 slot, u8 func, u8 offset, u16 value) {
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
port_word_out(PORT_PCI_CONFIG_DATA, value);
|
||||
}
|
||||
|
||||
void pci_config_write_byte(u8 bus, u8 slot, u8 func, u8 offset, u8 value) {
|
||||
u32 address = pci_config_address(bus, slot, func, offset);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
port_byte_out(PORT_PCI_CONFIG_DATA, value);
|
||||
}
|
||||
|
||||
u16 pci_get_vendor_id(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_word(bus, slot, func, PCI_CONFIG_VENDOR_ID);
|
||||
}
|
||||
|
||||
u16 pci_get_device_id(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_word(bus, slot, func, PCI_CONFIG_DEVICE_ID);
|
||||
}
|
||||
|
||||
u8 pci_get_prog_if(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_byte(bus, slot, func, PCI_CONFIG_PROG_IF);
|
||||
}
|
||||
|
||||
u8 pci_get_header_type(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_byte(bus, slot, func, PCI_CONFIG_HEADER_TYPE);
|
||||
}
|
||||
|
||||
u8 pci_get_class_code(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_byte(bus, slot, func, PCI_CONFIG_CLASS_CODE);
|
||||
}
|
||||
|
||||
u8 pci_get_subclass_code(u8 bus, u8 slot, u8 func) {
|
||||
return pci_config_read_byte(bus, slot, func, PCI_CONFIG_SUBCLASS);
|
||||
}
|
||||
|
||||
void print_u8(u8 val) {
|
||||
char buf[3];
|
||||
itoa(val, buf, 16);
|
||||
@@ -187,6 +160,7 @@ void pci_check_bus(u8 bus) {
|
||||
pci_check_device(bus, device);
|
||||
}
|
||||
}
|
||||
|
||||
void pci_sort_drivers() {
|
||||
// todo
|
||||
}
|
||||
@@ -253,6 +227,64 @@ void pci_print_info() {
|
||||
}
|
||||
}
|
||||
|
||||
// todo https://wiki.osdev.org/PCI
|
||||
// todo https://wiki.osdev.org/PCI_IDE_Controller
|
||||
void pci_init_bar(pci_device *device, u8 bar_index) {
|
||||
if (device->headerType != 0x00) {
|
||||
k_panics("Only header 0x00 supported for now");
|
||||
return;
|
||||
}
|
||||
u8 offset = 0;
|
||||
bar_info *bar;
|
||||
switch (bar_index) {
|
||||
case 0:
|
||||
offset = PCI_CONFIG_BAR0;
|
||||
bar = &device->bar0;
|
||||
break;
|
||||
case 1:
|
||||
offset = PCI_CONFIG_BAR1;
|
||||
bar = &device->bar1;
|
||||
break;
|
||||
case 2:
|
||||
offset = PCI_CONFIG_BAR2;
|
||||
bar = &device->bar2;
|
||||
break;
|
||||
case 3:
|
||||
offset = PCI_CONFIG_BAR3;
|
||||
bar = &device->bar3;
|
||||
break;
|
||||
case 4:
|
||||
offset = PCI_CONFIG_BAR4;
|
||||
bar = &device->bar4;
|
||||
break;
|
||||
case 5:
|
||||
offset = PCI_CONFIG_BAR5;
|
||||
bar = &device->bar5;
|
||||
break;
|
||||
default:
|
||||
k_panics("Bar index too high");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
u32 original_address = pci_config_read_double_word(device->bus, device->slot, device->func, offset);
|
||||
pci_config_write_double_word(device->bus, device->slot, device->func, offset, 0xFFFFFFFF);
|
||||
u32 masked_size = pci_config_read_double_word(device->bus, device->slot, device->func, offset);
|
||||
|
||||
if (original_address & 0x1) {
|
||||
// IO Space
|
||||
bar->size = ~(masked_size & MASK_BAR_IOSPACE) + 1;
|
||||
bar->address = original_address & MASK_BAR_IOSPACE;
|
||||
bar->is_io_space = 1;
|
||||
} else {
|
||||
// Memory space
|
||||
bar->size = ~(masked_size & MASK_BAR_MEMSPACE) + 1;
|
||||
bar->address = original_address & 0xFFFFFFF0;
|
||||
bar->is_io_space = 0;
|
||||
bar->type = (original_address & 0b110) >> 1;
|
||||
bar->prefetchable = (original_address & 0b111000) >> 3;
|
||||
}
|
||||
// todo identify conflicts, move to different address
|
||||
pci_config_write_double_word(device->bus, device->slot, device->func, offset, original_address);
|
||||
bar->present = 1;
|
||||
}
|
||||
|
||||
// todo https://wiki.osdev.org/Universal_Serial_Bus if i dare
|
||||
Reference in New Issue
Block a user