Să se scrie un driver pentru placa de rețea Intel 82559ER (device întâlnit şi sub numele de e100 sau eepro100). Modulul va trebui să suporte device-urile de rețea configurate în maşina virtuală qemu. Specificațiile se gasesc in documentul:
Nu va trebui să ciți în întregime documentul de mai sus, ci doar secțiunile indicate în enunț.
$ LABS=assignments/6-e100 make skels
Urmăriți comentariile marcate cu TODO 1:
struct pci_driver
şi inițializați următoarele câmpuri.name
- numele driverului, acesta va fi inițializat cu valoarea e100-ix
.id_table
- structură care identifică unic deviceul e100 în sistem. Vendor ID şi device ID vor fi găsite în secțiunea 4 din manualul dezvoltatorului..probe
- funcție apelată de subsystemul PCI din kernel atunci când în urma parcurgerii device-urilor din sistem se va găsi un device cu identitatea dată de .id_table
..remove
- funcție apelată atunci când driver-ul sau device-ul sunt scoase din sistem.init
a modulului înregistrați structura pci_driver
. Operația aceasta va avea ca efect apelarea funcției probe
exit
a modului deînregistrați structura pci_driver
. Operația aceasta va avea ca efect apelarea funcției remove
În acest moment puteți testa daca device-ul de rețea este enumerat pe magistrala de PCI (observați dacă se apelează funcția probe).
Magistrala PCI conține linii de date, adrese și întreruperi și permite procesorului să comunice cu device-urile conectate. După ce un device este descoperit (enumerat) pe magistrala PCI este nevoie să fie inițializat. În procesul de inițializare vom aloca spațiul de I/O și memorie și vom obține linia de întrerupere folosită.
Urmăriți comentariile marcate cu TODO 2:
pci_enable_device
(activeaza I/O și memoria și trezește device-ul dacă era suspendat)
Structura e100_priv_data
va contine informatii specifice fiecarui device de retea gestionat de driver. În primul rând va conține informații despre pci_dev și netdevice-ul curent, apoi informatii de stare, registre, unitatea de transmisie, unitatea de recepție, etc. Spațiul de memorie pentru e100_priv_data
se va aloca în funcția alloc_etherdev
urmăriți sectiunea structura_net_device.
Pentru a adauga câmpuri noi în structura e100_priv_data urmăriți TODO 3.
Este reprezentarea din kernel a interfeței de rețea din user-space (ixeth0
, ixeth1
, ș.a.m.d)
Urmăriți comentariile marcate cu TODO 4:
probe
) atunci când se descoperă un device de rețea pe magistrala PCIalloc etherdev
pentru a aloca memoriendo_open
, ndo_stop
şi ndo_start_xmit
din câmpul netdev_ops
register_netdev
pentru înregistrareremove
) atunci când device-ul sau modulul sunt înlăturateunregister_netdev
pentru deînregistrarefree_netdev
pentru eliberare de memoriee100 conține două unități funcționale descrise in capitolul 6.5 din manualul dezvoltatorului. Aceste unități funcționează ca două procesoare independente și îndeplinesc următoarele roluri:
Driverul comunică cu unitățile CU și RU prin intermediul registrului CSR (Command Register) și prin intermediul DMA rings.
.ndo_start_xmit
Driverul trebuie sa construiasca un ring DMA in RAM pentru a instrui device-ul e100 unde se găsesc pachetele pe care dorește să le trimită. Secțiunea 6.4 din manual descrie formatul unui DMA ring.
Un ring DMA de control este alcătuit din buffere denumite Control Blocks (CB). Un CB generic arată astfel:
+--------------+--------------+ | CONTROL | STATUS | +--------------+--------------+ | LINK | +--------------+--------------+ | COMMAND SPECIFIC DATA | +--------------+--------------+
Mai multe detalii despre trimiterea pachetelor citiți in secțiunea Transmitting Packets
de aici. Urmăriți comentariile marcate cu TODO 5.
e100
copiază datele într-o zonă DMA şi generează o întrerupere pentru a informa procesorul de sosirea unui nou pachet.Un al doilea DMA ring este necesar pentru recepționarea pachetelor. Fiecare buffer din DMA ring-ul de recepție este denumit RFD (Receive Frame Descriptor).
Unitatea de recepție (RU) se ocupă de primirea pachetelor. La primirea unui pachet din rețea, copiaza pachetul în urmator-ul RFD liber, marchează RFD-ul valid și se mută la următorul RFD.
Mai multe detalii despre trimiterea pachetelor citiți in secțiunea Receiving Packets
de aici. Urmăriți comentariile cu TODO 6.
Antetul e100 conține descrierea in memorie a structurilor importante expuse de device-ul e100.
struct csr
, Control/Status Register descris in secțiunea 6.3.1struct tcb
, Transmit Command Block descris in secțiunea 6.4.2.5struct cb
, descrie un Command Block generic.Pentru simplificarea procesului de corectare a temelor, dar și pentru a reduce greșelile temelor trimise, corectarea temelor se va face automat cu ajutorul unor teste publice.
Pentru a vă mări șansele de a obține nota maximă, citiți și respectați coding style-ul kernelului Linux descris din documentul Coding Style.
De asemenea, folosiți următoarele tool-uri de analiza statică pentru a verifica codul:
/path/to/linux-4.9.11/scripts/checkpatch.pl --no-tree --terse -f /path/to/your/src-file.c
sudo apt-get install sparse
cd /path/to/linux-4.9.11 make C=2 /path/to/your/src-file.c
sudo apt-get install cppcheck
cppcheck /path/to/your/src-file.c
Tema valorează 2 puncte.
Depunctările generale pentru teme se găsesc pe pagina de Indicații generale.
În cazuri excepționale (tema trece testele prin nerespectarea cerințelor) și în cazul în care tema nu trece toate testele se poate scădea mai mult decât este menționat mai sus.
Arhiva temei va fi submisă pe vmchecker, în conformitate cu precizările din pagina de reguli.
Din interfața vmchecker alegeți opțiunea e100 Driver
, aferentă acestei teme.
dev_addr
din structura net_device
înaintea înregistrării netdevice-ului în kernel (register_netdevice
) în funcția probe
.Pentru întrebări legate de temă puteți consulta arhivele listei de discuții sau puteți trimite un e-mail (trebuie să fiți înregistrați). Vă rugăm să urmăriți și să respectați indicațiile de utilizare a listei.