iPXE
Data Structures | Macros | Functions | Variables
undinet.c File Reference

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 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_profilerundinet_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...
 

Detailed Description

UNDI network device driver.

Definition in file undinet.c.

Macro Definition Documentation

◆ EINFO_EPXECALL

#define EINFO_EPXECALL
Value:
"External PXE API error" )
#define EINFO_EPLATFORM
Platform-generated base error.
Definition: errno.h:691
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition: errno.h:180

Definition at line 60 of file undinet.c.

◆ EPXECALL

#define EPXECALL (   status)    EPLATFORM ( EINFO_EPXECALL, status )

Definition at line 63 of file undinet.c.

◆ UNDI_INITIALIZE_RETRY_MAX

#define UNDI_INITIALIZE_RETRY_MAX   10

Maximum number of times to retry PXENV_UNDI_INITIALIZE.

Definition at line 76 of file undinet.c.

◆ UNDI_INITIALIZE_RETRY_DELAY_MS

#define UNDI_INITIALIZE_RETRY_DELAY_MS   200

Delay between retries of PXENV_UNDI_INITIALIZE.

Definition at line 79 of file undinet.c.

◆ UNDI_RX_QUOTA

#define UNDI_RX_QUOTA   4

Maximum number of received packets per poll.

Definition at line 82 of file undinet.c.

◆ UNDI_RX_ALIGN

#define UNDI_RX_ALIGN   16

Alignment of received frame payload.

Definition at line 85 of file undinet.c.

◆ undinet_params

#define undinet_params   __use_data16 ( undinet_params )

Definition at line 96 of file undinet.c.

◆ undinet_entry_point

#define undinet_entry_point   __use_data16 ( undinet_entry_point )

Definition at line 105 of file undinet.c.

◆ undiisr_irq

#define undiisr_irq   __use_data16 ( undiisr_irq )

Definition at line 367 of file undinet.c.

◆ undiisr_next_handler

#define undiisr_next_handler   __use_data16 ( undiisr_next_handler )

Definition at line 371 of file undinet.c.

◆ undiisr_trigger_count

#define undiisr_trigger_count   __use_data16 ( undiisr_trigger_count )

Definition at line 375 of file undinet.c.

◆ undinet_tbd

#define undinet_tbd   __use_data16 ( undinet_tbd )

Definition at line 439 of file undinet.c.

◆ undinet_destaddr

#define undinet_destaddr   __use_data16 ( undinet_destaddr )

Definition at line 443 of file undinet.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER  )

◆ undinet_close()

static void undinet_close ( struct net_device netdev)
static

Close NIC.

Parameters
netdevNet device

Definition at line 745 of file undinet.c.

745  {
746  struct undi_nic *undinic = netdev->priv;
747  struct s_PXENV_UNDI_ISR undi_isr;
748  struct s_PXENV_UNDI_CLOSE undi_close;
749  int rc;
750 
751  /* Ensure ISR has exited cleanly */
752  while ( undinic->isr_processing ) {
753  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
754  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
755  sizeof ( undi_isr ) ) ) != 0 )
756  break;
757  switch ( undi_isr.FuncFlag ) {
760  /* Continue draining */
761  break;
762  default:
763  /* Stop processing */
764  undinic->isr_processing = 0;
765  break;
766  }
767  }
768 
769  /* Close NIC */
770  undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
771  sizeof ( undi_close ) );
772 
773  /* Disable interrupt and unhook ISR if applicable */
774  if ( undinic->irq ) {
775  disable_irq ( undinic->irq );
776  undinet_unhook_isr ( undinic->irq );
777  }
778 
779  DBGC ( undinic, "UNDINIC %p closed\n", undinic );
780 }
Parameter block for pxenv_undi_isr()
Definition: pxe_api.h:1479
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
An UNDI NIC.
Definition: undinet.c:48
#define DBGC(...)
Definition: compiler.h:505
#define disable_irq(x)
Definition: pic8259.h:52
#define PXENV_UNDI_ISR_OUT_RECEIVE
A packet has been received.
Definition: pxe_api.h:1467
Parameter block for pxenv_undi_close()
Definition: pxe_api.h:993
#define PXENV_UNDI_CLOSE
PXE API function code for pxenv_undi_close()
Definition: pxe_api.h:990
void * priv
Driver private data.
Definition: netdevice.h:425
static struct net_device * netdev
Definition: gdbudp.c:52
unsigned int irq
Assigned IRQ number.
Definition: undinet.c:52
#define PXENV_UNDI_ISR_OUT_TRANSMIT
A packet transmission has completed.
Definition: pxe_api.h:1465
#define PXENV_UNDI_ISR_IN_GET_NEXT
Continue processing interrupt.
Definition: pxe_api.h:1457
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
static void undinet_unhook_isr(unsigned int irq)
Unhook UNDI interrupt service routine.
Definition: undinet.c:400
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition: pxe_api.h:1450
int isr_processing
Currently processing ISR.
Definition: undinet.c:54

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

◆ __bss16() [1/2]

static union u_PXENV_ANY __bss16 ( undinet_params  )
static

