Problem mit USB UHCI controllern und dem BIOS



  • Ich arbeite an einem single task RTOS auf einem D410PT Intel Atom board, hab den USB EHCI host korrekt am laufen aber ein seltsames Problem mit den 4 UHCI companion controllern. In Kuerze:

    Obwohl ich den EHCI korrekt vom BIOS uebernommen habe (via LEG_EXT_CAP register) werden einige UHCI Aktionen (zB STALL wegen falschem toggle bit) immernoch vom BIOS abgefangen, aber nur bei eingeschalteten Interrupts!
    Ich habe alle protected mode ISRs umgeleitet um zu sehen wo der interrupt herkommt, aber komm im Moment natuerlich nicht so ohne weiteres and die (alten BIOS-) real-mode ISRs ran (vielleicht im bootloader...).

    Hat jemand eine Idee warum das BIOS immernoch die UHCIs kontrolliert? Und wie man das abschalten kann? 😕


  • Mod

    Dies ist unser aktueller DeactivateLegacySupport Code:

    void DeactivateLegacySupport(pciDev_t* PCIdev)
    {
        // pci bus data
        uint8_t bus  = PCIdev->bus;
        uint8_t dev  = PCIdev->device;
        uint8_t func = PCIdev->func;
    
        eecp = BYTE2(pCapRegs->HCCPARAMS);
        printf("\nDeactivateLegacySupport: eecp = %x\n",eecp);
        /*
        cf. EHCI 1.0 spec, 2.2.4 HCCPARAMS - Capability Parameters, Bit 15:8 (BYTE2)
        EHCI Extended Capabilities Pointer (EECP). Default = Implementation Dependent.
        This optional field indicates the existence of a capabilities list.
        A value of 00h indicates no extended capabilities are implemented.
        A non-zero value in this register indicates the offset in PCI configuration space
        of the first EHCI extended capability. The pointer value must be 40h or greater
        if implemented to maintain the consistency of the PCI header defined for this class of device.
        */
        // cf. http://wiki.osdev.org/PCI#PCI_Device_Structure
    
        //               eecp       // RO - This field identifies the extended capability.
                                    //      01h identifies the capability as Legacy Support.
        if (eecp >= 0x40)
        {
            int32_t eecp_id=0;
    
            while (eecp)
            {
                uint32_t NextEHCIExtCapPtr; // RO  - 00h indicates end of the ext. cap. list.
    
                printf("eecp = %x, ",eecp);
                eecp_id = pci_config_read(bus, dev, func, 0x0100/*length 1 byte*/ | (eecp + 0));
                printf("eecp_id = %x\n",eecp_id);
                if (eecp_id == 1)
                     break;
                NextEHCIExtCapPtr = eecp + 1;
                eecp = pci_config_read(bus, dev, func, 0x0100 | NextEHCIExtCapPtr);
            }
            uint32_t BIOSownedSemaphore = eecp + 2; // R/W - only Bit 16 (Bit 23:17 Reserved, must be set to zero)
            uint32_t OSownedSemaphore   = eecp + 3; // R/W - only Bit 24 (Bit 31:25 Reserved, must be set to zero)
            uint32_t USBLEGCTLSTS       = eecp + 4; // USB Legacy Support Control/Status (DWORD, cf. EHCI 1.0 spec, 2.1.8)
    
            // Legacy-Support-EC found? BIOS-Semaphore set?
            if (eecp_id == 1 && (pci_config_read(bus, dev, func, 0x0100 | BIOSownedSemaphore) & 0x01))
            {
                printf("set OS-Semaphore.\n");
                pci_config_write_byte(bus, dev, func, OSownedSemaphore, 0x01);
    
                int32_t timeout=200;
                // Wait for BIOS-Semaphore being not set
                while ((pci_config_read(bus, dev, func, 0x0100 | BIOSownedSemaphore) & 0x01) && (timeout>0))
                {
                    printf(".");
                    timeout--;
                    sleepMilliSeconds(20);
                }
                if (!(pci_config_read(bus, dev, func, 0x0100 | BIOSownedSemaphore) & 0x01)) // not set
                {
                    printf("BIOS-Semaphore being not set.\n");
                    timeout=200;
                    while (!(pci_config_read(bus, dev, func, 0x0100 | OSownedSemaphore) & 0x01) && (timeout>0))
                    {
                        printf(".");
                        timeout--;
                        sleepMilliSeconds(20);
                    }
                }
                if (pci_config_read(bus, dev, func, 0x0100 | OSownedSemaphore) & 0x01)
                {
                    printf("OS-Semaphore being set.\n");
                }
    
                printf("Check: BIOSownedSemaphore: %u OSownedSemaphore: %u\n",
                    pci_config_read(bus, dev, func, 0x0100 | BIOSownedSemaphore),
                    pci_config_read(bus, dev, func, 0x0100 | OSownedSemaphore));
    
                // USB SMI Enable R/W. 0=Default.
                // The OS tries to set SMI to disabled in case that BIOS bit satys at one.
                pci_config_write_dword(bus, dev, func, USBLEGCTLSTS, 0x0); // USB SMI disabled
            }
            else
            {
                textColor(0x0A);
                printf("\nBIOS did not own the EHCI. No action needed.\n");
                textColor(0x0F);
            }
        }
        else
        {
            printf("No valid eecp found.\n");
        }
    }
    

Anmelden zum Antworten