diff --git a/kernel/device/idedrv.c b/kernel/device/idedrv.c index ef8ff92..b89a4bf 100644 --- a/kernel/device/idedrv.c +++ b/kernel/device/idedrv.c @@ -91,19 +91,16 @@ static void ide_irq (void* arg, void* regs, bool user, struct reschedule_ctx* rc uint64_t fd, fp; struct idedrv* idedrv = arg; - DEBUG ("1\n"); spin_lock (&idedrv->device->lock, &fd); struct idedrv_request* req = idedrv->current_req; - DEBUG ("2\n"); if (req == NULL) { (void)inb (idedrv->io + IDE_REG_STATUS); spin_unlock (&idedrv->device->lock, fd); return; } - DEBUG ("3\n"); uint8_t status = inb (idedrv->io + IDE_REG_STATUS); @@ -113,7 +110,6 @@ static void ide_irq (void* arg, void* regs, bool user, struct reschedule_ctx* rc spin_unlock (&idedrv->device->lock, fd); return; } - DEBUG ("4\n"); if ((status & IDE_DRQ) && (req->sector_done_count < req->sector_count)) { uint16_t* p = req->buffer + (req->sector_done_count * (idedrv->sector_size / 2)); @@ -124,17 +120,14 @@ static void ide_irq (void* arg, void* regs, bool user, struct reschedule_ctx* rc outsw (idedrv->io + IDE_REG_DATA, p, idedrv->sector_size / 2); req->sector_done_count++; - DEBUG ("4\n"); } if ((req->sector_done_count >= req->sector_count)) { atomic_store (&req->done, 1); idedrv->current_req = NULL; } - DEBUG ("6\n"); spin_unlock (&idedrv->device->lock, fd); - DEBUG ("7\n"); } void ide_probe (uint16_t io, uint16_t ctrl, uint8_t devno, struct ide_probe* probe) { @@ -164,7 +157,7 @@ void ide_probe (uint16_t io, uint16_t ctrl, uint8_t devno, struct ide_probe* pro if (status == 0) return; - if (!ide_wait (io, 100000, true, true)) { + if (!ide_wait (io, 90000000, true, true)) { return; } @@ -172,12 +165,10 @@ void ide_probe (uint16_t io, uint16_t ctrl, uint8_t devno, struct ide_probe* pro probe->flags |= IDE_PROBE_AVAIL; - if ((identify_buffer[106] & 0xC000) == 0x4000) { - if (identify_buffer[106] & (1 << 12)) { - uint32_t words_per_sector = - (uint32_t)identify_buffer[117] | ((uint32_t)identify_buffer[118] << 16); - probe->sector_size = (size_t)words_per_sector * 2; - } + if ((identify_buffer[106] & 0xC000) == 0x4000 && identify_buffer[106] & (1 << 12)) { + uint32_t words_per_sector = + (uint32_t)identify_buffer[117] | ((uint32_t)identify_buffer[118] << 16); + probe->sector_size = (size_t)words_per_sector * 2; } if ((identify_buffer[83] & (1 << 10)) != 0) @@ -258,10 +249,12 @@ bool idedrv_init (struct device* device, void* arg, struct proc* proc, idedrv->devno = init->devno; idedrv->irq = init->irq; idedrv->current_req = NULL; + idedrv->irqs_support = init->irqs_support; device->udata = idedrv; - irq_attach (&ide_irq, idedrv, idedrv->irq); + if (idedrv->irqs_support) + irq_attach (&ide_irq, idedrv, idedrv->irq); return true; } @@ -274,7 +267,9 @@ void idedrv_fini (struct device* device, struct proc* proc, struct reschedule_ct idedrv->current_req = NULL; } - irq_detach (idedrv->irq); + if (idedrv->irqs_support) + irq_detach (idedrv->irq); + free (idedrv); } @@ -291,46 +286,53 @@ int idedrv_read (struct device* device, struct proc* proc, struct reschedule_ctx struct idedrv* idedrv = device->udata; - DEBUG ("1\n"); - if (sector + sector_count > idedrv->sector_count) return -ST_OOB_ERROR; if (!ide_wait (idedrv->io, 100000, false, false)) return -ST_XDRV_READ_ERROR; - struct idedrv_request* req = malloc (sizeof (*req)); + if (idedrv->irqs_support) { + struct idedrv_request* req = malloc (sizeof (*req)); - if (req == NULL) - return -ST_OOM_ERROR; + if (req == NULL) + return -ST_OOM_ERROR; - memset (req, 0, sizeof (*req)); - req->buffer = buffer; - req->sector_count = sector_count; - req->sector_done_count = 0; - req->type = IDE_READ; - DEBUG ("2\n"); + memset (req, 0, sizeof (*req)); + req->buffer = buffer; + req->sector_count = sector_count; + req->sector_done_count = 0; + req->type = IDE_READ; - idedrv->current_req = req; + idedrv->current_req = req; - ide_prepare (idedrv, sector, sector_count, true); - DEBUG ("3\n"); + ide_prepare (idedrv, sector, sector_count, true); - DEBUG ("4\n"); + uint8_t cmd = idedrv->lba48 ? IDE_CMD_READ48 : IDE_CMD_READ28; + outb (idedrv->io + IDE_REG_CMD, cmd); - uint8_t cmd = idedrv->lba48 ? IDE_CMD_READ48 : IDE_CMD_READ28; - outb (idedrv->io + IDE_REG_CMD, cmd); - DEBUG ("5\n"); + spin_unlock (&device->lock, *lockflags); - spin_unlock (&device->lock, *lockflags); + while (!atomic_load (&req->done)) + spin_lock_relax (); - while (!atomic_load (&req->done)) - spin_lock_relax (); + spin_lock (&device->lock, lockflags); - spin_lock (&device->lock, lockflags); - DEBUG ("6\n"); + free (req); + } else { + ide_prepare (idedrv, sector, sector_count, false); - free (req); + uint8_t cmd = idedrv->lba48 ? IDE_CMD_READ48 : IDE_CMD_READ28; + outb (idedrv->io + IDE_REG_CMD, cmd); + + for (uint16_t s = 0; s < sector_count; s++) { + if (!ide_wait (idedrv->io, 100000, true, true)) + return -ST_XDRV_READ_ERROR; + + insw (idedrv->io + IDE_REG_DATA, buffer + (s * (idedrv->sector_size / 2)), + idedrv->sector_size / 2); + } + } return ST_OK; } @@ -355,43 +357,58 @@ int idedrv_write (struct device* device, struct proc* proc, struct reschedule_ct if (!ide_wait (idedrv->io, 100000, false, false)) return -ST_XDRV_WRITE_ERROR; - struct idedrv_request* req = malloc (sizeof (*req)); + if (idedrv->irqs_support) { + struct idedrv_request* req = malloc (sizeof (*req)); - if (req == NULL) - return -ST_OOM_ERROR; + if (req == NULL) + return -ST_OOM_ERROR; - memset (req, 0, sizeof (*req)); - req->buffer = buffer; - req->sector_count = sector_count; - req->sector_done_count = 0; - req->type = IDE_WRITE; + memset (req, 0, sizeof (*req)); + req->buffer = buffer; + req->sector_count = sector_count; + req->sector_done_count = 0; + req->type = IDE_WRITE; - idedrv->current_req = req; + idedrv->current_req = req; - ide_prepare (idedrv, sector, sector_count, true); + ide_prepare (idedrv, sector, sector_count, true); - uint8_t cmd = idedrv->lba48 ? IDE_CMD_WRITE48 : IDE_CMD_WRITE28; - outb (idedrv->io + IDE_REG_CMD, cmd); + uint8_t cmd = idedrv->lba48 ? IDE_CMD_WRITE48 : IDE_CMD_WRITE28; + outb (idedrv->io + IDE_REG_CMD, cmd); + + if (!ide_wait (idedrv->io, 100000, true, true)) { + idedrv->current_req = NULL; + free (req); + return -ST_XDRV_WRITE_ERROR; + } + + outsw (idedrv->io + IDE_REG_DATA, buffer, idedrv->sector_size / 2); + + req->sector_done_count = 1; + + spin_unlock (&device->lock, *lockflags); + + while (!atomic_load (&req->done)) + spin_lock_relax (); + + spin_lock (&device->lock, lockflags); - if (!ide_wait (idedrv->io, 100000, true, true)) { - idedrv->current_req = NULL; free (req); - return -ST_XDRV_WRITE_ERROR; + } else { + ide_prepare (idedrv, sector, sector_count, false); + + uint8_t cmd = idedrv->lba48 ? IDE_CMD_WRITE48 : IDE_CMD_WRITE28; + outb (idedrv->io + IDE_REG_CMD, cmd); + + for (uint16_t s = 0; s < sector_count; s++) { + if (!ide_wait (idedrv->io, 100000, true, true)) + return -ST_XDRV_WRITE_ERROR; + + outsw (idedrv->io + IDE_REG_DATA, buffer + (s * (idedrv->sector_size / 2)), + idedrv->sector_size / 2); + } } - outsw (idedrv->io + IDE_REG_DATA, buffer, idedrv->sector_size / 2); - - req->sector_done_count = 1; - - spin_unlock (&device->lock, *lockflags); - - while (!atomic_load (&req->done)) - spin_lock_relax (); - - spin_lock (&device->lock, lockflags); - - free (req); - uint8_t ctrl = inb (idedrv->ctrl); ctrl |= 0x02; outb (idedrv->ctrl, ctrl); diff --git a/kernel/device/idedrv.h b/kernel/device/idedrv.h index bd25d1d..5253b0e 100644 --- a/kernel/device/idedrv.h +++ b/kernel/device/idedrv.h @@ -20,6 +20,7 @@ struct idedrv_init { uint16_t io, ctrl; uint8_t devno; uint8_t irq; + bool irqs_support; }; struct idedrv_request { @@ -39,6 +40,7 @@ struct idedrv { uint8_t devno; uint8_t irq; struct idedrv_request* current_req; + bool irqs_support; }; struct ide_probe { @@ -48,6 +50,7 @@ struct ide_probe { uint16_t io, ctrl; uint8_t devno; uint8_t irq; + bool irqs_support; }; bool idedrv_init (struct device* device, void* arg, struct proc* proc, struct reschedule_ctx* rctx); diff --git a/kernel/device/partitions.c b/kernel/device/partitions.c index b1818f4..df5b43d 100644 --- a/kernel/device/partitions.c +++ b/kernel/device/partitions.c @@ -30,14 +30,11 @@ static int device_probe_partitions_dos (struct proc* proc, struct reschedule_ctx [XDRV_WRITE] = &partdrv_write, }; - DEBUG ("1\n"); spin_lock (&device->lock, &fd); device_op (device, XDRV_GET_SECTOR_SIZE, proc, rctx, &fd, §or_size); - DEBUG ("2\n"); int ret = device_op (device, XDRV_READ, proc, rctx, &fd, §or, §or_count, &mbr); - DEBUG ("3\n"); if (ret < 0) { spin_unlock (&device->lock, fd); @@ -48,7 +45,6 @@ static int device_probe_partitions_dos (struct proc* proc, struct reschedule_ctx spin_unlock (&device->lock, fd); return -ST_PARTITION_ERROR; } - DEBUG ("4\n"); for (size_t i = 0; i < lengthof (mbr.ptes); i++) { struct dos_pte* pte = &mbr.ptes[i]; @@ -64,11 +60,9 @@ static int device_probe_partitions_dos (struct proc* proc, struct reschedule_ctx snprintf (key, sizeof (key), "%sp%zu", device->key, i); device_create (key, ops, lengthof (ops), &partdrv_init, &partdrv_fini, &init, proc, rctx); - DEBUG ("5\n"); } spin_unlock (&device->lock, fd); - DEBUG ("6\n"); return ST_OK; } diff --git a/kernel/device/pci_ide.c b/kernel/device/pci_ide.c index 01f770f..46728e2 100644 --- a/kernel/device/pci_ide.c +++ b/kernel/device/pci_ide.c @@ -15,7 +15,8 @@ #include #include -static atomic_int ide_counter = 0; +static int ide_counter = 0; +/* static bool ide_legacy_claimed = false; */ static const char* progif_msg[] = { [0x00] = "ISA Compatibility mode-only controller", @@ -38,7 +39,7 @@ static void ide_make_device (struct proc* proc, struct reschedule_ctx* rctx, probe.devno, probe.sector_size, probe.sector_count); char device_key[fieldsizeof (struct device, key)]; - snprintf (device_key, sizeof (device_key), "IDE%d", atomic_fetch_add (&ide_counter, 1)); + snprintf (device_key, sizeof (device_key), "IDE%d", ide_counter++); device_op_func_t ops[] = { [XDRV_GET_SIZE] = &idedrv_get_size, @@ -56,6 +57,7 @@ static void ide_make_device (struct proc* proc, struct reschedule_ctx* rctx, .ctrl = probe.ctrl, .devno = probe.devno, .irq = probe.irq, + .irqs_support = probe.irqs_support, }; struct device* ide = device_create (device_key, ops, lengthof (ops), &idedrv_init, &idedrv_fini, &init, proc, rctx); @@ -90,21 +92,11 @@ bool pci_ide_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_in pcmd = (uint16_t)(bar0 & 0xFFFC); pctrl = (uint16_t)(bar1 & 0xFFFC); - uint8_t irq = pci_read8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT); - - if (irq == 0xFF) { - pci_write8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT, 14); - irq = pci_read8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT); - } - - ioapic_route_irq (IDE_DRIVE_PRIM, irq, 0, thiscpu->lapic_id); - DEBUG ("N pcmd=%x, pctrl=%x, irq=%u\n", pcmd, pctrl, irq); + if (pctrl) + pctrl += 2; } else { pcmd = 0x1F0; pctrl = 0x3F6; - - ioapic_route_irq (IDE_DRIVE_PRIM, 14, 0, thiscpu->lapic_id); - DEBUG ("L pcmd=%x, pctrl=%x, irq=%u\n", pcmd, pctrl, 14); } if ((progif & 0x04)) { @@ -119,23 +111,27 @@ bool pci_ide_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_in scmd = (uint16_t)(bar2 & 0xFFFC); sctrl = (uint16_t)(bar3 & 0xFFFC); - uint8_t irq = pci_read8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT); - - if (irq == 0xFF) { - pci_write8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT, 15); - irq = pci_read8 (pci_info.bus, pci_info.slot, pci_info.func, PCI_INTERRUPT); - } - - ioapic_route_irq (IDE_DRIVE_SCND, irq, 0, thiscpu->lapic_id); - DEBUG ("N pcmd=%x, pctrl=%x, irq=%u\n", scmd, sctrl, irq); + if (sctrl) + sctrl += 2; } else { scmd = 0x170; sctrl = 0x376; - - ioapic_route_irq (IDE_DRIVE_SCND, 15, 0, thiscpu->lapic_id); - DEBUG ("L pcmd=%x, pctrl=%x, irq=%u\n", scmd, sctrl, 15); } + bool irqs_support = false; + + if ((progif & 0x05)) { + irqs_support = false; + } else { + irqs_support = true; + ioapic_route_irq (IDE_DRIVE_PRIM, 14, 0, thiscpu->lapic_id); + ioapic_route_irq (IDE_DRIVE_SCND, 15, 0, thiscpu->lapic_id); + } + + DEBUG ("pcmd=%x, pctrl=%x\n", pcmd, pctrl); + DEBUG ("scmd=%x, sctrl=%x\n", scmd, sctrl); + DEBUG ("IRQ support=%d\n", irqs_support); + uint16_t channels[2][3] = {{pcmd, pctrl, IDE_DRIVE_PRIM}, {scmd, sctrl, IDE_DRIVE_SCND}}; for (size_t i = 0; i < lengthof (channels); i++) { @@ -143,15 +139,13 @@ bool pci_ide_init (struct proc* proc, struct reschedule_ctx* rctx, struct pci_in uint16_t ctrl = channels[i][1]; uint8_t irq = channels[i][2]; - if (cmd == 0) - continue; - for (size_t dev = 0; dev < 2; dev++) { ide_probe (cmd, ctrl, dev, &probe); probe.ctrl = ctrl; probe.io = cmd; probe.irq = irq; + probe.irqs_support = irqs_support; if ((probe.flags & IDE_PROBE_AVAIL)) ide_make_device (proc, rctx, probe);