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 RDTSC_IF_PROFILING   "rdtsc\n\t"
 
#define undiisr_irq   __use_data16 ( undiisr_irq )
 
#define undiisr_next_handler   __use_data16 ( undiisr_next_handler )
 
#define undiisr_trigger_count   __use_data16 ( undiisr_trigger_count )
 
#define undinet_tbd   __use_data16 ( undinet_tbd )
 
#define undinet_destaddr   __use_data16 ( undinet_destaddr )
 

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 
static void undinet_close (struct net_device *netdev)
 Close NIC. More...
 
static union u_PXENV_ANY __bss16 (undinet_params)
 UNDI parameter block. More...
 
SEGOFF16_t __bss16 (undinet_entry_point)
 UNDI entry point. More...
 
static const char * undinet_function_name (unsigned int function)
 Name PXE API call. More...
 
static struct undinet_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.

◆ RDTSC_IF_PROFILING

#define RDTSC_IF_PROFILING   "rdtsc\n\t"

Definition at line 109 of file undinet.c.

◆ undiisr_irq

#define undiisr_irq   __use_data16 ( undiisr_irq )

Definition at line 374 of file undinet.c.

◆ undiisr_next_handler

#define undiisr_next_handler   __use_data16 ( undiisr_next_handler )

Definition at line 378 of file undinet.c.

◆ undiisr_trigger_count

#define undiisr_trigger_count   __use_data16 ( undiisr_trigger_count )

Definition at line 382 of file undinet.c.

◆ undinet_tbd

#define undinet_tbd   __use_data16 ( undinet_tbd )

Definition at line 446 of file undinet.c.

◆ undinet_destaddr

#define undinet_destaddr   __use_data16 ( undinet_destaddr )

Definition at line 450 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 752 of file undinet.c.

752  {
753  struct undi_nic *undinic = netdev->priv;
754  struct s_PXENV_UNDI_ISR undi_isr;
755  struct s_PXENV_UNDI_CLOSE undi_close;
756  int rc;
757 
758  /* Ensure ISR has exited cleanly */
759  while ( undinic->isr_processing ) {
760  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
761  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
762  sizeof ( undi_isr ) ) ) != 0 )
763  break;
764  switch ( undi_isr.FuncFlag ) {
767  /* Continue draining */
768  break;
769  default:
770  /* Stop processing */
771  undinic->isr_processing = 0;
772  break;
773  }
774  }
775 
776  /* Close NIC */
777  undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
778  sizeof ( undi_close ) );
779 
780  /* Disable interrupt and unhook ISR if applicable */
781  if ( undinic->irq ) {
782  disable_irq ( undinic->irq );
783  undinet_unhook_isr ( undinic->irq );
784  }
785 
786  DBGC ( undinic, "UNDINIC %p closed\n", undinic );
787 }
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:431
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:278
static void undinet_unhook_isr(unsigned int irq)
Unhook UNDI interrupt service routine.
Definition: undinet.c:407
#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 189 of file undinet.c.

189  {
190  switch ( function ) {
191  case PXENV_START_UNDI:
192  return "PXENV_START_UNDI";
193  case PXENV_STOP_UNDI:
194  return "PXENV_STOP_UNDI";
195  case PXENV_UNDI_STARTUP:
196  return "PXENV_UNDI_STARTUP";
197  case PXENV_UNDI_CLEANUP:
198  return "PXENV_UNDI_CLEANUP";
200  return "PXENV_UNDI_INITIALIZE";
202  return "PXENV_UNDI_RESET_ADAPTER";
203  case PXENV_UNDI_SHUTDOWN:
204  return "PXENV_UNDI_SHUTDOWN";
205  case PXENV_UNDI_OPEN:
206  return "PXENV_UNDI_OPEN";
207  case PXENV_UNDI_CLOSE:
208  return "PXENV_UNDI_CLOSE";
209  case PXENV_UNDI_TRANSMIT:
210  return "PXENV_UNDI_TRANSMIT";
212  return "PXENV_UNDI_SET_MCAST_ADDRESS";
214  return "PXENV_UNDI_SET_STATION_ADDRESS";
216  return "PXENV_UNDI_SET_PACKET_FILTER";
218  return "PXENV_UNDI_GET_INFORMATION";
220  return "PXENV_UNDI_GET_STATISTICS";
222  return "PXENV_UNDI_CLEAR_STATISTICS";
224  return "PXENV_UNDI_INITIATE_DIAGS";
226  return "PXENV_UNDI_FORCE_INTERRUPT";
228  return "PXENV_UNDI_GET_MCAST_ADDRESS";
230  return "PXENV_UNDI_GET_NIC_TYPE";
232  return "PXENV_UNDI_GET_IFACE_INFO";
233  /*
234  * Duplicate case value; this is a bug in the PXE specification.
235  *
236  * case PXENV_UNDI_GET_STATE:
237  * return "PXENV_UNDI_GET_STATE";
238  */
239  case PXENV_UNDI_ISR:
240  return "PXENV_UNDI_ISR";
242  return "PXENV_GET_CACHED_INFO";
243  default:
244  return "UNKNOWN API CALL";
245  }
246 }
#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 254 of file undinet.c.

