iPXE
undinet.h File Reference

UNDI network device driver. More...

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int undinet_probe (struct undi_device *undi, struct device *dev)
 Probe UNDI device.
void undinet_remove (struct undi_device *undi)
 Remove UNDI device.

Detailed Description

UNDI network device driver.

Definition in file undinet.h.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ undinet_probe()

int undinet_probe ( struct undi_device * undi,
struct device * dev )
extern

Probe UNDI device.

Parameters
undiUNDI device
devUnderlying generic device
Return values
rcReturn status code

Definition at line 937 of file undinet.c.

937 {
938 struct net_device *netdev;
939 struct undi_nic *undinic;
940 struct s_PXENV_START_UNDI start_undi;
941 struct s_PXENV_UNDI_STARTUP undi_startup;
942 struct s_PXENV_UNDI_INITIALIZE undi_init;
943 struct s_PXENV_UNDI_GET_INFORMATION undi_info;
944 struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
945 struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
946 struct s_PXENV_UNDI_CLEANUP undi_cleanup;
947 struct s_PXENV_STOP_UNDI stop_undi;
948 unsigned int retry;
949 int rc;
950
951 /* Allocate net device */
952 netdev = alloc_etherdev ( sizeof ( *undinic ) );
953 if ( ! netdev )
954 return -ENOMEM;
956 undinic = netdev->priv;
957 undi_set_drvdata ( undi, netdev );
958 netdev->dev = dev;
959 memset ( undinic, 0, sizeof ( *undinic ) );
961 DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
962
963 /* Hook in UNDI stack */
964 if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
965 memset ( &start_undi, 0, sizeof ( start_undi ) );
966 start_undi.AX = undi->pci_busdevfn;
967 start_undi.BX = undi->isapnp_csn;
968 start_undi.DX = undi->isapnp_read_port;
969 start_undi.ES = BIOS_SEG;
970 start_undi.DI = find_pnp_bios();
971 if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
972 &start_undi,
973 sizeof ( start_undi ) ) ) != 0 )
974 goto err_start_undi;
975 }
976 undi->flags |= UNDI_FL_STARTED;
977
978 /* Bring up UNDI stack */
979 if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
980 memset ( &undi_startup, 0, sizeof ( undi_startup ) );
981 if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
982 &undi_startup,
983 sizeof ( undi_startup ) ) ) != 0 )
984 goto err_undi_startup;
985 /* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
986 * due to a transient condition (e.g. media test
987 * failing because the link has only just come out of
988 * reset). We may therefore need to retry this call
989 * several times.
990 */
991 for ( retry = 0 ; ; ) {
992 memset ( &undi_init, 0, sizeof ( undi_init ) );
993 if ( ( rc = undinet_call ( undinic,
995 &undi_init,
996 sizeof ( undi_init ) ) ) ==0)
997 break;
998 if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
999 goto err_undi_initialize;
1000 DBGC ( undinic, "UNDINIC %p retrying "
1001 "PXENV_UNDI_INITIALIZE (retry %d)\n",
1002 undinic, retry );
1003 /* Delay to allow link to settle if necessary */
1005 }
1006 }
1007 undi->flags |= UNDI_FL_INITIALIZED;
1008
1009 /* Get device information */
1010 memset ( &undi_info, 0, sizeof ( undi_info ) );
1011 if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
1012 &undi_info, sizeof ( undi_info ) ) ) != 0 )
1013 goto err_undi_get_information;
1014 memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
1015 memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
1016 undinic->irq = undi_info.IntNumber;
1017 if ( undinic->irq > IRQ_MAX ) {
1018 DBGC ( undinic, "UNDINIC %p ignoring invalid IRQ %d\n",
1019 undinic, undinic->irq );
1020 undinic->irq = 0;
1021 }
1022 DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
1023 undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
1024 if ( undinic->irq ) {
1025 /* Sanity check - prefix should have disabled the IRQ */
1026 assert ( ! irq_enabled ( undinic->irq ) );
1027 }
1028
1029 /* Get interface information */
1030 memset ( &undi_iface, 0, sizeof ( undi_iface ) );
1031 if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
1032 &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
1033 goto err_undi_get_iface_info;
1034 DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
1035 undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
1036 undi_iface.ServiceFlags );
1037 if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
1038 ( undinic->irq != 0 ) ) {
1039 undinic->irq_supported = 1;
1040 }
1041 DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
1042 ( undinic->irq_supported ? "interrupt" : "polling" ) );
1043 if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
1044 sizeof ( undi_iface.IfaceType ) ) == 0 ) {
1045 DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
1046 undinic );
1047 undinic->hacks |= UNDI_HACK_EB54;
1048 }
1049 if ( undinet_irq_is_broken ( netdev ) ) {
1050 DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
1051 "broken interrupts\n", undinic );
1052 undinic->irq_supported = 0;
1053 }
1054
1055 /* Register network device */
1056 if ( ( rc = register_netdev ( netdev ) ) != 0 )
1057 goto err_register;
1058
1059 /* Mark as link up; we don't handle link state */
1061
1062 DBGC ( undinic, "UNDINIC %p added\n", undinic );
1063 return 0;
1064
1065 err_register:
1066 err_undi_get_iface_info:
1067 err_undi_get_information:
1068 err_undi_initialize:
1069 /* Shut down UNDI stack */
1070 memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1071 undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
1072 sizeof ( undi_shutdown ) );
1073 memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1074 undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
1075 sizeof ( undi_cleanup ) );
1076 undi->flags &= ~UNDI_FL_INITIALIZED;
1077 err_undi_startup:
1078 /* Unhook UNDI stack */
1079 memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1080 undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1081 sizeof ( stop_undi ) );
1082 undi->flags &= ~UNDI_FL_STARTED;
1083 err_start_undi:
1085 netdev_put ( netdev );
1086 undi_set_drvdata ( undi, NULL );
1087 return rc;
1088}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:266
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:177
static struct net_device * netdev
Definition gdbudp.c:53
#define DBGC(...)
Definition compiler.h:530
#define ENOMEM
Not enough space.
Definition errno.h:578
#define PXENV_START_UNDI
PXE API function code for pxenv_start_undi().
Definition pxe_api.h:435
#define PXENV_STOP_UNDI
PXE API function code for pxenv_stop_undi().
Definition pxe_api.h:505
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup().
Definition pxe_api.h:841
#define PXENV_UNDI_GET_IFACE_INFO
PXE API function code for pxenv_undi_get_iface_info().
Definition pxe_api.h:1359
#define SUPPORTED_IRQ
Interrupt Request supported.
Definition pxe_api.h:1378
#define PXENV_UNDI_GET_INFORMATION
PXE API function code for pxenv_undi_get_information().
Definition pxe_api.h:1155
#define PXENV_UNDI_INITIALIZE
PXE API function code for pxenv_undi_initialize().
Definition pxe_api.h:860
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown().
Definition pxe_api.h:922
#define PXENV_UNDI_STARTUP
PXE API function code for pxenv_undi_startup().
Definition pxe_api.h:815
#define UNDI_HACK_EB54
Work around Etherboot 5.4 bugs.
Definition undinet.c:71
#define ETH_ALEN
Definition if_ether.h:9
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition netdevice.h:792
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:522
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:535
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:579
#define IRQ_MAX
Definition pic8259.h:60
int find_pnp_bios(void)
Locate Plug-and-Play BIOS.
Definition pnpbios.c:101
#define BIOS_SEG
Definition pnpbios.h:13
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition string.c:187
A network device.
Definition netdevice.h:353
Parameter block for pxenv_start_undi().
Definition pxe_api.h:438
Parameter block for pxenv_stop_undi().
Definition pxe_api.h:508
Parameter block for pxenv_undi_cleanup().
Definition pxe_api.h:844
Parameter block for pxenv_undi_get_iface_info().
Definition pxe_api.h:1381
Parameter block for pxenv_undi_get_information().
Definition pxe_api.h:1166
Parameter block for pxenv_undi_initialize().
Definition pxe_api.h:863
Parameter block for pxenv_undi_shutdown().
Definition pxe_api.h:925
Parameter block for pxenv_undi_startup().
Definition pxe_api.h:825
UINT16_t pci_busdevfn
PCI bus:dev.fn, or UNDI_NO_PCI_BUSDEVFN.
Definition undi.h:34
UINT16_t isapnp_csn
ISAPnP card select number, or UNDI_NO_ISAPNP_CSN.
Definition undi.h:36
UINT16_t isapnp_read_port
ISAPnP read port, or UNDI_NO_ISAPNP_READ_PORT.
Definition undi.h:38
UINT16_t flags
Flags.
Definition undi.h:54
SEGOFF16_t entry
Entry point.
Definition undi.h:28
An UNDI NIC.
Definition undinet.c:48
int hacks
Bug workarounds.
Definition undinet.c:56
unsigned int irq
Assigned IRQ number.
Definition undinet.c:52
int irq_supported
Device supports IRQs.
Definition undinet.c:50
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
static void undi_set_drvdata(struct undi_device *undi, void *priv)
Set UNDI driver-private data.
Definition undi.h:70
#define UNDI_FL_INITIALIZED
UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called.
Definition undi.h:99
#define UNDI_FL_STARTED
UNDI flag: START_UNDI has been called.
Definition undi.h:96
static int undinet_call(struct undi_nic *undinic, unsigned int function, void *params, size_t params_len)
Issue UNDI API call.
Definition undinet.c:278
static struct net_device_operations undinet_operations
UNDI network device operations.
Definition undinet.c:833
#define UNDI_INITIALIZE_RETRY_DELAY_MS
Delay between retries of PXENV_UNDI_INITIALIZE.
Definition undinet.c:79
#define UNDI_INITIALIZE_RETRY_MAX
Maximum number of times to retry PXENV_UNDI_INITIALIZE.
Definition undinet.c:76
#define undinet_entry_point
Definition undinet.c:105
static int undinet_irq_is_broken(struct net_device *netdev)
Check for devices with broken support for generating interrupts.
Definition undinet.c:880

