feat: started pci driver structure and ide driver structure
This commit is contained in:
19
kernel/drivers/ide.c
Normal file
19
kernel/drivers/ide.c
Normal file
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// Created by rick on 03-02-21.
|
||||
//
|
||||
|
||||
#include "ide.h"
|
||||
#include <types.h>
|
||||
#include <kprint.h>
|
||||
#include <drivers/pci.h>
|
||||
|
||||
const char* ide_pci_driver_name = "pci-ide";
|
||||
|
||||
void ide_handle_pci_device(u8 bus, u8 slot, u8 func) {
|
||||
kprint("IDE registered");
|
||||
// todo
|
||||
}
|
||||
|
||||
void ide_register() {
|
||||
pci_register_driver(PCI_CLASS_MASS_STORAGE, PCI_SUB_CLASS_IDE, PCI_FLAG_USE_SUBCLASS, ide_handle_pci_device, ide_pci_driver_name);
|
||||
}
|
||||
10
kernel/drivers/ide.h
Normal file
10
kernel/drivers/ide.h
Normal file
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// Created by rick on 03-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_IDE_H
|
||||
#define NEW_KERNEL_IDE_H
|
||||
|
||||
void ide_register();
|
||||
|
||||
#endif //NEW_KERNEL_IDE_H
|
||||
282
kernel/drivers/pci.c
Normal file
282
kernel/drivers/pci.c
Normal file
@@ -0,0 +1,282 @@
|
||||
//
|
||||
// Created by rick on 02-02-21.
|
||||
//
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#include <types.h>
|
||||
#include <drivers/ports.h>
|
||||
#include <libc/libc.h>
|
||||
#include <kprint.h>
|
||||
#include <libk.h>
|
||||
|
||||
#define PCI_CONFIG_ENABLE (1 << 31)
|
||||
|
||||
#define PCI_CONFIG_SHIFT_BUS_NUMBER 16
|
||||
#define PCI_CONFIG_SHIFT_DEV_NUMBER 11
|
||||
#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
|
||||
|
||||
typedef struct {
|
||||
pci_driver driver;
|
||||
const char *driver_name;
|
||||
u8 pci_class;
|
||||
u8 pci_subclass;
|
||||
union {
|
||||
u8 flags;
|
||||
struct {
|
||||
u8 pci_use_subclass: 1;
|
||||
};
|
||||
};
|
||||
} pci_driver_info;
|
||||
|
||||
typedef struct {
|
||||
u8 bus;
|
||||
u8 slot;
|
||||
u8 func;
|
||||
union {
|
||||
struct {
|
||||
u16 vendorId;
|
||||
u16 deviceId;
|
||||
};
|
||||
u32 config_line_0;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
u8 revisionId;
|
||||
u8 programInterface;
|
||||
u8 subclass;
|
||||
u8 class;
|
||||
};
|
||||
u32 config_line_2;
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
u8 cacheLineSize;
|
||||
u8 latencyTimer;
|
||||
u8 headerType;
|
||||
u8 bist;
|
||||
};
|
||||
u32 config_line_3;
|
||||
};
|
||||
pci_driver_info *driver_info;
|
||||
} pci_device;
|
||||
|
||||
pci_driver_info pci_drivers[MAX_PCI_DRIVERS];
|
||||
int last_pci_device_index = 0;
|
||||
pci_device pci_devices[MAX_PCI_DEVICES];
|
||||
|
||||
u32 pci_register_driver(u8 pci_class, u8 pci_subclass, u8 flags, pci_driver driver, const char *driver_name) {
|
||||
for (int i = 0; i < MAX_PCI_DRIVERS; ++i) {
|
||||
if (pci_drivers[i].driver == NULL) {
|
||||
pci_drivers[i].driver = driver;
|
||||
pci_drivers[i].pci_class = pci_class;
|
||||
pci_drivers[i].pci_subclass = pci_subclass;
|
||||
pci_drivers[i].flags = flags;
|
||||
pci_drivers[i].driver_name = driver_name;
|
||||
return PCI_REGISTER_OK;
|
||||
}
|
||||
}
|
||||
return PCI_REGISTER_ERR_FULL;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
port_double_word_out(PORT_PCI_CONFIG_ADDRESS, address);
|
||||
return port_double_word_in(PORT_PCI_CONFIG_DATA) >> ((offset & 0b11) * 8) & 0xFF;
|
||||
}
|
||||
|
||||
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);
|
||||
kprint(buf);
|
||||
}
|
||||
|
||||
void print_u16(u16 val) {
|
||||
char buf[5];
|
||||
itoa(val, buf, 16);
|
||||
kprint(buf);
|
||||
}
|
||||
|
||||
void pci_pick_driver(pci_device *device) {
|
||||
for (int i = 0; i < MAX_PCI_DRIVERS; ++i) {
|
||||
if (pci_drivers[i].driver == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (device->class == pci_drivers[i].pci_class) {
|
||||
if (!pci_drivers[i].pci_use_subclass || device->subclass == pci_drivers[i].pci_subclass) {
|
||||
pci_drivers[i].driver(device->bus, device->slot, device->func);
|
||||
device->driver_info = &pci_drivers[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pci_check_function(u8 bus, u8 slot, u8 func) {
|
||||
pci_devices[last_pci_device_index].bus = bus;
|
||||
pci_devices[last_pci_device_index].slot = slot;
|
||||
pci_devices[last_pci_device_index].func = func;
|
||||
pci_devices[last_pci_device_index].config_line_0 = pci_config_read_double_word(bus, slot, func, PCI_CONFIG_LINE_0);
|
||||
pci_devices[last_pci_device_index].config_line_2 = pci_config_read_double_word(bus, slot, func, PCI_CONFIG_LINE_2);
|
||||
pci_devices[last_pci_device_index].config_line_3 = pci_config_read_double_word(bus, slot, func, PCI_CONFIG_LINE_3);
|
||||
pci_pick_driver(&pci_devices[last_pci_device_index]);
|
||||
last_pci_device_index++;
|
||||
|
||||
// todo do something with the function
|
||||
}
|
||||
|
||||
void pci_check_device(u8 bus, u8 device) {
|
||||
u8 function = 0;
|
||||
u16 vendor_id = pci_get_vendor_id(bus, device, function);
|
||||
if (vendor_id == 0xFFFF) return;
|
||||
pci_check_function(bus, device, function);
|
||||
u8 header_type = pci_get_header_type(bus, device, function);
|
||||
if (header_type & PCI_HEADER_TYPE_MULTI_FUNC) {
|
||||
for (function = 1; function < 8; ++function) {
|
||||
if (pci_get_vendor_id(bus, device, function) != 0xFFFF) {
|
||||
pci_check_function(bus, device, function);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pci_check_bus(u8 bus) {
|
||||
for (int device = 0; device < 32; ++device) {
|
||||
pci_check_device(bus, device);
|
||||
}
|
||||
}
|
||||
|
||||
void pci_scan() {
|
||||
if (last_pci_device_index != 0) {
|
||||
k_panics("Can only scan once!");
|
||||
}
|
||||
u8 header_type = pci_get_header_type(0, 0, 0);
|
||||
if (header_type & PCI_HEADER_TYPE_MULTI_FUNC) {
|
||||
// multiple pci host controllers
|
||||
for (int function = 0; function < 8; ++function) {
|
||||
pci_check_bus(function);
|
||||
}
|
||||
} else {
|
||||
pci_check_bus(0);
|
||||
}
|
||||
}
|
||||
|
||||
void pci_print_info() {
|
||||
for (int i = 0; i < last_pci_device_index; ++i) {
|
||||
kprint("PCI BSF: ");
|
||||
print_u8(pci_devices[i].bus);
|
||||
kprint("/");
|
||||
print_u8(pci_devices[i].slot);
|
||||
kprint("/");
|
||||
print_u8(pci_devices[i].func);
|
||||
kprint(", Class/Sub/If: ");
|
||||
print_u8(pci_devices[i].class);
|
||||
kprint("/");
|
||||
print_u8(pci_devices[i].subclass);
|
||||
kprint("/");
|
||||
print_u8(pci_devices[i].programInterface);
|
||||
|
||||
kprint(", V/D: ");
|
||||
print_u16(pci_devices[i].vendorId);
|
||||
kprint("/");
|
||||
print_u16(pci_devices[i].deviceId);
|
||||
kprint(" driver_info: ");
|
||||
|
||||
if (pci_devices[i].driver_info == NULL) {
|
||||
kprint("NULL");
|
||||
} else {
|
||||
kprint(pci_devices[i].driver_info->driver_name);
|
||||
}
|
||||
|
||||
kprint("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// todo https://wiki.osdev.org/PCI
|
||||
// todo https://wiki.osdev.org/PCI_IDE_Controller
|
||||
// todo https://wiki.osdev.org/Universal_Serial_Bus if i dare
|
||||
25
kernel/drivers/pci.h
Normal file
25
kernel/drivers/pci.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Created by rick on 02-02-21.
|
||||
//
|
||||
|
||||
#ifndef NEW_KERNEL_PCI_H
|
||||
#define NEW_KERNEL_PCI_H
|
||||
#include <types.h>
|
||||
|
||||
#define PCI_CLASS_MASS_STORAGE 0x01
|
||||
|
||||
#define PCI_SUB_CLASS_IDE 0x01
|
||||
|
||||
#define PCI_FLAG_USE_SUBCLASS (1 << 0)
|
||||
#define PCI_REGISTER_OK 0;
|
||||
#define PCI_REGISTER_ERR_FULL -1;
|
||||
|
||||
typedef void (*pci_driver)(u8 bus, u8 slot, u8 func);
|
||||
|
||||
void pci_print_info();
|
||||
|
||||
u32 pci_register_driver(u8 pci_class, u8 pci_subclass, u8 flags, pci_driver driver, const char *driver_name);
|
||||
|
||||
void pci_scan();
|
||||
|
||||
#endif //NEW_KERNEL_PCI_H
|
||||
@@ -28,6 +28,15 @@ unsigned short port_word_in(unsigned short port) {
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_wordt_out(unsigned short port, unsigned short data) {
|
||||
void port_word_out(unsigned short port, unsigned short data) {
|
||||
__asm__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
unsigned int port_double_word_in(unsigned int port) {
|
||||
unsigned int result;
|
||||
__asm__("in %%dx, %%eax" : "=a" (result) : "d" (port));
|
||||
return result;
|
||||
}
|
||||
|
||||
void port_double_word_out(unsigned short port, unsigned int data) {
|
||||
__asm__("out %%eax, %%dx" : : "a" (data), "d" (port));
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
#define PORT_PS2_STATUS 0x64
|
||||
#define PORT_PS2_COMMAND 0x64
|
||||
|
||||
// https://wiki.osdev.org/PCI
|
||||
#define PORT_PCI_CONFIG_ADDRESS (0xCF8)
|
||||
#define PORT_PCI_CONFIG_DATA (0xCFC)
|
||||
|
||||
unsigned char port_byte_in(unsigned short port);
|
||||
|
||||
void port_byte_out(unsigned short port, unsigned char data);
|
||||
@@ -48,4 +52,8 @@ unsigned short port_word_in(unsigned short port);
|
||||
|
||||
void port_word_out(unsigned short port, unsigned short data);
|
||||
|
||||
unsigned int port_double_word_in(unsigned int port);
|
||||
|
||||
void port_double_word_out(unsigned short port, unsigned int data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <libc/readline.h>
|
||||
#include <libc/string.h>
|
||||
#include <libk.h>
|
||||
#include <drivers/pci.h>
|
||||
#include <drivers/ide.h>
|
||||
|
||||
#define BOOTLOADER_NAME_MAX_LENGTH 64
|
||||
#define CMDLINE_MAX_LENGTH 256
|
||||
@@ -78,6 +80,8 @@ void print(const char *arg) {
|
||||
print_current_tick();
|
||||
} else if (strcmp(arg, "bootinfo") == 0) {
|
||||
print_bootinfo();
|
||||
} else if (strcmp(arg, "pci") == 0) {
|
||||
pci_print_info();
|
||||
} else {
|
||||
kprint("Unknown print ");
|
||||
kprint(arg);
|
||||
@@ -129,6 +133,12 @@ void kmain(multiboot_info_t *multiboot_info) {
|
||||
store_bootloader_info(multiboot_info);
|
||||
init_mmap(multiboot_info);
|
||||
|
||||
// register drivers
|
||||
ide_register();
|
||||
|
||||
// scan PCI
|
||||
pci_scan();
|
||||
|
||||
kprint(msg_booted);
|
||||
kprint(newline);
|
||||
|
||||
|
||||
@@ -9,6 +9,13 @@ void k_wait_for_interrupt() {
|
||||
__asm__ __volatile__("hlt;");
|
||||
}
|
||||
|
||||
void k_panics(const char* msg) {
|
||||
kprint(msg);
|
||||
kprint("PANIC!");
|
||||
__asm__ __volatile__("cli;"
|
||||
"hlt;");
|
||||
}
|
||||
|
||||
void k_panic() {
|
||||
kprint("PANIC!");
|
||||
__asm__ __volatile__("cli;"
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
void k_wait_for_interrupt();
|
||||
|
||||
void k_panics(const char* msg);
|
||||
|
||||
void k_panic();
|
||||
|
||||
#endif //NEW_KERNEL_LIBK_H
|
||||
|
||||
Reference in New Issue
Block a user