254  {
255 
256  /* Determine applicable profiler */
257  switch ( function ) {
258  case PXENV_UNDI_TRANSMIT:
259  return &undinet_tx_profiler;
260  case PXENV_UNDI_ISR:
261  return &undinet_isr_profiler;
262  case PXENV_UNKNOWN:
263  return &undinet_unknown_profiler;
264  default:
265  return &undinet_misc_profiler;
266  }
267 }
#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 278 of file undinet.c.

279  {
280  struct undinet_profiler *profiler = undinet_profiler ( function );
281  PXENV_EXIT_t exit;
284  uint32_t stopped;
285  uint32_t after;
286  int discard_D;
287  int rc;
288 
289  /* Copy parameter block and entry point */
290  assert ( params_len <= sizeof ( undinet_params ) );
291  memcpy ( &undinet_params, params, params_len );
292 
293  /* Call real-mode entry point. This calling convention will
294  * work with both the !PXE and the PXENV+ entry points.
295  */
296  profile_start ( &profiler->total );
297  __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
299  "pushl %%eax\n\t"
300  "pushw %%es\n\t"
301  "pushw %%di\n\t"
302  "pushw %%bx\n\t"
303  "lcall *undinet_entry_point\n\t"
304  "movw %%ax, %%bx\n\t"
306  "addw $6, %%sp\n\t"
307  "popl %%edx\n\t"
308  "popl %%ebp\n\t" /* gcc bug */ )
309  : "=a" ( stopped ), "=d" ( started ),
310  "=b" ( exit ), "=D" ( discard_D )
311  : "b" ( function ),
312  "D" ( __from_data16 ( &undinet_params ) )
313  : "ecx", "esi" );
314  profile_stop ( &profiler->total );
315  before = profile_started ( &profiler->total );
316  after = profile_stopped ( &profiler->total );
317  profile_start_at ( &profiler->p2r, before );
318  profile_stop_at ( &profiler->p2r, started );
319  profile_start_at ( &profiler->ext, started );
320  profile_stop_at ( &profiler->ext, stopped );
321  profile_start_at ( &profiler->r2p, stopped );
322  profile_stop_at ( &profiler->r2p, after );
323 
324  /* Determine return status code based on PXENV_EXIT and
325  * PXENV_STATUS
326  */
327  rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
328  0 : -EPXECALL ( undinet_params.Status ) );
329 
330  /* If anything goes wrong, print as much debug information as
331  * it's possible to give.
332  */
333  if ( rc != 0 ) {
334  SEGOFF16_t rm_params = {
335  .segment = rm_ds,
336  .offset = __from_data16 ( &undinet_params ),
337  };
338 
339  DBGC ( undinic, "UNDINIC %p %s failed: %s\n", undinic,
340  undinet_function_name ( function ), strerror ( rc ) );
341  DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
342  "%#02zx, entry point at %04x:%04x\n", undinic,
343  rm_params.segment, rm_params.offset, params_len,
344  undinet_entry_point.segment,
345  undinet_entry_point.offset );
346  DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
347  DBGC_HDA ( undinic, rm_params, params, params_len );
348  DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
349  DBGC_HDA ( undinic, rm_params, &undinet_params, params_len );
350  }
351 
352  /* Copy parameter block back */
353  memcpy ( params, &undinet_params, params_len );
354 
355  return rc;
356 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define DBGC(...)
Definition: compiler.h:505
#define EPXECALL(status)
Definition: undinet.c:63
int32_t before
Initial microcode version.
Definition: ucode.h:16
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:254
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:189
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
void * discard_D
Definition: bigint.h:31
#define undinet_params
Definition: undinet.c:96
unsigned int uint32_t
Definition: stdint.h:12
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
#define RDTSC_IF_PROFILING
Definition: undinet.c:109
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
int32_t after
Final microcode version.
Definition: ucode.h:18
#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:123

