bool FindUSBControllers()
{
    bool retval = false;
    u32_t bus, last_bus;
    PCITAG tag;

    if( (last_bus = PciApi(1))==-1)
        return retval;

    dbgprintf("last bus %x\n", last_bus);

    for(bus=0;bus<=last_bus;bus++)
    {
        u32_t devfn;

        for(devfn=0;devfn<256;devfn++)
        {
            hc_t *hc;

            u32_t id;
            u16_t pcicmd;
            u16_t devclass;
            u8_t  interface;
            int i;

            interface = PciRead8(bus,devfn, 0x09);
            devclass = PciRead16(bus,devfn, 0x0A);
            if( devclass != 0x0C03)
                continue;

            if( interface != 0)
                continue;

            pcicmd = PciRead16(bus,devfn, PCI_COMMAND);
            if (! pcicmd & PCI_COMMAND_IO)
                continue;

            hc = (hc_t*)kmalloc(sizeof(hc_t), 0);
            INIT_LIST_HEAD(&hc->list);
            INIT_LIST_HEAD(&hc->rq_list);

            hc->pciId  = PciRead32(bus,devfn, 0);
            hc->PciTag = pciTag(bus,(devfn>>3)&0x1F,devfn&0x7);

            hc->irq_line = PciRead32(bus,devfn, 0x3C) & 0xFF;

            for (i = 0; i < 6; i++)
            {
                u32_t base;
                bool validSize;

                base = PciRead32(bus,devfn, PCI_MAP_REG_START + (i << 2));
                if(base)
                {
                    if (base & PCI_MAP_IO) {
                        hc->ioBase[i] = (addr_t)PCIGETIO(base);
                        hc->memType[i]   = base & PCI_MAP_IO_ATTR_MASK;
                    } else {
                        hc->memBase[i] = (u32_t)PCIGETMEMORY(base);
                        hc->memType[i] = base & PCI_MAP_MEMORY_ATTR_MASK;
                    }
                }
            };
            dbgprintf("host controller %x bus %x devfn %x, IRQ %d\n",
                       hc->pciId, bus, devfn, hc->irq_line);

            list_add_tail(&hc->list, &hc_list);
            retval = true;
        };
    };
    return retval;
};


#if 0

/* these helpers provide future and backwards compatibility
 * for accessing popular PCI BAR info */
#define pci_resource_start(dev, bar)    ((dev)->resource[(bar)].start)
#define pci_resource_end(dev, bar)  ((dev)->resource[(bar)].end)
#define pci_resource_flags(dev, bar)    ((dev)->resource[(bar)].flags)
#define pci_resource_len(dev,bar) \
    ((pci_resource_start((dev), (bar)) == 0 &&  \
      pci_resource_end((dev), (bar)) ==     \
      pci_resource_start((dev), (bar))) ? 0 :   \
                            \
     (pci_resource_end((dev), (bar)) -      \
      pci_resource_start((dev), (bar)) + 1))

static int __devinit mmio_resource_enabled(struct pci_dev *pdev, int idx)
{
    return pci_resource_start(pdev, idx) && mmio_enabled(pdev);
}

static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
{
    int wait_time, delta;
    void __iomem *base, *op_reg_base;
    u32 hcc_params, val;
    u8  offset, cap_length;
    int count = 256/4;
    int tried_handoff = 0;

    if (!mmio_resource_enabled(pdev, 0))
        return;

    base = pci_ioremap_bar(pdev, 0);
    if (base == NULL)
        return;

    cap_length = readb(base);
    op_reg_base = base + cap_length;

    /* EHCI 0.96 and later may have "extended capabilities"
     * spec section 5.1 explains the bios handoff, e.g. for
     * booting from USB disk or using a usb keyboard
     */
    hcc_params = readl(base + EHCI_HCC_PARAMS);
    offset = (hcc_params >> 8) & 0xff;
    while (offset && --count) {
        u32     cap;
        int     msec;

        pci_read_config_dword(pdev, offset, &cap);
        switch (cap & 0xff) {
        case 1:         /* BIOS/SMM/... handoff support */
            if ((cap & EHCI_USBLEGSUP_BIOS)) {
                dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");

#if 0
/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
 * but that seems dubious in general (the BIOS left it off intentionally)
 * and is known to prevent some systems from booting.  so we won't do this
 * unless maybe we can determine when we're on a system that needs SMI forced.
 */
                /* BIOS workaround (?): be sure the
                 * pre-Linux code receives the SMI
                 */
                pci_read_config_dword(pdev,
                        offset + EHCI_USBLEGCTLSTS,
                        &val);
                pci_write_config_dword(pdev,
                        offset + EHCI_USBLEGCTLSTS,
                        val | EHCI_USBLEGCTLSTS_SOOE);
#endif

                /* some systems get upset if this semaphore is
                 * set for any other reason than forcing a BIOS
                 * handoff..
                 */
                pci_write_config_byte(pdev, offset + 3, 1);
            }

            /* if boot firmware now owns EHCI, spin till
             * it hands it over.
             */
            msec = 1000;
            while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
                tried_handoff = 1;
                msleep(10);
                msec -= 10;
                pci_read_config_dword(pdev, offset, &cap);
            }

            if (cap & EHCI_USBLEGSUP_BIOS) {
                /* well, possibly buggy BIOS... try to shut
                 * it down, and hope nothing goes too wrong
                 */
                dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
                        " (BIOS bug?) %08x\n", cap);
                pci_write_config_byte(pdev, offset + 2, 0);
            }

            /* just in case, always disable EHCI SMIs */
            pci_write_config_dword(pdev,
                    offset + EHCI_USBLEGCTLSTS,
                    0);

            /* If the BIOS ever owned the controller then we
             * can't expect any power sessions to remain intact.
             */
            if (tried_handoff)
                writel(0, op_reg_base + EHCI_CONFIGFLAG);
            break;
        case 0:         /* illegal reserved capability */
            cap = 0;
            /* FALLTHROUGH */
        default:
            dev_warn(&pdev->dev, "EHCI: unrecognized capability "
                    "%02x\n", cap & 0xff);
            break;
        }
        offset = (cap >> 8) & 0xff;
    }
    if (!count)
        dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n");

    /*
     * halt EHCI & disable its interrupts in any case
     */
    val = readl(op_reg_base + EHCI_USBSTS);
    if ((val & EHCI_USBSTS_HALTED) == 0) {
        val = readl(op_reg_base + EHCI_USBCMD);
        val &= ~EHCI_USBCMD_RUN;
        writel(val, op_reg_base + EHCI_USBCMD);

        wait_time = 2000;
        delta = 100;
        do {
            writel(0x3f, op_reg_base + EHCI_USBSTS);
            udelay(delta);
            wait_time -= delta;
            val = readl(op_reg_base + EHCI_USBSTS);
            if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
                break;
            }
        } while (wait_time > 0);
    }
    writel(0, op_reg_base + EHCI_USBINTR);
    writel(0x3f, op_reg_base + EHCI_USBSTS);

    iounmap(base);

    return;
}

#endif