#include "ioport.h" // inb
#include "util.h" // dprintf
#include "cmos.h" // inb_cmos
-#include "pic.h" // unmask_pic2
+#include "pic.h" // enable_hwirq
#include "biosvar.h" // GET_EBDA
#include "pci.h" // pci_find_class
+#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
+#include "pci_regs.h" // PCI_INTERRUPT_LINE
#define TIMEOUT 0
#define BSY 1
static int
await_ide(u8 when_done, u16 base, u16 timeout)
{
- u32 time=0, last=0;
+ u64 end = calc_future_tsc(timeout);
for (;;) {
u8 status = inb(base+ATA_CB_STAT);
- time++;
u8 result = 0;
if (when_done == BSY)
result = status & ATA_CB_STAT_BSY;
if (result)
return status;
- // mod 2048 each 16 ms
- if (time>>16 != last) {
- last = time >>16;
- dprintf(6, "await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ"
- ",!BSY_!DRQ,!BSY_RDY) %d time= %d timeout= %d\n"
- , when_done, time>>11, timeout);
- }
if (status & ATA_CB_STAT_ERR) {
dprintf(1, "await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ"
- ",!BSY_!DRQ,!BSY_RDY) %d status=%x time= %d timeout= %d\n"
- , when_done, status, time>>11, timeout);
+ ",!BSY_!DRQ,!BSY_RDY) %d status=%x timeout=%d\n"
+ , when_done, status, timeout);
return -1;
}
- if (timeout == 0 || (time>>11) > timeout)
+ if (rdtscll() >= end)
break;
}
dprintf(1, "IDE time out\n");
return await_ide(when_done, iobase1, timeout);
}
-// Delay for x nanoseconds
-static void
-nsleep(u32 delay)
-{
- // XXX - how to implement ndelay?
- while (delay--)
- nop();
-}
-
// Wait for ide state - pause for 400ns first.
static __always_inline int
ndelay_await_ide(u8 when_done, u16 iobase1, u16 timeout)
{
- nsleep(400);
+ ndelay(400);
return await_ide(when_done, iobase1, timeout);
}
-// Delay for x milliseconds
-static void
-msleep(u32 delay)
-{
- usleep(delay * 1000);
-}
-
// Reset a drive
void
ata_reset(int driveid)
// 8.2.1 (g) -- check for sc==sn==0x01
// select device
outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
- msleep(50);
+ mdelay(50);
u8 sc = inb(iobase1+ATA_CB_SC);
u8 sn = inb(iobase1+ATA_CB_SN);
outb(cmd->device, iobase1 + ATA_CB_DH);
if ((device ^ cmd->device) & (1 << 4))
// Wait for device to become active.
- msleep(50);
+ mdelay(50);
if (cmd->command & 0x04) {
outb(0x00, iobase1 + ATA_CB_FR);
// Look for device
outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
- msleep(50);
+ mdelay(50);
outb(0x55, iobase1+ATA_CB_SC);
outb(0xaa, iobase1+ATA_CB_SN);
outb(0xaa, iobase1+ATA_CB_SC);
// check for ATA or ATAPI
outb(slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0, iobase1+ATA_CB_DH);
- msleep(50);
+ mdelay(50);
sc = inb(iobase1+ATA_CB_SC);
sn = inb(iobase1+ATA_CB_SN);
dprintf(6, "ata_detect(2) drive=%d sc=%x sn=%x\n", driveid, sc, sn);
}
// Scan PCI bus for ATA adapters
- int count=0, index=0;
- u16 classid = 0x0180; // SATA first
- while (count<CONFIG_MAX_ATA_INTERFACES-1) {
- PCIDevice d;
- int ret = pci_find_class(classid, index, &d);
- if (ret) {
- if (classid == 0x0101)
- // Done
- break;
- classid = 0x0101; // PATA controllers
- index = 0;
+ int count=0;
+ int bdf, max;
+ foreachpci(bdf, max) {
+ if (pci_config_readw(bdf, PCI_CLASS_DEVICE) != PCI_CLASS_STORAGE_IDE)
continue;
- }
- index++;
- u8 irq = pci_config_readb(d, PCI_INTERRUPT_LINE);
+ u8 irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
SET_EBDA(ata.channels[count].irq, irq);
- SET_EBDA(ata.channels[count].pci_bdf, pci_to_bdf(d));
+ SET_EBDA(ata.channels[count].pci_bdf, bdf);
- u8 prog_if = pci_config_readb(d, PCI_CLASS_PROG);
+ u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG);
u32 port1, port2;
- if (classid != 0x0101 || prog_if & 1) {
- port1 = pci_config_readl(d, PCI_BASE_ADDR_0) & ~3;
- port2 = pci_config_readl(d, PCI_BASE_ADDR_1) & ~3;
+ if (prog_if & 1) {
+ port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3;
+ port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3;
} else {
port1 = 0x1f0;
port2 = 0x3f0;
}
SET_EBDA(ata.channels[count].iobase1, port1);
SET_EBDA(ata.channels[count].iobase2, port2);
- dprintf(1, "ATA controller %d at %x/%x\n", count, port1, port2);
+ dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n"
+ , count, port1, port2, bdf, prog_if);
count++;
- if (classid != 0x0101 || prog_if & 4) {
- port1 = pci_config_readl(d, PCI_BASE_ADDR_2) & ~3;
- port2 = pci_config_readl(d, PCI_BASE_ADDR_3) & ~3;
+ if (prog_if & 4) {
+ port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3;
+ port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3;
} else {
port1 = 0x170;
port2 = 0x370;
}
- dprintf(1, "ATA controller %d at %x/%x\n", count, port1, port2);
+ dprintf(1, "ATA controller %d at %x/%x (dev %x prog_if %x)\n"
+ , count, port1, port2, bdf, prog_if);
SET_EBDA(ata.channels[count].iobase1, port1);
SET_EBDA(ata.channels[count].iobase2, port2);
count++;
SET_BDA(disk_control_byte, 0xc0);
- // Enable IRQ14 (handle_76)
- unmask_pic2(PIC2_IRQ14);
+ enable_hwirq(14, entry_76);
}