UNDI parameter block.

Used as the parameter block for all UNDI API calls. Resides in base memory.

◆ __bss16() [2/2]

SEGOFF16_t __bss16 ( undinet_entry_point  )

UNDI entry point.

Used as the indirection vector for all UNDI API calls. Resides in base memory.

◆ undinet_function_name()

static const char* undinet_function_name ( unsigned int  function)
inlinestatic

Name PXE API call.

Parameters
functionAPI call number
Return values
nameAPI call name

Definition at line 182 of file undinet.c.

182  {
183  switch ( function ) {
184  case PXENV_START_UNDI:
185  return "PXENV_START_UNDI";
186  case PXENV_STOP_UNDI:
187  return "PXENV_STOP_UNDI";
188  case PXENV_UNDI_STARTUP:
189  return "PXENV_UNDI_STARTUP";
190  case PXENV_UNDI_CLEANUP:
191  return "PXENV_UNDI_CLEANUP";
193  return "PXENV_UNDI_INITIALIZE";
195  return "PXENV_UNDI_RESET_ADAPTER";
196  case PXENV_UNDI_SHUTDOWN:
197  return "PXENV_UNDI_SHUTDOWN";
198  case PXENV_UNDI_OPEN:
199  return "PXENV_UNDI_OPEN";
200  case PXENV_UNDI_CLOSE:
201  return "PXENV_UNDI_CLOSE";
202  case PXENV_UNDI_TRANSMIT:
203  return "PXENV_UNDI_TRANSMIT";
205  return "PXENV_UNDI_SET_MCAST_ADDRESS";
207  return "PXENV_UNDI_SET_STATION_ADDRESS";
209  return "PXENV_UNDI_SET_PACKET_FILTER";
211  return "PXENV_UNDI_GET_INFORMATION";
213  return "PXENV_UNDI_GET_STATISTICS";
215  return "PXENV_UNDI_CLEAR_STATISTICS";
217  return "PXENV_UNDI_INITIATE_DIAGS";
219  return "PXENV_UNDI_FORCE_INTERRUPT";
221  return "PXENV_UNDI_GET_MCAST_ADDRESS";
223  return "PXENV_UNDI_GET_NIC_TYPE";
225  return "PXENV_UNDI_GET_IFACE_INFO";
226  /*
227  * Duplicate case value; this is a bug in the PXE specification.
228  *
229  * case PXENV_UNDI_GET_STATE:
230  * return "PXENV_UNDI_GET_STATE";
231  */
232  case PXENV_UNDI_ISR:
233  return "PXENV_UNDI_ISR";
235  return "PXENV_GET_CACHED_INFO";
236  default:
237  return "UNKNOWN API CALL";
238  }
239 }
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown()
Definition: pxe_api.h:922
#define PXENV_UNDI_FORCE_INTERRUPT
PXE API function code for pxenv_undi_force_interrupt()
Definition: pxe_api.h:1259
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup()
Definition: pxe_api.h:841
#define PXENV_UNDI_SET_STATION_ADDRESS
PXE API function code for pxenv_undi_set_station_address()
Definition: pxe_api.h:1105
#define PXENV_START_UNDI
PXE API function code for pxenv_start_undi()
Definition: pxe_api.h:435
#define PXENV_UNDI_CLEAR_STATISTICS
PXE API function code for pxenv_undi_clear_statistics()
Definition: pxe_api.h:1221
#define PXENV_STOP_UNDI
PXE API function code for pxenv_stop_undi()
Definition: pxe_api.h:505
#define PXENV_UNDI_GET_MCAST_ADDRESS
PXE API function code for pxenv_undi_get_mcast_address()
Definition: pxe_api.h:1278
#define PXENV_UNDI_GET_IFACE_INFO
PXE API function code for pxenv_undi_get_iface_info()
Definition: pxe_api.h:1359
#define PXENV_UNDI_SET_MCAST_ADDRESS
PXE API function code for pxenv_undi_set_mcast_address()
Definition: pxe_api.h:1084
#define PXENV_UNDI_GET_NIC_TYPE
PXE API function code for pxenv_undi_get_nic_type()
Definition: pxe_api.h:1299
#define PXENV_UNDI_CLOSE
PXE API function code for pxenv_undi_close()
Definition: pxe_api.h:990
#define PXENV_UNDI_TRANSMIT
PXE API function code for pxenv_undi_transmit()
Definition: pxe_api.h:1009
#define PXENV_UNDI_GET_STATISTICS
PXE API function code for pxenv_undi_get_statistics()
Definition: pxe_api.h:1198
#define PXENV_UNDI_SET_PACKET_FILTER
PXE API function code for pxenv_undi_set_packet_filter()
Definition: pxe_api.h:1125
#define PXENV_UNDI_INITIATE_DIAGS
PXE API function code for pxenv_undi_initiate_diags()
Definition: pxe_api.h:1240
#define PXENV_UNDI_OPEN
PXE API function code for pxenv_undi_open()
Definition: pxe_api.h:941
#define PXENV_UNDI_RESET_ADAPTER
PXE API function code for pxenv_undi_reset_adapter()
Definition: pxe_api.h:888
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition: pxe_api.h:1450
#define PXENV_GET_CACHED_INFO
PXE API function code for pxenv_get_cached_info()
Definition: pxe_api.h:270
#define PXENV_UNDI_GET_INFORMATION
PXE API function code for pxenv_undi_get_information()
Definition: pxe_api.h:1155
#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

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

