81 lines
2.0 KiB
C
81 lines
2.0 KiB
C
#include <socks/printk.h>
|
|
#include <socks/pci.h>
|
|
#include <socks/device.h>
|
|
#include <socks/kext.h>
|
|
#include <socks/pci.h>
|
|
#include <socks/util.h>
|
|
#include <socks/machine/init.h>
|
|
#include <socks/libc/stdio.h>
|
|
#include <socks/libc/ctype.h>
|
|
#include <arch/irq.h>
|
|
#include "ahci.h"
|
|
|
|
static struct pci_driver *__ahci_driver = NULL;
|
|
static volatile struct hba_config *hba_config = NULL;
|
|
|
|
static int irq_callback(void);
|
|
|
|
static struct irq_hook irq_hook = {
|
|
.irq_callback = irq_callback,
|
|
};
|
|
|
|
static struct pci_device_id ahci_device_ids[] = {
|
|
PCI_CLASS_ID(0x01, 0x06),
|
|
PCI_DEVICE_ID_INVALID,
|
|
};
|
|
|
|
struct driver *ahci_driver(void)
|
|
{
|
|
return pci_driver_base(__ahci_driver);
|
|
}
|
|
|
|
static kern_status_t ahci_scan(struct device *ahci_bus)
|
|
{
|
|
struct pci_device *pci_dev = device_get_pci_info(ahci_bus);
|
|
printk("ahci: probing ports on ahci controller at pci%04x:%02x.%02u", pci_dev->pci_bus, pci_dev->pci_slot, pci_dev->pci_func);
|
|
uint32_t abar = pci_device_read_field(ahci_bus, PCI_REG_BAR5, 4);
|
|
hba_config = vm_phys_to_virt(abar);
|
|
probe_ahci_ports(pci_driver_base(__ahci_driver), ahci_bus, hba_config, create_device_from_ahci_port);
|
|
return KERN_OK;
|
|
}
|
|
|
|
static struct bus_device_ops ahci_bus_ops = {
|
|
.scan = ahci_scan,
|
|
};
|
|
|
|
static int irq_callback(void)
|
|
{
|
|
printk("ahci: received IRQ");
|
|
return 0;
|
|
}
|
|
|
|
static kern_status_t ahci_probe(struct pci_driver *driver, struct device *dev)
|
|
{
|
|
struct bus_device *ahci_bus = bus_device_from_generic(dev);
|
|
ahci_bus->b_ops = &ahci_bus_ops;
|
|
snprintf(dev->dev_name, sizeof dev->dev_name, "ahci");
|
|
|
|
uint8_t irq_vec = pci_device_read_field(dev, PCI_REG_INTERRUPT_LINE, 1);
|
|
hook_irq(IRQ0 + irq_vec, &irq_hook);
|
|
|
|
return device_register(dev, pci_driver_base(__ahci_driver), NULL);
|
|
}
|
|
|
|
static kern_status_t online(struct kext *self)
|
|
{
|
|
printk("ahci: registering AHCI driver");
|
|
__ahci_driver = pci_driver_create(self, "ahci", ahci_device_ids);
|
|
if (!__ahci_driver) {
|
|
return KERN_NO_MEMORY;
|
|
}
|
|
|
|
__ahci_driver->probe = ahci_probe;
|
|
|
|
pci_driver_register(__ahci_driver);
|
|
return KERN_OK;
|
|
}
|
|
|
|
DEFINE_KEXT("net.doorstuck.socks.ahci",
|
|
online, NULL,
|
|
PCI_SUBSYSTEM_KEXT_ID);
|