iPXE
Functions
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. More...
 
void undinet_remove (struct undi_device *undi)
 Remove UNDI device. More...
 

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 
)

Probe UNDI device.

Parameters
undiUNDI device
devUnderlying generic device
Return values
rcReturn status code

Definition at line 888 of file undinet.c.

888  {
889  struct net_device *netdev;
890  struct undi_nic *undinic;
891  struct s_PXENV_START_UNDI start_undi;
892  struct s_PXENV_UNDI_STARTUP undi_startup;
893  struct s_PXENV_UNDI_INITIALIZE undi_init;
894  struct s_PXENV_UNDI_GET_INFORMATION undi_info;
895  struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
896  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
897  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
898  struct s_PXENV_STOP_UNDI stop_undi;
899  unsigned int retry;
900  int rc;
901 
902  /* Allocate net device */
903  netdev = alloc_etherdev ( sizeof ( *undinic ) );
904  if ( ! netdev )
905  return -ENOMEM;
907  undinic = netdev->priv;
908  undi_set_drvdata ( undi, netdev );
909  netdev->dev = dev;
910  memset ( undinic, 0, sizeof ( *undinic ) );
911  undinet_entry_point = undi->entry;
912  DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
913 
914  /* Hook in UNDI stack */
915  if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
916  memset ( &start_undi, 0, sizeof ( start_undi ) );
917  start_undi.AX = undi->pci_busdevfn;
918  start_undi.BX = undi->isapnp_csn;
919  start_undi.DX = undi->isapnp_read_port;
920  start_undi.ES = BIOS_SEG;
921  start_undi.DI = find_pnp_bios();
922  if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
923  &start_undi,
924  sizeof ( start_undi ) ) ) != 0 )
925  goto err_start_undi;
926  }
927  undi->flags |= UNDI_FL_STARTED;
928 
929  /* Bring up UNDI stack */
930  if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
931  memset ( &undi_startup, 0, sizeof ( undi_startup ) );
932  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
933  &undi_startup,
934  sizeof ( undi_startup ) ) ) != 0 )
935  goto err_undi_startup;
936  /* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
937  * due to a transient condition (e.g. media test
938  * failing because the link has only just come out of
939  * reset). We may therefore need to retry this call
940  * several times.
941  */
942  for ( retry = 0 ; ; ) {
943  memset ( &undi_init, 0, sizeof ( undi_init ) );
944  if ( ( rc = undinet_call ( undinic,
946  &undi_init,
947  sizeof ( undi_init ) ) ) ==0)
948  break;
949  if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
950  goto err_undi_initialize;
951  DBGC ( undinic, "UNDINIC %p retrying "
952  "PXENV_UNDI_INITIALIZE (retry %d)\n",
953  undinic, retry );
954  /* Delay to allow link to settle if necessary */
956  }
957  }
958  undi->flags |= UNDI_FL_INITIALIZED;
959 
960  /* Get device information */
961  memset ( &undi_info, 0, sizeof ( undi_info ) );
962  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
963  &undi_info, sizeof ( undi_info ) ) ) != 0 )
964  goto err_undi_get_information;
965  memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
966  memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
967  undinic->irq = undi_info.IntNumber;
968  if ( undinic->irq > IRQ_MAX ) {
969  DBGC ( undinic, "UNDINIC %p ignoring invalid IRQ %d\n",
970  undinic, undinic->irq );
971  undinic->irq = 0;
972  }
973  DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
974  undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
975 
976  /* Get interface information */
977  memset ( &undi_iface, 0, sizeof ( undi_iface ) );
978  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
979  &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
980  goto err_undi_get_iface_info;
981  DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
982  undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
983  undi_iface.ServiceFlags );
984  if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
985  ( undinic->irq != 0 ) ) {
986  undinic->irq_supported = 1;
987  }
988  DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
989  ( undinic->irq_supported ? "interrupt" : "polling" ) );
990  if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
991  sizeof ( undi_iface.IfaceType ) ) == 0 ) {
992  DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
993  undinic );
994  undinic->hacks |= UNDI_HACK_EB54;
995  }
996  if ( undinet_irq_is_broken ( &dev->desc ) ) {
997  DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
998  "broken interrupts\n", undinic );
999  undinic->irq_supported = 0;
1000  }
1001 
1002  /* Register network device */
1003  if ( ( rc = register_netdev ( netdev ) ) != 0 )
1004  goto err_register;
1005 
1006  /* Mark as link up; we don't handle link state */
1007  netdev_link_up ( netdev );
1008 
1009  DBGC ( undinic, "UNDINIC %p added\n", undinic );
1010  return 0;
1011 
1012  err_register:
1013  err_undi_get_iface_info:
1014  err_undi_get_information:
1015  err_undi_initialize:
1016  /* Shut down UNDI stack */
1017  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1018  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
1019  sizeof ( undi_shutdown ) );
1020  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1021  undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
1022  sizeof ( undi_cleanup ) );
1023  undi->flags &= ~UNDI_FL_INITIALIZED;
1024  err_undi_startup:
1025  /* Unhook UNDI stack */
1026  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1027  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1028  sizeof ( stop_undi ) );
1029  undi->flags &= ~UNDI_FL_STARTED;
1030  err_start_undi:
1031  netdev_nullify ( netdev );
1032  netdev_put ( netdev );
1033  undi_set_drvdata ( undi, NULL );
1034  return rc;
1035 }
#define UNDI_HACK_EB54
Work around Etherboot 5.4 bugs.
Definition: undinet.c:71
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown()
Definition: pxe_api.h:922
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define SUPPORTED_IRQ
Interrupt Request supported.
Definition: pxe_api.h:1378
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup()
Definition: pxe_api.h:841
An UNDI NIC.
Definition: undinet.c:48
#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 DBGC(...)
Definition: compiler.h:505
Parameter block for pxenv_undi_initialize()
Definition: pxe_api.h:863
#define PXENV_UNDI_GET_IFACE_INFO
PXE API function code for pxenv_undi_get_iface_info()
Definition: pxe_api.h:1359
#define UNDI_FL_INITIALIZED
UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called.
Definition: undi.h:99
UINT16_t flags
Flags.
Definition: undi.h:54
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:186
UINT16_t isapnp_csn
ISAPnP card select number, or UNDI_NO_ISAPNP_CSN.
Definition: undi.h:36
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition: netdevice.h:515
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:572
void * priv
Driver private data.
Definition: netdevice.h:431
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:774
static int undinet_irq_is_broken(struct device_description *desc)
Check for devices with broken support for generating interrupts.
Definition: undinet.c:849
static struct net_device * netdev
Definition: gdbudp.c:52
Parameter block for pxenv_undi_shutdown()
Definition: pxe_api.h:925
unsigned int irq
Assigned IRQ number.
Definition: undinet.c:52
Parameter block for pxenv_undi_startup()
Definition: pxe_api.h:825
SEGOFF16_t entry
Entry point.
Definition: undi.h:28
int hacks
Bug workarounds.
Definition: undinet.c:56
int register_netdev(struct net_device *netdev)
Register network device.
Definition: netdevice.c:759
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition: ethernet.c:175
A network device.
Definition: netdevice.h:352
UINT16_t isapnp_read_port
ISAPnP read port, or UNDI_NO_ISAPNP_READ_PORT.
Definition: undi.h:38
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:528
Parameter block for pxenv_undi_get_information()
Definition: pxe_api.h:1166
#define ETH_ALEN
Definition: if_ether.h:8
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
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
UINT16_t pci_busdevfn
PCI bus:dev.fn, or UNDI_NO_PCI_BUSDEVFN.
Definition: undi.h:34
Parameter block for pxenv_undi_cleanup()
Definition: pxe_api.h:844
#define UNDI_INITIALIZE_RETRY_MAX
Maximum number of times to retry PXENV_UNDI_INITIALIZE.
Definition: undinet.c:76
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
int find_pnp_bios(void)
Locate Plug-and-Play BIOS.
Definition: pnpbios.c:101
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition: ethernet.c:264
Parameter block for pxenv_undi_get_iface_info()
Definition: pxe_api.h:1381
#define undinet_entry_point
Definition: undinet.c:105
struct device_description desc
Device description.
Definition: device.h:79
static void undi_set_drvdata(struct undi_device *undi, void *priv)
Set UNDI driver-private data.
Definition: undi.h:70
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
#define PXENV_UNDI_GET_INFORMATION
PXE API function code for pxenv_undi_get_information()
Definition: pxe_api.h:1155
Parameter block for pxenv_start_undi()
Definition: pxe_api.h:438
#define PXENV_UNDI_STARTUP
PXE API function code for pxenv_undi_startup()
Definition: pxe_api.h:815
#define PXENV_UNDI_INITIALIZE
PXE API function code for pxenv_undi_initialize()
Definition: pxe_api.h:860
#define BIOS_SEG
Definition: pnpbios.h:13
static struct net_device_operations undinet_operations
UNDI network device operations.
Definition: undinet.c:804
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define IRQ_MAX
Definition: pic8259.h:63
#define UNDI_INITIALIZE_RETRY_DELAY_MS
Delay between retries of PXENV_UNDI_INITIALIZE.
Definition: undinet.c:79
#define UNDI_FL_STARTED
UNDI flag: START_UNDI has been called.
Definition: undi.h:96
Parameter block for pxenv_stop_undi()
Definition: pxe_api.h:508
int irq_supported
Device supports IRQs.
Definition: undinet.c:50
void * memset(void *dest, int character, size_t len) __nonnull

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().