◆ undinet_profiler()

static struct undinet_profiler* undinet_profiler ( unsigned int  function)
static

Determine applicable profiler pair (for debugging)

Parameters
functionAPI call number
Return values
profilerProfiler

Definition at line 247 of file undinet.c.

247  {
248 
249  /* Determine applicable profiler */
250  switch ( function ) {
251  case PXENV_UNDI_TRANSMIT:
252  return &undinet_tx_profiler;
253  case PXENV_UNDI_ISR:
254  return &undinet_isr_profiler;
255  case PXENV_UNKNOWN:
256  return &undinet_unknown_profiler;
257  default:
258  return &undinet_misc_profiler;
259  }
260 }
#define PXENV_UNKNOWN
PXE API invalid function code.
Definition: pxe.h:13
#define PXENV_UNDI_TRANSMIT
PXE API function code for pxenv_undi_transmit()
Definition: pxe_api.h:1009
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition: pxe_api.h:1450

References PXENV_UNDI_ISR, PXENV_UNDI_TRANSMIT, and PXENV_UNKNOWN.

Referenced by undinet_call().

◆ undinet_call()

static int undinet_call ( struct undi_nic undinic,
unsigned int  function,
void *  params,
size_t  params_len 
)
static

Issue UNDI API call.

Parameters
undinicUNDI NIC
functionAPI call number
paramsPXE parameter block
params_lenLength of PXE parameter block
Return values
rcReturn status code

Definition at line 271 of file undinet.c.

272  {
273  struct undinet_profiler *profiler = undinet_profiler ( function );
274  PXENV_EXIT_t exit;
275  uint32_t before;
277  uint32_t stopped;
278  uint32_t after;
279  int discard_D;
280  int rc;
281 
282  /* Copy parameter block and entry point */
283  assert ( params_len <= sizeof ( undinet_params ) );
284  memcpy ( &undinet_params, params, params_len );
285 
286  /* Call real-mode entry point. This calling convention will
287  * work with both the !PXE and the PXENV+ entry points.
288  */
289  profile_start ( &profiler->total );
290  __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
291  "rdtsc\n\t"
292  "pushl %%eax\n\t"
293  "pushw %%es\n\t"
294  "pushw %%di\n\t"
295  "pushw %%bx\n\t"
296  "lcall *undinet_entry_point\n\t"
297  "movw %%ax, %%bx\n\t"
298  "rdtsc\n\t"
299  "addw $6, %%sp\n\t"
300  "popl %%edx\n\t"
301  "popl %%ebp\n\t" /* gcc bug */ )
302  : "=a" ( stopped ), "=d" ( started ),
303  "=b" ( exit ), "=D" ( discard_D )
304  : "b" ( function ),
305  "D" ( __from_data16 ( &undinet_params ) )
306  : "ecx", "esi" );
307  profile_stop ( &profiler->total );
308  before = profile_started ( &profiler->total );
309  after = profile_stopped ( &profiler->total );
310  profile_start_at ( &profiler->p2r, before );
311  profile_stop_at ( &profiler->p2r, started );
312  profile_start_at ( &profiler->ext, started );
313  profile_stop_at ( &profiler->ext, stopped );
314  profile_start_at ( &profiler->r2p, stopped );
315  profile_stop_at ( &profiler->r2p, after );
316 
317  /* Determine return status code based on PXENV_EXIT and
318  * PXENV_STATUS
319  */
320  rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
321  0 : -EPXECALL ( undinet_params.Status ) );
322 
323  /* If anything goes wrong, print as much debug information as
324  * it's possible to give.
325  */
326  if ( rc != 0 ) {
327  SEGOFF16_t rm_params = {
328  .segment = rm_ds,
329  .offset = __from_data16 ( &undinet_params ),
330  };
331 
332  DBGC ( undinic, "UNDINIC %p %s failed: %s\n", undinic,
333  undinet_function_name ( function ), strerror ( rc ) );
334  DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
335  "%#02zx, entry point at %04x:%04x\n", undinic,
336  rm_params.segment, rm_params.offset, params_len,
337  undinet_entry_point.segment,
338  undinet_entry_point.offset );
339  DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
340  DBGC_HDA ( undinic, rm_params, params, params_len );
341  DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
342  DBGC_HDA ( undinic, rm_params, &undinet_params, params_len );
343  }
344 
345  /* Copy parameter block back */
346  memcpy ( params, &undinet_params, params_len );
347 
348  return rc;
349 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
#define EPXECALL(status)
Definition: undinet.c:63
static unsigned long profile_started(struct profiler *profiler)
Get start time.
Definition: profile.h:77
A data structure for storing profiling information.
Definition: profile.h:26
#define rm_ds
Definition: libkir.h:39
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
static void profile_stop_at(struct profiler *profiler, unsigned long stopped)
Stop profiling.
Definition: profile.h:143
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static int started
"startup() has been called" flag
Definition: init.c:37
UINT16_t PXENV_EXIT_t
A PXE exit code.
Definition: pxe_types.h:44
static struct undinet_profiler * undinet_profiler(unsigned int function)
Determine applicable profiler pair (for debugging)
Definition: undinet.c:247
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define DBGC_HDA(...)
Definition: compiler.h:506
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static const char * undinet_function_name(unsigned int function)
Name PXE API call.
Definition: undinet.c:182
void * discard_D
Definition: bigint.h:29
#define undinet_params
Definition: undinet.c:96
unsigned int uint32_t
Definition: stdint.h:12
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
static void profile_start_at(struct profiler *profiler, unsigned long started)
Start profiling.
Definition: profile.h:129
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
static unsigned long profile_stopped(struct profiler *profiler)
Get stop time.
Definition: profile.h:94
#define __from_data16(pointer)
Definition: libkir.h:22
#define undinet_entry_point
Definition: undinet.c:105
#define REAL_CODE(asm_code_str)
Definition: libkir.h:226
A PXE API call breakdown profiler.
Definition: undinet.c:116

