Der Interrupt-Handler

Die meisten Hardware-Schnittstellen werden mit Hilfe eines Interrupt-Handlers gesteuert. Die Schnittstelle unterbricht den Prozessor, um eines von zwei möglichen Ereignissen mitzuteilen: Entweder ist ein neues Paket angekommen, oder die Übertragung eines ausgehenden Paketes wurde abgeschlossen. Diese Generalisierung ist nicht immer ganz richtig, trifft aber bei allen Problemen der asynchronen Paket-Übertragung zu. Das Parallel Line Internet Protocol (PLIP) und das Point-to-Point Protocol (PPP) sind Beispiele für Schnittstellen, die nicht in diese Generalisierung passen. Sie haben es mit den gleichen Ereignissen zu tun, aber die Interrupt-Verarbeitung auf der unteren Ebene ist geringfügig anders.

Die normale Interrupt-Routine kann den Unterschied zwischen einem Interrupt wegen eines neu eingetroffenen Paketes und einem Interrupt wegen einer vollständig durchgeführten Übertragung anhand eines Status-Registers auf dem physikalischen Gerät selbst feststellen. snull arbeitet ähnlich, wenn auch dieser Zustandswert in der Software implementiert wird und in dev->priv steht. Der Interrupt-Handler für eine Netzwerk-Schnittstelle sieht folgendermaßen aus:


voidsnull_interrupt(intirq,void*dev_id,structpt_regs*regs)
{
intstatusword;
structsnull_priv*priv;
/*
*Wieueblichden"Geraete"-ZeigeraufgemeinsamgenutzteHandler
*ueberpruefen,dann"structnet_device*dev"zuweisen.
*/
structnet_device*dev=(structnet_device*)dev_id;
/*...undbeiderHardwareueberpruefen,obdasunserGeraetist*/

if(!dev/*paranoid*/)return;

/*DasGeraetsperren*/
priv=(structsnull_priv*)dev->priv;
spin_lock(&priv->lock);

/*Statuswertholen:richtigeGeraeteverwendenI/O-Anweisungen*/
statusword=priv->status;
if(statusword&SNULL_RX_INTR){
/*ansnull_rxzurBearbeitungsenden*/
snull_rx(dev,priv->rx_packetlen,priv->rx_packetdata);
}
if(statusword&SNULL_TX_INTR){
/*eineUebertragungisterledigt:denskbfreigeben*/
priv->stats.tx_packets++;
priv->stats.tx_bytes+=priv->tx_packetlen;
dev_kfree_skb(priv->skb);
}

/*DasGeraetfreigebenundfertig*/
spin_unlock(&priv->lock);
return;
}

Die erste Aufgabe des Handlers ist es, den Zeiger auf die richtige net_device-Struktur zu finden. Dieser Zeiger stammt normalerweise aus dem Zeiger dev_id, der als Argument übergeben wird.

Der interessante Teil des Handlers behandelt abgeschlossene Übertragungen. In diesem Fall wird die Statistik aktualisiert und dev_kfree_skb aufgerufen, um den (nicht mehr benötigten) Socket-Buffer an das System zurückzugeben. Wenn Ihr Treiber die Übertragungswarteschlange vorübergehend angehalten hat, ist dies auch die richtige Stelle, um sie mit netif_wake_queue wieder in Gang zu bringen.

Zum Empfangen der Pakete ist dagegen keine besondere Interrupt-Behandlung notwendig. Es muß lediglich snull_rx aufgerufen werden.