Prozessor IO-Ports



  • Hey,
    ich verstehe überhaupt nicht, wie Peripherie vom CPU angesprochen wird. Wenn ich mir den Keyboardtreiber von PrettyOS ansehe (oder auch andere Keyboardtreiber), dann gibt's da wohl diese IO-Ports.
    Kann mir wer erklären wie das mit den IO-Ports vom Prozessor funktioniert, oder kennt da wer etwas zum Einlesen?



  • Du hast einen Satz von Befehlen (inb, outb, outw, inw, etc.), über den Du Bytes senden bzw. empfangen kannst. Jeder dieser Befehle nimmt die Nummer eines dieser Ports. Was für Daten du dem Gerät senden oder von ihm empfangen kannst (und wohin, d.h. an welchen Port), steht in der Spezifikation des Geräts.



  • Und wie genau funktioniert das mit den Ports, kann man im Protectedmode auch einfach über solche Interrupts mit der Peripherie reden? - ich schätze nicht. In welcher Spezifikation? Chipsatz, Prozessor? Wie würde ich denn vorgehen, wenn ich z. B. die Netzwerkkarte ansprechbar machen will?


  • Mod

    Ich demonstriere das mal mit dem cmos:

    #ifndef CMOS_H
    #define CMOS_H
    
    #include "os.h"
    
    #define CMOS_SECOND      0x00
    #define CMOS_ALARMSECOND 0x01
    #define CMOS_MINUTE      0x02
    #define CMOS_ALARMMINUTE 0x03
    #define CMOS_HOUR        0x04
    #define CMOS_ALARMHOUR   0x05
    #define CMOS_WEEKDAY     0x06
    #define CMOS_DAYOFMONTH  0x07
    #define CMOS_MONTH       0x08
    #define CMOS_YEAR        0x09
    #define CMOS_CENTURY     0x32 // BCD value
    
    #define CMOS_STATUS_A    0x0A // read/write
    #define CMOS_STATUS_B    0x0B // read/write
    #define CMOS_STATUS_C    0x0C // read only
    #define CMOS_STATUS_D    0x0D // read only
    #define CMOS_STATUS_POST 0x0E // POST diagnosis
    #define CMOS_STATUS_SD   0x0F // shutdown
    
    #define CMOS_FLOPPYTYPE  0x10 // 2 nibbles: high=fd0, low=fd1 (4: 1.44 MB)
    #define CMOS_HDDTYPE     0x12
    
    #define CMOS_DEVICES     0x14 // 7-6: num of FDD,     5-4: display type,            3: display (y/n),
                                  // 2:   keyboard (y/n), 1:   math co-processor (y/n), 0: FDD (y/n)
    
    #define CMOS_CHECKSUM_HI 0x2E
    #define CMOS_CHECKSUM_LO 0x2F
    
    #define CMOS_NUM_CPU     0x5F // number of processors
    
    uint8_t cmos_read(uint8_t off); // Read byte from CMOS
    void cmos_write(uint8_t off, uint8_t val); // Write byte to CMOS
    
    #endif
    
    #include "cmos.h"
    #include "util/util.h"
    #include "tasking/synchronisation.h"
    
    #define CMOS_ADDRESS  0x70
    #define CMOS_DATA     0x71
    
    #define BIT_6_TO_0    0x7F
    
    static mutex_t mutex = mutex_init();
    
    uint8_t cmos_read(uint8_t offset) // Read byte from CMOS
    {
        mutex_lock(&mutex);
        uint8_t tmp = inportb(CMOS_ADDRESS) & BIT(7);
        outportb(CMOS_ADDRESS, (tmp | (offset & BIT_6_TO_0))); // do not change bit7 (NMI mask)
        uint8_t retVal = inportb(CMOS_DATA);
        mutex_unlock(&mutex);
        return retVal;
    }
    
    void cmos_write(uint8_t offset, uint8_t val) // Write byte to CMOS
    {
        mutex_lock(&mutex);
        uint8_t tmp = inportb(CMOS_ADDRESS) & BIT(7);
        outportb(CMOS_ADDRESS, (tmp | (offset & BIT_6_TO_0))); // do not change bit7 (NMI mask)
        outportb(CMOS_DATA, val);
        mutex_unlock(&mutex);
    }
    

    Die Port-Funktion sieht so aus:

    static inline uint8_t inportb(uint16_t port)
    {
        uint8_t ret_val;
        __asm__ volatile ("inb %1, %0" : "=a"(ret_val) : "d"(port));
        return ret_val;
    }
    
    static inline void outportb(uint16_t port, uint8_t val)
    {
        __asm__ volatile ("outb %0, %1" :: "a"(val), "d"(port));
    }
    


  • Mr.Long schrieb:

    Und wie genau funktioniert das mit den Ports, kann man im Protectedmode auch einfach über solche Interrupts mit der Peripherie reden?

    Es sind keine Interrupts, es ist ein separater Adressraum, auf den man über spezielle Maschinenbefehle Lesend/Schreibend zugreifen kann. Im Prinzip ist es eine Altlast, über die man auf Geräte zugreifen kann, die es im 486er vielleicht noch gab, heutzutage aber nur noch vorgegaukelt werden (PIC, Tastaturcontroller etc.)

    Mr.Long schrieb:

    - ich schätze nicht. In welcher Spezifikation? Chipsatz, Prozessor?

    Zumindest der PIC ist in der Chipsatz Spec beschrieben. Der Rest vermutlich auch.

    Mr.Long schrieb:

    Wie würde ich denn vorgehen, wenn ich z. B. die Netzwerkkarte ansprechbar machen will?

    Die IO-Ports ignorieren, denn Netzwerkkarten sind üblicherweise über den PCI-Bus angebunden (auch die im Chipsatz enthaltenen) und dessen Teilnehmer werden über den normalen Adressraum angesprochen.

    Eine ausführliche Antwort würde den Rahmen sprengen, aber grundsätzlich sagt dir (bzw. du bestimmst) im PCI-Controller eine Basisadresse und dann hast du ab dieser Adresse ein paar Bytes in die du Daten durch lesen/schreiben an das Gerät senden und vom Gerät empfangen kannst. Was dann dort wann und wo reingeschrieben und auslesen musst, sagt dir dann die Spec der Netzwerkkarte.


  • Mod

    Vieles wird heute via MMIO anstelle IO geregelt. Das ist einfacher und bietet vor allem mehr Speicherraum. Wenn ich bei uns in PrettyOS nach den port-Funtkionen suche, finde ich cmos, Systemlautsprecher, Floppydisk, ata, ac97, Tastatur, Maus, vm86, vbe, apic, power management, serielle Schnittstelle, uhci, ...

    Man sollte sich damit also schon noch auskennen.



  • Schon mal ein fettes Danke an euch!

    Tobiking2 schrieb:

    Eine ausführliche Antwort würde den Rahmen sprengen.

    Ich wäre auch mal mega glücklich, wenn ich wüsste, womit ich anfangen könnte mich einzulesen. Darf auch gern ein Buch sein.

    Momentan habe ich gerade zwar wenig Zeit mich wieder mit dem Thema zu beschäftigen (weiter am zumindest selbst kompilierten C-Kernel zu programmieren).
    Nur bin ich bei den HowTos schon ständig über Sachen wie die GDT gestoßen, welche ich ohne "HowTo Write your own C-Kernel" nie entdeckt hätte. Und ich hätte eben gern etwas, wo solche Dinge genauer (in Assemblerbüchern sucht man vergebens) erklärt werden.
    Z. B. steht in der knapp 4000 Seiten langen Spec von Intel auch nur so viel, wenn nicht sogar weniger, zum Thema GDT drin, wie auf der dazugehörigen Wikipediaseite.
    Zu den Befehlen inb und outb habe ich in der Spec gar nichts anständiges gefunden.
    Also wo liest man sich da am besten ein?



  • Ich vermute, da steht so wenig, weil sich zu outb und co einfach (aus Betriebssystemsicht) wenig sagen lässt. Sind einfach Befehle wie andere Instruktionen auch.


  • Mod

    Zu OSDev Themen habe ich mir hier eine Link-Übersicht gebaut: http://henkessoft.de/OS_Dev/OSDEV Ressourcen.html

    Vielleicht hilft dir auch dies hier, falls Du es noch nicht kennst: http://henkessoft.de/OS_Dev/OS_Dev1.htm

    Die besten grundsätzlichen Artikel findet man auf osdev.org:
    http://wiki.osdev.org/I/O_Ports
    Bei lowlevel findet man deutschsprachige Erklärungen: http://www.lowlevel.eu/wiki/Hardware_Abstraction_Layer und http://www.lowlevel.eu/wiki/I/O-Port <== Da hast Du eine ausführliche Auflistung der Anwendungen dieser Ports. Was willst Du mehr? 😉

    Falls Du Probleme hast, AT&T Assembler zu lesen/schreiben: http://csiflabs.cs.ucdavis.edu/~ssdavis/50/att-syntax.htm

    Wenn Du unbedingt ein Buch suchst: http://www.pearson-studium.de/9783827373427.html (viel hat es mir - gerade am Anfang - nicht geholfen, steht nur nutzlos im Regal)

    Der beste Weg ist, wenn Du zu uns in den Chat kommst. Wegweiser: www.prettyos.de
    Da erhältst Du wirklich kompetente und praktisch verwertbare Antworten und Anregungen. Und immer locker bleiben. 👍


Log in to reply