References __asm__(), __from_data16, __volatile__(), assert(), 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, 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().

◆ undiisr()

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

◆ __data16() [1/4]

uint8_t __data16 ( undiisr_irq  )

IRQ number.

◆ __data16() [2/4]

struct segoff __data16 ( undiisr_next_handler  )

IRQ chain vector.

◆ __data16() [3/4]

volatile uint8_t __data16 ( undiisr_trigger_count  )
pure virtual

IRQ trigger count.

◆ undinet_hook_isr()

static void undinet_hook_isr ( unsigned int  irq)
static

Hook UNDI interrupt service routine.

Parameters
irqIRQ number

Definition at line 385 of file undinet.c.

385  {
386 
387  assert ( irq <= IRQ_MAX );
388  assert ( undiisr_irq == 0 );
389 
390  undiisr_irq = irq;
391  hook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
393 }
unsigned long intptr_t
Definition: stdint.h:21
void hook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Hook INT vector.
Definition: biosint.c:24
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define IRQ_INT(irq)
Definition: pic8259.h:60
#define undiisr_irq
Definition: undinet.c:367
#define undiisr_next_handler
Definition: undinet.c:371
void undiisr(void)
UNDI interrupt service routine.
#define IRQ_MAX
Definition: pic8259.h:63

References assert(), hook_bios_interrupt(), IRQ_INT, IRQ_MAX, undiisr(), undiisr_irq, and undiisr_next_handler.

Referenced by undinet_open().

◆ undinet_unhook_isr()

static void undinet_unhook_isr ( unsigned int  irq)
static

Unhook UNDI interrupt service routine.

Parameters
irqIRQ number

Definition at line 400 of file undinet.c.

400  {
401 
402  assert ( irq <= IRQ_MAX );
403 
404  unhook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
406  undiisr_irq = 0;
407 }
unsigned long intptr_t
Definition: stdint.h:21
int unhook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Unhook INT vector.
Definition: biosint.c:69
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define IRQ_INT(irq)
Definition: pic8259.h:60
#define undiisr_irq
Definition: undinet.c:367
#define undiisr_next_handler
Definition: undinet.c:371
void undiisr(void)
UNDI interrupt service routine.
#define IRQ_MAX
Definition: pic8259.h:63

References assert(), IRQ_INT, IRQ_MAX, undiisr(), undiisr_irq, undiisr_next_handler, and unhook_bios_interrupt().

Referenced by undinet_close().

◆ undinet_isr_triggered()

static int undinet_isr_triggered ( void  )
static

Test to see if UNDI ISR has been triggered.

Return values
triggeredISR has been triggered since last check

Definition at line 414 of file undinet.c.

414  {
415  unsigned int this_trigger_count;
416 
417  /* Read trigger_count. Do this only once; it is volatile */
418  this_trigger_count = undiisr_trigger_count;
419 
420  if ( this_trigger_count == last_trigger_count ) {
421  /* Not triggered */
422  return 0;
423  } else {
424  /* Triggered */
425  last_trigger_count = this_trigger_count;
426  return 1;
427  }
428 }
#define undiisr_trigger_count
Definition: undinet.c:375
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:378

References last_trigger_count, and undiisr_trigger_count.

Referenced by undinet_poll().

◆ __data16() [4/4]

static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd  )
static

UNDI transmit buffer descriptor.

◆ __data16_array()

static uint8_t __data16_array ( undinet_destaddr  )
static

UNDI transmit destination address.

◆ undinet_transmit()

static int undinet_transmit ( struct net_device netdev,
struct io_buffer iobuf 
)
static

Transmit packet.

Parameters
netdevNetwork device
iobufI/O buffer
Return values
rcReturn status code

Definition at line 452 of file undinet.c.

