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 881 of file undinet.c.

881  {
882  struct net_device *netdev;
883  struct undi_nic *undinic;
884  struct s_PXENV_START_UNDI start_undi;
885  struct s_PXENV_UNDI_STARTUP undi_startup;
886  struct s_PXENV_UNDI_INITIALIZE undi_init;
887  struct s_PXENV_UNDI_GET_INFORMATION undi_info;
888  struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
889  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
890  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
891  struct s_PXENV_STOP_UNDI stop_undi;
892  unsigned int retry;
893  int rc;
894 
895  /* Allocate net device */
896  netdev = alloc_etherdev ( sizeof ( *undinic ) );
897  if ( ! netdev )
898  return -ENOMEM;
900  undinic = netdev->priv;
901  undi_set_drvdata ( undi, netdev );
902  netdev->dev = dev;
903  memset ( undinic, 0, sizeof ( *undinic ) );
904  undinet_entry_point = undi->entry;
905  DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
906 
907  /* Hook in UNDI stack */
908  if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
909  memset ( &start_undi, 0, sizeof ( start_undi ) );
910  start_undi.AX = undi->pci_busdevfn;
911  start_undi.BX = undi->isapnp_csn;
912  start_undi.DX = undi->isapnp_read_port;
913  start_undi.ES = BIOS_SEG;
914  start_undi.DI = find_pnp_bios();
915  if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
916  &start_undi,
917  sizeof ( start_undi ) ) ) != 0 )
918  goto err_start_undi;
919  }
920  undi->flags |= UNDI_FL_STARTED;
921 
922  /* Bring up UNDI stack */
923  if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
924  memset ( &undi_startup, 0, sizeof ( undi_startup ) );
925  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
926  &undi_startup,
927  sizeof ( undi_startup ) ) ) != 0 )
928  goto err_undi_startup;
929  /* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
930  * due to a transient condition (e.g. media test
931  * failing because the link has only just come out of
932  * reset). We may therefore need to retry this call
933  * several times.
934  */
935  for ( retry = 0 ; ; ) {
936  memset ( &undi_init, 0, sizeof ( undi_init ) );
937  if ( ( rc = undinet_call ( undinic,
939  &undi_init,
940  sizeof ( undi_init ) ) ) ==0)
941  break;
942  if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
943  goto err_undi_initialize;
944  DBGC ( undinic, "UNDINIC %p retrying "
945  "PXENV_UNDI_INITIALIZE (retry %d)\n",
946  undinic, retry );
947  /* Delay to allow link to settle if necessary */
949  }
950  }
951  undi->flags |= UNDI_FL_INITIALIZED;
952 
953  /* Get device information */
954  memset ( &undi_info, 0, sizeof ( undi_info ) );
955  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
956  &undi_info, sizeof ( undi_info ) ) ) != 0 )
957  goto err_undi_get_information;
958  memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
959  memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
960  undinic->irq = undi_info.IntNumber;
961  if ( undinic->irq > IRQ_MAX ) {
962  DBGC ( undinic, "UNDINIC %p ignoring invalid IRQ %d\n",
963  undinic, undinic->irq );
964  undinic->irq = 0;
965  }
966  DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
967  undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
968 
969  /* Get interface information */
970  memset ( &undi_iface, 0, sizeof ( undi_iface ) );
971  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
972  &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
973  goto err_undi_get_iface_info;
974  DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
975  undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
976  undi_iface.ServiceFlags );
977  if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
978  ( undinic->irq != 0 ) ) {
979  undinic->irq_supported = 1;
980  }
981  DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
982  ( undinic->irq_supported ? "interrupt" : "polling" ) );
983  if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
984  sizeof ( undi_iface.IfaceType ) ) == 0 ) {
985  DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
986  undinic );
987  undinic->hacks |= UNDI_HACK_EB54;
988  }
989  if ( undinet_irq_is_broken ( &dev->desc ) ) {
990  DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
991  "broken interrupts\n", undinic );
992  undinic->irq_supported = 0;
993  }
994 
995  /* Register network device */
996  if ( ( rc = register_netdev ( netdev ) ) != 0 )
997  goto err_register;
998 
999  /* Mark as link up; we don't handle link state */
1000  netdev_link_up ( netdev );
1001 
1002  DBGC ( undinic, "UNDINIC %p added\n", undinic );
1003  return 0;
1004 
1005  err_register:
1006  err_undi_get_iface_info:
1007  err_undi_get_information:
1008  err_undi_initialize:
1009  /* Shut down UNDI stack */
1010  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1011  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
1012  sizeof ( undi_shutdown ) );
1013  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1014  undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
1015  sizeof ( undi_cleanup ) );
1016  undi->flags &= ~UNDI_FL_INITIALIZED;
1017  err_undi_startup:
1018  /* Unhook UNDI stack */
1019  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1020  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1021  sizeof ( stop_undi ) );
1022  undi->flags &= ~UNDI_FL_STARTED;
1023  err_start_undi:
1024  netdev_nullify ( netdev );
1025  netdev_put ( netdev );
1026  undi_set_drvdata ( undi, NULL );
1027  return rc;
1028 }
#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:170
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:498
#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:555
void * priv
Driver private data.
Definition: netdevice.h:425
static void netdev_link_up(struct net_device *netdev)
Mark network device as having link up.
Definition: netdevice.h:768
static int undinet_irq_is_broken(struct device_description *desc)
Check for devices with broken support for generating interrupts.
Definition: undinet.c:842
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:667
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition: ethernet.c:175
A network device.
Definition: netdevice.h:348
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:511
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:271
struct device * dev
Underlying hardware device.
Definition: netdevice.h:360
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:381
#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:797
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:375
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#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 1035 of file undinet.c.

1035  {
1036  struct net_device *netdev = undi_get_drvdata ( undi );
1037  struct undi_nic *undinic = netdev->priv;
1038  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
1039  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
1040  struct s_PXENV_STOP_UNDI stop_undi;
1041 
1042  /* Unregister net device */
1044 
1045  /* If we are preparing for an OS boot, or if we cannot exit
1046  * via the PXE stack, then shut down the PXE stack.
1047  */
1048  if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
1049 
1050  /* Shut down UNDI stack */
1051  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1052  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN,
1053  &undi_shutdown, sizeof ( undi_shutdown ) );
1054  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1055  undinet_call ( undinic, PXENV_UNDI_CLEANUP,
1056  &undi_cleanup, sizeof ( undi_cleanup ) );
1057  undi->flags &= ~UNDI_FL_INITIALIZED;
1058 
1059  /* Unhook UNDI stack */
1060  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1061  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1062  sizeof ( stop_undi ) );
1063  undi->flags &= ~UNDI_FL_STARTED;
1064  }
1065 
1066  /* Clear entry point */
1067  memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
1068 
1069  /* Free network device */
1070  netdev_nullify ( netdev );
1071  netdev_put ( netdev );
1072 
1073  DBGC ( undinic, "UNDINIC %p removed\n", undinic );
1074 }
#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:555
void * priv
Driver private data.
Definition: netdevice.h:425
#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:844
A network device.
Definition: netdevice.h:348
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition: netdevice.h:511
static int undinet_call(struct undi_nic *undinic, unsigned int function, void *params, size_t params_len)
Issue UNDI API call.
Definition: undinet.c:271
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().