References __asm__(), __from_data16, __volatile__(), after, assert(), before, DBGC, DBGC_HDA, discard_D, EPXECALL, memcpy(), profile_start(), profile_start_at(), profile_started(), profile_stop(), profile_stop_at(), profile_stopped(), PXENV_EXIT_SUCCESS, rc, RDTSC_IF_PROFILING, REAL_CODE, rm_ds, started, strerror(), undinet_entry_point, undinet_function_name(), undinet_params, and undinet_profiler().

Referenced by undinet_close(), undinet_open(), undinet_poll(), undinet_probe(), undinet_remove(), and undinet_transmit().

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

392  {
393 
394  assert ( irq <= IRQ_MAX );
395  assert ( undiisr_irq == 0 );
396 
397  undiisr_irq = irq;
398  hook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
400 }
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:374
#define undiisr_next_handler
Definition: undinet.c:378
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 407 of file undinet.c.

407  {
408 
409  assert ( irq <= IRQ_MAX );
410 
411  unhook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
413  undiisr_irq = 0;
414 }
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:374
#define undiisr_next_handler
Definition: undinet.c:378
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 421 of file undinet.c.

421  {
422  unsigned int this_trigger_count;
423 
424  /* Read trigger_count. Do this only once; it is volatile */
425  this_trigger_count = undiisr_trigger_count;
426 
427  if ( this_trigger_count == last_trigger_count ) {
428  /* Not triggered */
429  return 0;
430  } else {
431  /* Triggered */
432  last_trigger_count = this_trigger_count;
433  return 1;
434  }
435 }
#define undiisr_trigger_count
Definition: undinet.c:382
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:385

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

