| Zeile 34: | Zeile 34: | ||
6. Nun muss die Karte initialisiert werden. Dies geschieht mittels eines Initialization Block, der folgendermaßen aussieht: | 6. Nun muss die Karte initialisiert werden. Dies geschieht mittels eines Initialization Block, der folgendermaßen aussieht: | ||
| − | <c>struct initialization_block | + | <syntaxhighlight lang=c> |
| + | struct initialization_block | ||
{ | { | ||
uint16_t mode; | uint16_t mode; | ||
| Zeile 46: | Zeile 47: | ||
uint32_t receive_descriptor; | uint32_t receive_descriptor; | ||
uint32_t transmit_descriptor; | uint32_t transmit_descriptor; | ||
| − | } __attribute__((packed));</ | + | } __attribute__((packed)); |
| + | </syntaxhighlight> | ||
| + | |||
„reservedX“-Felder sind reserviert. „mode“ ist 0x8000, wenn die Karte in den Promiscuous-Mode geschaltet werden soll (Alle Pakete empfangen, nicht nur Broadcasts und die für die eigene MAC-Adresse), sonst 0x0000. „receive_length“ gibt die Anzahl der Empfangsdeskriptoren an, dazu später. „transfer_length“ enthält im Gegensatz dazu die Anzahl der Sendedeskriptoren. Beide Werte können auf 3 gesetzt werden, dies entspricht jeweils acht Deskriptoren. „physical_address“ enthält die MAC-Adresse der Karte. „logical_address“ kann auf 0 gesetzt werden. „receive_descriptor“ enthält die physische Adresse zu einem 2-kB-Puffer, „transmit_descriptor“ zu einem anderen. Beide Puffer müssen physisch kontinuierlich sein und an 16-Bytes-Grenzen ausgerichtet. | „reservedX“-Felder sind reserviert. „mode“ ist 0x8000, wenn die Karte in den Promiscuous-Mode geschaltet werden soll (Alle Pakete empfangen, nicht nur Broadcasts und die für die eigene MAC-Adresse), sonst 0x0000. „receive_length“ gibt die Anzahl der Empfangsdeskriptoren an, dazu später. „transfer_length“ enthält im Gegensatz dazu die Anzahl der Sendedeskriptoren. Beide Werte können auf 3 gesetzt werden, dies entspricht jeweils acht Deskriptoren. „physical_address“ enthält die MAC-Adresse der Karte. „logical_address“ kann auf 0 gesetzt werden. „receive_descriptor“ enthält die physische Adresse zu einem 2-kB-Puffer, „transmit_descriptor“ zu einem anderen. Beide Puffer müssen physisch kontinuierlich sein und an 16-Bytes-Grenzen ausgerichtet. | ||
7. Jetzt müssen die Empfangs- und Sendedeskriptoren initialisiert werden. So ein Deskriptor sieht so aus: | 7. Jetzt müssen die Empfangs- und Sendedeskriptoren initialisiert werden. So ein Deskriptor sieht so aus: | ||
| − | <c>struct descriptor | + | <syntaxhighlight lang=c>struct descriptor |
{ | { | ||
uint32_t address; | uint32_t address; | ||
| Zeile 56: | Zeile 59: | ||
uint32_t flags2; | uint32_t flags2; | ||
uint32_t avail; | uint32_t avail; | ||
| − | } __attribute__((packed));</ | + | } __attribute__((packed));</syntaxhighlight> |
„address“ gibt die physische Adresse eines 2-kB-Puffers (physisch kontinuierlich) an, „flags“ und „flags2“ enthalten Flags (siehe unten), „avail“ kann vom Benutzer (also von dir) frei verwendet werden. Bei den Empfangsdeskriptoren muss das OWN-Bit (0x80000000) im „flags“-Feld gesetzt werden, zudem müssen die Bits 0 bis 11 des „flags“-Feldes auf 0x7FF gesetzt werden (negative Länge des Puffers, also -2048). Außerdem müssen in beiden Deskriptortypen die Bits 12 bis 15 (0x0000F000) im „flags“-Feld gesetzt werden. Die acht Empfangsdeskriptoren müssen hintereinander in den Puffer geschrieben werden, der in das „receive_descriptor“-Feld des Initialization Blocks eingetragen wurde. Die acht Sendedeskriptoren müssen analog dazu in den Puffer geschrieben werden, der in das „transmit_descriptor“-Feld eingetragen wurde. | „address“ gibt die physische Adresse eines 2-kB-Puffers (physisch kontinuierlich) an, „flags“ und „flags2“ enthalten Flags (siehe unten), „avail“ kann vom Benutzer (also von dir) frei verwendet werden. Bei den Empfangsdeskriptoren muss das OWN-Bit (0x80000000) im „flags“-Feld gesetzt werden, zudem müssen die Bits 0 bis 11 des „flags“-Feldes auf 0x7FF gesetzt werden (negative Länge des Puffers, also -2048). Außerdem müssen in beiden Deskriptortypen die Bits 12 bis 15 (0x0000F000) im „flags“-Feld gesetzt werden. Die acht Empfangsdeskriptoren müssen hintereinander in den Puffer geschrieben werden, der in das „receive_descriptor“-Feld des Initialization Blocks eingetragen wurde. Die acht Sendedeskriptoren müssen analog dazu in den Puffer geschrieben werden, der in das „transmit_descriptor“-Feld eingetragen wurde. | ||
| Zeile 68: | Zeile 71: | ||
=== Konstanten === | === Konstanten === | ||
| − | <c>//Die Werte, auf die RAP gesetzt werden muss, um dieses Register zu benutzen | + | <syntaxhighlight lang=c>//Die Werte, auf die RAP gesetzt werden muss, um dieses Register zu benutzen |
#define CSR0 0 | #define CSR0 0 | ||
#define CSR1 1 | #define CSR1 1 | ||
| Zeile 88: | Zeile 91: | ||
#define RAP 0x12 | #define RAP 0x12 | ||
#define RESET 0x14 | #define RESET 0x14 | ||
| − | #define BDP 0x16</ | + | #define BDP 0x16</syntaxhighlight> |
=== Die ISR === | === Die ISR === | ||
| Zeile 131: | Zeile 134: | ||
Dazu ein Codebeispiel: | Dazu ein Codebeispiel: | ||
| − | <c>void write_csr(struct pcnet_card *ncard, uint16_t csr, uint16_t val) | + | <syntaxhighlight lang=c>void write_csr(struct pcnet_card *ncard, uint16_t csr, uint16_t val) |
{ | { | ||
outw(ncard->port_base + RAP, csr); | outw(ncard->port_base + RAP, csr); | ||
| Zeile 165: | Zeile 168: | ||
ncard->linear_transmit_descriptor[current_descriptor].flags = 0x8300F000 | ((-length) & 0xFFF); | ncard->linear_transmit_descriptor[current_descriptor].flags = 0x8300F000 | ((-length) & 0xFFF); | ||
write_csr(ncard, CSR0, 0x48); | write_csr(ncard, CSR0, 0x48); | ||
| − | }</ | + | }</syntaxhighlight> |
=== Empfangen von Paketen === | === Empfangen von Paketen === | ||
| Zeile 173: | Zeile 176: | ||
Beispielcode: | Beispielcode: | ||
| − | <c>size_t size_of_packet; | + | <syntaxhighlight lang=c>size_t size_of_packet; |
while ((ncard->linear_receive_descriptor[ncard->receive_descriptor].flags & 0x80000000) == 0) | while ((ncard->linear_receive_descriptor[ncard->receive_descriptor].flags & 0x80000000) == 0) | ||
| Zeile 189: | Zeile 192: | ||
if (netcard->last_receive_descriptor == 8) | if (netcard->last_receive_descriptor == 8) | ||
netcard->last_receive_descriptor = 0; | netcard->last_receive_descriptor = 0; | ||
| − | }</ | + | }</syntaxhighlight> |