MenuetOS The Assembly Language Programmers OS!


Home | Das Wiki | Screenshots | Dokumente | Downloads | Foren | Kontakt

Netzwerk Treiber unter Menuet schreiben

Mike Hibbett, (Übersetzung: Ringo Leese)

4. September 2003

Hintergrund

Der Protokol-Stack wird im Main Loop Kernel gehandled, os_loop.

Der gesamte Stack-Code wird in diesem loop von einer einzelnen Stack-Funktion namens stack_handler gehandled. Diese Funktion befragt die Netzwerk-Treiber nach empfangenen Daten und ruft die IP & TCP Prozesse auf.

Dieses Release des Stacks nutzt ein sehr simples Puffer-Array für IP-Pakete. Das Array ist in stack.inc festgelegt. IPBuffers ist ein Array von NUM_IPBUFFERS einträgen, wo jedes IPBUFFERSIZE groß ist. Jeder Eintrag sieht wie folgender aus:

Version IHL Art des Service komplette Größe
Identifikation Flags Fragment Offset
Time to Live Protocol Header Checksumme
Quell-Adresse
Ziel-Adresse
Daten......
d.h. es ist ein 'normales' IP-Paket.

Hinweis: Diese Implementation erlaubt nicht die Optionsfelder in den IP-Header zu veröffentlichen.

Die Funktion ethernet_driver ruft zuerst eth_rx auf, welches die niedrigeren Level der Netzwerktreiber nach Daten abfragt. Wenn ein Paket Verfügbar ist, wird es ent- gegengenommen und in einem IP-Puffer gespeichert. ethernet_driver ruft dann eth_rx auf, welches durch die IPBuffers guckt, ob dort Puffer sind, die als senden markiert sind. Wenn dort einer ist, wird es durch den Netzwerktreiber geschickt und sofort gesendet.

Ethernettreiber benötigen einen Plan zwischen den IP-Adressen und der Ethernet Hardware Adresse (MAC). Diese wird durch das sogenannte ARP-Protokoll gemanaged. ARP ist nur dem Netzwerktreiber sichtbar; IP kümmert sich nicht um die Adress- Auflösung.

Treiber Vorraussetzungen

Nur PCI-Bus Ethernet Hardware wird momentan unterstützt. Dies kann eine Einsteck- karte oder OnBoard Hardware sein (wie bei den meisten Laptops)

Die Treiber Vorraussetzungen sind sehr einfach.

Menuets Ethernettreiber basieren auf den etherboot-Projekte-Treibercode, welcher in C geschrieben wurde. besorge dir dafür eine Kopie der Quelldateien.

Ich empfehle dir, die Dateien ns8390.c und eepro100.c zu überprüfen, welche auf die Dateien RTL8029.inc, respektive i8255x.inc basieren.

Ein Treiber muss 4 Funktionen besitzen:

drivername_reset
drivername_probe
drivername_poll
drivername_transmit

ich empfehle, dass du die Namen dieser Funktionen im ähnlichen Format für andere Treiber beibehältst, um es für andere einfacher zu machen, diesen Code zu lesen.

_reset Funktion

Eingabe Paramter: Ausgabe Parameter: Diese Funktion sollte die Karte in ihren Grundzustand aktiv versetzen, fertig um Daten zu empfangen. Es wird gewöhnlich am Ende der Hardware Initialisierung aufgerufen. Die Funktion ist momentan nicht extern aufrufbar, aber wird es wahrscheinlich in der Zukunft.

_probe Funktion

Eingabe Parameter: Ausgabe Parameter: Diese Funktion wird einmal aufgerufen, wenn der Hardware I/O Adresse-Bereich bekannt ist. Die Funktion wird die Hardware komplett initialisiert, und extrahiert die MAC-Adresse. Es gibt zurück, ob die Hardware aktiviert ist, und auf senden oder empfangen von Daten wartet. Wenn die _probe Funktion erfolgreich war, werden die folgenden zwei Zeilen ausgeführt

;zeigt an, dass die Karte erfolgreich resettet wurde
mov eax, [pci_data]
mov [eth_status], eax

_poll Funktion