460  {
461  struct undi_nic *undinic = netdev->priv;
462  struct s_PXENV_UNDI_TRANSMIT undi_transmit;
463  const void *ll_dest;
464  const void *ll_source;
465  uint16_t net_proto;
466  unsigned int flags;
468  size_t len;
469  int rc;
470 
471  /* Technically, we ought to make sure that the previous
472  * transmission has completed before we re-use the buffer.
473  * However, many PXE stacks (including at least some Intel PXE
474  * stacks and Etherboot 5.4) fail to generate TX completions.
475  * In practice this won't be a problem, since our TX datapath
476  * has a very low packet volume and we can get away with
477  * assuming that a TX will be complete by the time we want to
478  * transmit the next packet.
479  */
480 
481  /* Some PXE stacks are unable to cope with P_UNKNOWN, and will
482  * always try to prepend a link-layer header. Work around
483  * these stacks by stripping the existing link-layer header
484  * and allowing the PXE stack to (re)construct the link-layer
485  * header itself.
486  */
487  if ( ( rc = eth_pull ( netdev, iobuf, &ll_dest, &ll_source,
488  &net_proto, &flags ) ) != 0 ) {
489  DBGC ( undinic, "UNDINIC %p could not strip Ethernet header: "
490  "%s\n", undinic, strerror ( rc ) );
491  return rc;
492  }
493  memcpy ( undinet_destaddr, ll_dest, sizeof ( undinet_destaddr ) );
494  switch ( net_proto ) {
495  case htons ( ETH_P_IP ) :
496  protocol = P_IP;
497  break;
498  case htons ( ETH_P_ARP ) :
499  protocol = P_ARP;
500  break;
501  case htons ( ETH_P_RARP ) :
502  protocol = P_RARP;
503  break;
504  default:
505  /* Unknown protocol; restore the original link-layer header */
506  iob_push ( iobuf, sizeof ( struct ethhdr ) );
508  break;
509  }
510 
511  /* Copy packet to UNDI I/O buffer */
512  len = iob_len ( iobuf );
513  if ( len > sizeof ( basemem_packet ) )
514  len = sizeof ( basemem_packet );
515  memcpy ( &basemem_packet, iobuf->data, len );
516 
517  /* Create PXENV_UNDI_TRANSMIT data structure */
518  memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
519  undi_transmit.Protocol = protocol;
520  undi_transmit.XmitFlag = ( ( flags & LL_BROADCAST ) ?
522  undi_transmit.DestAddr.segment = rm_ds;
523  undi_transmit.DestAddr.offset = __from_data16 ( &undinet_destaddr );
524  undi_transmit.TBD.segment = rm_ds;
525  undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd );
526 
527  /* Create PXENV_UNDI_TBD data structure */
528  undinet_tbd.ImmedLength = len;
529  undinet_tbd.Xmit.segment = rm_ds;
530  undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
531 
532  /* Issue PXE API call */
533  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT, &undi_transmit,
534  sizeof ( undi_transmit ) ) ) != 0 )
535  goto done;
536 
537  /* Free I/O buffer */
538  netdev_tx_complete ( netdev, iobuf );
539  done:
540  return rc;
541 }
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:752
#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:84
#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:431
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:155
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:278
#define undinet_destaddr
Definition: undinet.c:450
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
#define undinet_tbd
Definition: undinet.c:446
uint32_t len
Length.
Definition: ena.h:14
#define __from_data16(pointer)
Definition: libkir.h:22
void * data
Start of data.
Definition: iobuf.h:48
#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:31
#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 573 of file undinet.c.

