−Table of Contents
gPXE Network Driver Initialization
What happens when gPXE starts up?
How does a network driver get initialized?
Let's follow the call stack at key points from instantiation.
Reaching probe
- src/core/main.c »
main()– Entry point. - src/core/init.c »
startup() - src/core/device.c »
probe_devices()– Probe buses sequentially. - src/core/device.c »
rootdev_probe()– Probe this bus. {struct root_device}->driver->probe()== src/drivers/bus/pci.c »pcibus_probe()– Probe PCI devices sequentially.- src/drivers/bus/pci.c »
pci_probe()– Probe this device. {struct pci_driver}->probe()== src/drivers/net/NAME.c »NAME_probe()– The network driver'sprobe()routine is finally reached.
At this point netdev_init() associates netdev with driver functions.
register_netdev() adds to the device list.
We return up the call stack to main().
Reaching close
- src/core/main.c »
main() - src/usr/autoboot.c »
autoboot()– Boot network devices sequentially. - src/usr/autoboot.c »
close_all_netdevs() - src/usr/ifmgmt.c »
ifclose() - src/net/netdevice.c »
netdev_close() {struct net_device}->op->close()== src/drivers/net/NAME.c »NAME_close()– The network driver'sclose()routine is reached.
All network devices are closed before attempting to boot each network device.
We return up the call stack to autoboot().
Reaching open
- src/usr/autoboot.c »
autoboot()– Still booting network devices sequentially. - src/usr/autoboot.c »
netboot()– Boot this network device - src/usr/ifmgmt.c »
ifopen() - src/net/netdevice.c »
netdev_open() {struct net_device}->op->open()== src/drivers/net/NAME.c »NAME_open()– The network driver'sopen()routine is reached.
At this point transmit and receive are enabled.
root_device and pci_device structs
Both struct root_device and struct pci_device have a special function in gPXE. Bus drivers are root_devices, thus there is one for PCI, ISA, etc. PCI devices are self-explanatory. Both root_device and pci_device structs are defined within their respective driver code. These structs hold function pointers to essential interface routines, such as probe() and remove(). The __pci_driver and __root_driver tags cause the drivers to be added to a list of modules, resulting in their probe() routines being called during initialization.