Eingabe Parameter: Ausgabe Parameter: Diese Funktion untersucht die Hardware um festzustellen, ob ein Datenpaket empfangen wurde. Wenn dies der Fall ist, sind die Daten im Ether_buffer Puffer extrahiert und gespeichert (welches Global Verfügbar ist und in stack.inc definiert ist).

Zuerst, versichere dich, dass die folgenden Zeilen zu beginn ausgeführt werden

mov ax, 0 ;keine Daten festlegen
mov [eth_rx_data_len], ax

eth_rx_data_len wird von der oberen Schicht genutzt um festzustellen ob Daten empfangen wurden.

_transmit Funktion

Eingabe Parameter: Ausgabe Parameter: Reicht ein Datenpaket an die Hardware durch und wartet auf die Versendung. Die Ziel-Adresse ist im Aufruf spezifiziert, so das die Funktion sich nicht um die Adress-Auflösung kümmern muss.

Die Treiber integrieren

Zuerst, schreibe deinen Code in eine neue Include-Datei und gieb der Datei einen Namen, welches des Treiber identifiziert, z.B. 3c509.inc

In der Ethernet.inc Datei gibt es folgende Zeilen:

include "RTL8029.INC"
include "I8255X.INC"

welche recht weit oben sind. füge deine Include-Datei hier ein.

Weiter unten in der ethernet.inc Datei befinden sich folgende Zeilen:

PCICards:
dd 0x12098086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit
dd 0x10298086, I8255x_probe, I8255x_reset, I8255x_poll, I8255x_transmit

Füge eine neue Zeile hinzu und fülle diese mit den Details deiner Treiber aus. Das erste DWord ist der PCI Bus-Device und die Anbieterangaben. Diese können mit dem etherboot-Projekt herausgefunden werden, welche eine Liste der PCI-Werte für verschiedene Kartentypen enthält. Du benötigst diesen Wert bevor du den Treiber implementieren kannst!

Das ist es. Assembliere den Kernel neu, kopiere ihn zu deiner Bootdiskette und boote. Wenn du jetzt den Pakettreiber aktivierst, wird deine Karte hoffentlich erkannt und kann verwendet werden. Du kannst es prüfen, indem du die Status- Anwendung ausführt.

Ratschläge

Der etherboot Quellcode stützt sich auf einige Timer-Funktionen, die im moment noch nicht in Menuet Verfügbar sind. Diese Timer werden benutzt, um Timeouts zu generieren, während die auf die Hardware wartet um Tasks zu beenden. Ich habe mich entschlossen dies erstmal zu ignorieren und es nicht zu implementieren. Für diesen Zweck ist das kein Problem und wir werden es zu einem späteren Zeitpunkt anpeilen. Kleine Verzögerungen zu generieren kann ein Problem sein, und dort wo es einen wirklichen nutzen hat, 2-10s Verzögerung zu generieren, habe ich viel größere Verzögerungen ohne Probleme benutzt. Wir arbeiten an einem Akkuraten Mittel um kleine Verzögerungen in Menuet zu erzeugen.

Meine Taktik ist es, einfach die I/O Aufrufe in der Original Quelldatei zu identifizieren und diese in Assembler zu coden. Mit den beiden Treibern, die ich implementiert habe, war es kein Problem. Sendet mir eine E-Mail, wenn du irgendwelche fragen zu deinen Treibern hast.

Das etherboot Projekt besitzt eine enorme Hilfestellung, d.h. das ein ein detailliertes Verständnis der Hardware nicht vorrausgesetzt wird. Ich habe für die beiden Implementationen keine Chip-Spezifikationen von jemanden bezogen.

Hinweise

Die Treiber implementation ist weitaus mehr gefragt als das interrupt basierte. Dieses verringert die Transfergeschwindigkeit, aber es macht die Treiber- entwicklung sehr einfach. Wir werden diese für die Zukunft anpeilen, wenn ich herrausgearbeitet habe, wie man interrupts mit der Hardware nutzt!

Ich sollte herausstellen das der Weg in welchem die Netzwerktreiber implementiert werden, bald in Vorbereitung für die Implementierung von TCP geändert wird. Jedoch wird das Prinzip größtenteils das gleiche bleiben, also wenn du in betracht ziehst Treiber zu schreiben, tu es lieber jetzt als zu warten!


Kommentare/Fragen an mikehibbett [@] oceanfree.net