iPXE
|
UNDI network device driver. More...
#include <string.h>
#include <unistd.h>
#include <byteswap.h>
#include <pxe.h>
#include <realmode.h>
#include <pic8259.h>
#include <biosint.h>
#include <pnpbios.h>
#include <basemem_packet.h>
#include <ipxe/io.h>
#include <ipxe/iobuf.h>
#include <ipxe/netdevice.h>
#include <ipxe/if_ether.h>
#include <ipxe/ethernet.h>
#include <ipxe/pci.h>
#include <ipxe/profile.h>
#include <undi.h>
#include <undinet.h>
Go to the source code of this file.
Data Structures | |
struct | undi_nic |
An UNDI NIC. More... | |
struct | undinet_profiler |
A PXE API call breakdown profiler. More... | |
struct | undinet_irq_broken |
A device with broken support for generating interrupts. More... | |
Macros | |
#define | EINFO_EPXECALL |
#define | EPXECALL(status) EPLATFORM ( EINFO_EPXECALL, status ) |
#define | UNDI_HACK_EB54 0x0001 |
Work around Etherboot 5.4 bugs. More... | |
#define | UNDI_INITIALIZE_RETRY_MAX 10 |
Maximum number of times to retry PXENV_UNDI_INITIALIZE. More... | |
#define | UNDI_INITIALIZE_RETRY_DELAY_MS 200 |
Delay between retries of PXENV_UNDI_INITIALIZE. More... | |
#define | UNDI_RX_QUOTA 4 |
Maximum number of received packets per poll. More... | |
#define | UNDI_RX_ALIGN 16 |
Alignment of received frame payload. More... | |
#define | undinet_params __use_data16 ( undinet_params ) |
#define | undinet_entry_point __use_data16 ( undinet_entry_point ) |
#define | RDTSC_IF_PROFILING "rdtsc\n\t" |
#define | undiisr_irq __use_data16 ( undiisr_irq ) |
#define | undiisr_next_handler __use_data16 ( undiisr_next_handler ) |
#define | undiisr_trigger_count __use_data16 ( undiisr_trigger_count ) |
#define | undinet_tbd __use_data16 ( undinet_tbd ) |
#define | undinet_destaddr __use_data16 ( undinet_destaddr ) |
Functions | |
FILE_LICENCE (GPL2_OR_LATER) | |
static void | undinet_close (struct net_device *netdev) |
Close NIC. More... | |
static union u_PXENV_ANY | __bss16 (undinet_params) |
UNDI parameter block. More... | |
SEGOFF16_t | __bss16 (undinet_entry_point) |
UNDI entry point. More... | |
static const char * | undinet_function_name (unsigned int function) |
Name PXE API call. More... | |
static struct undinet_profiler * | undinet_profiler (unsigned int function) |
Determine applicable profiler pair (for debugging) More... | |
static int | undinet_call (struct undi_nic *undinic, unsigned int function, void *params, size_t params_len) |
Issue UNDI API call. More... | |
void | undiisr (void) |
UNDI interrupt service routine. More... | |
uint8_t | __data16 (undiisr_irq) |
IRQ number. More... | |
struct segoff | __data16 (undiisr_next_handler) |
IRQ chain vector. More... | |
volatile uint8_t | __data16 (undiisr_trigger_count)=0 |
IRQ trigger count. More... | |
static void | undinet_hook_isr (unsigned int irq) |
Hook UNDI interrupt service routine. More... | |
static void | undinet_unhook_isr (unsigned int irq) |
Unhook UNDI interrupt service routine. More... | |
static int | undinet_isr_triggered (void) |
Test to see if UNDI ISR has been triggered. More... | |
static struct s_PXENV_UNDI_TBD | __data16 (undinet_tbd) |
UNDI transmit buffer descriptor. More... | |
static uint8_t | __data16_array (undinet_destaddr, [ETH_ALEN]) |
UNDI transmit destination address. More... | |
static int | undinet_transmit (struct net_device *netdev, struct io_buffer *iobuf) |
Transmit packet. More... | |
static void | undinet_poll (struct net_device *netdev) |
Poll for received packets. More... | |
static int | undinet_open (struct net_device *netdev) |
Open NIC. More... | |
static void | undinet_irq (struct net_device *netdev, int enable) |
Enable/disable interrupts. More... | |
static int | undinet_irq_is_broken (struct device_description *desc) |
Check for devices with broken support for generating interrupts. More... | |
int | undinet_probe (struct undi_device *undi, struct device *dev) |
Probe UNDI device. More... | |
void | undinet_remove (struct undi_device *undi) |
Remove UNDI device. More... | |
Variables | |
static struct profiler undinet_irq_profiler | __profiler |
IRQ profiler. More... | |
static unsigned int | last_trigger_count = 0 |
Last observed trigger count. More... | |
static struct net_device_operations | undinet_operations |
UNDI network device operations. More... | |
static const struct undinet_irq_broken | undinet_irq_broken_list [] |
List of devices with broken support for generating interrupts. More... | |
UNDI network device driver.
Definition in file undinet.c.
#define EINFO_EPXECALL |
#define EPXECALL | ( | status | ) | EPLATFORM ( EINFO_EPXECALL, status ) |
#define UNDI_INITIALIZE_RETRY_MAX 10 |
#define UNDI_INITIALIZE_RETRY_DELAY_MS 200 |
#define UNDI_RX_QUOTA 4 |
#define UNDI_RX_ALIGN 16 |
#define undinet_params __use_data16 ( undinet_params ) |
#define undinet_entry_point __use_data16 ( undinet_entry_point ) |
#define undiisr_irq __use_data16 ( undiisr_irq ) |
#define undiisr_next_handler __use_data16 ( undiisr_next_handler ) |
#define undiisr_trigger_count __use_data16 ( undiisr_trigger_count ) |
#define undinet_tbd __use_data16 ( undinet_tbd ) |
#define undinet_destaddr __use_data16 ( undinet_destaddr ) |
FILE_LICENCE | ( | GPL2_OR_LATER | ) |
|
static |
Close NIC.
netdev | Net device |
Definition at line 752 of file undinet.c.
References DBGC, disable_irq, s_PXENV_UNDI_ISR::FuncFlag, undi_nic::irq, undi_nic::isr_processing, netdev, net_device::priv, PXENV_UNDI_CLOSE, PXENV_UNDI_ISR, PXENV_UNDI_ISR_IN_GET_NEXT, PXENV_UNDI_ISR_OUT_RECEIVE, PXENV_UNDI_ISR_OUT_TRANSMIT, rc, undinet_call(), and undinet_unhook_isr().
Referenced by undinet_open().
|
static |
UNDI parameter block.
Used as the parameter block for all UNDI API calls. Resides in base memory.
SEGOFF16_t __bss16 | ( | undinet_entry_point | ) |
UNDI entry point.
Used as the indirection vector for all UNDI API calls. Resides in base memory.
|
inlinestatic |
Name PXE API call.
function | API call number |
name | API call name |
Definition at line 189 of file undinet.c.
References PXENV_GET_CACHED_INFO, PXENV_START_UNDI, PXENV_STOP_UNDI, PXENV_UNDI_CLEANUP, PXENV_UNDI_CLEAR_STATISTICS, PXENV_UNDI_CLOSE, PXENV_UNDI_FORCE_INTERRUPT, PXENV_UNDI_GET_IFACE_INFO, PXENV_UNDI_GET_INFORMATION, PXENV_UNDI_GET_MCAST_ADDRESS, PXENV_UNDI_GET_NIC_TYPE, PXENV_UNDI_GET_STATISTICS, PXENV_UNDI_INITIALIZE, PXENV_UNDI_INITIATE_DIAGS, PXENV_UNDI_ISR, PXENV_UNDI_OPEN, PXENV_UNDI_RESET_ADAPTER, PXENV_UNDI_SET_MCAST_ADDRESS, PXENV_UNDI_SET_PACKET_FILTER, PXENV_UNDI_SET_STATION_ADDRESS, PXENV_UNDI_SHUTDOWN, PXENV_UNDI_STARTUP, and PXENV_UNDI_TRANSMIT.
Referenced by undinet_call().
|
static |
Determine applicable profiler pair (for debugging)
function | API call number |
profiler | Profiler |
Definition at line 254 of file undinet.c.
References PXENV_UNDI_ISR, PXENV_UNDI_TRANSMIT, and PXENV_UNKNOWN.
Referenced by undinet_call().
|
static |
Issue UNDI API call.
undinic | UNDI NIC |
function | API call number |
params | PXE parameter block |
params_len | Length of PXE parameter block |
rc | Return status code |
Definition at line 278 of file undinet.c.
References __asm__(), __from_data16, __volatile__(), after, assert(), before, DBGC, DBGC_HDA, discard_D, EPXECALL, memcpy(), profile_start(), profile_start_at(), profile_started(), profile_stop(), profile_stop_at(), profile_stopped(), PXENV_EXIT_SUCCESS, rc, RDTSC_IF_PROFILING, REAL_CODE, rm_ds, started, strerror(), undinet_entry_point, undinet_function_name(), undinet_params, and undinet_profiler().
Referenced by undinet_close(), undinet_open(), undinet_poll(), undinet_probe(), undinet_remove(), and undinet_transmit().
void undiisr | ( | void | ) |
UNDI interrupt service routine.
The UNDI ISR increments a counter (trigger_count
) and exits.
Referenced by undinet_hook_isr(), and undinet_unhook_isr().
uint8_t __data16 | ( | undiisr_irq | ) |
IRQ number.
struct segoff __data16 | ( | undiisr_next_handler | ) |
IRQ chain vector.
|
pure virtual |
IRQ trigger count.
|
static |
Hook UNDI interrupt service routine.
irq | IRQ number |
Definition at line 392 of file undinet.c.
References assert(), hook_bios_interrupt(), IRQ_INT, IRQ_MAX, undiisr(), undiisr_irq, and undiisr_next_handler.
Referenced by undinet_open().
|
static |
Unhook UNDI interrupt service routine.
irq | IRQ number |
Definition at line 407 of file undinet.c.
References assert(), IRQ_INT, IRQ_MAX, undiisr(), undiisr_irq, undiisr_next_handler, and unhook_bios_interrupt().
Referenced by undinet_close().
|
static |
Test to see if UNDI ISR has been triggered.
triggered | ISR has been triggered since last check |
Definition at line 421 of file undinet.c.
References last_trigger_count, and undiisr_trigger_count.
Referenced by undinet_poll().
|
static |
UNDI transmit buffer descriptor.
|
static |
UNDI transmit destination address.
|
static |
Transmit packet.
netdev | Network device |
iobuf | I/O buffer |
rc | Return status code |
Definition at line 459 of file undinet.c.
References __from_data16, basemem_packet, io_buffer::data, DBGC, s_PXENV_UNDI_TRANSMIT::DestAddr, done, ETH_P_ARP, ETH_P_IP, ETH_P_RARP, eth_pull(), flags, htons, iob_len(), iob_push, len, LL_BROADCAST, memcpy(), memset(), netdev, netdev_tx_complete(), P_ARP, P_IP, P_RARP, P_UNKNOWN, net_device::priv, protocol, s_PXENV_UNDI_TRANSMIT::Protocol, PXENV_UNDI_TRANSMIT, rc, rm_ds, strerror(), s_PXENV_UNDI_TRANSMIT::TBD, undinet_call(), undinet_destaddr, undinet_tbd, s_PXENV_UNDI_TRANSMIT::XmitFlag, XMT_BROADCAST, and XMT_DESTADDR.
|
static |
Poll for received packets.
netdev | Network device |
Fun, fun, fun. UNDI drivers don't use polling; they use interrupts. We therefore cheat and pretend that an interrupt has occurred every time undinet_poll() is called. This isn't too much of a hack; PCI devices share IRQs and so the first thing that a proper ISR should do is call PXENV_UNDI_ISR to determine whether or not the UNDI NIC generated the interrupt; there is no harm done by spurious calls to PXENV_UNDI_ISR. Similarly, we wouldn't be handling them any more rapidly than the usual rate of undinet_poll() being called even if we did implement a full ISR. So it should work. Ha!
Addendum (21/10/03). Some cards don't play nicely with this trick, so instead of doing it the easy way we have to go to all the hassle of installing a genuine interrupt service routine and dealing with the wonderful 8259 Programmable Interrupt Controller. Joy.
Addendum (10/07/07). When doing things such as iSCSI boot, in which we have to co-operate with a running OS, we can't get away with the "ISR-just-increments-a-counter-and-returns" trick at all, because it involves tying up the PIC for far too long, and other interrupt-dependent components (e.g. local disks) start breaking. We therefore implement a "proper" ISR which calls PXENV_UNDI_ISR from within interrupt context in order to deassert the device interrupt, and sends EOI if applicable.
Definition at line 573 of file undinet.c.
References __asm__(), __volatile__(), alloc_iob(), s_PXENV_UNDI_ISR::BufferLength, copy_from_real, DBGC, done, EINVAL, ENOMEM, s_PXENV_UNDI_ISR::Frame, s_PXENV_UNDI_ISR::FrameHeaderLength, s_PXENV_UNDI_ISR::FrameLength, s_PXENV_UNDI_ISR::FuncFlag, undi_nic::hacks, iob_disown, iob_len(), iob_put, iob_reserve, iob_tailroom(), undi_nic::irq_supported, undi_nic::isr_processing, last_trigger_count, len, netdev, netdev_rx(), netdev_rx_err(), NULL, net_device::priv, profile_start(), profile_stop(), PXENV_UNDI_ISR, PXENV_UNDI_ISR_IN_GET_NEXT, PXENV_UNDI_ISR_IN_PROCESS, PXENV_UNDI_ISR_OUT_DONE, PXENV_UNDI_ISR_OUT_RECEIVE, PXENV_UNDI_ISR_OUT_TRANSMIT, rc, UNDI_HACK_EB54, UNDI_RX_ALIGN, UNDI_RX_QUOTA, undinet_call(), and undinet_isr_triggered().
|
static |
Open NIC.
netdev | Net device |
rc | Return status code |
Definition at line 705 of file undinet.c.
References DBGC, enable_irq, FLTR_BRDCST, FLTR_DIRECTED, FLTR_PRMSCS, undi_nic::irq, net_device::ll_addr, memcpy(), memset(), netdev, s_PXENV_UNDI_OPEN::PktFilter, net_device::priv, PXENV_UNDI_OPEN, PXENV_UNDI_SET_STATION_ADDRESS, rc, send_eoi(), s_PXENV_UNDI_SET_STATION_ADDRESS::StationAddress, undinet_call(), undinet_close(), and undinet_hook_isr().
|
static |
Enable/disable interrupts.
netdev | Net device |
enable | Interrupts should be enabled |
Definition at line 795 of file undinet.c.
References DBGC, netdev, and net_device::priv.
|
static |
Check for devices with broken support for generating interrupts.
desc | Device description |
irq_is_broken | Interrupt support is broken; no interrupts are generated |
Definition at line 849 of file undinet.c.
References BUS_TYPE_PCI, desc, PCI_ANY_ID, undinet_irq_broken::pci_device, pci_init(), pci_read_config_word(), undinet_irq_broken::pci_subsys, undinet_irq_broken::pci_subsys_vendor, PCI_SUBSYSTEM_ID, PCI_SUBSYSTEM_VENDOR_ID, undinet_irq_broken::pci_vendor, and undinet_irq_broken_list.
Referenced by undinet_probe().
int undinet_probe | ( | struct undi_device * | undi, |
struct device * | dev | ||
) |
Probe UNDI device.
undi | UNDI device |
dev | Underlying generic device |
rc | Return status code |
Definition at line 888 of file undinet.c.
References alloc_etherdev(), s_PXENV_START_UNDI::AX, BIOS_SEG, s_PXENV_START_UNDI::BX, s_PXENV_UNDI_GET_INFORMATION::CurrentNodeAddress, DBGC, device::desc, net_device::dev, s_PXENV_START_UNDI::DI, s_PXENV_START_UNDI::DX, ENOMEM, undi_device::entry, s_PXENV_START_UNDI::ES, ETH_ALEN, eth_ntoa(), find_pnp_bios(), undi_device::flags, undi_nic::hacks, net_device::hw_addr, s_PXENV_UNDI_GET_IFACE_INFO::IfaceType, s_PXENV_UNDI_GET_INFORMATION::IntNumber, undi_nic::irq, IRQ_MAX, undi_nic::irq_supported, undi_device::isapnp_csn, undi_device::isapnp_read_port, s_PXENV_UNDI_GET_IFACE_INFO::LinkSpeed, net_device::ll_addr, mdelay(), memcpy(), memset(), netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), NULL, undi_device::pci_busdevfn, s_PXENV_UNDI_GET_INFORMATION::PermNodeAddress, net_device::priv, PXENV_START_UNDI, PXENV_STOP_UNDI, PXENV_UNDI_CLEANUP, PXENV_UNDI_GET_IFACE_INFO, PXENV_UNDI_GET_INFORMATION, PXENV_UNDI_INITIALIZE, PXENV_UNDI_SHUTDOWN, PXENV_UNDI_STARTUP, rc, register_netdev(), s_PXENV_UNDI_GET_IFACE_INFO::ServiceFlags, strncmp(), SUPPORTED_IRQ, UNDI_FL_INITIALIZED, UNDI_FL_STARTED, UNDI_HACK_EB54, UNDI_INITIALIZE_RETRY_DELAY_MS, UNDI_INITIALIZE_RETRY_MAX, undi_set_drvdata(), undinet_call(), undinet_entry_point, undinet_irq_is_broken(), and undinet_operations.
Referenced by undibus_probe(), and undipci_probe().
void undinet_remove | ( | struct undi_device * | undi | ) |
Remove UNDI device.
undi | UNDI device |
Definition at line 1042 of file undinet.c.
References DBGC, undi_device::flags, memset(), netdev, netdev_nullify(), netdev_put(), net_device::priv, PXENV_STOP_UNDI, PXENV_UNDI_CLEANUP, PXENV_UNDI_SHUTDOWN, UNDI_FL_INITIALIZED, UNDI_FL_KEEP_ALL, UNDI_FL_STARTED, undi_get_drvdata(), undinet_call(), undinet_entry_point, and unregister_netdev().
Referenced by undibus_remove(), and undipci_remove().
|
static |
IRQ profiler.
Miscellaneous PXE API call profiler.
PXE unknown API call profiler.
PXENV_UNDI_ISR profiler.
PXENV_UNDI_TRANSMIT profiler.
Receive profiler.
Note that this profiler will not see calls to PXENV_UNDI_ISR_IN_START, which are handled by the UNDI ISR and do not go via undinet_call().
This profiler can be used to measure the overhead of a dummy PXE API call.
|
static |
Last observed trigger count.
Definition at line 385 of file undinet.c.
Referenced by undinet_isr_triggered(), and undinet_poll().
|
static |
UNDI network device operations.
Definition at line 804 of file undinet.c.
Referenced by undinet_probe().
|
static |
List of devices with broken support for generating interrupts.
Some PXE stacks are known to claim that IRQs are supported, but then never generate interrupts. No satisfactory solution has been found to this problem; the workaround is to add the PCI vendor and device IDs to this list. This is something of a hack, since it will generate false positives for identical devices with a working PXE stack (e.g. those that have been reflashed with iPXE), but it's an improvement on the current situation.
Definition at line 835 of file undinet.c.
Referenced by undinet_irq_is_broken().