573  {
574  struct undi_nic *undinic = netdev->priv;
575  struct s_PXENV_UNDI_ISR undi_isr;
576  struct io_buffer *iobuf = NULL;
577  unsigned int quota = UNDI_RX_QUOTA;
578  size_t len;
579  size_t reserve_len;
580  size_t frag_len;
581  size_t max_frag_len;
582  int rc;
583 
584  if ( ! undinic->isr_processing ) {
585  /* Allow interrupt to occur. Do this even if
586  * interrupts are not known to be supported, since
587  * some cards erroneously report that they do not
588  * support interrupts.
589  */
590  if ( ! undinet_isr_triggered() ) {
591  /* Allow interrupt to occur */
592  profile_start ( &undinet_irq_profiler );
593  __asm__ __volatile__ ( "sti\n\t"
594  "nop\n\t"
595  "nop\n\t"
596  "cli\n\t" );
597  profile_stop ( &undinet_irq_profiler );
598 
599  /* If interrupts are known to be supported,
600  * then do nothing on this poll; wait for the
601  * interrupt to be triggered.
602  */
603  if ( undinic->irq_supported )
604  return;
605  }
606 
607  /* Start ISR processing */
608  undinic->isr_processing = 1;
609  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
610  } else {
611  /* Continue ISR processing */
612  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
613  }
614 
615  /* Run through the ISR loop */
616  while ( quota ) {
617  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
618  sizeof ( undi_isr ) ) ) != 0 ) {
619  netdev_rx_err ( netdev, NULL, rc );
620  break;
621  }
622  switch ( undi_isr.FuncFlag ) {
624  /* We don't care about transmit completions */
625  break;
627  /* Packet fragment received */
628  profile_start ( &undinet_rx_profiler );
629  len = undi_isr.FrameLength;
630  frag_len = undi_isr.BufferLength;
631  reserve_len = ( -undi_isr.FrameHeaderLength &
632  ( UNDI_RX_ALIGN - 1 ) );
633  if ( ( len == 0 ) || ( len < frag_len ) ) {
634  /* Don't laugh. VMWare does it. */
635  DBGC ( undinic, "UNDINIC %p reported insane "
636  "fragment (%zd of %zd bytes)\n",
637  undinic, frag_len, len );
639  break;
640  }
641  if ( ! iobuf ) {
642  iobuf = alloc_iob ( reserve_len + len );
643  if ( ! iobuf ) {
644  DBGC ( undinic, "UNDINIC %p could not "
645  "allocate %zd bytes for RX "
646  "buffer\n", undinic, len );
647  /* Fragment will be dropped */
649  goto done;
650  }
651  iob_reserve ( iobuf, reserve_len );
652  }
653  max_frag_len = iob_tailroom ( iobuf );
654  if ( frag_len > max_frag_len ) {
655  DBGC ( undinic, "UNDINIC %p fragment too big "
656  "(%zd+%zd does not fit into %zd)\n",
657  undinic, iob_len ( iobuf ), frag_len,
658  ( iob_len ( iobuf ) + max_frag_len ) );
659  frag_len = max_frag_len;
660  }
661  copy_from_real ( iob_put ( iobuf, frag_len ),
662  undi_isr.Frame.segment,
663  undi_isr.Frame.offset, frag_len );
664  if ( iob_len ( iobuf ) == len ) {
665  /* Whole packet received; deliver it */
666  netdev_rx ( netdev, iob_disown ( iobuf ) );
667  quota--;
668  /* Etherboot 5.4 fails to return all packets
669  * under mild load; pretend it retriggered.
670  */
671  if ( undinic->hacks & UNDI_HACK_EB54 )
673  }
674  profile_stop ( &undinet_rx_profiler );
675  break;
677  /* Processing complete */
678  undinic->isr_processing = 0;
679  goto done;
680  default:
681  /* Should never happen. VMWare does it routinely. */
682  DBGC ( undinic, "UNDINIC %p ISR returned invalid "
683  "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
684  undinic->isr_processing = 0;
685  goto done;
686  }
687  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
688  }
689 
690  done:
691  if ( iobuf ) {
692  DBGC ( undinic, "UNDINIC %p returned incomplete packet "
693  "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
694  ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
695  netdev_rx_err ( netdev, iobuf, -EINVAL );
696  }
697 }
#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:120
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition: netdevice.c:586
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:129
#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:421
#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:212
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:385
void * priv
Driver private data.
Definition: netdevice.h:431
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:155
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:175
__asm__ __volatile__("\n1:\n\t" "movb -1(%3,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %4, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c), "+m"(*value) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
#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:278
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition: netdevice.c:548
#define copy_from_real
Definition: libkir.h:79
#define iob_reserve(iobuf, len)
Definition: iobuf.h:67
__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:321
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:33

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

705  {
706  struct undi_nic *undinic = netdev->priv;
707  struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address;
708  struct s_PXENV_UNDI_OPEN undi_open;
709  int rc;
710 
711  /* Hook interrupt service routine and enable interrupt if applicable */
712  if ( undinic->irq ) {
713  undinet_hook_isr ( undinic->irq );
714  enable_irq ( undinic->irq );
715  send_eoi ( undinic->irq );
716  }
717 
718  /* Set station address. Required for some PXE stacks; will
719  * spuriously fail on others. Ignore failures. We only ever
720  * use it to set the MAC address to the card's permanent value
721  * anyway.
722  */
723  memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
724  sizeof ( undi_set_address.StationAddress ) );
726  &undi_set_address, sizeof ( undi_set_address ) );
727 
728  /* Open NIC. We ask for promiscuous operation, since it's the
729  * only way to ask for all multicast addresses. On any
730  * switched network, it shouldn't really make a difference to
731  * performance.
732  */
733  memset ( &undi_open, 0, sizeof ( undi_open ) );
734  undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
735  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
736  sizeof ( undi_open ) ) ) != 0 )
737  goto err;
738 
739  DBGC ( undinic, "UNDINIC %p opened\n", undinic );
740  return 0;
741 
742  err:
743  undinet_close ( netdev );
744  return rc;
745 }
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:752
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * priv
Driver private data.
Definition: netdevice.h:431
#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:392
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:278
#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:387
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 795 of file undinet.c.

