idedrv Implement DMA reading/writing without IRQ support
All checks were successful
Build ISO image / build-and-deploy (push) Successful in 1m35s
Build documentation / build-and-deploy (push) Successful in 38s

This commit is contained in:
2026-04-26 18:47:05 +02:00
parent 05ab0d4c86
commit a2ed5c2b8a
4 changed files with 326 additions and 89 deletions

View File

@@ -36,6 +36,17 @@
#define PCI_BAR_MEM64 0x04
#define PCI_BAR_PREFETCH 0x08
#define PCI_CMD_IOSPACE 0
#define PCI_CMD_MEMSPACE 1
#define PCI_CMD_BUSMASTER 2
#define PCI_CMD_SPECIAL_CYCLES 3
#define PCI_CMD_MEMWRIVENA 4
#define PCI_CMD_VGA_PALT_SNOOP 5
#define PCI_CMD_PARITY_ERR_RESP 6
#define PCI_CMD_SERR 8
#define PCI_CMD_FBBENA 9
#define PCI_CMD_INTRDISABLE 10
#define PCI_CAP_MSI 0x05
struct pci_vendor {

View File

@@ -57,7 +57,9 @@ static void ide_make_device(struct proc* proc, struct reschedule_ctx* rctx,
.ctrl = probe.ctrl,
.devno = probe.devno,
.irq = probe.irq,
.bmbase = probe.bmbase,
.irqs_support = probe.irqs_support,
.bm_support = probe.bm_support,
};
struct device* ide = device_create(DEVICE_TYPE_DRIVE, device_key, ops, lengthof(ops),
@@ -68,7 +70,10 @@ static void ide_make_device(struct proc* proc, struct reschedule_ctx* rctx,
bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_info pci_info) {
uint16_t pci_cmd = pci_read16(pci_info.bus, pci_info.slot, pci_info.func, PCI_COMMAND);
uint16_t new_cmd = (pci_cmd | (1 << 0) | (1 << 2)) & ~(1 << 10);
uint16_t new_cmd = pci_cmd;
new_cmd |= (1 << PCI_CMD_IOSPACE);
new_cmd |= (1 << PCI_CMD_BUSMASTER);
new_cmd &= ~(1 << PCI_CMD_INTRDISABLE);
if (pci_cmd != new_cmd) {
pci_write16(pci_info.bus, pci_info.slot, pci_info.func, PCI_COMMAND, new_cmd);
@@ -79,7 +84,14 @@ bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_inf
uint8_t progif = pci_read8(pci_info.bus, pci_info.slot, pci_info.func, PCI_PROG_IF);
DEBUG("progif: %s\n", progif_msg[progif]);
uint16_t pcmd, pctrl, scmd, sctrl;
uint16_t pcmd, pctrl, pbmbase, scmd, sctrl, sbmbase;
bool irqs_support = false;
bool bm_support = false;
uint32_t bar4 = pci_read32(pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR4);
uint16_t bmbase = (uint16_t)(bar4 & 0xFFFC);
bm_support = (bmbase != 0) && (bar4 & PCI_BAR_IO);
if ((progif & 0x01)) {
uint32_t bar0 = pci_read32(pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR0);
@@ -99,6 +111,7 @@ bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_inf
pcmd = 0x1F0;
pctrl = 0x3F6;
}
pbmbase = bmbase;
if ((progif & 0x04)) {
uint32_t bar2 = pci_read32(pci_info.bus, pci_info.slot, pci_info.func, PCI_BAR2);
@@ -118,8 +131,7 @@ bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_inf
scmd = 0x170;
sctrl = 0x376;
}
bool irqs_support = false;
sbmbase = bmbase + 8;
if ((progif & 0x05)) {
irqs_support = false;
@@ -134,17 +146,18 @@ bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_inf
}
}
DEBUG("pcmd=%x, pctrl=%x\n", pcmd, pctrl);
DEBUG("scmd=%x, sctrl=%x\n", scmd, sctrl);
DEBUG("IRQ support=%d\n", irqs_support);
DEBUG("pcmd=%x, pctrl=%x, pbmbase=%x\n", pcmd, pctrl, pbmbase);
DEBUG("scmd=%x, sctrl=%x, sbmbase=%x\n", scmd, sctrl, sbmbase);
DEBUG("IRQ support=%d, Bus mastering supported=%d\n", irqs_support, bm_support);
uint16_t channels[2][3] = {{pcmd, pctrl, INTR_IDE_DRIVE_PRIM},
{scmd, sctrl, INTR_IDE_DRIVE_SCND}};
uint16_t channels[2][4] = {{pcmd, pctrl, INTR_IDE_DRIVE_PRIM, pbmbase},
{scmd, sctrl, INTR_IDE_DRIVE_SCND, sbmbase}};
for (size_t i = 0; i < lengthof(channels); i++) {
uint16_t cmd = channels[i][0];
uint16_t ctrl = channels[i][1];
uint8_t irq = channels[i][2];
uint16_t bmbase = channels[i][3];
for (size_t dev = 0; dev < 2; dev++) {
ide_probe(cmd, ctrl, dev, &probe);
@@ -153,6 +166,8 @@ bool pci_ide_init(struct proc* proc, struct reschedule_ctx* rctx, struct pci_inf
probe.io = cmd;
probe.irq = irq;
probe.irqs_support = irqs_support;
probe.bmbase = bmbase;
probe.bm_support = bm_support;
if ((probe.flags & IDE_PROBE_AVAIL))
ide_make_device(proc, rctx, probe);