453  {
454  struct undi_nic *undinic = netdev->priv;
455  struct s_PXENV_UNDI_TRANSMIT undi_transmit;
456  const void *ll_dest;
457  const void *ll_source;
458  uint16_t net_proto;
459  unsigned int flags;
461  size_t len;
462  int rc;
463 
464  /* Technically, we ought to make sure that the previous
465  * transmission has completed before we re-use the buffer.
466  * However, many PXE stacks (including at least some Intel PXE
467  * stacks and Etherboot 5.4) fail to generate TX completions.
468  * In practice this won't be a problem, since our TX datapath
469  * has a very low packet volume and we can get away with
470  * assuming that a TX will be complete by the time we want to
471  * transmit the next packet.
472  */
473 
474  /* Some PXE stacks are unable to cope with P_UNKNOWN, and will
475  * always try to prepend a link-layer header. Work around
476  * these stacks by stripping the existing link-layer header
477  * and allowing the PXE stack to (re)construct the link-layer
478  * header itself.
479  */
480  if ( ( rc = eth_pull ( netdev, iobuf, &ll_dest, &ll_source,
481  &net_proto, &flags ) ) != 0 ) {
482  DBGC ( undinic, "UNDINIC %p could not strip Ethernet header: "
483  "%s\n", undinic, strerror ( rc ) );
484  return rc;
485  }
486  memcpy ( undinet_destaddr, ll_dest, sizeof ( undinet_destaddr ) );
487  switch ( net_proto ) {
488  case htons ( ETH_P_IP ) :
489  protocol = P_IP;
490  break;
491  case htons ( ETH_P_ARP ) :
492  protocol = P_ARP;
493  break;
494  case htons ( ETH_P_RARP ) :
495  protocol = P_RARP;
496  break;
497  default:
498  /* Unknown protocol; restore the original link-layer header */
499  iob_push ( iobuf, sizeof ( struct ethhdr ) );
501  break;
502  }
503 
504  /* Copy packet to UNDI I/O buffer */
505  len = iob_len ( iobuf );
506  if ( len > sizeof ( basemem_packet ) )
507  len = sizeof ( basemem_packet );
508  memcpy ( &basemem_packet, iobuf->data, len );
509 
510  /* Create PXENV_UNDI_TRANSMIT data structure */
511  memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
512  undi_transmit.Protocol = protocol;
513  undi_transmit.XmitFlag = ( ( flags & LL_BROADCAST ) ?
515  undi_transmit.DestAddr.segment = rm_ds;
516  undi_transmit.DestAddr.offset = __from_data16 ( &undinet_destaddr );
517  undi_transmit.TBD.segment = rm_ds;
518  undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd );
519 
520  /* Create PXENV_UNDI_TBD data structure */
521  undinet_tbd.ImmedLength = len;
522  undinet_tbd.Xmit.segment = rm_ds;
523  undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
524 
525  /* Issue PXE API call */
526  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT, &undi_transmit,
527  sizeof ( undi_transmit ) ) ) != 0 )
528  goto done;
529 
530  /* Free I/O buffer */
531  netdev_tx_complete ( netdev, iobuf );
532  done:
533  return rc;
534 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
static void netdev_tx_complete(struct net_device *netdev, struct io_buffer *iobuf)
Complete network transmission.
Definition: netdevice.h:746
#define P_IP
IP protocol.
Definition: pxe_api.h:1012
An UNDI NIC.
Definition: undinet.c:48
#define iob_push(iobuf, len)
Definition: iobuf.h:80
#define ETH_P_IP
Definition: if_ether.h:18
#define DBGC(...)
Definition: compiler.h:505
Parameter block for pxenv_undi_transmit()
Definition: pxe_api.h:1049
#define rm_ds
Definition: libkir.h:39
#define XMT_BROADCAST
Broadcast packet.
Definition: pxe_api.h:1018
int eth_pull(struct net_device *netdev __unused, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
Remove Ethernet link-layer header.
Definition: ethernet.c:101
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * priv
Driver private data.
Definition: netdevice.h:425
static struct net_device * netdev
Definition: gdbudp.c:52
#define PXENV_UNDI_TRANSMIT
PXE API function code for pxenv_undi_transmit()
Definition: pxe_api.h:1009
#define basemem_packet
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
unsigned char uint8_t
Definition: stdint.h:10
#define XMT_DESTADDR
Unicast packet.
Definition: pxe_api.h:1017
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
#define undinet_destaddr
Definition: undinet.c:443
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
#define undinet_tbd
Definition: undinet.c:439
uint32_t len
Length.
Definition: ena.h:14
#define __from_data16(pointer)
Definition: libkir.h:22
void * data
Start of data.
Definition: iobuf.h:44
#define P_RARP
RARP protocol.
Definition: pxe_api.h:1014
uint16_t protocol
Protocol ID.
Definition: stp.h:18
#define ETH_P_ARP
Definition: if_ether.h:19
#define ETH_P_RARP
Definition: if_ether.h:20
#define P_ARP
ARP protocol.
Definition: pxe_api.h:1013
#define P_UNKNOWN
Media header already filled in.
Definition: pxe_api.h:1011
An Ethernet link-layer header.
Definition: if_ether.h:30
#define htons(value)
Definition: byteswap.h:135
struct bofm_section_header done
Definition: bofm_test.c:46
void * memset(void *dest, int character, size_t len) __nonnull
uint8_t flags
Flags.
Definition: ena.h:18

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.

◆ undinet_poll()

static void undinet_poll ( struct net_device netdev)
static

Poll for received packets.

Parameters
netdevNetwork 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 566 of file undinet.c.

566  {
567  struct undi_nic *undinic = netdev->priv;
568  struct s_PXENV_UNDI_ISR undi_isr;
569  struct io_buffer *iobuf = NULL;
570  unsigned int quota = UNDI_RX_QUOTA;
571  size_t len;
572  size_t reserve_len;
573  size_t frag_len;
574  size_t max_frag_len;
575  int rc;
576 
577  if ( ! undinic->isr_processing ) {
578  /* Allow interrupt to occur. Do this even if
579  * interrupts are not known to be supported, since
580  * some cards erroneously report that they do not
581  * support interrupts.
582  */
583  if ( ! undinet_isr_triggered() ) {
584  /* Allow interrupt to occur */
585  profile_start ( &undinet_irq_profiler );
586  __asm__ __volatile__ ( "sti\n\t"
587  "nop\n\t"
588  "nop\n\t"
589  "cli\n\t" );
590  profile_stop ( &undinet_irq_profiler );
591 
592  /* If interrupts are known to be supported,
593  * then do nothing on this poll; wait for the
594  * interrupt to be triggered.
595  */
596  if ( undinic->irq_supported )
597  return;
598  }
599 
600  /* Start ISR processing */
601  undinic->isr_processing = 1;
602  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
603  } else {
604  /* Continue ISR processing */
605  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
606  }
607 
608  /* Run through the ISR loop */
609  while ( quota ) {
610  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
611  sizeof ( undi_isr ) ) ) != 0 ) {
612  netdev_rx_err ( netdev, NULL, rc );
613  break;
614  }
615  switch ( undi_isr.FuncFlag ) {
617  /* We don't care about transmit completions */
618  break;
620  /* Packet fragment received */
621  profile_start ( &undinet_rx_profiler );
622  len = undi_isr.FrameLength;
623  frag_len = undi_isr.BufferLength;
624  reserve_len = ( -undi_isr.FrameHeaderLength &
625  ( UNDI_RX_ALIGN - 1 ) );
626  if ( ( len == 0 ) || ( len < frag_len ) ) {
627  /* Don't laugh. VMWare does it. */
628  DBGC ( undinic, "UNDINIC %p reported insane "
629  "fragment (%zd of %zd bytes)\n",
630  undinic, frag_len, len );
632  break;
633  }
634  if ( ! iobuf ) {
635  iobuf = alloc_iob ( reserve_len + len );
636  if ( ! iobuf ) {
637  DBGC ( undinic, "UNDINIC %p could not "
638  "allocate %zd bytes for RX "
639  "buffer\n", undinic, len );
640  /* Fragment will be dropped */
642  goto done;
643  }
644  iob_reserve ( iobuf, reserve_len );
645  }
646  max_frag_len = iob_tailroom ( iobuf );
647  if ( frag_len > max_frag_len ) {
648  DBGC ( undinic, "UNDINIC %p fragment too big "
649  "(%zd+%zd does not fit into %zd)\n",
650  undinic, iob_len ( iobuf ), frag_len,
651  ( iob_len ( iobuf ) + max_frag_len ) );
652  frag_len = max_frag_len;
653  }
654  copy_from_real ( iob_put ( iobuf, frag_len ),
655  undi_isr.Frame.segment,
656  undi_isr.Frame.offset, frag_len );
657  if ( iob_len ( iobuf ) == len ) {
658  /* Whole packet received; deliver it */
659  netdev_rx ( netdev, iob_disown ( iobuf ) );
660  quota--;
661  /* Etherboot 5.4 fails to return all packets
662  * under mild load; pretend it retriggered.
663  */
664  if ( undinic->hacks & UNDI_HACK_EB54 )
666  }
667  profile_stop ( &undinet_rx_profiler );
668  break;
670  /* Processing complete */
671  undinic->isr_processing = 0;
672  goto done;
673  default:
674  /* Should never happen. VMWare does it routinely. */
675  DBGC ( undinic, "UNDINIC %p ISR returned invalid "
676  "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
677  undinic->isr_processing = 0;
678  goto done;
679  }
680  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
681  }
682 
683  done:
684  if ( iobuf ) {
685  DBGC ( undinic, "UNDINIC %p returned incomplete packet "
686  "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
687  ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
688  netdev_rx_err ( netdev, iobuf, -EINVAL );
689  }
690 }
#define UNDI_HACK_EB54
Work around Etherboot 5.4 bugs.
Definition: undinet.c:71
#define EINVAL
Invalid argument.
Definition: errno.h:428
Parameter block for pxenv_undi_isr()
Definition: pxe_api.h:1479
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_put(iobuf, len)
Definition: iobuf.h:116
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition: netdevice.c:501
An UNDI NIC.
Definition: undinet.c:48
#define DBGC(...)
Definition: compiler.h:505
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:128
#define PXENV_UNDI_ISR_OUT_RECEIVE
A packet has been received.
Definition: pxe_api.h:1467
static int undinet_isr_triggered(void)
Test to see if UNDI ISR has been triggered.
Definition: undinet.c:414
#define PXENV_UNDI_ISR_IN_PROCESS
Start processing interrupt.
Definition: pxe_api.h:1455
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:208
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:378
void * priv
Driver private data.
Definition: netdevice.h:425
static struct net_device * netdev
Definition: gdbudp.c:52
#define UNDI_RX_ALIGN
Alignment of received frame payload.
Definition: undinet.c:85
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
#define PXENV_UNDI_ISR_OUT_TRANSMIT
A packet transmission has completed.
Definition: pxe_api.h:1465
int hacks
Bug workarounds.
Definition: undinet.c:56
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:171
#define PXENV_UNDI_ISR_IN_GET_NEXT
Continue processing interrupt.
Definition: pxe_api.h:1457
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
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:470
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#define copy_from_real
Definition: libkir.h:79
#define iob_reserve(iobuf, len)
Definition: iobuf.h:63
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
uint32_t len
Length.
Definition: ena.h:14
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition: pxe_api.h:1450
int isr_processing
Currently processing ISR.
Definition: undinet.c:54
#define PXENV_UNDI_ISR_OUT_DONE
Finished processing interrupt.
Definition: pxe_api.h:1463
#define UNDI_RX_QUOTA
Maximum number of received packets per poll.
Definition: undinet.c:82
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct bofm_section_header done
Definition: bofm_test.c:46
int irq_supported
Device supports IRQs.
Definition: undinet.c:50
A persistent I/O buffer.
Definition: iobuf.h:32

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

