Synchrone und asynchrone Codecbefehle
Mit der TransferCodecVerbs-Routine können Funktionstreiber Befehle an Audio- und Modemcodecs senden, die mit einem HD-Audiocontroller verbunden sind. Die Codecbefehle können entweder synchron oder asynchron ausgeführt werden:
Wenn ein Aufruf von TransferCodecVerbs eine Liste von Befehlen übermittelt, die synchron verarbeitet werden sollen, wird die Routine erst zurückgegeben, nachdem der Codec oder die Codecs alle Befehle verarbeitet haben.
Wenn ein Aufruf von TransferCodecVerbs eine Liste von Befehlen übermittelt, die asynchron verarbeitet werden sollen, wird die Routine zurückgegeben, sobald der HD Audio Bus-Treiber die Befehle zu seiner internen Befehlswarteschlange hinzufügt, ohne darauf zu warten, dass der Codec oder Codec die Befehle verarbeitet. Nachdem die Codecs die Befehle verarbeitet haben, benachrichtigt der Bustreiber den Funktionstreiber durch Aufrufen einer Rückrufroutine.
Abhängig von der Art der codec-Befehle, die er sendet, verwendet der Funktionstreiber eine oder mehrere der folgenden Techniken, um Antworten von einem Codec abzurufen:
Wenn der Funktionstreiber die Antwort des Codecs haben muss, bevor er eine zusätzliche Verarbeitung durchführen kann, verwendet er den synchronen Modus.
Wenn der Funktionstreiber nicht auf den Abschluss der Codecbefehle warten muss, um die Codecantworten anzuzeigen und zu wissen, wann die Befehle abgeschlossen sind, verwendet er den asynchronen Modus, ignoriert die Rückrufroutine (außer um den Speicher für die Codecbefehle freizusetzen), und verwirft oder ignoriert die Antworten auf die Codecbefehle.
Wenn der Funktionstreiber wissen muss, wann die Codecbefehle abgeschlossen sind, die Antworten jedoch nicht angezeigt werden müssen, verwendet er den asynchronen Modus und basiert für die Benachrichtigung auf der Rückrufroutine. Die Antworten auf die Codecbefehle werden jedoch verworfen oder ignoriert. Die Rückrufroutine kann ein Kernelstreamingereignis (KS) verwenden, um die Benachrichtigung an den Standard Teil des Treibers zu senden.
Wenn der Funktionstreiber sowohl den Abschluss der Codecbefehle als auch die Antworten kennen muss, aber die Verarbeitung sofort fortsetzen muss, anstatt auf den Abschluss der Befehle zu warten, verwendet er den asynchronen Modus und vermeidet das Lesen der Antworten, bis er die Rückrufroutine empfängt. Entweder die Rückrufroutine oder der Standard Teil des Treibers kann die Antworten überprüfen.
TransferCodecVerbs gibt STATUS_SUCCESS zurück, wenn die Liste der Befehle der internen Befehlswarteschlange des Bustreibers hinzugefügt werden kann. Auch wenn der Aufruf erfolgreich ist, sind die Antworten möglicherweise immer noch ungültig. Der Funktionstreiber muss die status Bits in den Codecantworten überprüfen, um zu bestimmen, ob sie gültig sind. Diese Regel gilt sowohl für den synchronen als auch für den asynchronen Modus.
Die Ursache für eine ungültige Antwort ist wahrscheinlich eine der folgenden:
Der Befehl hat den Codec nicht erreicht.
Der Codec hat geantwortet, aber die Antwort ist verloren gegangen, als ein FIFO-Überschreitung (First-In, First Out) im RIRB aufgetreten ist.
Das letztere Problem weist darauf hin, dass die RIRB-FIFO nicht ausreichend groß ist.
Jede Codecantwort enthält ein IsValid-Flag , das angibt, ob die Antwort gültig ist, und ein HasFifoOverrun-Flag , das angibt, ob ein RIRB FIFO-Überschreitung aufgetreten ist. Wenn IsValid = 0 ist, was angibt, dass eine Antwort ungültig ist, hilft das HasFifoOverrun-Flag , die Ursache des Fehlers zu identifizieren:
Wenn HasFifoOverrun = 0 ist, konnte der Codec nicht innerhalb des erforderlichen Zeitintervalls reagieren. Die wahrscheinliche Ursache ist, dass der Befehl nie den Codec erreicht hat.
Wenn HasFifoOverrun = 1, dann hat der Befehl wahrscheinlich den Codec erreicht, aber die Antwort ist aufgrund eines FIFO-Überlaufs verloren gegangen.
Während eines Aufrufs von TransferCodecCommands stellt der Aufrufer einen Zeiger auf ein Array von HDAUDIO_CODEC_TRANSFER Strukturen bereit. Jede Struktur enthält einen Befehl und bietet Platz für eine Antwort. Der Bustreiber schreibt immer jede Antwort in die Struktur, die den Befehl enthält, der die Antwort ausgelöst hat.
Für jeden Aufruf von TransferCodecCommands wird die Reihenfolge, in der die Befehle verarbeitet werden, durch die Reihenfolge der Befehle im Array bestimmt. Die Verarbeitung des ersten Befehls im Array wird immer abgeschlossen, bevor mit der Verarbeitung des zweiten Befehls begonnen wird usw.
Wenn ein Client einen asynchronen Aufruf von TransferCodecCommands durchführt und dann transferCodecCommands ein zweites Mal aufruft, ohne auf die Rückrufroutine ab dem ersten Aufruf zu warten, wird die relative Reihenfolge, in der die beiden Befehlsgruppen der beiden Aufrufe verarbeitet werden, durch die Reihenfolge definiert, in der der Client die beiden Befehlsgruppen übermittelt hat. Daher verarbeitet der Bustreiber alle Befehle des ersten Aufrufs, bevor er mit der Verarbeitung der Befehle aus dem zweiten Aufruf beginnt.
Die relative Reihenfolge der Befehle, die von zwei verschiedenen Funktionstreiberinstanzen gesendet werden, ist jedoch nicht definiert. (Jede instance verfügt über ein eigenes physisches Geräteobjekt.) Wenn beispielsweise instance 1 TransferCodecCommands aufruft, um die Befehle A, B und C in der Reihenfolge A-B-C zu senden, und instance 2 TransferCodecCommands aufruft, um die Befehle X, Y und Z in der Reihenfolge X-Y-Z zu senden, kann der Bustreiber die Befehle in der Reihenfolge A-X-Y-B-Z-C ausführen.
Wenn separate Funktionstreiberthreads zugriff auf denselben Satz von Hardwareressourcen gemeinsam nutzen, kann die relative Reihenfolge der Befehle aus verschiedenen Treiberthreads wichtig sein. Wenn ja, ist der Funktionstreiber für die Synchronisierung der Freigabe der Ressourcen zwischen den Threads verantwortlich.
Beispielsweise kann die Hardwareschnittstelle zum Schreiben einer Sequenz von Datenbytes in einen Codec aus einem Indexregister und einem 8-Bit-Datenregister bestehen. Zunächst übermittelt der Funktionstreiber einen Codecbefehl, um den Startindex in das Indexregister zu laden. Als Nächstes übermittelt der Treiber einen Befehl, um das erste Byte der Daten in das Datenregister zu schreiben. Das Indexregister wird nach jedem aufeinanderfolgenden Schreibvorgang in das Datenregister erhöht, bis die Übertragung abgeschlossen ist. Wenn jedoch zwei Treiberthreads ihren Zugriff auf den Index und die Datenregister nicht ordnungsgemäß synchronisieren können, ist die relative Reihenfolge des einzelnen Registerzugriffs durch die beiden Threads nicht definiert, und das wahrscheinliche Ergebnis ist eine Datenbeschädigung oder eine ungültige Hardwarekonfiguration.
Die TransferCodecVerbs-Routine ist in beiden Versionen des HD Audio DDI verfügbar.