| Zeile 175: | Zeile 175: | ||
VIAs AC'97-Soundkarte ist Funktion 5 der Southbridge, die sich ihre IO-Adressräume mit dem integrierten Modem (MC97) in Funktion 6 teilt. Wir behandeln im Folgenden nur AC'97. Der für uns relevante IO-Raum für DMA residiert im ersten PCI-BAR. | VIAs AC'97-Soundkarte ist Funktion 5 der Southbridge, die sich ihre IO-Adressräume mit dem integrierten Modem (MC97) in Funktion 6 teilt. Wir behandeln im Folgenden nur AC'97. Der für uns relevante IO-Raum für DMA residiert im ersten PCI-BAR. | ||
| − | Die Karte bezieht Sounddaten aus aus mehreren Puffern, die in | + | Die Karte bezieht Sounddaten aus aus mehreren Puffern, die in SGD-Tabellen ("Scatter/Gather DMA Table") durch Deskriptoren folgenden Formats beschrieben werden. Die physischen Adressen der Tabellen sind in die 32-bit-Register AC97_VIA_R_SGD_TABLE_BASE bzw. AC97_VIA_W_SGD_TABLE_BASE zu schreiben und an 2-Byte-Grenzen auszurichten: |
<c>typedef struct | <c>typedef struct | ||
{ | { | ||
| Zeile 185: | Zeile 185: | ||
uint32_t eol : 1; // Letzter Eintrag. Löst einen EOL-Interrupt aus. | uint32_t eol : 1; // Letzter Eintrag. Löst einen EOL-Interrupt aus. | ||
} __attribute__((packed)) ac97Via_SGDEntry_t;</c> | } __attribute__((packed)) ac97Via_SGDEntry_t;</c> | ||
| + | |||
| + | === Zugriff auf den AC97-Codec === | ||
| + | |||
| + | Der Zugriff auf den AC97-Codec gestaltet sich schwieriger als bei der o.g. AC97-Implementation von Intel, weil dessen Register nicht in einen eigenen Adressraum gemappt sind, sondern über das 4 Bytes lange Register an Offset 0x80 gelesen und geschrieben werden müssen. Der folgende Code implementiert den Zugriff auf diese Register: | ||
| + | <c>void codec_sendCommand(ac97Via_t* ac97, uint8_t reg, bool primary, uint16_t data) | ||
| + | { | ||
| + | while (inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & AC97_VIA_CODEC_BUSY) // Warte, bis der Codec Zeit hat | ||
| + | ; | ||
| + | if (primary) | ||
| + | outl(ac97->iobase + AC97_VIA_ACCESS_CODEC, AC97_VIA_CODEC_SEL_PRIM | AC97_VIA_CODEC_WRITE | ((uint32_t)reg << 16) | data); | ||
| + | else | ||
| + | outl(ac97->iobase + AC97_VIA_ACCESS_CODEC, AC97_VIA_CODEC_SEL_SEC | AC97_VIA_CODEC_WRITE | ((uint32_t)reg << 16) | data); | ||
| + | } | ||
| + | |||
| + | uint16_t codec_readStatus(ac97Via_t* ac97, uint8_t reg, bool primary) | ||
| + | { | ||
| + | while (inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & AC97_VIA_CODEC_BUSY) // Warte, bis der Codec Zeit hat | ||
| + | ; | ||
| + | if (primary) | ||
| + | { | ||
| + | outl(ac97->iobase + AC97_VIA_ACCESS_CODEC, AC97_VIA_CODEC_SEL_PRIM | AC97_VIA_CODEC_READ | AC97_VIA_CODEC_PRIM_VALID | ((uint32_t)reg << 16)); | ||
| + | while (!(inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & AC97_VIA_CODEC_PRIM_VALID)) // Warte, bis der Codec die Daten geliefert hat | ||
| + | ; | ||
| + | return inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & 0xFFFF; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | outl(ac97->iobase + AC97_VIA_ACCESS_CODEC, AC97_VIA_CODEC_SEL_SEC | AC97_VIA_CODEC_READ | AC97_VIA_CODEC_SEC_VALID | ((uint32_t)reg << 16)); | ||
| + | while (!(inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & AC97_VIA_CODEC_SEC_VALID)) // Warte, bis der Codec die Daten geliefert hat | ||
| + | ; | ||
| + | return inl(ac97->iobase + AC97_VIA_ACCESS_CODEC) & 0xFFFF; | ||
| + | } | ||
| + | }</c> | ||
| + | |||
| + | === Anhang === | ||
| + | Definitionen der oben verwendeten Konstanten: | ||
| + | <c>// Register-Offsets | ||
| + | #define AC97_VIA_R_SGD_CONTROL 0x01 | ||
| + | #define AC97_VIA_R_SGD_TABLE_BASE 0x04 | ||
| + | #define AC97_VIA_W_SGD_CONTROL 0x11 | ||
| + | #define AC97_VIA_W_SGD_TABLE_BASE 0x14 | ||
| + | #define AC97_VIA_ACCESS_CODEC 0x80 | ||
| + | |||
| + | // Bits des AC97_VIA_ACCESS_CODEC-Registers | ||
| + | #define AC97_VIA_CODEC_SEL_PRIM 0 | ||
| + | #define AC97_VIA_CODEC_PRIM_VALID BIT(25) | ||
| + | #define AC97_VIA_CODEC_SEL_SEC BIT(30) | ||
| + | #define AC97_VIA_CODEC_SEC_VALID BIT(27) | ||
| + | #define AC97_VIA_CODEC_BUSY BIT(24) | ||
| + | #define AC97_VIA_CODEC_WRITE 0 | ||
| + | #define AC97_VIA_CODEC_READ BIT(23)</c> | ||
== Weblinks == | == Weblinks == | ||