◆ undinet_open()

static int undinet_open ( struct net_device netdev)
static

Open NIC.

Parameters
netdevNet device
Return values
rcReturn status code

Definition at line 698 of file undinet.c.

698  {
699  struct undi_nic *undinic = netdev->priv;
700  struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address;
701  struct s_PXENV_UNDI_OPEN undi_open;
702  int rc;
703 
704  /* Hook interrupt service routine and enable interrupt if applicable */
705  if ( undinic->irq ) {
706  undinet_hook_isr ( undinic->irq );
707  enable_irq ( undinic->irq );
708  send_eoi ( undinic->irq );
709  }
710 
711  /* Set station address. Required for some PXE stacks; will
712  * spuriously fail on others. Ignore failures. We only ever
713  * use it to set the MAC address to the card's permanent value
714  * anyway.
715  */
716  memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
717  sizeof ( undi_set_address.StationAddress ) );
719  &undi_set_address, sizeof ( undi_set_address ) );
720 
721  /* Open NIC. We ask for promiscuous operation, since it's the
722  * only way to ask for all multicast addresses. On any
723  * switched network, it shouldn't really make a difference to
724  * performance.
725  */
726  memset ( &undi_open, 0, sizeof ( undi_open ) );
727  undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
728  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
729  sizeof ( undi_open ) ) ) != 0 )
730  goto err;
731 
732  DBGC ( undinic, "UNDINIC %p opened\n", undinic );
733  return 0;
734 
735  err:
736  undinet_close ( netdev );
737  return rc;
738 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define PXENV_UNDI_SET_STATION_ADDRESS
PXE API function code for pxenv_undi_set_station_address()
Definition: pxe_api.h:1105
An UNDI NIC.
Definition: undinet.c:48
#define FLTR_PRMSCS
Accept all packets; listen in promiscuous mode.
Definition: pxe_api.h:953
#define DBGC(...)
Definition: compiler.h:505
void send_eoi(unsigned int irq)
Send End-Of-Interrupt to the PIC.
Definition: pic8259.c:65
static void undinet_close(struct net_device *netdev)
Close NIC.
Definition: undinet.c:745
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * priv
Driver private data.
Definition: netdevice.h:425
#define FLTR_BRDCST
Accept broadcast packets.
Definition: pxe_api.h:951
Parameter block for pxenv_undi_set_station_address()
Definition: pxe_api.h:1108
static struct net_device * netdev
Definition: gdbudp.c:52
static void undinet_hook_isr(unsigned int irq)
Hook UNDI interrupt service routine.
Definition: undinet.c:385
unsigned int irq
Assigned IRQ number.
Definition: undinet.c:52
#define PXENV_UNDI_OPEN
PXE API function code for pxenv_undi_open()
Definition: pxe_api.h:941
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
#define enable_irq(x)
Definition: pic8259.h:51
#define FLTR_DIRECTED
Accept "directed" packets.
Definition: pxe_api.h:949
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:381
Parameter block for pxenv_undi_open()
Definition: pxe_api.h:958
void * memset(void *dest, int character, size_t len) __nonnull

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