References alloc_etherdev(), assert, s_PXENV_START_UNDI::AX, BIOS_SEG, s_PXENV_START_UNDI::BX, s_PXENV_UNDI_GET_INFORMATION::CurrentNodeAddress, DBGC, 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, 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, mdelay(), memcpy(), memset(), netdev, netdev_init(), netdev_link_up(), netdev_nullify(), netdev_put(), NULL, undi_device::pci_busdevfn, s_PXENV_UNDI_GET_INFORMATION::PermNodeAddress, 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 REQUIRING_SYMBOL(), undibus_probe(), and undipci_probe().

◆ undinet_remove()

void undinet_remove ( struct undi_device * undi)
extern

Remove UNDI device.

Parameters
undiUNDI device

Definition at line 1095 of file undinet.c.

1095 {
1096 struct net_device *netdev = undi_get_drvdata ( undi );
1097 struct undi_nic *undinic = netdev->priv;
1098 struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
1099 struct s_PXENV_UNDI_CLEANUP undi_cleanup;
1100 struct s_PXENV_STOP_UNDI stop_undi;
1101
1102 /* Unregister net device */
1104
1105 /* If we are preparing for an OS boot, or if we cannot exit
1106 * via the PXE stack, then shut down the PXE stack.
1107 */
1108 if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
1109
1110 /* Shut down UNDI stack */
1111 memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1113 &undi_shutdown, sizeof ( undi_shutdown ) );
1114 memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1116 &undi_cleanup, sizeof ( undi_cleanup ) );
1117 undi->flags &= ~UNDI_FL_INITIALIZED;
1118
1119 /* Unhook UNDI stack */
1120 memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1121 undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1122 sizeof ( stop_undi ) );
1123 undi->flags &= ~UNDI_FL_STARTED;
1124 }
1125
1126 /* Clear entry point */
1128
1129 /* Free network device */
1131 netdev_put ( netdev );
1132
1133 DBGC ( undinic, "UNDINIC %p removed\n", undinic );
1134}
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:946
#define UNDI_FL_KEEP_ALL
UNDI flag: keep stack resident.
Definition undi.h:102
static void * undi_get_drvdata(struct undi_device *undi)
Get UNDI driver-private data.
Definition undi.h:80

References DBGC, undi_device::flags, memset(), netdev, netdev_nullify(), netdev_put(), 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().