CMOS

Aus Lowlevel
Wechseln zu:Navigation, Suche

Ein Complementary Metal Oxide Semiconductor (= CMOS) ist eigentlich ein elektronischer Baustein, aber im Bereich der Betriebssystemprogrammierung ist damit meistens der Batterie-gepufferte SRAM eines x86- bzw. x86-64-Computers gemeint. In diesem speichert das BIOS Informationen beispielsweise über die angeschlossene Hardware. Außerdem wird darin die momentane Uhrzeit und das Datum gespeichert und von einer Echtzeituhr aktualisiert.

Aufbau

Im CMOS werden folgende jeweils 1 Byte große Felder gespeichert. Die mit BCD markierten Einträge sind standardmässig im BCD-Format kodiert. Die Kodierung kann aber auch im Statusregister B (Bit 2) geändert werden. Dabei ist allerdings zu beachten, dass die momentanen Werte im Register an die neue Kodierung angepasst werden müssen und dies nicht von selbst geschieht.


Offset Beschreibung
0x00 Sekunde (BCD)
0x01 Alarmsekunde (BCD)
0x02 Minute (BCD)
0x03 Alarmminute (BCD)
0x04 Stunde (BCD)
0x05 Alarmstunde (BCD)
0x06 Wochentag (BCD)
0x07 Tag des Monats (BCD)
0x08 Monat (BCD)
0x09 Jahr (letzten zwei Stellen) (BCD)
0x0A Statusregister A
0x0B Statusregister B
0x0C Statusregister C (schreibgeschützt)
0x0D Statusregister D (schreibgeschützt)
0x0E POST-Diagnosestatusbyte
0x0F Shutdown-Statusbyte
0x10 Typ der Diskettenlaufwerke
0x11 reserviert
0x12 Typ der Festplattenlaufwerke
0x13 reserviert
0x14 Gerätebyte
0x15 Größe des Basisspeichers in kB (niederwertiges Byte)
0x16 Größe des Basisspeichers in kB (höherwertiges Byte)
0x17 Größe des Erweiterungsspeichers in kB (niederwertiges Byte)
0x18 Größe des Erweiterungsspeichers in kB (höherwertiges Byte)
0x19 Erweiterungsbyte 1. Festplatte
0x1A Erweiterungsbyte 2. Festplatte
0x1B - 0x2D Reserviert / vom BIOS abhängig
0x2E CMOS-Prüfsumme (höherwertiges Byte)
0x2F CMOS-Prüfsumme (niederwertiges Byte)
0x30 Erweiterter Speicher (niederwertiges Byte)
0x31 Erweiterter Speicher (höherwertiges Byte)
0x32 Jahrhundert (BCD)
0x33 - 0x3F Reserviert / vom BIOS abhängig


0x0A - Statusregister A

Bit Beschreibung
7 Zeit-Update-Zyklus (1 = Update läuft => Zeitangaben undefiniert)
6-4 Zeit-Basis (Standard = 010b = 32768 Hz)
3-0
Auswahl-Bits zum Einstellen der Wiederholrate des periodischen Interrupts. Frequenz = 65536 Hz / 2Rate-Bits
Rate-Bits Teiler Frequenz Periode Bemerkung
0000b 0 - - kein Interrupt
0011b 23=8 8192 Hz 122.070 µs Minimum
0100b 24=16 4096 Hz 244.141 µs
0101b 25=32 2048 Hz 488.281 µs
0110b 26=64 1024 Hz 976.562 µs Standard
0111b 27=128 512 Hz 1.953125 ms
1000b 28=256 256 Hz 3.90625 ms
1001b 29=512 128 Hz 7.8125 ms
1010b 210=1024 64 Hz 15.625 ms
1011b 211=2048 32 Hz 31.25 ms
1100b 212=4096 16 Hz 62.5 ms
1101b 213=8192 8 Hz 125 ms
1110b 214=16384 4 Hz 250 ms
1111b 215=32768 2 Hz 500 ms


0x0B - Statusregister B

Bit Beschreibung
7 Zeit-Update (0 = Zeit aktualisieren, 1 = Zeit-update anhalten)
6 Periodischer Interrupt mit Rate aus Statusregister A (0 = deaktiviert (Standard), 1 = aktiviert)
5 Alarm Interrupt wenn Uhrzeit = Alarmzeit (0 = deaktiviert (Standard), 1 = aktiviert)
4 Update-Interrupt (0 = deaktiviert (Standard), 1 = aktiviert)
3 Rechtecks-Frequenz mit Rate aus Statusregister A erzeugen (0 = deaktiviert (Standard), 1 = aktiviert)
2 Daten Modus (0 = BCD, 1 = Binär)
1 24 Stundenformat (0 = 12 Stunden, 1 = 24 Stunden (Standard))
0 Sommerzeit (0 = deaktiviert (Standard), 1 = aktiviert)



0x0C - Statusregister C

Bit Beschreibung
7 Interrupt-Request (1 = RTC hat Interrupt angefordert)
6 IRQ-Quelle ist periodischer Interrupt (0 = nein, 1 = ja)
5 IRQ-Quelle ist Alarm-Interrupt (0 = nein, 1 = ja)
4 IRQ-Interrupt ist Update-Interrupt (0 = nein, 1 = ja)
3-0 Reserviert



0x0D - Statusregister D

Bit Beschreibung
7 Gültigkeit der Daten im CMOS (0 = ungültig, 1 = Daten sind gültig)
6-0 Reserviert



0x0E - POST-Diagnosestatusbyte

