Dienstsenke und Dienstgruppenobjekte
Der PortCls-Systemtreiber implementiert die IServiceSink - und IServiceGroup-Schnittstellen zugunsten von Port- und Miniporttreibern. Der Porttreiber verwendet diese Schnittstellen, um Interruptbenachrichtigungen an seine eigenen Dienstroutinen zu verteilen, und ein Miniporttreiber hat die Möglichkeit, diese Schnittstellen für ähnliche Zwecke zu verwenden. Ein IServiceSink-Objekt kapselt eine Dienstroutine, und ein IServiceGroup-Objekt stellt eine Gruppe von IServiceSink-Objekten dar. Wenn eine Dienstgruppe eine Dienstanforderung empfängt, verteilt sie die Anforderung an jede ihrer Dienstsenken.
IServiceGroup erbt von IServiceSink. Da eine Dienstgruppe auch eine Dienstsenke ist, kann eine Dienstgruppe andere Dienstgruppen enthalten, obwohl Audiotreiber diese Funktion in der Regel nicht nutzen. Porttreiber verwenden derzeit Dienstgruppen, um Anforderungen für interrupt-Dienst zu demultiplexieren, obwohl die Funktionalität einer Dienstgruppe allgemein genug ist, um sie auch für andere Zwecke nützlich zu machen.
Die Interruptdienstroutine (ISR) des Miniporttreibers ruft eine der folgenden Benachrichtigungsmethoden im Porttreiber auf:
Die Benachrichtigungsmethode verwendet einen Zeiger auf die Dienstgruppe als Aufrufparameter. Während dieses Aufrufs ruft der Porttreiber die IServiceSink::RequestService-Methode der Dienstgruppe auf, die einen verzögerten Prozeduraufruf (DPC) in die Warteschlange stellt. Wenn der DPC ausgeführt wird, leitet er die Dienstanforderung an alle Memberobjekte in der Dienstgruppe weiter.
Der Miniport-Treibercode muss in der Regel keine IServiceGroup-Schnittstellenmethoden aufrufen. Der Porttreiber ruft diese Methoden jedoch auf, um den Dienstgruppen, die er vom Miniporttreiber abruft, eigene IServiceSink-Objekte hinzuzufügen. Miniporttreiber erstellen nach Bedarf Dienstgruppenobjekte und ordnen diese Dienstgruppen Miniport- und Streamobjekten zu, die regelmäßig gewartet werden müssen. Beispielsweise ordnet ein WaveCyclic-Miniporttreiber der Dienstgruppe, die er als Ausgabeparameter angibt, ein Streamobjekt der IMiniportWaveCyclic::NewStream-Methode zu.
Im Kontext von WaveCyclic-Miniporttreibern bewirkt das Zuordnen aller Streams zu einer Dienstgruppe, dass der Porttreiber alle Datenströme basierend auf einer einzelnen Benachrichtigung bedient. Durch das Zuordnen jedes Datenstroms zu einer eigenen Dienstgruppe kann die Interruptdienstroutine den Stream auswählen, der während der Ausführung des DPC vom Porttreiber bedient wird.
Ein Miniporttreiber gibt einen Verweis auf seine Dienstgruppe aus, wenn der Porttreiber eine der folgenden Initialisierungsmethoden aufruft:
Der Porttreiber fügt der Dienstgruppe, die er aus dem Init-Aufruf abruft, ein eigenes IServiceSink-Objekt hinzu. Wenn der ISR des Miniporttreibers später Notify aufruft, um eine Benachrichtigung an diese Dienstgruppe zu senden, stellt die Dienstgruppe einen DPC in die Warteschlange, der eine Benachrichtigung an das IServiceSink-Objekt des Porttreibers weiterleitet, das wiederum die Benachrichtigung an den Miniporttreiber weiterleitet, indem eine der folgenden Dienstmethoden aufgerufen wird:
IMiniportDMus::Service (nicht verwendet)
Ein Miniporttreiber gibt auch einen Verweis auf seine Dienstgruppe aus, wenn der Porttreiber eine der folgenden Streamerstellungsmethoden aufruft:
IMiniportWaveCyclic::NewStream
Wie bereits erwähnt, hat der Miniporttreiber die Möglichkeit, eine andere Dienstgruppe für jeden Stream zu erstellen oder eine einzelne Dienstgruppe für alle Datenströme freizugeben.
Die folgenden Methoden helfen MIDI- und DMus-Porttreibern, Hardwareunterbrechungen zu vermeiden:
IPortMidi::RegisterServiceGroup
IPortDMus::RegisterServiceGroup
Während der Ausführung der Init-Methode ruft ein MIDI- oder DMus-Miniporttreiber in der Regel die RegisterServiceGroup-Methode des Porttreibers auf, bevor der Synthesizer gestartet wird. Der Zweck dieses Aufrufs besteht darin, dem Porttreiber zu ermöglichen, sein Dienstsenkenobjekt (das seinen Interrupthandler enthält) in die Dienstgruppe einzufügen, bevor die Hardware mit dem Generieren von Interrupts beginnt. Obwohl die Init-Methode einen Dienstgruppenzeiger an den Porttreiber ausgibt, kann der Porttreiber diesen Zeiger erst nach der Rückgabe von Init verwenden.
Im Fall eines WavePci-Porttreibers fügt das Portobjekt der Dienstgruppe, die es aus dem IMiniportWavePci::NewStream-Aufruf abruft, ein eigenes IServiceSink-Objekt hinzu. Wenn der ISR des Miniporttreibers später Notify aufruft, um eine Benachrichtigung an diese Dienstgruppe zu senden, stellt die Dienstgruppe einen DPC in die Warteschlange, der die Benachrichtigung an das IServiceSink-Objekt des Porttreibers weiterleitet, was wiederum Wie folgt ausführt:
Leitet die Benachrichtigung an den Miniportstream weiter, indem die Dienstmethode IMiniportWavePciStream::Service aufgerufen wird.
Löst alle Positions- und/oder Uhrereignisse auf dem Pin aus, die ausgelöst werden können.
Die IServiceSink-Schnittstelle unterstützt eine einzelne Methode:
Die IServiceGroup-Schnittstelle unterstützt die folgenden Methoden:
IServiceGroup::CancelDelayedService
IServiceGroup::RequestDelayedService
IServiceGroup::SupportDelayedService
Darüber hinaus stellt der PortCls-Systemtreiber eine PcNewServiceGroup-Funktion zum Erstellen eines neuen Dienstgruppenobjekts bereit. Es ist jedoch keine ähnliche Funktion zum Erstellen eines Dienstsenkenobjekts vorhanden. Der Porttreiber fügt der Implementierung seines Standard Portobjekts einfach eine IServiceSink-Schnittstelle hinzu, wenn das Objekt erstellt wird, also die Dienstsenke. Der Porttreiber kann die IServiceSink-Schnittstelle des Portobjekts der Dienstgruppe hinzufügen, die er von der Init - oder NewStream-Methode des Miniporttreibers empfängt. Zur Vereinfachung definiert die Headerdatei Portcls.h IMP_IServiceSink und IMP_IServiceGroup Konstanten zum Hinzufügen von IServiceSink- und IServiceGroup-Schnittstellen zu Treiberobjekten.