Ziel: USB-Treiber



  • Hm, du versuchst, auf die EECP im Hauptspeicher zuzugreifen? Da sind aber keine, die sind im PCI-Konfigurationsraum. Bei mir sieht das Deaktivieren des Legacy Supports so aus:

    eecp = (hc->usbbase->hcc_params & 0x0000FF00) >> 8;
        if (eecp >= 0x40)
        {
            int eecp_id;
    
            while (eecp)
            {
                eecp_id = pci_inb(pci->bus, pci->dev, pci->func, eecp);
                // Legacy-Support-Zeugs
                if (eecp_id == 1)
                    break;
                eecp = pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x01);
            }
    
            // Nachsehen, ob eine Legacy-Support-EC gefunden wurde und der BIOS-Semaphor gesetzt ist
            if ((eecp_id == 1) && pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x02) & 0x01)
            {
                // OS-Semaphor setzen
                pci_outb(pci->bus, pci->dev, pci->func, eecp + 0x03, 0x01);
    
                failed = 1;
                // Eine Sekunde
                timeout = heart_beat_count + 1000000000LL;
                // Warten, bis der BIOS-Semaphor nicht mehr gesetzt ist
                while ((pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x02) & 0x01) && (heart_beat_count < timeout));
                if (!(pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x02) & 0x01))
                {
                    // Wieder eine Sekunde
                    timeout = heart_beat_count + 1000000000LL;
                    // Warten, bis der OS-Semaphor gesetzt ist
                    while (!(pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x03) & 0x01) && (heart_beat_count < timeout));
                    if (pci_inb(pci->bus, pci->dev, pci->func, eecp + 0x03) & 0x01)
                        failed = 0;
                }
    
                if (failed)
                {
                    // Manuell den Legacy Support deaktivieren
                    pci_outl(pci->bus, pci->dev, pci->func, eecp + 0x04, 0x0000);
                }
            }
        }
    

    Hinweis: heart_beat_count ist die Zeitzählvariable meines OS. Sie ist vom Typ unsigned long long und zählt in Nanosekunden (eine Millisekunde ist also 1000000).


  • Mod

    Danke für den Versuch und den Code.

    Nach Diskussion mit XanClic im IRC gehört der Code offensichtlich hierhin:

    void initEHCIHostController(uint32_t number)
    {
        irq_install_handler(32 + pciDev_Array[number].irq, ehci_handler);
    
        /// TODO: with EECP: DeactivateLegacySupport(number)
    
        // ...
    
        /// TODO 
    
        pOpRegs->USBCMD &= ~CMD_RUN_STOP; // set Run-Stop-Bit to 0
    
        // ...
    }
    

    Aber gekapselt in eine Funktion "DeactivateLegacySupport(number)".


  • Mod

    Rev. 181:
    ...

    PC-Test bei Cuervo:

    jetzt kommt er bis zum 2. 'waiting for HC reset'



  • Hab mal wieder angefangenen nicht funktionierenden Code zum Datentransfer:

    ehci.c
    ehci.h

    Bei mir schaltet der Host Controller auf Halted. Ich hab versucht das ganze recht ausführlich zu Kommentieren, da ich teilweise echt suchen musste wie manche Werte gesetzt werden müssen.



  • Mein aktueller Stand:

    ehci.c

    Es fehlt noch nen ganzes Stückchen, aber man sieht wie es funktionieren soll. CreateQH/CreateQTD erstellt eine recht generische Version, die dann in den spezifischen Funktionen wie die IN und OUT Varianten weiter manipuliert werden. Durch die übergebene Adresse werden die Einträge direkt an der richtigen Stelle erstellt. Am Ende müssen diese nur noch zusammen gehängt werden. Fehlen tun auf jeden Fall noch ein paar Parameter und die spezifische Funktion für SETUP Einträge. Das mit dem SETUP ist allerdings wieder etwas komplexer.


  • Mod

    Echt toll! 🙂 👍

    Ich habe den aktuellen Stand als Zwischenschritt in Rev. 194 implementiert, damit sich da nichts auseinander entwickelt.
    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1865696.html#1865696

    SETUP:
    http://wiki.osdev.org/USB#USB_Device_Requests
    http://lowlevel.brainsware.org/wiki/index.php/Universal_Serial_Bus#Setuppaket
    USB 2.0 Spec: 5.3.1.1 Endpoint Zero Requirements, 9.4 Standard Device Requests, Table 9-4: Standard Request Codes, Table 11-14: Hub Responses to Standard Device Requests.

    Da gibt es das gesuchte SET_ADDRESS, damit wir von der 0 weg kommen.



  • Erhard Henkes schrieb:

    Da gibt es das gesuchte SET_ADDRESS, damit wir von der 0 weg kommen.

    Ja, nur bringt es im Moment nicht viel damit anzufangen, da man nicht überprüfen kann ob das ganze geklappt hat. Der erste Schritt ist daher erstmal das auslesen des Device Desciptor.

    Ich hab das ganze nochmal umgebaut, und es sieht nun deutlich sinniger aus. Der QH beinhaltet jetzt einen kompletten QTD. Das elemeniert einiges an doppelten Code.

    ehci.h
    ehci.c

    Der Test sollte eigentlich soweit vollständig sein. Funktionieren tut es allerdings nicht. Data ist nicht 18 wie es sein sollte und der Controller schaltet auf Halted. Das heißt jetzt erstmal Fehler suchen.


  • Mod

    Ich habe es in Rev. 196 als Zwischenschritt eingespielt. Bei mir kommt immer 80h als Data zurück. Ich werde da mal an einigen Parametern drehen, mir sind beim Lesen der EHCI und USB 2.0 Specs einiges aufgefallen, was noch nicht passt bei uns.



  • Und der nächste neue Ansatz.

    Meine komplette ehci.c. Ich hab die alten Funktionen und die Ausgaben komplett rausgeworfen. Die passten nicht mehr so richtig.

    Hintergrund ist das ich die EHCI Spezifikation mal gezielt nach Schritten durchsucht habe, die von der Software durchgeführt werden müssen. Da habe ich in dem Abschnitt vor 4.10.1 folgendes gefunden:

    For the very first use of a queue head, software may zero-out the queue head transfer overlay, then set the Next qTD Pointer field value to reference a valid qTD.

    Das ist im Prinzip auch das was ich nun mache. Der Overlay Bereich wird genullt und nur der next pointer wird auf die Setup QTD gesetzt, dessen next pointer dann auf die In QTD zeigt. Also keinerlei queue heads außer dem ersten mehr.

    Die qemu ehci Testversion läuft damit schon recht weit. An meinem Laptop kriege ich leider wieder Host System Error.


  • Mod

    Der erste Erfolg! http://www.henkessoft.de/OS_Dev/Bilder/rev219a.jpg
    die lang ersehnte 12h wurde mittels 80 06 00 01 00 00 12 00 (setup request) geholt. http://www.jungo.com/st/support/documentation/windriver/1002/wdusb_man_mhtml/node55.html#SECTION001221600000000000000 👍

    Allerdings noch nicht stabil und schwierig reproduzierbar an anderen Stellen und Sims.

    ➡ Das Problem liegt in resetPort(...) (<--- grausam). da müssen wir weiter machen.

    ➡ resetPort wird einmal vom initEHCI... udn einmal vom EHCI-Handler via ShowPortSC(...) aufgerufen, einmal mit sleep... und einmal mit diesem bescheuerten Zähler-Work-around. 🙄


  • Mod

    Geht übrigens auch mit qemu:
    http://www.henkessoft.de/OS_Dev/Bilder/rev219qemu.jpg

    Das qemu erhält man hier: http://download.tyndur.org/temp/qemu-ehci.tgz 👍

    Skript:

    qemu.exe  -fda FloppyImage.bin -soundhw pcspk -localtime -usb -usbdevice disk:format=raw:dummy.bin
    

    oder mit netzwerk

    qemu.exe  -fda FloppyImage.bin -soundhw pcspk -net nic,model=rtl8139,addr=1F,macaddr=00:12:12:12:12:12 -localtime -usb -usbdevice disk:format=raw:dummy.bin
    

  • Mod

    ... und nach einem Tipp von XanClic, dass VBox eine IRQ tiefer verwendet (also 10 anstelle 11 wie beim PCI festgestellt), nun auch VBox:
    http://www.henkessoft.de/OS_Dev/Bilder/rev221VB.jpg (data: 12h)

    Also alles bestens. 🙂


  • Mod

    Hier ein Test mit 2 QHs in der async. Liste, einer davon mit 3 QTD: http://www.henkessoft.de/OS_Dev/Bilder/rev268_asyncList.PNG (ab Rev. 268)


  • Mod

    Nach dem Einbau des Multithreadings geht es langsam wieder weiter bei USB:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-254893-and-start-is-378.html

    Allerdings klappt es im EHCI-Bereich noch nicht sauber auf real PC.


  • Mod

    Bei der Suche nach Problemen bezüglich Real PC und Simulationen bezüglich USB-Transfer sind wir bisher auf folgendes gestoßen:

    1. Extended Buffer Pointer (64 Bit) bei QTD notwendig

    2. PCI Command Register: Bus Mastering (Bit 2) muss gesetzt sein (real PC: das erledigt das BIOS bereits); VMWare: setzt dies nicht, USB läuft aber erst nach dem Setzen dieses Bits

    3. PCI Capabilities List: hier ist unklar, ob dies eine Bedeutung für EHCI hat?!
      Hier eine Auswertung:
      **
      PCI Capabilities List: first Pointer: 0050h
      PCI Capabilities List: ID: 01h, next Pointer: 00h**

    PrettyOS [Version 0.0.0.384]                                     Console 0: EHCI
    --------------------------------------------------------------------------------
    
    >>> >>> function: initEHCIHostController                                        
    PCI Command Register before:          0106h                                     
    PCI Command Register plus bus master: 0106h                                     
    PCI Capabilities List: first Pointer: 0050h                                     
    PCI Capabilities List: ID: 01h, next Pointer: 00h                               
    >>> >>> function: startHostController (reset HC)                                
    DeactivateLegacySupport: eecp = 0070h                                           
    eecp = 0070h, eecp_id = 0001h                                                   
    
    BIOS did not own the EHCI. No action needed.                                    
    
    >>> >>> function: enablePorts                                                   
    >>> >>> function: resetPort 1                                                   
    >>> >>> function: resetPort 2                                                   
    >>> >>> function: resetPort 3                                                   
    >>> >>> function: resetPort 4                                                   
    >>> >>> function: resetPort 5                                                   
    >>> >>> function: resetPort 6                                                   
    >>> Press key to close this console. <<<    
    
    --------------------------------------------------------------------------------
    Saturday, April 19, 2064, 19:13:42   51 s runtime. CPU: 1121 MHz               /
    

    Zugehöriger Code in ehci.c:

    uint16_t pciCapabilitiesList = pci_config_read(bus, dev, func, 0x0234);
    	printf("\nPCI Capabilities List: first Pointer: %x", pciCapabilitiesList);
    
    	if (pciCapabilitiesList) // pointer != NULL
    	{
    	    uint16_t nextCapability = pci_config_read(bus, dev, func, 0x0200 | pciCapabilitiesList);
    	    printf("\nPCI Capabilities List: ID: %y, next Pointer: %y",BYTE1(nextCapability),BYTE2(nextCapability));
    
            while (BYTE2(nextCapability)) // pointer != NULL
    	    {
    	        nextCapability = pci_config_read(bus, dev, func, 0x0200 | BYTE2(nextCapability));
    	        printf("\nPCI Capabilities List: ID: %y, next Pointer: %y",BYTE1(nextCapability),BYTE2(nextCapability));
    	    }
    	}
    

    Die Bedeutungen der IDs sind in Anhang H der PCI Local Bus Specification beschrieben:

    Die ID=1 von obigem PC bedeutet:

    PCI Power Management Interface – This capability structure provides a standard interface to control power management features in a PCI device. ...

    Hier ein Beispiel eines PC, der mit Host System Error reagiert:**
    PCI Capabilities List: first Pointer: 0050h
    PCI Capabilities List: ID: 01h, next Pointer: 58h
    PCI Capabilities List: ID: 0Ah, next Pointer: 00h**

    PrettyOS [Version 0.0.0.384]                                     Console 0: EHCI
    --------------------------------------------------------------------------------
    
    >>> >>> function: initEHCIHostController                                        
    PCI Command Register before:          0006h                                     
    PCI Command Register plus bus master: 0006h                                     
    PCI Capabilities List: first Pointer: 0050h                                     
    PCI Capabilities List: ID: 01h, next Pointer: 58h                               
    PCI Capabilities List: ID: 0Ah, next Pointer: 00h                               
    >>> >>> function: startHostController (reset HC)waiting for HC reset            
    
    DeactivateLegacySupport: eecp = 0068h                                           
    eecp = 0068h, eecp_id = 0001h                                                   
    set OS-Semaphore.                                                               
    BIOS-Semaphore being not set.                                                   
    OS-Semaphore being set.                                                         
    Check: BIOSownedSemaphore: 0 OSownedSemaphore: 1                                
    
    ehci_handler: Port Change                                                       
    >>> >>> function: enablePorts                                                   
    >>> >>> function: resetPort 1  Port 1: high speed enabled, device attached      
    
    >>> Press key to start USB-Test. <<<
    

    ID 0x0A bedeuetet: Debug Port Capability (siehe EHCI spec, Appendix C. Debug Port)


  • Mod

    http://www.c-plusplus.net/forum/viewtopic-var-p-is-1885822.html#1885822

    Die Ursache für den hartnäckigen Host System Error ist gefunden. 👍
    Er liegt im USB-Transfer begraben (hält am H-Bit nicht an).


  • Mod

    Ein Meilenstein erreicht:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-254893-and-start-is-423.html
    LBA 0 von einem USB-Stick auf einem real PC korrekt mit read(10) ausgelesen. Version ist allerdings noch nicht stabil (klappt nur bei wenigen Konstellationen), aber das Ziel ist in Sicht, nun ist wieder die übliche Fleißarbeit angesagt. 😃


  • Mod

    Leider immer noch nicht stabil. Konstruktive Unterstützung erwünscht. 🙂

    siehe: http://www.c-plusplus.net/forum/viewtopic-var-p-is-1891501.html#1891501
    Ich würde dies geren verallgemeinern, finde aber den Hebel dazu einfach nicht. Die community ist noch nicht schlagkräftig genug, das schnell zu lösen. Bei tatkräftiger Unterstützung Belohnung (Fachbuch aus meiner breiten Sammlung) nicht ausgeschlossen.

    Wir benötigen Unterstützung im Bereich USB, damit wir rascher voran kommen. Die Floppy hat ausgedient, es leben die USB Mass Storage Devices. 😉


  • Mod

    tatOS verwendet usb MSD, alles in Assembler.

    Hier ein sehr interessanter Kommentar zur Abfolge der SCSI commands nach dem Setzen der Konfiguration:

    ;now we start on the SCSI commands
    	;the order of the commands and redundancy is important
    	;we init the flash toggles here and then let prepareTDchain touch them only
    	mov dword  [bulktogglein] ,0
    	mov dword  [bulktoggleout],0
    
    	STDCALL mpdstr18,putmessage
    	call Inquiry
    
    	STDCALL mpdstr19,putmessage
    	call TestUnitReady
    
    	STDCALL mpdstr20,putmessage
    	call RequestSense
    
    	STDCALL mpdstr19,putmessage
    	call TestUnitReady
    
    	STDCALL mpdstr20,putmessage
    	call RequestSense
    
    	STDCALL mpdstr21,putmessage
    	call ReadCapacity
    
    	;done-ready for read10/write10
    

  • Mod

    Mit Rev. 441 ff. gelingt der Ablauf endlich auch auf real PC. Versuche zeigen jedoch, dass der Ablauf am IN-endpoint noch nicht ausreichend stabil ist. Daher muss nun eine Optimierung des async Schedulers statt finden und Fehlerbehandlungen eingebaut werden. Wir suchen zu diesem Thema noch Mitstreiter, die sich mit EHCI/USB/SCSI auskennen. 🙂


Anmelden zum Antworten