Nucleus
Barry Driver core e4c4dfe (3 years, 2 months ago)
diff --git a/drivers/devices.c b/drivers/devices.c
new file mode 100644
index 0000000..19ec2e5
--- /dev/null
+++ b/drivers/devices.c
@@ -0,0 +1,63 @@
+/*
+ * This is the main file of the PCI driver core. It contains the PCI Device
+ * database and controls device initialisation.
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <nucleus/pci.h>
+#include <nucleus/panic.h>
+
+/* Structure for a Device */
+struct Device {
+ uint16_t vendor, device;
+ char *name;
+ void (*init)(uint8_t, uint8_t, uint8_t);
+};
+
+void pci_init_ide(uint8_t bus, uint8_t dev, uint8_t func);
+
+/* Device database */
+struct Device devices[] = {
+ /* Intel system devices */
+ {0x8086, 0x1237, "Intel i440FX Chipset", NULL},
+ {0x8086, 0x7000, "Intel PIIX3 PCI-to-ISA Bridge (Triton II)", NULL},
+ {0x8086, 0x7010, "Intel PIIX3 IDE Interface (Triton II)", pci_init_ide},
+ {0x8086, 0x7020, "Intel PIIX3 USB (Natoma/Triton II)", NULL},
+ {0x8086, 0x7113, "Intel PIIX4/4E/4M Power Management Controller", NULL},
+
+ /* Network devices */
+ {0x10EC, 0x8139, "Realtek RTL8139 10/100 NIC", NULL},
+ {0x8086, 0x100E, "Intel Pro 1000/MT NIC", NULL},
+
+ /* Virtual devices */
+ {0x1B36, 0x000D, "QEMU XHCI Host Adapter", NULL},
+ {0x1234, 0x1111, "QEMU/Bochs VBE Framebuffer", NULL},
+};
+
+/* Initialise a PCI device */
+void
+init_pci_device(int bus, int dev, int func)
+{
+ uint32_t d;
+ uint16_t vendor, device;
+
+ vendor = pci_read_word(bus, dev, func, 0);
+ device = pci_read_word(bus, dev, func, 2);
+
+ /* Lookup device details */
+ for (d = 0; d < sizeof(devices) / sizeof(struct Device); d++) {
+ if (devices[d].vendor != vendor
+ || devices[d].device != device)
+ continue;
+ kprintf("PCI(%d,%d,%d) \"%s\"", bus, dev, func,
+ devices[d].name);
+ if (devices[d].init)
+ devices[d].init(bus, dev, func);
+ return;
+ }
+
+ /* No match */
+ kprintf("PCI(%d,%d,%d) = %#.4x:%#.4x", bus, dev, func,
+ vendor, device);
+}
diff --git a/drivers/storage/ata.c b/drivers/storage/ata.c
new file mode 100644
index 0000000..4d26ab2
--- /dev/null
+++ b/drivers/storage/ata.c
@@ -0,0 +1,209 @@
+/*
+ * This is the driver for ATA storage devices. It controls access to the drives
+ * and contains the devfs functions. It uses the IDE driver for access to the
+ * actual hardware.
+ */
+
+#include <stdint.h>
+#include <io.h>
+#include <nucleus/panic.h>
+#include <nucleus/vfs.h>
+#include "ide.h"
+
+/* Structure for a MBR Partition entry */
+struct Partition {
+ uint8_t drive;
+ uint8_t shead, ssect, scyl;
+ uint8_t type;
+ uint8_t ehead, esect, ecyl;
+ uint32_t lba;
+ uint32_t size;
+};
+
+size_t ata_dev_read(File *file, char *buf, size_t size, off_t offset);
+size_t ata_dev_write(File *file, char *buf, size_t size, off_t offset);
+
+FileOps ataFileOps = {
+ .read = ata_dev_read,
+ .write = ata_dev_write,
+};
+
+/* Access an ATA drive */
+static uint8_t
+ata_access(int write, struct IDEDevice *dev, uint32_t lba, uint8_t sectors,
+ void *buf)
+{
+ struct IDEChannelRegs *channel = &ideChannels[dev->channel];
+ uint8_t lbaMode, dma, cmd;
+ uint8_t lbaIO[6];
+ uint16_t cyl, i;
+ uint8_t head, sect, err;
+
+// ideIrqInvoked = 0;
+ channel->noint = 2;
+ ide_write(dev->channel, IDE_REG_CONTROL, channel->noint);
+
+ /* Configure access mode */
+ if (lba >= 0x10000000) {
+ lbaMode = LBA_48;
+ lbaIO[0] = (lba & 0x000000FF) >> 0;
+ lbaIO[1] = (lba & 0x0000FF00) >> 8;
+ lbaIO[2] = (lba & 0x00FF0000) >> 16;
+ lbaIO[3] = (lba & 0xFF000000) >> 24;
+ lbaIO[4] = 0;
+ lbaIO[5] = 0;
+ head = 0;
+ } else if (dev->capabilities & 0x200) {
+ lbaMode = LBA_28;
+ lbaIO[0] = (lba & 0x000000FF) >> 0;
+ lbaIO[1] = (lba & 0x0000FF00) >> 8;
+ lbaIO[2] = (lba & 0x00FF0000) >> 16;
+ lbaIO[3] = 0;
+ lbaIO[4] = 0;
+ lbaIO[5] = 0;
+ head = (lba & 0x0F000000) >> 24;
+ } else {
+ lbaMode = LBA_CHS;
+ sect = (lba % 63) + 1;
+ cyl = (lba + 1 - sect) / (16 * 63);
+ lbaIO[0] = sect;
+ lbaIO[1] = (cyl >> 0) & 0xFF;
+ lbaIO[2] = (cyl >> 8) & 0xFF;
+ lbaIO[3] = 0;
+ lbaIO[4] = 0;
+ lbaIO[5] = 0;
+ head = (lba + 1 - sect) % (16 * 63) / 63;
+ }
+
+ dma = 0; //dev->busmaster;
+
+ /* Wait for device to become available */
+ while (ide_read(dev->channel, IDE_REG_STATUS) & IDE_SR_BUSY);
+
+ /* Select drive */
+ if (lbaMode == LBA_CHS)
+ ide_write(dev->channel, IDE_REG_HDDEVSEL,
+ 0xA0 | (dev->drive << 4) | head);
+ else
+ ide_write(dev->channel, IDE_REG_HDDEVSEL,
+ 0xE0 | (dev->drive << 4) | head);
+
+ /* Specify sectors to read */
+ if (lbaMode = LBA_48) {
+ ide_write(dev->channel, IDE_REG_SECCOUNT1, 0);
+ ide_write(dev->channel, IDE_REG_LBA3, lbaIO[3]);
+ ide_write(dev->channel, IDE_REG_LBA4, lbaIO[4]);
+ ide_write(dev->channel, IDE_REG_LBA5, lbaIO[5]);
+ }
+ ide_write(dev->channel, IDE_REG_SECCOUNT0, sectors);
+ ide_write(dev->channel, IDE_REG_LBA0, lbaIO[0]);
+ ide_write(dev->channel, IDE_REG_LBA1, lbaIO[1]);
+ ide_write(dev->channel, IDE_REG_LBA2, lbaIO[2]);
+
+ /* Send command */
+ if (lbaMode == LBA_CHS && !dma && !write) cmd = IDE_CMD_READ_PIO;
+ if (lbaMode == LBA_28 && !dma && !write) cmd = IDE_CMD_READ_PIO;
+ if (lbaMode == LBA_48 && !dma && !write) cmd = IDE_CMD_READ_PIO_EXT;
+ if (lbaMode == LBA_CHS && dma && !write) cmd = IDE_CMD_READ_DMA;
+ if (lbaMode == LBA_28 && dma && !write) cmd = IDE_CMD_READ_DMA;
+ if (lbaMode == LBA_48 && dma && !write) cmd = IDE_CMD_READ_DMA_EXT;
+ if (lbaMode == LBA_CHS && !dma && write) cmd = IDE_CMD_WRITE_PIO;
+ if (lbaMode == LBA_28 && !dma && write) cmd = IDE_CMD_WRITE_PIO;
+ if (lbaMode == LBA_48 && !dma && write) cmd = IDE_CMD_WRITE_PIO_EXT;
+ if (lbaMode == LBA_CHS && dma && write) cmd = IDE_CMD_WRITE_DMA;
+ if (lbaMode == LBA_28 && dma && write) cmd = IDE_CMD_WRITE_DMA;
+ if (lbaMode == LBA_48 && dma && write) cmd = IDE_CMD_WRITE_DMA_EXT;
+ ide_write(dev->channel, IDE_REG_COMMAND, cmd);
+
+ /* Read/Write data */
+ if (dma) {
+ /* Use DMA */
+ if (write) {
+ /* TODO */
+ } else {
+ /* TODO */
+ }
+ } else {
+ /* Use PIO */
+ if (write) {
+ for (i = 0; i < sectors; i++) {
+ ide_poll_status(dev->channel, 0);
+ outsw(channel->base, buf + (i * 512), 256);
+ }
+ ide_write(dev->channel, IDE_REG_COMMAND,
+ (lbaMode == LBA_48)
+ ? IDE_CMD_CACHE_FLUSH_EXT
+ : IDE_CMD_CACHE_FLUSH);
+ ide_poll_status(dev->channel, 0);
+ } else {
+ for (i = 0; i < sectors; i++) {
+ if (err = ide_poll_status(dev->channel, 1))
+ return err;
+ insw(channel->base, buf + (i * 512), 256);
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Read from an ATA drive */
+static inline uint8_t
+ata_read(struct IDEDevice *dev, uint32_t lba, uint8_t sectors, void *buf)
+{
+ ata_access(0, dev, lba, sectors, buf);
+}
+
+/* Write to an ATA drive */
+static inline uint8_t
+ata_write(struct IDEDevice *dev, uint32_t lba, uint8_t sectors, void *buf)
+{
+ ata_access(1, dev, lba, sectors, buf);
+}
+
+/* Initialise an ATA drive */
+void
+ata_init(struct IDEDevice *dev)
+{
+ static int drive = 0;
+ static void *ataDmaArea = NULL;
+ if (!ataDmaArea)
+ ataDmaArea = (void *) alloc_frame();
+
+ /* Create device node */
+ char name[16];
+ sprintf(name, "/dev/hd%d", drive);
+// mknod(name, S_IFBLK | 0600, MKDEV());
+ kprintf(" ATA drive [%s] (%d MB) %s", name,
+ dev->size / 1024 / 2, dev->model);
+
+ /* Attempt to read partition table */
+ int i;
+ struct Partition *part = ataDmaArea + 446;
+ if (ata_read(dev, 0, 1, ataDmaArea))
+ return;
+ for (i = 0; i < 4; i++) {
+ if (!part[i].type)
+ continue;
+ sprintf(name, "/dev/hd%dp%d", drive, i);
+// mknod(name, S_IFBLK | 0600, MKDEV(ideDriver.major, ());
+ kprintf(" Partition [%s] %#.8x - %#.8x", name,
+ part[i].lba*512, (part[i].lba + part[i].size) * 512);
+ }
+
+ drive++;
+}
+
+/* Read from an ATA drive */
+size_t
+ata_dev_read(File *file, char *buf, size_t size, off_t offset)
+{
+
+}
+
+/* Write to an ATA drive */
+size_t
+ata_dev_write(File *file, char *buf, size_t size, off_t offset)
+{
+
+}
diff --git a/drivers/storage/ide.c b/drivers/storage/ide.c
new file mode 100644
index 0000000..0cc9253
--- /dev/null
+++ b/drivers/storage/ide.c
@@ -0,0 +1,222 @@
+/*
+ * This file is the driver for the PCI IDE devices. It handles detecting drives
+ * and accessing them through the IDE interface. The ATA and ATAPI drivers
+ * handle reading and writing to the devices individually through this.
+ * This driver will access the drives in the best available way, presenting a
+ * uniform interface for any other code to use. It also adds a device node to
+ * the devfs mount for every device it finds, to provide access for the rest of
+ * the OS easily.
+ */
+
+#include <stdint.h>
+#include <io.h>
+#include <nucleus/pci.h>
+#include "ide.h"
+
+struct IDEChannelRegs ideChannels[2];
+struct IDEDevice ideDevices[4];
+uint8_t ideBuf[2048] = {0};
+int ideIrqInvoked = 0;
+
+/* Read identification space */
+static void
+ide_read_buffer(uint8_t channel, void *buffer, uint32_t dwords)
+{
+ struct IDEChannelRegs *c = &ideChannels[channel];
+ insl(c->base, buffer, dwords);
+}
+
+/* Initialise an IDE drive */
+static void
+ide_drive_init(uint32_t bar0, uint32_t bar1, uint32_t bar2, uint32_t bar3,
+ uint32_t bar4)
+{
+ ideChannels[IDE_PRIMARY].base = bar0 & ~3;
+ ideChannels[IDE_PRIMARY].ctrl = bar1 & ~3;
+ ideChannels[IDE_PRIMARY].busmaster = bar4 & ~3;
+ ideChannels[IDE_SECONDARY].base = bar2 & ~3;
+ ideChannels[IDE_SECONDARY].ctrl = bar3 & ~3;
+ ideChannels[IDE_SECONDARY].busmaster = (bar4 & ~3) + 8;
+
+ /* Disable IRQs */
+ ide_write(IDE_PRIMARY, IDE_REG_CONTROL, 2);
+ ide_write(IDE_SECONDARY, IDE_REG_CONTROL, 2);
+
+ /* Iterate all possible devices */
+ uint32_t count = 0;
+ uint8_t channel, drive, err, type, status;
+ struct IDEDevice *dev;
+ for (count = 0; count < 4; count++) {
+ dev = &ideDevices[count];
+ dev->reserved = 0;
+ channel = count / 2;
+ drive = count % 2;
+ type = IDE_ATA;
+ err = 0;
+
+ ide_write(channel, IDE_REG_HDDEVSEL, 0xA0 | (drive << 4));
+ ide_write(channel, IDE_REG_COMMAND, IDE_CMD_IDENTIFY);
+ if (ide_read(channel, IDE_REG_STATUS) == 0)
+ continue;
+
+ /* Wait for response */
+ while (1) {
+ status = ide_read(channel, IDE_REG_STATUS);
+ if ((status & IDE_SR_ERROR)) {
+ err = 1;
+ break;
+ }
+ if (!(status & IDE_SR_BUSY)
+ && (status & IDE_SR_DATA_READY))
+ break;
+ }
+
+ /* Check type */
+ if (err) {
+ uint8_t cl = ide_read(channel, IDE_REG_LBA1);
+ uint8_t ch = ide_read(channel, IDE_REG_LBA2);
+ if (cl == 0x14 && ch == 0xEB)
+ type = IDE_ATAPI;
+ else if (cl == 0x69 && ch == 0x96)
+ type = IDE_ATAPI;
+ else
+ continue;
+
+ ide_write(channel, IDE_REG_COMMAND,
+ IDE_CMD_IDENTIFY_PACKET);
+ }
+
+ /* Fill in IDE Device structure */
+ ide_read_buffer(channel, ideBuf, 128);
+ uint32_t size;
+ uint16_t sig, cap, set;
+ sig = *(uint16_t *) (ideBuf + IDE_IDENT_DEVICETYPE);
+ cap = *(uint16_t *) (ideBuf + IDE_IDENT_CAPABILITIES);
+ set = *(uint16_t *) (ideBuf + IDE_IDENT_COMMANDSETS);
+ if (set & (1 << 26))
+ size = *(uint32_t *) (ideBuf + IDE_IDENT_MAX_LBA_EXT);
+ else
+ size = *(uint32_t *) (ideBuf + IDE_IDENT_MAX_LBA);
+
+ dev->reserved = 1;
+ dev->type = type;
+ dev->channel = channel;
+ dev->drive = drive;
+ dev->signature = sig;
+ dev->capabilities = cap;
+ dev->commandSets = set;
+ dev->size = size;
+
+ uint32_t k;
+ for (k = 0; k < 40; k += 2) {
+ dev->model[k] = ideBuf[IDE_IDENT_MODEL + k + 1];
+ dev->model[k + 1] = ideBuf[IDE_IDENT_MODEL + k];
+ }
+ dev->model[40] = 0;
+ }
+}
+
+/* Read channel */
+uint8_t
+ide_read(uint8_t channel, uint8_t reg)
+{
+ uint8_t result;
+ struct IDEChannelRegs *c = &ideChannels[channel];
+ if (reg > 0x07 && reg < 0x0C)
+ ide_write(channel, IDE_REG_CONTROL, 0x80 | c->noint);
+ if (reg < 0x08)
+ result = inb(c->base + reg - 0);
+ else if (reg < 0x0C)
+ result = inb(c->base + reg - 6);
+ else if (reg < 0x0E)
+ result = inb(c->ctrl + reg - 10);
+ else if (reg < 0x16)
+ result = inb(c->busmaster + reg - 14);
+ if (reg > 0x07 && reg < 0x0C)
+ ide_write(channel, IDE_REG_CONTROL, c->noint);
+ return result;
+}
+
+/* Write channel */
+void
+ide_write(uint8_t channel, uint8_t reg, uint8_t data)
+{
+ struct IDEChannelRegs *c = &ideChannels[channel];
+ if (reg > 0x07 && reg < 0x0C)
+ ide_write(channel, IDE_REG_CONTROL, 0x80 | c->noint);
+ if (reg < 0x08)
+ outb(c->base + reg - 0, data);
+ else if (reg < 0x0C)
+ outb(c->base + reg - 6, data);
+ else if (reg < 0x0E)
+ outb(c->ctrl + reg - 10, data);
+ else if (reg < 0x16)
+ outb(c->busmaster + reg - 14, data);
+ if (reg > 0x07 && reg < 0x0C)
+ ide_write(channel, IDE_REG_CONTROL, c->noint);
+}
+
+/* Poll for status after command */
+uint8_t
+ide_poll_status(uint8_t channel, uint32_t check)
+{
+ uint8_t i, state;
+ /* Wait for BUSY */
+ for (i = 0; i < 4; i++)
+ ide_read(channel, IDE_REG_ALTSTATUS);
+ /* Wait for BUSY to clear */
+ while (ide_read(channel, IDE_REG_STATUS) & IDE_SR_BUSY);
+
+ /* Check the status */
+ if (check) {
+ state = ide_read(channel, IDE_REG_STATUS);
+ if (state & IDE_SR_ERROR)
+ return ERROR_GENERIC;
+ if (state & IDE_SR_WRITE_FAULT)
+ return ERROR_WRITE_FAULT;
+ if ((state & IDE_SR_DATA_READY) == 0)
+ return ERROR_NOT_READY;
+ }
+
+ return ERROR_NONE;
+}
+
+/* Initialise a PCI IDE controller */
+void
+pci_init_ide(uint8_t bus, uint8_t dev, uint8_t func)
+{
+ uint8_t class, subclass, progif, header;
+ class = pci_read_byte(bus, dev, func, 11);
+ subclass = pci_read_byte(bus, dev, func, 10);
+ progif = pci_read_byte(bus, dev, func, 9);
+ header = pci_read_byte(bus, dev, func, 14);
+
+ /* Parallel IDE defaults */
+ uint32_t bar[5] = {0x1F0, 0x3F6, 0x170, 0x376, 0x00};
+
+ /* Primary Native */
+ if (progif & (1 << 0)) {
+ bar[0] = pci_read_dword(bus, dev, func, 0x10);
+ bar[1] = pci_read_dword(bus, dev, func, 0x14);
+ }
+ /* Secondary Native */
+ if (progif & (1 << 2)) {
+ bar[2] = pci_read_dword(bus, dev, func, 0x18);
+ bar[3] = pci_read_dword(bus, dev, func, 0x1C);
+ }
+ /* Bus Master */
+ if (progif & (1 << 7))
+ bar[4] = pci_read_dword(bus, dev, func, 0x20);
+
+ ide_drive_init(bar[0], bar[1], bar[2], bar[3], bar[4]);
+
+ uint8_t i;
+ for (i = 0; i < 4; i++) {
+ if (!ideDevices[i].reserved)
+ continue;
+ if (ideDevices[i].type == IDE_ATA)
+ ata_init(&ideDevices[i]);
+// if (ideDevices[i].type == IDE_ATAPI)
+// atapi_init(&ideDevices[i]);
+ }
+}
diff --git a/drivers/storage/ide.h b/drivers/storage/ide.h
new file mode 100644
index 0000000..b59bf18
--- /dev/null
+++ b/drivers/storage/ide.h
@@ -0,0 +1,124 @@
+#ifndef DRIVERS_STORAGE_IDE_H
+#define DRIVERS_STORAGE_IDE_H
+
+/* IDE Types */
+enum IDEType {
+ IDE_ATA,
+ IDE_ATAPI,
+};
+
+/* LBA Modes */
+enum LBAMode {
+ LBA_CHS,
+ LBA_28,
+ LBA_48,
+};
+
+/* IDE Poll Response Errors */
+enum IDEPollError {
+ ERROR_NONE,
+ ERROR_GENERIC,
+ ERROR_WRITE_FAULT,
+ ERROR_NOT_READY,
+};
+
+/* IDE Status Responses */
+enum IDEStatus {
+ IDE_SR_BUSY = 0x80,
+ IDE_SR_READY = 0x40,
+ IDE_SR_WRITE_FAULT = 0x20,
+ IDE_SR_SEEK_COMPLETE = 0x10,
+ IDE_SR_DATA_READY = 0x08,
+ IDE_SR_CORRECTED_DATA = 0x04,
+ IDE_SR_INDEX = 0x02,
+ IDE_SR_ERROR = 0x01,
+};
+
+/* IDE Commands */
+enum IDECommand {
+ IDE_CMD_READ_PIO = 0x20,
+ IDE_CMD_READ_PIO_EXT = 0x24,
+ IDE_CMD_READ_DMA = 0xC8,
+ IDE_CMD_READ_DMA_EXT = 0x25,
+ IDE_CMD_WRITE_PIO = 0x30,
+ IDE_CMD_WRITE_PIO_EXT = 0x34,
+ IDE_CMD_WRITE_DMA = 0xCA,
+ IDE_CMD_WRITE_DMA_EXT = 0x35,
+ IDE_CMD_CACHE_FLUSH = 0xE7,
+ IDE_CMD_CACHE_FLUSH_EXT = 0xEA,
+ IDE_CMD_PACKET = 0xA0,
+ IDE_CMD_IDENTIFY_PACKET = 0xA1,
+ IDE_CMD_IDENTIFY = 0xEC,
+};
+
+/* IDE Identities */
+enum IDEIdentity {
+ IDE_IDENT_DEVICETYPE = 0,
+ IDE_IDENT_CYLINDERS = 2,
+ IDE_IDENT_HEADS = 6,
+ IDE_IDENT_SECTORS = 12,
+ IDE_IDENT_SERIAL = 20,
+ IDE_IDENT_MODEL = 54,
+ IDE_IDENT_CAPABILITIES = 98,
+ IDE_IDENT_FIELDVALID = 106,
+ IDE_IDENT_MAX_LBA = 120,
+ IDE_IDENT_COMMANDSETS = 164,
+ IDE_IDENT_MAX_LBA_EXT = 200,
+};
+
+/* IDE Registers */
+enum IDERegister {
+ IDE_REG_DATA = 0x00,
+ IDE_REG_ERROR = 0x01,
+ IDE_REG_FEATURES = 0x01,
+ IDE_REG_SECCOUNT0 = 0x02,
+ IDE_REG_LBA0 = 0x03,
+ IDE_REG_LBA1 = 0x04,
+ IDE_REG_LBA2 = 0x05,
+ IDE_REG_HDDEVSEL = 0x06,
+ IDE_REG_COMMAND = 0x07,
+ IDE_REG_STATUS = 0x07,
+ IDE_REG_SECCOUNT1 = 0x08,
+ IDE_REG_LBA3 = 0x09,
+ IDE_REG_LBA4 = 0x0A,
+ IDE_REG_LBA5 = 0x0B,
+ IDE_REG_CONTROL = 0x0C,
+ IDE_REG_ALTSTATUS = 0x0C,
+ IDE_REG_DEVADDRESS = 0x0D,
+};
+
+/* IDE Channels */
+enum IDEChannel {
+ IDE_PRIMARY,
+ IDE_SECONDARY,
+};
+struct IDEChannelRegs {
+ uint16_t base;
+ uint16_t ctrl;
+ uint16_t busmaster;
+ uint8_t noint;
+};
+
+/* Structure for an IDE Device */
+struct IDEDevice {
+ uint8_t reserved;
+ uint8_t channel;
+ uint8_t drive;
+ uint16_t type;
+ uint16_t signature;
+ uint16_t capabilities;
+ uint32_t commandSets;
+ uint32_t size;
+ char model[41];
+};
+
+extern struct IDEChannelRegs ideChannels[];
+extern struct IDEDevice ideDevices[];
+
+uint8_t ide_read(uint8_t channel, uint8_t reg);
+void ide_write(uint8_t channel, uint8_t reg, uint8_t data);
+uint8_t ide_poll_status(uint8_t channel, uint32_t check);
+
+void ata_init(struct IDEDevice *dev);
+
+#endif
diff --git a/kernel/pci/pci.h b/include/nucleus/pci.h
similarity index 81%
rename from kernel/pci/pci.h
rename to include/nucleus/pci.h
index b61dec3..3811908 100644
--- a/kernel/pci/pci.h
+++ b/include/nucleus/pci.h
@@ -1,5 +1,5 @@
-#ifndef KERNEL_PCI_H
-#define KERNEL_PCI_H
+#ifndef _NUCLEUS_PCI_H
+#define _NUCLEUS_PCI_H
#include <stdint.h>
@@ -10,6 +10,6 @@ void pci_write_byte(int bus, int dev, int func, int off, uint8_t value);
void pci_write_word(int bus, int dev, int func, int off, uint16_t value);
void pci_write_dword(int bus, int dev, int func, int off, uint32_t value);
-void init_pci(void);
+void init_pci_device(int bus, int dev, int func);
#endif
diff --git a/kernel/acpi/acpi.h b/kernel/acpi/acpi.h
index 0c39b19..13d79a7 100644
--- a/kernel/acpi/acpi.h
+++ b/kernel/acpi/acpi.h
@@ -16,5 +16,6 @@ struct SDTHeader {
void init_table(struct SDTHeader *table);
void init_acpi(void *ebda);
+void init_pci(void);
#endif
diff --git a/kernel/pci/pci.c b/kernel/acpi/pci.c
similarity index 77%
rename from kernel/pci/pci.c
rename to kernel/acpi/pci.c
index 408aeb8..b7c74c1 100644
--- a/kernel/pci/pci.c
+++ b/kernel/acpi/pci.c
@@ -1,13 +1,18 @@
/*
- *
+ * This file controls the PCI interface. It contains utility functions for
+ * accessing PCI configuration space. It scans all devices connected to the
+ * system and tries to initialise them.
*/
#include <stdint.h>
#include <io.h>
-#include "pci.h"
+#include <nucleus/pci.h>
-const uint16_t CONFIG_ADDRESS = 0xCF8;
-const uint16_t CONFIG_DATA = 0xCFC;
+/* PCI Configuration Ports */
+enum PCIConfigPort {
+ CONFIG_ADDRESS = 0xCF8,
+ CONFIG_DATA = 0xCFC,
+};
/* Make a PCI Address */
static inline uint32_t
@@ -69,18 +74,11 @@ pci_write_dword(int bus, int dev, int func, int off, uint32_t value)
void
init_pci(void)
{
- uint16_t bus, slot, func;
- uint16_t vendor, device;
- uint8_t class, subclass;
- uint32_t dev;
+ uint16_t bus, dev, func;
/* This is one massive iteration */
for (bus = 0; bus < 256; bus++)
- for (slot = 0; slot < 32; slot++)
+ for (dev = 0; dev < 32; dev++)
for (func = 0; func < 8; func++)
- if ((vendor = pci_read_word(bus, slot, func, 0)) != 0xFFFF) {
- device = pci_read_word(bus, slot, func, 2);
- /* do something */
-// kprintf("PCI(%d,%d,%d) = %#.4x:%#.4x",
-// bus, slot, func, vendor, device);
- }
+ if (pci_read_word(bus, dev, func, 0) != 0xFFFF)
+ init_pci_device(bus, dev, func);
}
diff --git a/kernel/main.c b/kernel/main.c
index 0b45511..7d37563 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -13,7 +13,6 @@
#include "multiboot.h"
#include "desc.h"
#include "acpi/acpi.h"
-#include "pci/pci.h"
extern char _bss[], _end[];