◆ undinet_irq()

static void undinet_irq ( struct net_device netdev,
int  enable 
)
static

Enable/disable interrupts.

Parameters
netdevNet device
enableInterrupts should be enabled

Definition at line 788 of file undinet.c.

788  {
789  struct undi_nic *undinic = netdev->priv;
790 
791  /* Cannot support interrupts yet */
792  DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
793  undinic, ( enable ? "enable" : "disable" ) );
794 }
An UNDI NIC.
Definition: undinet.c:48
#define DBGC(...)
Definition: compiler.h:505
void * priv
Driver private data.
Definition: netdevice.h:425
static struct net_device * netdev
Definition: gdbudp.c:52

References DBGC, netdev, and net_device::priv.

◆ undinet_irq_is_broken()

static int undinet_irq_is_broken ( struct device_description desc)
static

Check for devices with broken support for generating interrupts.

Parameters
descDevice description
Return values
irq_is_brokenInterrupt support is broken; no interrupts are generated

Definition at line 842 of file undinet.c.

842  {
843  const struct undinet_irq_broken *broken;
844  struct pci_device pci;
845  uint16_t subsys_vendor;
846  uint16_t subsys;
847  unsigned int i;
848 
849  /* Ignore non-PCI devices */
850  if ( desc->bus_type != BUS_TYPE_PCI )
851  return 0;
852 
853  /* Read subsystem IDs */
854  pci_init ( &pci, desc->location );
855  pci_read_config_word ( &pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor );
856  pci_read_config_word ( &pci, PCI_SUBSYSTEM_ID, &subsys );
857 
858  /* Check for a match against the broken device list */
859  for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
860  sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
861  broken = &undinet_irq_broken_list[i];
862  if ( ( broken->pci_vendor == desc->vendor ) &&
863  ( broken->pci_device == desc->device ) &&
864  ( ( broken->pci_subsys_vendor == subsys_vendor ) ||
865  ( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
866  ( ( broken->pci_subsys == subsys ) ||
867  ( broken->pci_subsys == PCI_ANY_ID ) ) ) {
868  return 1;
869  }
870  }
871  return 0;
872 }
unsigned short uint16_t
Definition: stdint.h:11
uint16_t pci_subsys_vendor
PCI subsystem vendor ID.
Definition: undinet.c:812
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
Read 16-bit word from PCI configuration space.
unsigned int vendor
Vendor ID.
Definition: device.h:31
#define PCI_SUBSYSTEM_ID
PCI subsystem ID.
Definition: pci.h:77
uint16_t pci_vendor
PCI vendor ID.
Definition: undinet.c:808
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
unsigned int location
Location.
Definition: device.h:29
A PCI device.
Definition: pci.h:187
static const struct undinet_irq_broken undinet_irq_broken_list[]
List of devices with broken support for generating interrupts.
Definition: undinet.c:828
uint16_t pci_device
PCI device ID.
Definition: undinet.c:810
unsigned int bus_type
Bus type.
Definition: device.h:24
unsigned int device
Device ID.
Definition: device.h:33
#define PCI_SUBSYSTEM_VENDOR_ID
PCI subsystem vendor ID.
Definition: pci.h:74
static void pci_init(struct pci_device *pci, unsigned int busdevfn)
Initialise PCI device.
Definition: pci.h:313
uint16_t pci_subsys
PCI subsystem ID.
Definition: undinet.c:814
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:163
A device with broken support for generating interrupts.
Definition: undinet.c:806

References device_description::bus_type, BUS_TYPE_PCI, device_description::device, device_description::location, 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, undinet_irq_broken_list, and device_description::vendor.

Referenced by undinet_probe().

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

Variable Documentation

◆ __profiler

struct undinet_profiler undinet_misc_profiler __profiler
static
Initial value:
=
{ .name = "undinet.irq" }

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.

Definition at line 108 of file undinet.c.

◆ last_trigger_count

unsigned int last_trigger_count = 0
static

Last observed trigger count.

Definition at line 378 of file undinet.c.

Referenced by undinet_isr_triggered(), and undinet_poll().

◆ undinet_operations

struct net_device_operations undinet_operations
static
Initial value:
= {
.open = undinet_open,
.close = undinet_close,
.transmit = undinet_transmit,
.poll = undinet_poll,
.irq = undinet_irq,
}
static void undinet_poll(struct net_device *netdev)
Poll for received packets.
Definition: undinet.c:566
static void undinet_close(struct net_device *netdev)
Close NIC.
Definition: undinet.c:745
static int undinet_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition: undinet.c:452
static void undinet_irq(struct net_device *netdev, int enable)
Enable/disable interrupts.
Definition: undinet.c:788
static int undinet_open(struct net_device *netdev)
Open NIC.
Definition: undinet.c:698

UNDI network device operations.

Definition at line 797 of file undinet.c.

Referenced by undinet_probe().

◆ undinet_irq_broken_list

const struct undinet_irq_broken undinet_irq_broken_list[]
static
Initial value:
= {
{ 0x8086, 0x1502, PCI_ANY_ID, PCI_ANY_ID },
{ 0x8086, 0x1503, PCI_ANY_ID, PCI_ANY_ID },
{ 0x14e4, 0x1687, PCI_ANY_ID, PCI_ANY_ID },
}
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:163

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

Referenced by undinet_irq_is_broken().