795  {
796  struct undi_nic *undinic = netdev->priv;
797 
798  /* Cannot support interrupts yet */
799  DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
800  undinic, ( enable ? "enable" : "disable" ) );
801 }
An UNDI NIC.
Definition: undinet.c:48
#define DBGC(...)
Definition: compiler.h:505
void * priv
Driver private data.
Definition: netdevice.h:431
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 849 of file undinet.c.

849  {
850  const struct undinet_irq_broken *broken;
851  struct pci_device pci;
852  uint16_t subsys_vendor;
853  uint16_t subsys;
854  unsigned int i;
855 
856  /* Ignore non-PCI devices */
857  if ( desc->bus_type != BUS_TYPE_PCI )
858  return 0;
859 
860  /* Read subsystem IDs */
861  pci_init ( &pci, desc->location );
862  pci_read_config_word ( &pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor );
863  pci_read_config_word ( &pci, PCI_SUBSYSTEM_ID, &subsys );
864 
865  /* Check for a match against the broken device list */
866  for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
867  sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
868  broken = &undinet_irq_broken_list[i];
869  if ( ( broken->pci_vendor == desc->vendor ) &&
870  ( broken->pci_device == desc->device ) &&
871  ( ( broken->pci_subsys_vendor == subsys_vendor ) ||
872  ( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
873  ( ( broken->pci_subsys == subsys ) ||
874  ( broken->pci_subsys == PCI_ANY_ID ) ) ) {
875  return 1;
876  }
877  }
878  return 0;
879 }
unsigned short uint16_t
Definition: stdint.h:11
uint64_t desc
Microcode descriptor list physical address.
Definition: ucode.h:12
uint16_t pci_subsys_vendor
PCI subsystem vendor ID.
Definition: undinet.c:819
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
Read 16-bit word from PCI configuration space.
#define PCI_SUBSYSTEM_ID
PCI subsystem ID.
Definition: pci.h:78
uint16_t pci_vendor
PCI vendor ID.
Definition: undinet.c:815
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
A PCI device.
Definition: pci.h:206
static const struct undinet_irq_broken undinet_irq_broken_list[]
List of devices with broken support for generating interrupts.
Definition: undinet.c:835
uint16_t pci_device
PCI device ID.
Definition: undinet.c:817
#define PCI_SUBSYSTEM_VENDOR_ID
PCI subsystem vendor ID.
Definition: pci.h:75
static void pci_init(struct pci_device *pci, unsigned int busdevfn)
Initialise PCI device.
Definition: pci.h:334
uint16_t pci_subsys
PCI subsystem ID.
Definition: undinet.c:821
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:182
A device with broken support for generating interrupts.
Definition: undinet.c:813

References BUS_TYPE_PCI, desc, PCI_ANY_ID, undinet_irq_broken::pci_device, pci_init(), pci_read_config_word(), undinet_irq_broken::pci_subsys, undinet_irq_broken::pci_subsys_vendor, PCI_SUBSYSTEM_ID, PCI_SUBSYSTEM_VENDOR_ID, undinet_irq_broken::pci_vendor, and undinet_irq_broken_list.

Referenced by undinet_probe().

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

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

◆ last_trigger_count

unsigned int last_trigger_count = 0
static

Last observed trigger count.

Definition at line 385 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:573
static void undinet_close(struct net_device *netdev)
Close NIC.
Definition: undinet.c:752
static int undinet_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition: undinet.c:459
static void undinet_irq(struct net_device *netdev, int enable)
Enable/disable interrupts.
Definition: undinet.c:795
static int undinet_open(struct net_device *netdev)
Open NIC.
Definition: undinet.c:705

UNDI network device operations.

Definition at line 804 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:182

List of devices with broken support for generating interrupts.

Some PXE stacks are known to claim that IRQs are supported, but then never generate interrupts. No satisfactory solution has been found to this problem; the workaround is to add the PCI vendor and device IDs to this list. This is something of a hack, since it will generate false positives for identical devices with a working PXE stack (e.g. those that have been reflashed with iPXE), but it's an improvement on the current situation.

Definition at line 835 of file undinet.c.

Referenced by undinet_irq_is_broken().