From 28aa7499563bc5e07e9350aa997c0e4dbffa82fd Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 22 Jan 2020 15:38:56 +0200 Subject: [PATCH] Get rid of old AHCI/IDE drivers --- etc/make/amd64/platform.mk | 4 - include/sys/amd64/hw/ide/ahci.h | 233 ----------------- include/sys/amd64/hw/ide/ata.h | 44 ---- include/sys/amd64/hw/ide/ide.h | 52 ---- include/sys/amd64/hw/pci/ahci.h | 9 - sys/amd64/hw/ide/ahci.c | 377 --------------------------- sys/amd64/hw/ide/ide.c | 433 -------------------------------- sys/amd64/hw/pci/ahci.c | 36 --- sys/amd64/hw/pci/ide.c | 102 -------- 9 files changed, 1290 deletions(-) delete mode 100644 include/sys/amd64/hw/ide/ahci.h delete mode 100644 include/sys/amd64/hw/ide/ata.h delete mode 100644 include/sys/amd64/hw/ide/ide.h delete mode 100644 include/sys/amd64/hw/pci/ahci.h delete mode 100644 sys/amd64/hw/ide/ahci.c delete mode 100644 sys/amd64/hw/ide/ide.c delete mode 100644 sys/amd64/hw/pci/ahci.c delete mode 100644 sys/amd64/hw/pci/ide.c diff --git a/etc/make/amd64/platform.mk b/etc/make/amd64/platform.mk index 9288ea9..bf62d60 100644 --- a/etc/make/amd64/platform.mk +++ b/etc/make/amd64/platform.mk @@ -34,10 +34,6 @@ OBJS+=$(O)/sys/amd64/hw/rs232.o \ $(O)/sys/amd64/syscall.o \ $(O)/sys/amd64/sys/thread.o \ $(O)/sys/amd64/hw/pci/pci.o \ - $(O)/sys/amd64/hw/pci/ide.o \ - $(O)/sys/amd64/hw/pci/ahci.o \ - $(O)/sys/amd64/hw/ide/ahci.o \ - $(O)/sys/amd64/hw/ide/ide.o \ $(O)/sys/amd64/hw/pci/pcidb.o \ $(O)/sys/amd64/hw/ps2.o \ $(O)/sys/amd64/hw/irq.o \ diff --git a/include/sys/amd64/hw/ide/ahci.h b/include/sys/amd64/hw/ide/ahci.h deleted file mode 100644 index d35d851..0000000 --- a/include/sys/amd64/hw/ide/ahci.h +++ /dev/null @@ -1,233 +0,0 @@ -#pragma once -#include "sys/types.h" - -#define AHCI_PORT_SSTS_DET_OK 0x3 -#define AHCI_PORT_SSTS_IPM_ACTIVE 0x1 -#define AHCI_PORT_SIG_SATA 0x00000101 -#define AHCI_PORT_SIG_SATAPI 0xEB140101 -#define AHCI_PORT_IS_TFES (1 << 30) - -#define AHCI_PORT_CMD_ST (1 << 0) -#define AHCI_PORT_CMD_FRE (1 << 4) -#define AHCI_PORT_CMD_FR (1 << 14) -#define AHCI_PORT_CMD_CR (1 << 15) - -enum ahci_fis_type { - FIS_REG_H2D = 0x27, - FIS_REG_D2H = 0x34, - FIS_DMA_ACT = 0x39, - FIS_DMA_SETUP = 0x41, - FIS_DATA = 0x46, - FIS_BIST = 0x58, - FIS_PIO_SETUP = 0x5F, - FIS_DEV_BITS = 0xA1 -}; - -struct ahci_registers { - // Generic host control - uint32_t cap; // 0x00 - uint32_t ghc; // 0x04 - uint32_t is; // 0x08 - uint32_t pi; // 0x0C - uint32_t vs; // 0x10 - uint32_t ccc_ctl; // 0x14 - uint32_t ccc_ports; // 0x18 - uint32_t em_loc; // 0x1C - uint32_t em_ctl; // 0x20 - uint32_t cap2; // 0x24 - uint32_t bohc; // 0x28 - // Reserved - uint32_t __res0[13]; - // Reserved for NVMHCI - // Also vendor specific settings - uint32_t __res1[40]; - - // Port control registers - struct ahci_port_registers { - uint32_t p_clb; - uint32_t p_clbu; - uint32_t p_fb; - uint32_t p_fbu; - uint32_t p_is; - uint32_t p_ie; - uint32_t p_cmd; - uint32_t __res0; - uint32_t p_tfd; - uint32_t p_sig; - uint32_t p_ssts; - uint32_t p_sctl; - uint32_t p_serr; - uint32_t p_sact; - uint32_t p_ci; - uint32_t p_sntf; - uint32_t p_fbs; - uint32_t p_devslp; - uint32_t __res1[14]; - } __attribute__((packed)) ports[32]; -} __attribute__((packed)); - -struct ahci_fis_reg_h2d { - uint8_t type; - uint8_t cmd_port; - uint8_t cmd; - uint8_t feature_low; - - uint8_t lba0; - uint8_t lba1; - uint8_t lba2; - uint8_t dev; - - uint8_t lba3; - uint8_t lba4; - uint8_t lba5; - uint8_t feature_high; - - uint8_t countl; - uint8_t counth; - uint8_t icc; - uint8_t control; - - uint8_t __res0[4]; -}; - -struct ahci_fis_reg_d2h { - uint8_t type; - uint8_t cmd_port; - uint8_t status; - uint8_t error; - - uint8_t lba0; - uint8_t lba1; - uint8_t lba2; - uint8_t dev; - - uint8_t lba3; - uint8_t lba4; - uint8_t lba5; - uint8_t __res0; - - uint8_t countl; - uint8_t counth; - - uint8_t __res1[6]; -}; - -struct ahci_fis_dma_setup { - uint8_t type; - uint8_t cmd_port; - uint8_t __res0[2]; - uint64_t dma_buffer_id; - uint32_t __res1; - uint32_t dma_buffer_offset; - uint32_t transfer_count; - uint32_t __res2; -}; - -struct ahci_fis_pio_setup { - uint8_t type; - uint8_t cmd_port; - uint8_t status; - uint8_t error; - - uint8_t lba0; - uint8_t lba1; - uint8_t lba2; - uint8_t device; - - uint8_t lba3; - uint8_t lba4; - uint8_t lba5; - uint8_t __res0; - - uint8_t countl; - uint8_t counth; - uint8_t __res1; - uint8_t e_status; - - uint16_t tc; - uint8_t __res2[2]; -}; - -struct ahci_fis_data { - uint8_t type; - uint8_t cmd_port; - - uint8_t __res0[2]; - - uint32_t data[]; -}; - -struct ahci_recv_fis { - union { - // DMA setup FIS - struct ahci_fis_dma_setup dsfis; - char __block0[0x20]; - }; - union { - // PIO setup FIS - struct ahci_fis_pio_setup psfis; - char __block1[0x20]; - }; - union { - // Register FIS - struct ahci_fis_reg_d2h rfis; - char __block2[0x18]; - }; - union { - // Set device bits FIS - char __block3[0x2]; - }; - union { - // Unknown FIS - char __block4[0x40]; - }; -}; - -struct ahci_command_header { - // Bits: - // 0..4 Command length in dwords - // 5 ATAPI - uint16_t attr; - uint16_t prdtl; - volatile uint32_t prdbc; - uint32_t ctba; - uint32_t ctbau; - uint32_t __res0[4]; -} __attribute__((packed)); - -struct ahci_prdt_entry { - uint32_t dba; - uint32_t dbau; - uint32_t __res0; - // Bits: - // 0 1 - // 1..21 Data byte count - // 22..30 Reserved - // 31 Interrupt - uint32_t dbc; -} __attribute__((packed)); - -struct ahci_command_table_entry { - union { - struct ahci_fis_reg_h2d fis_reg_h2d; - uint8_t __cmd_fis[64]; - } __attribute__((packed)); - uint8_t acmd[16]; - uint8_t __res0[48]; - struct ahci_prdt_entry prdt[]; -} __attribute__((packed)); - -#define AHCI_PORT_CMD_LIST(p) (struct ahci_command_header *) MM_VIRTUALIZE(((uintptr_t) (p)->p_clbu << 32) | ((p)->p_clb)) -#define AHCI_CMD_TABLE_ENTRY(l, i) (struct ahci_command_table_entry *) MM_VIRTUALIZE(((uintptr_t) (l)[i].ctbau << 32) | ((l)[i].ctba)) - -uint32_t ahci_irq(void *ctx); - -void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba); -void ahci_sata_write(struct ahci_port_registers *port, const void *buf, uint32_t nsect, uint64_t lba); - -void ahci_port_start(struct ahci_port_registers *port); -void ahci_port_stop(struct ahci_port_registers *port); - -void ahci_port_init(uint8_t n, struct ahci_port_registers *port); - -void ahci_init(struct ahci_registers *regs); diff --git a/include/sys/amd64/hw/ide/ata.h b/include/sys/amd64/hw/ide/ata.h deleted file mode 100644 index 9a24cfd..0000000 --- a/include/sys/amd64/hw/ide/ata.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#define ATA_REG_DATA 0x00 -#define ATA_REG_ERROR 0x01 -#define ATA_REG_FEATURES 0x01 -#define ATA_REG_SECCOUNT0 0x02 -#define ATA_REG_LBA0 0x03 -#define ATA_REG_LBA1 0x04 -#define ATA_REG_LBA2 0x05 -#define ATA_REG_HDDEVSEL 0x06 -#define ATA_REG_COMMAND 0x07 -#define ATA_REG_STATUS 0x07 -#define ATA_REG_SECCOUNT1 0x08 -#define ATA_REG_LBA3 0x09 -#define ATA_REG_LBA4 0x0A -#define ATA_REG_LBA5 0x0B -#define ATA_REG_CONTROL 0x0C -#define ATA_REG_ALTSTATUS 0x0C -#define ATA_REG_DEVADDRESS 0x0D - -#define ATA_CONTROL_NO_INT (1 << 1) - -#define ATA_CMD_IDENTIFY 0xEC -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EX 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EX 0x25 -#define ATA_CMD_WRITE_DMA_EX 0x35 - -#define ATA_SR_BUSY (1 << 7) -#define ATA_SR_DRQ (1 << 3) -#define ATA_SR_ERR (1 << 0) - -#define ATA_IDENT_DEVICE_TYPE 0x00 -#define ATA_IDENT_CYLINDERS 0x02 -#define ATA_IDENT_HEADS 0x06 -#define ATA_IDENT_SECTORS 0x0C -#define ATA_IDENT_SERIAL 0x14 -#define ATA_IDENT_MODEL 0x36 -#define ATA_IDENT_CAPS 0x62 -#define ATA_IDENT_MAX_LBA 0x78 -#define ATA_IDENT_CMD_SETS 0xA4 -#define ATA_IDENT_MAX_LBAEXT 0xC8 diff --git a/include/sys/amd64/hw/ide/ide.h b/include/sys/amd64/hw/ide/ide.h deleted file mode 100644 index a27f8c1..0000000 --- a/include/sys/amd64/hw/ide/ide.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once -#include "sys/types.h" - -#define IDE_DEFAULT_BAR0 0x1F0 -#define IDE_DEFAULT_BAR1 0x3F6 -#define IDE_DEFAULT_BAR2 0x170 -#define IDE_DEFAULT_BAR3 0x376 - -struct ide_prdt_entry { - uint32_t addr; - uint16_t size; - uint16_t attr; -} __attribute__((packed)); - -struct ide_controller { - uint16_t bar0; // Primary channel - uint16_t bar1; // Primary control port - uint16_t bar2; // Secondary channel - uint16_t bar3; // Secondary control port - uint16_t bar4; // Bus master control - uint8_t irq0, irq1; - - uintptr_t dma_page; - - struct ide_channel { - uint16_t base; - uint16_t ctrl; - uint16_t bmide; - uint8_t no_int; - } channels[2]; - - struct ide_device { - // Bits: - // 0 1 if device is present here - // 1 0 if on primary channel - // 2 1 if slave device - // 3 1 if device is ATAPI (ATA otherwise) - // ... - struct ide_controller *ide; - uint8_t attr; - uint16_t signature; - uint16_t caps; - uint32_t cmd_sets; - size_t size; - char model[41]; - } devices[4]; -}; - -int ide_ata_read_pio(struct ide_device *dev, void *buf, size_t nsect, uint64_t lba); -int ide_ata_read_dma(struct ide_device *dev, void *buf, size_t nsect, uint64_t lba); - -void ide_init(struct ide_controller *ide); diff --git a/include/sys/amd64/hw/pci/ahci.h b/include/sys/amd64/hw/pci/ahci.h deleted file mode 100644 index 0fb2a75..0000000 --- a/include/sys/amd64/hw/pci/ahci.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "pci.h" -#include "sys/amd64/hw/ide/ahci.h" - -struct pci_ahci { - pci_addr_t addr; - uint32_t abar_phys; - struct ahci_registers *volatile regs; -}; diff --git a/sys/amd64/hw/ide/ahci.c b/sys/amd64/hw/ide/ahci.c deleted file mode 100644 index 0cab9ee..0000000 --- a/sys/amd64/hw/ide/ahci.c +++ /dev/null @@ -1,377 +0,0 @@ -#include "sys/amd64/hw/ide/ahci.h" -#include "sys/amd64/hw/ide/ata.h" -#include "sys/amd64/hw/irq.h" -#include "sys/amd64/mm/phys.h" -#include "sys/string.h" -#include "sys/assert.h" -#include "sys/debug.h" -#include "sys/heap.h" -#include "sys/dev.h" -#include "sys/blk.h" -#include "sys/mm.h" - -// Memory required for a port: -// 1024 - command list (32 * sizeof(ahci_command_header)) -// 256 - received FIS -// 8192 - command table (32 * sizeof(ahci_command_table_entry)) -// So we need at least 3 pages for all the stuff (buffers not included) - -static int ahci_alloc_cmd(struct ahci_port_registers *port) { - uint32_t slots = (port->p_sact | port->p_ci); - for (int i = 0; i < 32; ++i) { - if (!(slots & (1 << i))) { - return i; - } - } - return -1; -} - -static void ahci_irq_port(struct ahci_port_registers *port) { - if (port->p_is & (1 << 0)) { - // TODO: integrate this with reading code - } - - port->p_is = 0; -} - -static ssize_t ahci_blk_read(struct blkdev *blk, void *buf, size_t off, size_t count) { - _assert(blk && blk->dev_data); - _assert(!(off & 511)); - _assert(!(count & 511)); - - size_t nsect = count / 512; - size_t lba = off / 512; - - // TODO: error? - ahci_sata_read((struct ahci_port_registers *) blk->dev_data, buf, nsect, lba); - - return count; -} - -static ssize_t ahci_blk_write(struct blkdev *blk, const void *buf, size_t off, size_t count) { - _assert(blk && blk->dev_data); - _assert(!(off & 511)); - _assert(!(count & 511)); - - size_t nsect = count / 512; - size_t lba = off / 512; - - ahci_sata_write((struct ahci_port_registers *) blk->dev_data, buf, nsect, lba); - - return count; -} - -static int ahci_add_port_dev(struct ahci_port_registers *port) { - // Create a new device - // XXX: Replace kmalloc with dev_blk_create - struct blkdev *blk = kmalloc(sizeof(struct blkdev)); - blk->dev_data = port; - blk->read = ahci_blk_read; - blk->write = ahci_blk_write; - blk->flags = 0; - - return dev_add(DEV_CLASS_BLOCK, DEV_BLOCK_SDx, blk, NULL); -} -// //void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry)); -// //struct dev_entry *ent = (struct dev_entry *) buf; -// //struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry)); -// //_assert(ent); -// -// //blk->dev_data = port; -// //blk->read = ahci_blk_read; -// //blk->write = ahci_blk_write; -// -// //ent->dev = blk; -// //ent->dev_class = DEV_CLASS_BLOCK; -// //ent->dev_subclass = DEV_BLOCK_SDx; -// //if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) { -// // return -1; -// //} -// -// //dev_entry_add(ent); -// -// return 0; -//} - -uint32_t ahci_irq(void *ctx) { - struct ahci_registers *controller = ctx; - - if (controller->is) { - for (size_t port = 0; port < 32; ++port) { - ahci_irq_port(&controller->ports[port]); - controller->is &= ~(1 << port); - } - - return IRQ_HANDLED; - } - - return IRQ_UNHANDLED; -} - -static void ahci_sata_access(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba, uint8_t dir) { - kdebug("%s access to AHCI drive\n", dir ? "Write" : "Read"); - port->p_is = -1; - - int cmd = ahci_alloc_cmd(port); - _assert(cmd != -1); - - // Command list - struct ahci_command_header *cmd_list = AHCI_PORT_CMD_LIST(port); - struct ahci_command_header *cmd_header = &cmd_list[cmd]; - // Command table entry for the slot - struct ahci_command_table_entry *cmd_table = AHCI_CMD_TABLE_ENTRY(cmd_list, cmd); - - size_t byte_count = nsect * 512; - // Maximum PRDT entry size is 8K, so maximum read from disk using this call is 64K - size_t prd_count = (byte_count + 8191) / 8192; - - if (prd_count > 8) { - panic("Too many PRDT entries\n"); - } - - size_t bytes_left = byte_count; - - cmd_header->attr = sizeof(struct ahci_fis_reg_h2d) / sizeof(uint32_t); - cmd_header->prdtl = prd_count; - cmd_header->prdbc = 0; - - uintptr_t buf_phys = ((uintptr_t) buf) - 0xFFFFFF0000000000; - - memset(cmd_table, 0, sizeof(struct ahci_command_table_entry) + sizeof(struct ahci_prdt_entry) * prd_count); - - for (size_t i = 0; i < prd_count; ++i) { - size_t prd_size = MIN(8192, bytes_left); - _assert(prd_size); - uintptr_t prd_buf = buf_phys + 8192 * i; - - cmd_table->prdt[i].dba = prd_buf & 0xFFFFFFFF; - cmd_table->prdt[i].dbau = prd_buf >> 32; - cmd_table->prdt[i].dbc = ((prd_size - 1) << 1) | 1; - - kdebug("PRD%d: %S at %p\n", i, prd_size, prd_buf); - - if (i == prd_count - 1) { - // XXX: Enable interrupt on last entry? - cmd_table->prdt[i].dbc |= 1 << 31; - } - - bytes_left -= prd_size; - } - - _assert(!bytes_left); - - // Prepare command - struct ahci_fis_reg_h2d *fis_reg_h2d = &cmd_table->fis_reg_h2d; - memset(fis_reg_h2d, 0, sizeof(struct ahci_fis_reg_h2d)); - fis_reg_h2d->type = FIS_REG_H2D; - fis_reg_h2d->cmd = dir ? ATA_CMD_WRITE_DMA_EX : ATA_CMD_READ_DMA_EX; - fis_reg_h2d->cmd_port = 1 << 7; - fis_reg_h2d->lba0 = lba & 0xFF; - fis_reg_h2d->lba1 = (lba >> 8) & 0xFF; - fis_reg_h2d->lba2 = (lba >> 16) & 0xFF; - fis_reg_h2d->dev = (1 << 6); // LBA mode - fis_reg_h2d->lba3 = (lba >> 24) & 0xFF; - fis_reg_h2d->lba4 = (lba >> 32) & 0xFF; - fis_reg_h2d->lba5 = (lba >> 40) & 0xFF; - fis_reg_h2d->countl = nsect & 0xFF; - fis_reg_h2d->counth = (nsect >> 8) & 0xFF; - - uint32_t spin = 0; - while ((port->p_tfd & (ATA_SR_BUSY | ATA_SR_DRQ)) && spin < 1000000) { - ++spin; - } - if (spin == 1000000) { - panic("SATA port hang\n"); - } - - port->p_ci |= 1 << cmd; - - while (1) { - // TODO: interrupts? - - if (!(port->p_ci & (1 << cmd))) { - break; - } - - if (port->p_is & AHCI_PORT_IS_TFES) { - panic("Port task file error\n"); - } - } - - if (port->p_is & AHCI_PORT_IS_TFES) { - panic("Port task file error\n"); - } -} - -void ahci_sata_read(struct ahci_port_registers *port, void *buf, uint32_t nsect, uint64_t lba) { - ahci_sata_access(port, buf, nsect, lba, 0); -} - -void ahci_sata_write(struct ahci_port_registers *port, const void *buf, uint32_t nsect, uint64_t lba) { - ahci_sata_access(port, (void *) buf, nsect, lba, 1); -} - -static void ahci_sata_port_identify(struct ahci_port_registers *port) { - port->p_is = -1; - - int cmd = ahci_alloc_cmd(port); - _assert(cmd != -1); - - // Command list - struct ahci_command_header *cmd_list = AHCI_PORT_CMD_LIST(port); - struct ahci_command_header *cmd_header = &cmd_list[cmd]; - // Command table entry for the slot - struct ahci_command_table_entry *cmd_table = AHCI_CMD_TABLE_ENTRY(cmd_list, cmd); - - // One PRDT entry - char ident_buf[1024] = {0}; - uintptr_t ident_buf_phys = ((uintptr_t) ident_buf) - 0xFFFFFF0000000000; - - cmd_header->attr = (sizeof(struct ahci_fis_reg_h2d) / 4); - cmd_header->prdtl = 1; - - memset(cmd_table, 0, sizeof(struct ahci_command_table_entry) + sizeof(struct ahci_prdt_entry)); - cmd_table->prdt[0].dba = ident_buf_phys & 0xFFFFFFFF; - cmd_table->prdt[0].dbau = ident_buf_phys >> 32; - cmd_table->prdt[0].dbc = 1 | ((sizeof(ident_buf) - 1) << 1); - - struct ahci_fis_reg_h2d *fis_reg_h2d = &cmd_table->fis_reg_h2d; - memset(fis_reg_h2d, 0, sizeof(struct ahci_fis_reg_h2d)); - fis_reg_h2d->type = FIS_REG_H2D; - fis_reg_h2d->cmd = ATA_CMD_IDENTIFY; - fis_reg_h2d->cmd_port = 1 << 7; - - uint32_t spin = 0; - while ((port->p_tfd & (ATA_SR_BUSY | ATA_SR_DRQ)) && spin < 1000000) { - ++spin; - } - if (spin == 1000000) { - panic("SATA port hang\n"); - } - - port->p_ci |= 1 << cmd; - - while (1) { - if (!(port->p_ci & (1 << cmd))) { - break; - } - - if (port->p_is & AHCI_PORT_IS_TFES) { - panic("Port task file error\n"); - } - } - - kdebug("Drive identification:\n"); - - char model_str[41] = {0}; - uint32_t cmd_sets = *(uint32_t *) (ident_buf + ATA_IDENT_CMD_SETS); - uint32_t disk_size = 0; - for (size_t i = 0; i < 40; i += 2) { - model_str[i] = ident_buf[ATA_IDENT_MODEL + i + 1]; - model_str[i + 1] = ident_buf[ATA_IDENT_MODEL + i]; - } - - if (cmd_sets & (1 << 26)) { - disk_size = *((uint32_t *) (ident_buf + ATA_IDENT_MAX_LBAEXT)); - } else { - disk_size = *((uint32_t *) (ident_buf + ATA_IDENT_MAX_LBA)); - } - - kdebug("Model: %s\n", model_str); - kdebug("Size: %S\n", disk_size * 512); -} - -static void ahci_sata_port_init(struct ahci_port_registers *port) { - ahci_port_stop(port); - - uintptr_t page0 = amd64_phys_alloc_page(); - _assert(page0 != MM_NADDR); - kdebug("Command list/recv FIS: %p\n", page0); - - memset((void *) MM_VIRTUALIZE(page0), 0, 4096); - - port->p_clb = page0 & 0xFFFFFFFF; - port->p_clbu = page0 >> 32; - - port->p_fb = (page0 + 0x400) & 0xFFFFFFFF; - port->p_fbu = (page0 + 0x400) >> 32; - - // 8K - uintptr_t page1 = amd64_phys_alloc_contiguous(2); - _assert(page1 != MM_NADDR); - memset((void *) MM_VIRTUALIZE(page1), 0, 8192); - - struct ahci_command_header *cmd_list = (struct ahci_command_header *) MM_VIRTUALIZE(page0); - for (size_t i = 0; i < 32; ++i) { - uintptr_t addr = page1 + i * 256; - - cmd_list[i].prdtl = 8; - cmd_list[i].ctba = addr & 0xFFFFFFFF; - cmd_list[i].ctbau = addr >> 32; - } - - ahci_port_start(port); - - // TODO: add the device somewhere to kernel as /dev/sdX - // guess I should implement device management eventually -} - -// Setup a SATA port -void ahci_port_init(uint8_t n, struct ahci_port_registers *port) { - switch (port->p_sig) { - case AHCI_PORT_SIG_SATA: - ahci_sata_port_init(port); - ahci_sata_port_identify(port); - _assert(ahci_add_port_dev(port) == 0); - - // Enable IRQs - port->p_ie |= (1 << 0); - break; - default: - kdebug("Skipping unknown drive type\n"); - break; - } -} - -void ahci_port_stop(struct ahci_port_registers *port) { - port->p_cmd &= ~(AHCI_PORT_CMD_ST | AHCI_PORT_CMD_FRE); - - while (port->p_cmd & (AHCI_PORT_CMD_CR | AHCI_PORT_CMD_FR)); -} - -void ahci_port_start(struct ahci_port_registers *port) { - while (port->p_cmd & AHCI_PORT_CMD_CR); - - port->p_cmd |= AHCI_PORT_CMD_FRE | AHCI_PORT_CMD_ST; -} - -void ahci_init(struct ahci_registers *regs) { - // Read AHCI version - kdebug("Initializing AHCI controller version %d.%d\n", regs->vs >> 16, regs->vs & 0xFFFF); - - uint32_t pi = regs->pi; - - // Find available ports - for (size_t i = 0; i < 32; ++i) { - uint32_t bit = 1 << i; - - if (pi & bit) { - struct ahci_port_registers *port = ®s->ports[i]; - uint32_t ssts = port->p_ssts; - - uint8_t ipm = (ssts >> 8) & 0x0F; - uint8_t spd = (ssts >> 4) & 0x0F; - uint8_t det = ssts & 0x0F; - - if (ipm != AHCI_PORT_SSTS_IPM_ACTIVE || spd == 0 || det != AHCI_PORT_SSTS_DET_OK) { - // For one of the reasons the device is not available at this port - continue; - } - - ahci_port_init(i, port); - } - } - - // Enable HBA interrupts - regs->ghc |= 1 << 1; -} diff --git a/sys/amd64/hw/ide/ide.c b/sys/amd64/hw/ide/ide.c deleted file mode 100644 index 6615b78..0000000 --- a/sys/amd64/hw/ide/ide.c +++ /dev/null @@ -1,433 +0,0 @@ -#include "sys/amd64/hw/ide/ide.h" -#include "sys/amd64/hw/ide/ata.h" -#include "sys/amd64/mm/phys.h" -#include "sys/amd64/hw/io.h" -#include "sys/assert.h" -#include "sys/string.h" -#include "sys/debug.h" -#include "sys/panic.h" -#include "sys/heap.h" -#include "sys/dev.h" -#include "sys/blk.h" -#include "sys/mm.h" - -static void ide_reg_write(struct ide_controller *ide, uint8_t channel, uint8_t reg, uint8_t data) { - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, 0x80 | ide->channels[channel].no_int); - } - - if (reg < 0x08) { - outb(ide->channels[channel].base + reg - 0x00, data); - } else if (reg < 0x0C) { - outb(ide->channels[channel].base + reg - 0x06, data); - } else if (reg < 0x0E) { - outb(ide->channels[channel].ctrl + reg - 0x0A, data); - } else if (reg < 0x16) { - outb(ide->channels[channel].bmide + reg - 0x0E, data); - } - - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, ide->channels[channel].no_int); - } -} - -uint8_t ide_reg_read(struct ide_controller *ide, uint8_t channel, uint8_t reg) { - uint8_t result; - - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, 0x80 | ide->channels[channel].no_int); - } - - if (reg < 0x08) { - result = inb(ide->channels[channel].base + reg - 0x00); - } else if (reg < 0x0C) { - result = inb(ide->channels[channel].base + reg - 0x06); - } else if (reg < 0x0E) { - result = inb(ide->channels[channel].ctrl + reg - 0x0A); - } else if (reg < 0x16) { - result = inb(ide->channels[channel].bmide + reg - 0x0E); - } - - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, ide->channels[channel].no_int); - } - return result; -} - -void ide_reg_read_dbuf(struct ide_controller *ide, uint8_t channel, uint8_t reg, uint32_t *buf, size_t count) { - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, 0x80 | ide->channels[channel].no_int); - } - - while (count) { - if (reg < 0x08) { - *buf++ = inl(ide->channels[channel].base + reg - 0x00); - } else if (reg < 0x0C) { - *buf++ = inl(ide->channels[channel].base + reg - 0x06); - } else if (reg < 0x0E) { - *buf++ = inl(ide->channels[channel].ctrl + reg - 0x0A); - } else if (reg < 0x16) { - *buf++ = inl(ide->channels[channel].bmide + reg - 0x0E); - } - - --count; - } - - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, ide->channels[channel].no_int); - } -} - -void ide_reg_read_wbuf(struct ide_controller *ide, uint8_t channel, uint8_t reg, uint16_t *buf, size_t count) { - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, 0x80 | ide->channels[channel].no_int); - } - - while (count) { - if (reg < 0x08) { - *buf++ = inw(ide->channels[channel].base + reg - 0x00); - } else if (reg < 0x0C) { - *buf++ = inw(ide->channels[channel].base + reg - 0x06); - } else if (reg < 0x0E) { - *buf++ = inw(ide->channels[channel].ctrl + reg - 0x0A); - } else if (reg < 0x16) { - *buf++ = inw(ide->channels[channel].bmide + reg - 0x0E); - } - - --count; - } - - if (reg > 0x07 && reg < 0x0C) { - ide_reg_write(ide, channel, ATA_REG_CONTROL, ide->channels[channel].no_int); - } -} - -// TODO: this is bad -#define ide_delay() for (size_t i = 0; i < 1000000; ++i); - -static int ide_wait_busy(struct ide_controller *ide, uint8_t ch) { - uint8_t status; - - while (1) { - status = ide_reg_read(ide, ch, ATA_REG_STATUS); - if (status & ATA_SR_ERR) { - return -1; - } - if (!(status & ATA_SR_BUSY)) { - break; - } - } - - return 0; -} - -static int ide_wait_poll(struct ide_controller *ide, uint8_t ch) { - // 400ns delay - for(int i = 0; i < 4; i++) { - ide_reg_read(ide, ch, ATA_REG_ALTSTATUS); - } - - return ide_wait_busy(ide, ch); -} - -int ide_ata_set_addr(struct ide_device *dev, uint64_t lba, size_t nsect) { - struct ide_controller *ide = dev->ide; - uint8_t ch = (dev->attr >> 1) & 1; - uint8_t sl = (dev->attr >> 2) & 1; - - uint8_t lba_buf[6] = {0}; - int lba_mode; - - uint16_t cyl; - uint8_t head, sect = 0; - - if (lba >= 0x10000000) { - lba_mode = 2; - // LBA48 - lba_buf[0] = lba & 0xFF; - lba_buf[1] = (lba >> 8) & 0xFF; - lba_buf[2] = (lba >> 16) & 0xFF; - lba_buf[3] = (lba >> 24) & 0xFF; - lba_buf[4] = (lba >> 32) & 0xFF; - lba_buf[5] = (lba >> 40) & 0xFF; - } else if (dev->caps & 0x200) { - lba_mode = 1; - // LBA24 - lba_buf[0] = lba & 0xFF; - lba_buf[1] = (lba >> 8) & 0xFF; - lba_buf[1] = (lba >> 16) & 0xFF; - } else { - lba_mode = 0; - - sect = (lba % 63) + 1; - cyl = (lba + 1 - sect) / (16 * 63); - head = (lba + 1 - sect) % (16 * 63) / (63); - - // CHS - lba_buf[0] = sect; - lba_buf[1] = cyl & 0xFF; - lba_buf[2] = cyl >> 8; - } - - while (ide_reg_read(ide, ch, ATA_REG_STATUS) & ATA_SR_BUSY); - - if (lba_mode) { - ide_reg_write(ide, ch, ATA_REG_HDDEVSEL, 0xE0 | (sl << 4)); - } else { - ide_reg_write(ide, ch, ATA_REG_HDDEVSEL, 0xA0 | (sl << 4) | head); - } - - if (lba_mode == 2) { - ide_reg_write(ide, ch, ATA_REG_SECCOUNT1, 0); - ide_reg_write(ide, ch, ATA_REG_LBA3, lba_buf[3]); - ide_reg_write(ide, ch, ATA_REG_LBA4, lba_buf[4]); - ide_reg_write(ide, ch, ATA_REG_LBA5, lba_buf[5]); - } - - ide_reg_write(ide, ch, ATA_REG_SECCOUNT0, nsect); - ide_reg_write(ide, ch, ATA_REG_LBA0, lba_buf[0]); - ide_reg_write(ide, ch, ATA_REG_LBA1, lba_buf[1]); - ide_reg_write(ide, ch, ATA_REG_LBA2, lba_buf[2]); - - return lba_mode; -} - -int ide_ata_read_dma(struct ide_device *dev, void *buf, size_t nsect, uint64_t lba) { - struct ide_controller *ide = dev->ide; - uint8_t ch = (dev->attr >> 1) & 1; - uint8_t sl = (dev->attr >> 2) & 1; - - // Disable IRQs - ide_reg_write(ide, ch, ATA_REG_CONTROL, ATA_CONTROL_NO_INT); - - // TODO: wait until previous DMA operation finishes - struct ide_prdt_entry *ent = (struct ide_prdt_entry *) MM_VIRTUALIZE(ide->dma_page + ch * 2048); - - size_t bytes_count = nsect * 512; - size_t bytes_left = bytes_count; - size_t prd_count = (bytes_count + 65535) / 65536; - // TODO: do this properly: check alignments etc - uintptr_t buf_phys = MM_PHYS(buf); - - // Fill out PRDT - for (size_t i = 0; i < prd_count; ++i) { - size_t prd_size = MIN(65536, bytes_left); - _assert((buf_phys + i * 65536) < 0xFFFFFFFF); - ent[i].addr = (buf_phys + i * 65536) & 0xFFFFFFFF; - ent[i].size = prd_size == 65536 ? 0 : prd_size; - ent[i].attr = 0; - if (i == prd_count - 1) { - ent[i].attr = 1 << 15; - } - bytes_left -= prd_size; - } - - // Start DMA transfer - outb(ide->channels[ch].bmide + 0x00, 1); - - int lba_mode = ide_ata_set_addr(dev, lba, nsect); - uint8_t cmd; - if (lba_mode == 2) { - cmd = ATA_CMD_READ_DMA_EX; - } else { - cmd = ATA_CMD_READ_DMA; - } - - ide_reg_write(ide, ch, ATA_REG_COMMAND, cmd); - - // Wait for the drive to receive the command before sending another one - if (ide_wait_poll(ide, ch) < 0) { - panic("Read failed\n"); - } - - // TODO: IRQs? - while (1) { - uint8_t status = inb(ide->channels[ch].bmide + 0x02); - - if (status & (1 << 1)) { - panic("DMA error\n"); - } - - if (!(status & (1 << 0))) { - break; - } - } - - return 0; -} -int ide_ata_read_pio(struct ide_device *dev, void *buf, size_t nsect, uint64_t lba) { - struct ide_controller *ide = dev->ide; - uint8_t ch = (dev->attr >> 1) & 1; - uint8_t sl = (dev->attr >> 2) & 1; - - // Disable IRQs - ide_reg_write(ide, ch, ATA_REG_CONTROL, ATA_CONTROL_NO_INT); - - int lba_mode = ide_ata_set_addr(dev, lba, nsect); - - uint8_t cmd; - if (lba_mode == 2) { - cmd = ATA_CMD_READ_PIO_EX; - } else { - cmd = ATA_CMD_READ_PIO; - } - - ide_reg_write(ide, ch, ATA_REG_COMMAND, cmd); - - uint16_t *word = (uint16_t *) buf; - for (size_t i = 0; i < nsect; ++i) { - if (ide_wait_poll(ide, ch) != 0) { - return -1; - } - - // Read a sector - ide_reg_read_wbuf(ide, ch, ATA_REG_DATA, word + 256 * i, 256); - } - - return 0; -} - -//static ssize_t ide_blk_read(struct blkdev *blk, void *buf, size_t off, size_t count) { -// _assert(blk && blk->dev_data); -// _assert(!(off & 511)); -// _assert(!(count & 511)); -// -// size_t nsect = count / 512; -// size_t lba = off / 512; -// -// // XXX: DMA fucks up for some reason, investigate that -// ide_ata_read_pio((struct ide_device *) blk->dev_data, buf, nsect, lba); -// -// return count; -//} - -static int ide_add_ata_dev(struct ide_device *dev) { - //void *buf = kmalloc(sizeof(struct blkdev) + sizeof(struct dev_entry)); - //struct dev_entry *ent = (struct dev_entry *) buf; - //struct blkdev *blk = (struct blkdev *) ((uintptr_t) buf + sizeof(struct dev_entry)); - //_assert(ent); - - //blk->dev_data = dev; - //blk->write = NULL; - //blk->read = ide_blk_read; - ////blk->write = ahci_blk_write; - - //ent->dev = blk; - //ent->dev_class = DEV_CLASS_BLOCK; - //ent->dev_subclass = DEV_BLOCK_HDx; - //if (dev_alloc_name(ent->dev_class, ent->dev_subclass, ent->dev_name) != 0) { - // return -1; - //} - - //dev_entry_add(ent); - - return 0; -} - -void ide_init(struct ide_controller *ide) { - // Initialize from PCI IDE information: BARs - ide->channels[0].base = ide->bar0; - ide->channels[0].ctrl = ide->bar1; - ide->channels[0].bmide = ide->bar4; - ide->channels[0].no_int = 0; - - ide->channels[1].base = ide->bar2; - ide->channels[1].ctrl = ide->bar3; - ide->channels[1].bmide = ide->bar4 + 8; - ide->channels[1].no_int = 0; - - // Disable IRQs for both channels - ide_reg_write(ide, 0, ATA_REG_CONTROL, ATA_CONTROL_NO_INT); - ide_reg_write(ide, 1, ATA_REG_CONTROL, ATA_CONTROL_NO_INT); - - // Setup busmastering DMA - ide->dma_page = amd64_phys_alloc_page(); - _assert(ide->dma_page != MM_NADDR); - outb(ide->channels[0].bmide + 0x00, 0); - outb(ide->channels[0].bmide + 0x04, ide->dma_page & 0xFF); - outb(ide->channels[0].bmide + 0x05, (ide->dma_page >> 8) & 0xFF); - outb(ide->channels[0].bmide + 0x06, (ide->dma_page >> 16) & 0xFF); - outb(ide->channels[0].bmide + 0x07, (ide->dma_page >> 24) & 0xFF); - outb(ide->channels[1].bmide + 0x00, 0); - outb(ide->channels[1].bmide + 0x04, (ide->dma_page + 2048) & 0xFF); - outb(ide->channels[1].bmide + 0x05, ((ide->dma_page + 2048) >> 8) & 0xFF); - outb(ide->channels[1].bmide + 0x06, ((ide->dma_page + 2048) >> 16) & 0xFF); - outb(ide->channels[1].bmide + 0x07, ((ide->dma_page + 2048) >> 24) & 0xFF); - - char ident_buf[1024]; - - for (size_t ch = 0; ch < 2; ++ch) { - for (size_t sl = 0; sl < 2; ++sl) { - struct ide_device *dev = &ide->devices[ch * 2 + sl]; - dev->ide = ide; - - dev->attr = 0; - - ide_reg_write(ide, ch, ATA_REG_HDDEVSEL, 0xA0 | (sl << 4)); - ide_delay(); - - ide_reg_write(ide, ch, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - ide_delay(); - - if (ide_reg_read(ide, ch, ATA_REG_STATUS) == 0) { - continue; - } - - if (ide_wait_busy(ide, ch) != 0) { - // May be an ATAPI device - uint8_t b0 = ide_reg_read(ide, ch, ATA_REG_LBA1); - uint8_t b1 = ide_reg_read(ide, ch, ATA_REG_LBA2); - - if ((b0 == 0x14 && b1 == 0xEB) || (b0 == 0x69 && b1 == 0x96)) { - dev->attr |= (1 << 3); - } else { - // Skip invalid device - continue; - } - - // Try again with correct ATAPI command - ide_reg_write(ide, ch, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); - ide_delay(); - } - - // Read result from device's I/O buffer - ide_reg_read_dbuf(ide, ch, ATA_REG_DATA, (uint32_t *) ident_buf, 128); - - // Set device present, channel and slave/master - dev->attr |= (1 << 0) | (ch << 1) | (sl << 2); - dev->caps = *(uint16_t *) (ident_buf + ATA_IDENT_CAPS); - dev->signature = *(uint16_t *) (ident_buf + ATA_IDENT_DEVICE_TYPE); - dev->cmd_sets = *(uint32_t *) (ident_buf + ATA_IDENT_CMD_SETS); - - if (dev->cmd_sets & (1 << 26)) { - dev->size = *(uint32_t *) (ident_buf + ATA_IDENT_MAX_LBAEXT); - } else { - dev->size = *(uint32_t *) (ident_buf + ATA_IDENT_MAX_LBA); - } - - for (size_t i = 0; i < 40; i += 2) { - dev->model[i] = ident_buf[ATA_IDENT_MODEL + i + 1]; - dev->model[i + 1] = ident_buf[ATA_IDENT_MODEL + i]; - } - // Trim padding whitespace - for (size_t i = 39; i > 0; --i) { - if (dev->model[i] != ' ') { - break; - } - dev->model[i] = 0; - } - dev->model[40] = 0; - - kdebug("Channel %s, %s, %s: %s, %S\n", - ch ? "Secondary" : "Primary", - sl ? "Slave" : "Master", - dev->attr & (1 << 3) ? "ATAPI" : "ATA", - dev->model, - dev->size * 512); - - if (!(dev->attr & (1 << 3))) { - ide_add_ata_dev(dev); - } - } - } -} diff --git a/sys/amd64/hw/pci/ahci.c b/sys/amd64/hw/pci/ahci.c deleted file mode 100644 index 06a815b..0000000 --- a/sys/amd64/hw/pci/ahci.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "sys/amd64/hw/pci/ahci.h" -#include "sys/amd64/hw/ide/ahci.h" -#include "sys/amd64/hw/ide/ata.h" -#include "sys/amd64/hw/irq.h" -#include "sys/amd64/mm/phys.h" -#include "sys/assert.h" -#include "sys/string.h" -#include "sys/debug.h" -#include "sys/attr.h" -#include "sys/mm.h" - -// Only one controller is supported now -static struct pci_ahci ahci; - -static void pci_ahci_init(pci_addr_t addr) { - kdebug("Initializing AHCI controller at " PCI_FMTADDR "\n", PCI_VAADDR(addr)); - - uint32_t irq = pci_config_read_dword(addr, PCI_CONFIG_IRQ); - - ahci.addr = addr; - ahci.abar_phys = pci_config_read_dword(addr, PCI_CONFIG_BAR(5)); - ahci.regs = (struct ahci_registers *) MM_VIRTUALIZE(ahci.abar_phys); - - kdebug("AHCI registers: %p\n", ahci.regs); - - ahci_init(ahci.regs); - - uint8_t int_pin = ((irq >> 8) & 0xFF); - if (int_pin) { - irq_add_pci_handler(addr, int_pin - 1, ahci_irq, ahci.regs); - } -} - -static __init void pci_ahci_register(void) { - pci_add_class_driver(0x0106, pci_ahci_init); -} diff --git a/sys/amd64/hw/pci/ide.c b/sys/amd64/hw/pci/ide.c deleted file mode 100644 index e0904a1..0000000 --- a/sys/amd64/hw/pci/ide.c +++ /dev/null @@ -1,102 +0,0 @@ -#include "sys/amd64/hw/pci/pci.h" -#include "sys/amd64/hw/ide/ide.h" -#include "sys/assert.h" -#include "sys/panic.h" -#include "sys/debug.h" -#include "sys/attr.h" - -// XXX: only one IDE controller per host -static struct ide_controller pci_ide; - -static void pci_ide_init(pci_addr_t addr) { - kdebug("Initializing PCI IDE controller at " PCI_FMTADDR "\n", PCI_VAADDR(addr)); - - uint32_t irq_config = pci_config_read_dword(addr, PCI_CONFIG_IRQ); - uint32_t class = pci_config_read_dword(addr, PCI_CONFIG_CLASS); - uint8_t prog_if = (class >> 8) & 0xFF; - uint32_t bar; - uint32_t cmd = pci_config_read_dword(addr, PCI_CONFIG_CMD); - - // Read BARs - bar = pci_config_read_dword(addr, PCI_CONFIG_BAR(0)); - assert(!bar || (bar & 1), "IDE BAR not in I/O space\n"); - if (bar & ~3) { - pci_ide.bar0 = bar & ~3; - } else { - pci_ide.bar0 = IDE_DEFAULT_BAR0; - } - bar = pci_config_read_dword(addr, PCI_CONFIG_BAR(1)); - assert(!bar || (bar & 1), "IDE BAR not in I/O space\n"); - if (bar & ~3) { - pci_ide.bar1 = bar & ~3; - } else { - pci_ide.bar1 = IDE_DEFAULT_BAR1; - } - bar = pci_config_read_dword(addr, PCI_CONFIG_BAR(2)); - assert(!bar || (bar & 1), "IDE BAR not in I/O space\n"); - if (bar & ~3) { - pci_ide.bar2 = bar & ~3; - } else { - pci_ide.bar2 = IDE_DEFAULT_BAR2; - } - bar = pci_config_read_dword(addr, PCI_CONFIG_BAR(3)); - assert(!bar || (bar & 1), "IDE BAR not in I/O space\n"); - if (bar & ~3) { - pci_ide.bar3 = bar & ~3; - } else { - pci_ide.bar3 = IDE_DEFAULT_BAR3; - } - bar = pci_config_read_dword(addr, PCI_CONFIG_BAR(4)); - assert(!bar || (bar & 1), "IDE BAR not in I/O space\n"); - pci_ide.bar4 = bar & ~3; - if (!pci_ide.bar4) { - kwarn("No IDE busmastering BAR4 in PCI configuration space\n"); - } - - if ((irq_config >> 8) & 0xFF) { - panic("TODO: support IDE controllers with non-legacy IRQs\n"); - } - - // Enable PCI busmastering for IDE controller - cmd |= (1 << 2); - pci_config_write_dword(addr, PCI_CONFIG_CMD, cmd); - - irq_config &= ~0xFF; - irq_config |= 0xFE; - pci_config_write_dword(addr, PCI_CONFIG_IRQ, irq_config); - - irq_config = pci_config_read_dword(addr, PCI_CONFIG_IRQ); - - if ((irq_config & 0xFF) == 0xFE) { - // Need IRQ assignment - kdebug("Assigning ISA IRQ14 to IDE controller\n"); - - // I guess using ISA 14 IRQ is a good idea - irq_config &= ~0xFF; - irq_config |= 14; - - pci_config_write_dword(addr, PCI_CONFIG_IRQ, irq_config); - irq_config = pci_config_read_dword(addr, PCI_CONFIG_IRQ); - - assert((irq_config & 0xFF) == 14, "Failed to assign IRQ14 to IDE drive controller\n"); - - pci_ide.irq0 = 14; - } else { - // The device either does not use IRQs or is a - // paraller IDE with IRQs 14 and 15 - if (prog_if == 0x80 || prog_if == 0x8A) { - // TODO: handle this case - //panic("This is a parallel IDE controller\n"); - return; - } else { - // TODO: handle this case - panic("The device has no IRQs\n"); - } - } - - ide_init(&pci_ide); -} - -static __init void pci_ide_register(void) { - pci_add_class_driver(0x0101, pci_ide_init); -}