Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
soc:2008:mdeck:notes:gpxe_driver_api [2008/05/29 07:38] mdeck |
soc:2008:mdeck:notes:gpxe_driver_api [2009/11/03 08:58] (current) meteger |
||
---|---|---|---|
Line 7: | Line 7: | ||
Note the [[:dev:netdriverapi|previous driver model]] of Etherboot is deprecated. | Note the [[:dev:netdriverapi|previous driver model]] of Etherboot is deprecated. | ||
Existing Etherboot PCI drivers are temporarily supported via the compatibility layer in src/drivers/net/legacy.c | Existing Etherboot PCI drivers are temporarily supported via the compatibility layer in src/drivers/net/legacy.c | ||
- | Drivers conforming to the gPXE Network Driver API are: | + | Drivers currently conforming to the gPXE Network Driver API are: |
+ | * 3c90x | ||
+ | * ath5k | ||
+ | * atl1e | ||
+ | * b44 | ||
* e1000 | * e1000 | ||
+ | * etherfabric | ||
+ | * mtnic | ||
* natsemi | * natsemi | ||
+ | * phantom | ||
+ | * pnic | ||
+ | * r8169 | ||
* rtl8139 | * rtl8139 | ||
+ | * rtl818x | ||
+ | * sis190 | ||
+ | * sky2 | ||
===== gPXE PCI Device Driver API ===== | ===== gPXE PCI Device Driver API ===== | ||
- | A PCI driver provides its API routines to gPXE via a ''struct pci_driver'': | + | A PCI driver provides its API routines to gPXE via a ''struct pci_driver''. For example, in natsemi.c: |
<code c> | <code c> | ||
struct pci_driver natsemi_driver __pci_driver = { | struct pci_driver natsemi_driver __pci_driver = { | ||
Line 40: | Line 51: | ||
- Initialize [[#EEPROM|EEPROM]]. | - Initialize [[#EEPROM|EEPROM]]. | ||
- Read the MAC address from EEPROM. | - Read the MAC address from EEPROM. | ||
- | - Mark the ''net_device'' as having a link up with ''netdev_link_up()'', as we don't yet handle the link state. | + | - Check the link state and report ''netdev_link_up()'' if connected. Many drivers don't yet handle the link state and simply assume the link is up. |
- Name the device and add it to the list of network devices via ''register_netdev()''. | - Name the device and add it to the list of network devices via ''register_netdev()''. | ||
- Possibly setup a non-volatile stored options block with ''nvo_init()'' & ''register_nvo()''. | - Possibly setup a non-volatile stored options block with ''nvo_init()'' & ''register_nvo()''. | ||
Line 69: | Line 80: | ||
</code> | </code> | ||
Here, natsemi_open/close/etc are driver implementations of the required network driver API functions: | Here, natsemi_open/close/etc are driver implementations of the required network driver API functions: | ||
- | * ''[[#open|static int open ( struct net_device* )]]'' | ||
* ''[[#close|static void close ( struct net_device* )]]'' | * ''[[#close|static void close ( struct net_device* )]]'' | ||
+ | * ''[[#open|static int open ( struct net_device* )]]'' | ||
* ''[[#transmit|static int transmit ( struct net_device*, struct io_buffer* )]]'' | * ''[[#transmit|static int transmit ( struct net_device*, struct io_buffer* )]]'' | ||
* ''[[#poll|static void poll ( struct net_device* )]]'' | * ''[[#poll|static void poll ( struct net_device* )]]'' | ||
* ''[[#irq|static void irq ( struct net_device*, int enable )]]'' | * ''[[#irq|static void irq ( struct net_device*, int enable )]]'' | ||
+ | |||
+ | ==== close ==== | ||
+ | ''static void close ( struct net_device* )''\\ | ||
+ | This function is called if the device is open in ''autoboot()'' during [[:soc:2008:mdeck:notes:initialization|initialization]], after a failed or successful attempt to boot the network device. In this routine, a typical driver might: | ||
+ | - Acknowledge interrupts. | ||
+ | - Disable irq, receives. | ||
+ | - Reset the device. | ||
+ | - Free any used resources (e.g. rx/tx rings, dma buffers, etc). | ||
==== open ==== | ==== open ==== | ||
''static int open ( struct net_device* )''\\ | ''static int open ( struct net_device* )''\\ | ||
- | This function is called after ''probe()'' during [[:soc:2008:mdeck:notes:initialization|initialization]]. A driver would: | + | This function is first called in ''netboot()'' when attempting a device boot during [[:soc:2008:mdeck:notes:initialization|initialization]], after ''close()'' of any previous device attempt is called. A driver would: |
- Program MAC address to device. | - Program MAC address to device. | ||
- Setup TX & RX rings. | - Setup TX & RX rings. | ||
- Perform other configuration (e.g. filters, bursts, interrupts). | - Perform other configuration (e.g. filters, bursts, interrupts). | ||
- Enable RX and TX. | - Enable RX and TX. | ||
- | |||
- | ==== close ==== | ||
- | ''static void close ( struct net_device* )''\\ | ||
- | In this function, a typical driver might: | ||
- | - Acknowledge interrupts. | ||
- | - Disable irq, receives. | ||
- | - Reset the device. | ||
- | - Free any used resources (e.g. rx/tx rings, dma buffers, etc). | ||
==== transmit ==== | ==== transmit ==== | ||
Line 102: | Line 113: | ||
==== poll ==== | ==== poll ==== | ||
''static void poll ( struct net_device* )''\\ | ''static void poll ( struct net_device* )''\\ | ||
- | This function is called periodically to process tx completions and rx packets. A typical driver would: | + | This function is called periodically by the network stack to process tx completions and rx packets. A typical driver would: |
- Acknowledge interrupts. | - Acknowledge interrupts. | ||
- | - Feed tx completions to ''netdev_tx_complete()'' or ''netdev_tx_complete_err()''. | + | - Check hardware and feed tx completions to ''netdev_tx_complete()'' or ''netdev_tx_complete_err()''. |
- | - Add good received packets to receive queue with ''netdev_rx()'', or feed corrupted packets to ''netdev_rx_err()'' | + | - Add good received packets to receive queue with ''netdev_rx()'', or report corrupted packets to ''netdev_rx_err()'' |
+ | - Check link state occasionally, and report changes with ''netdev_link_up()'' or ''netdev_link_down()'' | ||
==== irq ==== | ==== irq ==== | ||
Line 111: | Line 123: | ||
In this function, a typical driver will: | In this function, a typical driver will: | ||
- Enable interrupts if the int parameter is non-zero | - Enable interrupts if the int parameter is non-zero | ||
+ | Note the //force interrupt// behavior from Etherboot is deprecated. | ||
Line 123: | Line 135: | ||
- A ''struct spi_device'' is initialized (EEPROM-model dependent). | - A ''struct spi_device'' is initialized (EEPROM-model dependent). | ||
- Bus is copied: ''spidev.bus = &spibb.bus'' | - Bus is copied: ''spidev.bus = &spibb.bus'' | ||
- | - EITHER | + | - If non-volatile options will be utilized: |
+ | - Call ''nvo_init(&nvob, &spidev.nvs, nvof, ..)'' where ''nvof'' is an array of ''struct nvo_fragment''s that specify the usable regions. This will also initialize a settings block. | ||
+ | - Else, if non-volatile options will //not// be used: | ||
- Initialize a ''struct nvo_block'' with ''nvob.nvs = &spidev.nvs'' | - Initialize a ''struct nvo_block'' with ''nvob.nvs = &spidev.nvs'' | ||
- Assign usable regions via ''nvob.fragments = nvof'' where ''nvof'' is an array of ''struct nvo_fragment''s that specify the usable regions. | - Assign usable regions via ''nvob.fragments = nvof'' where ''nvof'' is an array of ''struct nvo_fragment''s that specify the usable regions. | ||
- | - OR | ||
- | - Call ''nvo_init(&nvob, &spidev.nvs, nvof, ..)'' where ''nvof'' is an array of ''struct nvo_fragment''s that specify the usable regions. | ||
* Use ''nvs_read()'' to perform a serial read @ a specific address. | * Use ''nvs_read()'' to perform a serial read @ a specific address. | ||
* Use ''nvs_write()'' to perform a serial write @ a specific address. | * Use ''nvs_write()'' to perform a serial write @ a specific address. |