◆ undinet_remove()

void undinet_remove ( struct undi_device undi)

Remove UNDI device.

Parameters
undiUNDI device

Definition at line 1042 of file undinet.c.

1042  {
1043  struct net_device *netdev = undi_get_drvdata ( undi );
1044  struct undi_nic *undinic = netdev->priv;
1045  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
1046  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
1047  struct s_PXENV_STOP_UNDI stop_undi;
1048 
1049  /* Unregister net device */
1051 
1052  /* If we are preparing for an OS boot, or if we cannot exit
1053  * via the PXE stack, then shut down the PXE stack.
1054  */
1055  if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
1056 
1057  /* Shut down UNDI stack */
1058  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1059  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN,
1060  &undi_shutdown, sizeof ( undi_shutdown ) );
1061  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1062  undinet_call ( undinic, PXENV_UNDI_CLEANUP,
1063  &undi_cleanup, sizeof ( undi_cleanup ) );
1064  undi->flags &= ~UNDI_FL_INITIALIZED;
1065 
1066  /* Unhook UNDI stack */
1067  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1068  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1069  sizeof ( stop_undi ) );
1070  undi->flags &= ~UNDI_FL_STARTED;
1071  }
1072 
1073  /* Clear entry point */
1074  memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
1075 
1076  /* Free network device */
1077  netdev_nullify ( netdev );
1078  netdev_put ( netdev );
1079 
1080  DBGC ( undinic, "UNDINIC %p removed\n", undinic );
1081 }
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown()
Definition: pxe_api.h:922
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup()
Definition: pxe_api.h:841
An UNDI NIC.
Definition: undinet.c:48
#define PXENV_STOP_UNDI
PXE API function code for pxenv_stop_undi()
Definition: pxe_api.h:505
#define DBGC(...)
Definition: compiler.h:505
#define UNDI_FL_INITIALIZED
UNDI flag: UNDI_STARTUP and UNDI_INITIALIZE have been called.
Definition: undi.h:99
UINT16_t flags
Flags.
Definition: undi.h:54
static void * undi_get_drvdata(struct undi_device *undi)
Get UNDI driver-private data.
Definition: undi.h:80
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:572
void * priv
Driver private data.
Definition: netdevice.h:431
#define UNDI_FL_KEEP_ALL
UNDI flag: keep stack resident.
Definition: undi.h:102
static struct net_device * netdev
Definition: gdbudp.c:52
Parameter block for pxenv_undi_shutdown()
Definition: pxe_api.h:925
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition: netdevice.c:941
A network device.
Definition: netdevice.h:352
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:528
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
Parameter block for pxenv_undi_cleanup()
Definition: pxe_api.h:844
#define undinet_entry_point
Definition: undinet.c:105
#define UNDI_FL_STARTED
UNDI flag: START_UNDI has been called.
Definition: undi.h:96
Parameter block for pxenv_stop_undi()
Definition: pxe_api.h:508
void * memset(void *dest, int character, size_t len) __nonnull

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().