summaryrefslogtreecommitdiff
path: root/kernel/src/devices
diff options
context:
space:
mode:
authorAleksa Vuckovic <aleksa@vuckovic.cc>2023-06-07 01:23:03 +0200
committerAleksa Vuckovic <aleksa@vuckovic.cc>2023-06-07 01:23:03 +0200
commit90e2de72ef2688986c206fd08605aec81b5890d6 (patch)
tree0a72bf0b2f2a564f3fc18314e6ea1cbe524eb28f /kernel/src/devices
parentf5826164936359560ef5b88b97fc953065eb7794 (diff)
sata & ahciHEADmaster
Diffstat (limited to 'kernel/src/devices')
-rw-r--r--kernel/src/devices/pci.c67
-rw-r--r--kernel/src/devices/sata.c73
2 files changed, 110 insertions, 30 deletions
diff --git a/kernel/src/devices/pci.c b/kernel/src/devices/pci.c
index 9862dee..ea6c80e 100644
--- a/kernel/src/devices/pci.c
+++ b/kernel/src/devices/pci.c
@@ -9,7 +9,9 @@
#include <pci.h>
#include <pci_info.h>
-inline void pci_print_dev(pci_dev *pci_func)
+pci_dev_list_t pci_dev_list;
+
+inline void pci_print_dev(pci_dev_t *pci_func)
{
const char *vendor_str = get_vendor(pci_func->vendor_id);
const char *class_str = get_class(pci_func->class_);
@@ -54,18 +56,20 @@ void enumerate_function(uint64_t dev_addr, uint64_t function)
uint64_t func_addr = dev_addr + (function << 12);
map_addr(func_addr, func_addr, FLAG_PRESENT);
- pci_dev *pci_func = (pci_dev *)kalloc(sizeof(pci_dev));
- memcpy(pci_func, (uint64_t *)func_addr, sizeof(pci_dev));
+ pci_dev0_t *pci_func = (pci_dev0_t *)kalloc(sizeof(pci_dev0_t));
+ memcpy(pci_func, (uint64_t *)func_addr, sizeof(pci_dev0_t));
- if (pci_func->device_id == 0)
- goto error;
- if (pci_func->device_id == 0xFFFF)
- goto error;
+ int id = pci_func->pci_dev.device_id;
+ if (id == 0 || id == 0xFFFF) {
+ kfree(pci_func);
+ return;
+ }
- pci_print_dev(pci_func);
+ pci_dev_list_t *dev_list = kalloc(sizeof(pci_dev_list_t));
+ dev_list->dev = pci_func;
-error:
- kfree(pci_func);
+ add_to_list(&dev_list->list, &pci_dev_list.list,
+ pci_dev_list.list.next);
}
void enumerate_device(uint64_t bus_addr, uint64_t device)
@@ -73,21 +77,18 @@ void enumerate_device(uint64_t bus_addr, uint64_t device)
uint64_t dev_addr = bus_addr + (device << 15);
map_addr(dev_addr, dev_addr, FLAG_PRESENT);
- pci_dev *pci_device = (pci_dev *)kalloc(sizeof(pci_dev));
- memcpy(pci_device, (uint64_t *)bus_addr, sizeof(pci_dev));
+ pci_dev_t *pci_device = (pci_dev_t *)kalloc(sizeof(pci_dev_t));
+ memcpy(pci_device, (uint64_t *)bus_addr, sizeof(pci_dev_t));
- if (pci_device->device_id == 0)
- goto error;
- if (pci_device->device_id == 0xFFFF)
- goto error;
+ if (pci_device->device_id == 0 || pci_device->device_id == 0xFFFF) {
+ kfree(pci_device);
+ return;
+ }
size_t func;
for (func = 0; func < 8; func++) {
enumerate_function(dev_addr, func);
}
-
-error:
- kfree(pci_device);
}
void enumerate_bus(uint64_t base_addr, uint64_t bus)
@@ -95,31 +96,39 @@ void enumerate_bus(uint64_t base_addr, uint64_t bus)
uint64_t bus_addr = base_addr + (bus << 20);
map_addr(bus_addr, bus_addr, FLAG_PRESENT);
- pci_dev *pci_device = (pci_dev *)kalloc(sizeof(pci_dev));
- memcpy(pci_device, (uint64_t *)bus_addr, sizeof(pci_dev));
+ pci_dev_t *pci_device = (pci_dev_t *)kalloc(sizeof(pci_dev_t));
+ memcpy(pci_device, (uint64_t *)bus_addr, sizeof(pci_dev_t));
- if (pci_device->device_id == 0)
- goto error;
- if (pci_device->device_id == 0xFFFF)
- goto error;
+ if (pci_device->device_id == 0 || pci_device->device_id == 0xFFFF) {
+ kfree(pci_device);
+ return;
+ }
size_t dev;
for (dev = 0; dev < 32; dev++) {
enumerate_device(bus_addr, dev);
}
-
-error:
- kfree(pci_device);
}
void enumerate_cfg_space(config_space_mcfgt *cfg_space)
{
+ INIT_LIST(pci_dev_list.list);
+
size_t i;
for (i = cfg_space->start_bus; i < cfg_space->end_bus; i++) {
enumerate_bus(cfg_space->base_addr, i);
}
}
+void pci_print_all()
+{
+ pci_dev_list_t *curr;
+ list_for_each_entry(curr, (&pci_dev_list.list), list) {
+ pci_print_dev(&curr->dev->pci_dev);
+ }
+ printf("\n");
+}
+
void read_mcfgt()
{
uint64_t *mcfgt_addr = find_sys_table_addr("MCFG");
@@ -145,9 +154,7 @@ void read_mcfgt()
for (i = 0; i < len; i++) {
memcpy(cfg_space, (uint64_t *)mcfgt_cfg_addr,
sizeof(config_space_mcfgt));
- /* printf("addr: 0x%x, group: %d, start: %d, stop: %d\n", cfg_space->base_addr, cfg_space->pci_seg_group, cfg_space->start_bus, cfg_space->end_bus); */
enumerate_cfg_space(cfg_space);
}
- printf("\n");
kfree(cfg_space);
}
diff --git a/kernel/src/devices/sata.c b/kernel/src/devices/sata.c
new file mode 100644
index 0000000..d091941
--- /dev/null
+++ b/kernel/src/devices/sata.c
@@ -0,0 +1,73 @@
+#include <sata.h>
+#include <libk/string.h>
+#include <libk/stdio.h>
+#include <heap.h>
+#include <paging.h>
+#include <pci.h>
+#include <ahci.h>
+
+// Check device type
+static int check_type(HBA_PORT *port)
+{
+ uint32_t ssts = port->ssts;
+
+ uint8_t ipm = (ssts >> 8) & 0x0F;
+ uint8_t det = ssts & 0x0F;
+
+ if (det != HBA_PORT_DET_PRESENT) // Check drive status
+ return AHCI_DEV_NULL;
+ if (ipm != HBA_PORT_IPM_ACTIVE)
+ return AHCI_DEV_NULL;
+
+ switch (port->sig) {
+ case SATA_SIG_ATAPI:
+ return AHCI_DEV_SATAPI;
+ case SATA_SIG_SEMB:
+ return AHCI_DEV_SEMB;
+ case SATA_SIG_PM:
+ return AHCI_DEV_PM;
+ default:
+ return AHCI_DEV_SATA;
+ }
+}
+
+void probe_port(HBA_MEM *abar)
+{
+ // Search disk in implemented ports
+ uint32_t pi = abar->pi;
+ int i = 0;
+ while (i < 32) {
+ if (pi & 1) {
+ int dt = check_type(&abar->ports[i]);
+ if (dt == AHCI_DEV_SATA) {
+ printf("SATA drive found at port %d\n", i);
+ } else if (dt == AHCI_DEV_SATAPI) {
+ printf("SATAPI drive found at port %d\n", i);
+ } else if (dt == AHCI_DEV_SEMB) {
+ printf("SEMB drive found at port %d\n", i);
+ } else if (dt == AHCI_DEV_PM) {
+ printf("PM drive found at port %d\n", i);
+ }
+ }
+
+ pi >>= 1;
+ i++;
+ }
+}
+
+void ahci()
+{
+ pci_dev_list_t *pos;
+ list_for_each_entry(pos, (&pci_dev_list.list), list) {
+ pci_dev_t *dev = &pos->dev->pci_dev;
+ if (dev->class_ != 0x1 || dev->subclass != 0x6)
+ continue;
+
+ HBA_MEM *abar = (HBA_MEM *)(uint64_t)pos->dev->bar[5];
+ printf("AHCI: %x\n", abar);
+ map_addr((uint64_t)abar, (uint64_t)abar,
+ FLAG_PRESENT | FLAG_WRITABLE | FLAG_HUGE);
+
+ probe_port(abar);
+ }
+}