Bit Beschreibung
7 Stromversorgung (0 = OK, 1 = Stromversorgung war unterbrochen)
6 CMOS-Prüfsumme (0 = OK, 1 = Prüfsumme falsch)
5 Konfiguration im CMOS stimmt mit ermittelten Werten überein (0 = OK, 1 = nein)
4 Speichergröße im CMOS == ermittelte Speichergröße (0 = ja, 1 = nein)
3 Laufwerk bzw Controllerfehler (0 = OK, 1 = Fehler)
2 Uhrzeit gültig (0 = OK, 1 = Fehler)
1 Fehler bei Adapterinitialisierung (0 = OK, 1 = Fehler)
0 Timeout beim Adapter-ID lesen



0x0F - Shutdown-Statusbyte

80286-Prozessoren konnten nicht vom Protected Mode in den Realmode zurückgeschaltet werden. Zu diesem Zweck war ein Prozessor-Reset nötig. Das Shutdown-Statusbyte dient dazu dem BIOS anzuzeigen, ob der PC neu gebootet oder der Prozessor nur im Realmode neu gestartet werden soll.

Wert Beschreibung
0x00 Normale Ausführung des POST
0x01 Chip Satz Initialisierung für Real Mode
0x02 Power-On Reset durchführen
0x03 Power-On Reset durchführen
0x04 int 0x19-reboot
0x05 EOI an PIC ausgeben, Tastatur resetten, Sprung zur Addresse [0x0040:0x0067]
0x06 Sprung zur Addresse [0x0040:0x0067] ohne EOI
0x07 zurück zu Int 0x15, Funktion 0x87 (Block im Extenden Memory verschieben)
0x08 zurück zum POST Speicher Test
0x09 zurück zu Int 0x15, Funktion 0x87 (Block im Extenden Memory verschieben)
0x0A JMP zu [0x0040:0x0067]
0x0B IRET zu [0x0040:0x0067]
0x0C RET zu [0x0040:0x0067]


0x10 - Typ der Diskettenlaufwerke

In diesem Byte wird der Typ der Diskettenlaufwerke gespeichert, wobei in den Bits 4-7 der Typ des ersten Laufwerks gespeichert ist und in den Bits 0-3 der Typ des zweiten Laufwerks. Die Typen sind wie folgt kodiert:

0000b = Laufwerk nicht vorhanden
0001b = 5 1/4 - 360 kB
0010b = 5 1/4 - 1.2 MB
0011b = 3 1/2 - 720 kB
0100b = 3 1/2 - 1.44 MB (sollte eigentlich heutzutage der Standard sein)
0101b - 1111b sind unbenutzt



0x12 - Typ der Festplattenlaufwerke

In diesem Byte wird der Typ der Festplattenlaufwerke gespeichert, wobei in den Bits 4-7 der Typ des ersten Laufwerks gespeichert ist und in den Bits 0-3 der Typ des zweiten Laufwerks. Die Typen sind wie folgt kodiert:

0000b = Laufwerk nicht vorhanden
0001b - 1110b = Typen 1-14
1111b = Typ laut Erweiterungsbyte der Festplatte


0x14 - Gerätebyte

Hier werden Informationen über die allgemeine Hardwarekonfiguration des PCs gespeichert.

Bits 7-6 5-4 3 2 1 0
Anzahl Floppys Display-Typ Display vorhanden? Keyboard vorhanden? Mathematischer Koprozessor vorhanden? Floppy

Anzahl Floppys
Auf diesen Wert nur verlassen wenn Floppy=1

00b  1 Floppy-Laufwerk
01b  2 Floppy-Laufwerke

Display-Typ

00b  BIOS-Display-Adapter
01b  CGA (40 Spalten)
10b  CGA (80 Spalten)
11b  Monochrom


0x2E & 0x2F - CMOS-Prüfsumme

Die CMOS-Prüfsumme ist eine 16 Bit grosse, byteweise Summe der Werte der Bytes von 0x10 bis 0x2D.

Programmierung

Die Programmierung des CMOS ist denkbar einfach: Die sieben niederwertigen Bits des I/O Ports 0x70 dienen als Offset (siehe Tabelle). Das höchste Bit sollte nicht verändert werden, es dient als NMI-Maskierungsregister. Durch Lesen bzw. Schreiben des I/O Ports 0x71 kann dann der Wert an diesem Offset gelesen bzw. geschrieben werden.

Assembler Beispielcode

;Ein Makro um ein Byte aus dem CMOS auszulesen
;Der einzige Parameter ist das Offset des Bytes welches gelesen werden soll
;Rückgabe ist das gelesene Byte in AL

%macro read_byte 1
  in al, 0x70         ;Bit 7 des Ports sichern
  and al, 10000000b
  or al, %1           ;Offset (Parameter 1) dazumixen
  out 0x70, al        ;Offset setzen
  in al, 0x71         ;Byte lesen
%endmacro

C/C++ Beispielcode

#define CMOS_PORT_ADDRESS 0x70
#define CMOS_PORT_DATA    0x71

/**
 * Liest ein Byte aus den CMOS
 *  @param offset Offset im CMOS
 *  @return Gelesener Wert
 */
uint8_t cmos_read(uint8_t offset) {
  uint8_t tmp = inb(CMOS_PORT_ADDRESS);
  outb(CMOS_PORT_ADDRESS, (tmp & 0x80) | (offset & 0x7F));
  return inb(CMOS_PORT_DATA);
}

/**
 * Schreibt ein Byte in das CMOS
 *  @param offset Offset im CMOS
 *  @param val Zu schreibender Wert
 */
void cmos_write(uint8_t offset,uint8_t val) {
  uint8_t tmp = inb(CMOS_PORT_ADDRESS);
  outb(CMOS_PORT_ADDRESS, (tmp & 0x80) | (offset & 0x7F));
  outb(CMOS_PORT_DATA,val);
}

Weblinks