AMD PCnet — Änderungen 11245 → 11406

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));</c>
+
} __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));</c>
+
} __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</c>
+
#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);
−
}</c>
+
}</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;
−
}</c>
+
}</syntaxhighlight>