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_imr   __use_data16 ( undiisr_imr )
 
#define undiisr_bit   __use_data16 ( undiisr_bit )
 
#define undiisr_rearm   __use_data16 ( undiisr_rearm )
 
#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...
 
uint16_t __data16 (undiisr_imr)
 IRQ mask register. More...
 
uint8_t __data16 (undiisr_bit)
 IRQ mask bit. More...
 
uint8_t __data16 (undiisr_rearm)
 IRQ rearm flag. 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 net_device *netdev)
 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_imr

#define undiisr_imr   __use_data16 ( undiisr_imr )

Definition at line 378 of file undinet.c.

◆ undiisr_bit

#define undiisr_bit   __use_data16 ( undiisr_bit )

Definition at line 382 of file undinet.c.

◆ undiisr_rearm

#define undiisr_rearm   __use_data16 ( undiisr_rearm )

Definition at line 386 of file undinet.c.

◆ undiisr_next_handler

#define undiisr_next_handler   __use_data16 ( undiisr_next_handler )

Definition at line 390 of file undinet.c.

◆ undiisr_trigger_count

#define undiisr_trigger_count   __use_data16 ( undiisr_trigger_count )

Definition at line 394 of file undinet.c.

◆ undinet_tbd

#define undinet_tbd   __use_data16 ( undinet_tbd )

Definition at line 461 of file undinet.c.

◆ undinet_destaddr

#define undinet_destaddr   __use_data16 ( undinet_destaddr )

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

775  {
776  struct undi_nic *undinic = netdev->priv;
777  struct s_PXENV_UNDI_ISR undi_isr;
778  struct s_PXENV_UNDI_CLOSE undi_close;
779  int rc;
780 
781  /* Ensure ISR has exited cleanly */
782  while ( undinic->isr_processing ) {
783  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
784  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
785  sizeof ( undi_isr ) ) ) != 0 )
786  break;
787  switch ( undi_isr.FuncFlag ) {
790  /* Continue draining */
791  break;
792  default:
793  /* Stop processing */
794  undinic->isr_processing = 0;
795  break;
796  }
797  }
798 
799  /* Close NIC */
800  undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
801  sizeof ( undi_close ) );
802 
803  /* Disable interrupt and unhook ISR if applicable */
804  if ( undinic->irq ) {
805  disable_irq ( undinic->irq );
806  undinet_unhook_isr ( undinic->irq );
807  }
808 
809  DBGC ( undinic, "UNDINIC %p closed\n", undinic );
810 }
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 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:422
#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, 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:79
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:173
static void profile_stop_at(struct profiler *profiler, unsigned long stopped)
Stop profiling.
Definition: profile.h:145
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:160
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__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
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:131
__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:96
#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/7]

uint8_t __data16 ( undiisr_irq  )

IRQ number.

◆ __data16() [2/7]

uint16_t __data16 ( undiisr_imr  )

IRQ mask register.

◆ __data16() [3/7]

uint8_t __data16 ( undiisr_bit  )

IRQ mask bit.

◆ __data16() [4/7]

uint8_t __data16 ( undiisr_rearm  )

IRQ rearm flag.

◆ __data16() [5/7]

struct segoff __data16 ( undiisr_next_handler  )

IRQ chain vector.

◆ __data16() [6/7]

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

404  {
405 
406  assert ( irq <= IRQ_MAX );
407  assert ( undiisr_irq == 0 );
408 
409  undiisr_irq = irq;
410  undiisr_imr = IMR_REG ( irq );
411  undiisr_bit = IMR_BIT ( irq );
412  undiisr_rearm = 0;
413  hook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
415 }
#define undiisr_rearm
Definition: undinet.c:386
#define IMR_BIT(x)
Definition: pic8259.h:49
unsigned long intptr_t
Definition: stdint.h:21
#define undiisr_imr
Definition: undinet.c:378
void hook_bios_interrupt(unsigned int interrupt, unsigned int handler, struct segoff *chain_vector)
Hook INT vector.
Definition: biosint.c:25
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define IRQ_INT(irq)
Definition: pic8259.h:57
#define undiisr_irq
Definition: undinet.c:374
#define undiisr_bit
Definition: undinet.c:382
#define IMR_REG(x)
Definition: pic8259.h:48
#define undiisr_next_handler
Definition: undinet.c:390
void undiisr(void)
UNDI interrupt service routine.
#define IRQ_MAX
Definition: pic8259.h:60

References assert(), hook_bios_interrupt(), IMR_BIT, IMR_REG, IRQ_INT, IRQ_MAX, undiisr(), undiisr_bit, undiisr_imr, undiisr_irq, undiisr_next_handler, and undiisr_rearm.

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

422  {
423 
424  assert ( irq <= IRQ_MAX );
425 
426  unhook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
428  undiisr_irq = 0;
429 }
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:70
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define IRQ_INT(irq)
Definition: pic8259.h:57
#define undiisr_irq
Definition: undinet.c:374
#define undiisr_next_handler
Definition: undinet.c:390
void undiisr(void)
UNDI interrupt service routine.
#define IRQ_MAX
Definition: pic8259.h:60

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

436  {
437  unsigned int this_trigger_count;
438 
439  /* Read trigger_count. Do this only once; it is volatile */
440  this_trigger_count = undiisr_trigger_count;
441 
442  if ( this_trigger_count == last_trigger_count ) {
443  /* Not triggered */
444  return 0;
445  } else {
446  /* Triggered */
447  last_trigger_count = this_trigger_count;
448  return 1;
449  }
450 }
#define undiisr_trigger_count
Definition: undinet.c:394
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:397

References last_trigger_count, and undiisr_trigger_count.

Referenced by undinet_poll().

◆ __data16() [7/7]

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

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

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

588  {
589  struct undi_nic *undinic = netdev->priv;
590  struct s_PXENV_UNDI_ISR undi_isr;
591  struct io_buffer *iobuf = NULL;
592  unsigned int quota = UNDI_RX_QUOTA;
593  size_t len;
594  size_t reserve_len;
595  size_t frag_len;
596  size_t max_frag_len;
597  int rc;
598 
599  if ( ! undinic->isr_processing ) {
600  /* Allow interrupt to occur. Do this even if
601  * interrupts are not known to be supported, since
602  * some cards erroneously report that they do not
603  * support interrupts.
604  */
605  if ( ! undinet_isr_triggered() ) {
606 
607  /* Rearm interrupt if needed */
608  if ( undiisr_rearm ) {
609  undiisr_rearm = 0;
610  assert ( undinic->irq != 0 );
611  enable_irq ( undinic->irq );
612  }
613 
614  /* Allow interrupt to occur */
615  profile_start ( &undinet_irq_profiler );
616  __asm__ __volatile__ ( "sti\n\t"
617  "nop\n\t"
618  "nop\n\t"
619  "cli\n\t" );
620  profile_stop ( &undinet_irq_profiler );
621 
622  /* If interrupts are known to be supported,
623  * then do nothing on this poll; wait for the
624  * interrupt to be triggered.
625  */
626  if ( undinic->irq_supported )
627  return;
628  }
629 
630  /* Start ISR processing */
631  undinic->isr_processing = 1;
632  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
633  } else {
634  /* Continue ISR processing */
635  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
636  }
637 
638  /* Run through the ISR loop */
639  while ( quota ) {
640  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
641  sizeof ( undi_isr ) ) ) != 0 ) {
642  netdev_rx_err ( netdev, NULL, rc );
643  break;
644  }
645  switch ( undi_isr.FuncFlag ) {
647  /* We don't care about transmit completions */
648  break;
650  /* Packet fragment received */
651  profile_start ( &undinet_rx_profiler );
652  len = undi_isr.FrameLength;
653  frag_len = undi_isr.BufferLength;
654  reserve_len = ( -undi_isr.FrameHeaderLength &
655  ( UNDI_RX_ALIGN - 1 ) );
656  if ( ( len == 0 ) || ( len < frag_len ) ) {
657  /* Don't laugh. VMWare does it. */
658  DBGC ( undinic, "UNDINIC %p reported insane "
659  "fragment (%zd of %zd bytes)\n",
660  undinic, frag_len, len );
662  break;
663  }
664  if ( ! iobuf ) {
665  iobuf = alloc_iob ( reserve_len + len );
666  if ( ! iobuf ) {
667  DBGC ( undinic, "UNDINIC %p could not "
668  "allocate %zd bytes for RX "
669  "buffer\n", undinic, len );
670  /* Fragment will be dropped */
672  goto done;
673  }
674  iob_reserve ( iobuf, reserve_len );
675  }
676  max_frag_len = iob_tailroom ( iobuf );
677  if ( frag_len > max_frag_len ) {
678  DBGC ( undinic, "UNDINIC %p fragment too big "
679  "(%zd+%zd does not fit into %zd)\n",
680  undinic, iob_len ( iobuf ), frag_len,
681  ( iob_len ( iobuf ) + max_frag_len ) );
682  frag_len = max_frag_len;
683  }
684  copy_from_real ( iob_put ( iobuf, frag_len ),
685  undi_isr.Frame.segment,
686  undi_isr.Frame.offset, frag_len );
687  if ( iob_len ( iobuf ) == len ) {
688  /* Whole packet received; deliver it */
689  netdev_rx ( netdev, iob_disown ( iobuf ) );
690  quota--;
691  /* Etherboot 5.4 fails to return all packets
692  * under mild load; pretend it retriggered.
693  */
694  if ( undinic->hacks & UNDI_HACK_EB54 )
696  }
697  profile_stop ( &undinet_rx_profiler );
698  break;
700  /* Processing complete */
701  undinic->isr_processing = 0;
702  goto done;
703  default:
704  /* Should never happen. VMWare does it routinely. */
705  DBGC ( undinic, "UNDINIC %p ISR returned invalid "
706  "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
707  undinic->isr_processing = 0;
708  goto done;
709  }
710  undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
711  }
712 
713  done:
714  if ( iobuf ) {
715  DBGC ( undinic, "UNDINIC %p returned incomplete packet "
716  "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
717  ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
718  netdev_rx_err ( netdev, iobuf, -EINVAL );
719  }
720 }
#define UNDI_HACK_EB54
Work around Etherboot 5.4 bugs.
Definition: undinet.c:71
#define undiisr_rearm
Definition: undinet.c:386
#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:124
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:173
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:130
#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:436
#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:216
static unsigned int last_trigger_count
Last observed trigger count.
Definition: undinet.c:397
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
void * priv
Driver private data.
Definition: netdevice.h:431
ring len
Length.
Definition: dwmac.h:231
static struct net_device * netdev
Definition: gdbudp.c:52
#define UNDI_RX_ALIGN
Alignment of received frame payload.
Definition: undinet.c:85
unsigned int irq
Assigned IRQ number.
Definition: undinet.c:52
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:160
#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:159
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
static size_t iob_tailroom(struct io_buffer *iobuf)
Calculate available space at end of an I/O buffer.
Definition: iobuf.h:179
#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:71
__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")
#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:37

References __asm__(), __volatile__(), alloc_iob(), assert(), 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, 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, undiisr_rearm, 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 728 of file undinet.c.

728  {
729  struct undi_nic *undinic = netdev->priv;
730  struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address;
731  struct s_PXENV_UNDI_OPEN undi_open;
732  int rc;
733 
734  /* Hook interrupt service routine and enable interrupt if applicable */
735  if ( undinic->irq ) {
736  undinet_hook_isr ( undinic->irq );
737  enable_irq ( undinic->irq );
738  send_eoi ( undinic->irq );
739  }
740 
741  /* Set station address. Required for some PXE stacks; will
742  * spuriously fail on others. Ignore failures. We only ever
743  * use it to set the MAC address to the card's permanent value
744  * anyway.
745  */
746  memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
747  sizeof ( undi_set_address.StationAddress ) );
749  &undi_set_address, sizeof ( undi_set_address ) );
750 
751  /* Open NIC. We ask for promiscuous operation, since it's the
752  * only way to ask for all multicast addresses. On any
753  * switched network, it shouldn't really make a difference to
754  * performance.
755  */
756  memset ( &undi_open, 0, sizeof ( undi_open ) );
757  undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
758  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
759  sizeof ( undi_open ) ) ) != 0 )
760  goto err;
761 
762  DBGC ( undinic, "UNDINIC %p opened\n", undinic );
763  return 0;
764 
765  err:
766  undinet_close ( netdev );
767  return rc;
768 }
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:775
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:404
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 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, 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 818 of file undinet.c.

818  {
819  struct undi_nic *undinic = netdev->priv;
820 
821  /* Cannot support interrupts yet */
822  DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
823  undinic, ( enable ? "enable" : "disable" ) );
824 }
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 net_device netdev)
static

Check for devices with broken support for generating interrupts.

Parameters
netdevNet device
Return values
irq_is_brokenInterrupt support is broken; no interrupts are generated

Definition at line 874 of file undinet.c.

874  {
875  struct undi_nic *undinic = netdev->priv;
876  struct device_description *desc = &netdev->dev->desc;
877  const struct undinet_irq_broken *broken;
878  struct pci_device pci;
879  uint16_t subsys_vendor;
880  uint16_t subsys;
881  unsigned int i;
882 
883  /* Ignore non-PCI devices */
884  if ( desc->bus_type != BUS_TYPE_PCI )
885  return 0;
886 
887  /* Read subsystem IDs */
888  pci_init ( &pci, desc->location );
889  pci_read_config_word ( &pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor );
890  pci_read_config_word ( &pci, PCI_SUBSYSTEM_ID, &subsys );
891 
892  /* Check for a match against the broken device list */
893  for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
894  sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
895  broken = &undinet_irq_broken_list[i];
896  if ( ( broken->pci_vendor == desc->vendor ) &&
897  ( broken->pci_device == desc->device ) &&
898  ( ( broken->pci_subsys_vendor == subsys_vendor ) ||
899  ( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
900  ( ( broken->pci_subsys == subsys ) ||
901  ( broken->pci_subsys == PCI_ANY_ID ) ) ) {
902  DBGC ( undinic, "UNDINIC %p %04x:%04x subsys "
903  "%04x:%04x has broken interrupts\n",
904  undinic, desc->vendor, desc->device,
905  subsys_vendor, subsys );
906  return 1;
907  }
908  }
909 
910  /* Check for a PCI Express capability. Given the number of
911  * issues found with legacy INTx emulation on PCIe systems, we
912  * assume that there is a high chance of interrupts not
913  * working on any PCIe device.
914  */
915  if ( pci_find_capability ( &pci, PCI_CAP_ID_EXP ) ) {
916  DBGC ( undinic, "UNDINIC %p is PCI Express: assuming "
917  "interrupts are unreliable\n", undinic );
918  return 1;
919  }
920 
921  return 0;
922 }
unsigned short uint16_t
Definition: stdint.h:11
An UNDI NIC.
Definition: undinet.c:48
int pci_find_capability(struct pci_device *pci, int cap)
Look for a PCI capability.
Definition: pciextra.c:38
#define DBGC(...)
Definition: compiler.h:505
uint16_t pci_subsys_vendor
PCI subsystem vendor ID.
Definition: undinet.c:842
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
A hardware device description.
Definition: device.h:19
struct ena_llq_option desc
Descriptor counts.
Definition: ena.h:20
uint16_t pci_vendor
PCI vendor ID.
Definition: undinet.c:838
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
void * priv
Driver private data.
Definition: netdevice.h:431
static struct net_device * netdev
Definition: gdbudp.c:52
A PCI device.
Definition: pci.h:210
#define PCI_CAP_ID_EXP
PCI Express.
Definition: pci.h:97
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
static const struct undinet_irq_broken undinet_irq_broken_list[]
List of devices with broken support for generating interrupts.
Definition: undinet.c:858
uint16_t pci_device
PCI device ID.
Definition: undinet.c:840
struct device_description desc
Device description.
Definition: device.h:82
#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:340
uint16_t pci_subsys
PCI subsystem ID.
Definition: undinet.c:844
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:186
A device with broken support for generating interrupts.
Definition: undinet.c:836

References BUS_TYPE_PCI, DBGC, desc, device::desc, net_device::dev, netdev, PCI_ANY_ID, PCI_CAP_ID_EXP, undinet_irq_broken::pci_device, pci_find_capability(), 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, net_device::priv, 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 931 of file undinet.c.

931  {
932  struct net_device *netdev;
933  struct undi_nic *undinic;
934  struct s_PXENV_START_UNDI start_undi;
935  struct s_PXENV_UNDI_STARTUP undi_startup;
936  struct s_PXENV_UNDI_INITIALIZE undi_init;
937  struct s_PXENV_UNDI_GET_INFORMATION undi_info;
938  struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
939  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
940  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
941  struct s_PXENV_STOP_UNDI stop_undi;
942  unsigned int retry;
943  int rc;
944 
945  /* Allocate net device */
946  netdev = alloc_etherdev ( sizeof ( *undinic ) );
947  if ( ! netdev )
948  return -ENOMEM;
950  undinic = netdev->priv;
951  undi_set_drvdata ( undi, netdev );
952  netdev->dev = dev;
953  memset ( undinic, 0, sizeof ( *undinic ) );
954  undinet_entry_point = undi->entry;
955  DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
956 
957  /* Hook in UNDI stack */
958  if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
959  memset ( &start_undi, 0, sizeof ( start_undi ) );
960  start_undi.AX = undi->pci_busdevfn;
961  start_undi.BX = undi->isapnp_csn;
962  start_undi.DX = undi->isapnp_read_port;
963  start_undi.ES = BIOS_SEG;
964  start_undi.DI = find_pnp_bios();
965  if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
966  &start_undi,
967  sizeof ( start_undi ) ) ) != 0 )
968  goto err_start_undi;
969  }
970  undi->flags |= UNDI_FL_STARTED;
971 
972  /* Bring up UNDI stack */
973  if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
974  memset ( &undi_startup, 0, sizeof ( undi_startup ) );
975  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
976  &undi_startup,
977  sizeof ( undi_startup ) ) ) != 0 )
978  goto err_undi_startup;
979  /* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
980  * due to a transient condition (e.g. media test
981  * failing because the link has only just come out of
982  * reset). We may therefore need to retry this call
983  * several times.
984  */
985  for ( retry = 0 ; ; ) {
986  memset ( &undi_init, 0, sizeof ( undi_init ) );
987  if ( ( rc = undinet_call ( undinic,
989  &undi_init,
990  sizeof ( undi_init ) ) ) ==0)
991  break;
992  if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
993  goto err_undi_initialize;
994  DBGC ( undinic, "UNDINIC %p retrying "
995  "PXENV_UNDI_INITIALIZE (retry %d)\n",
996  undinic, retry );
997  /* Delay to allow link to settle if necessary */
999  }
1000  }
1001  undi->flags |= UNDI_FL_INITIALIZED;
1002 
1003  /* Get device information */
1004  memset ( &undi_info, 0, sizeof ( undi_info ) );
1005  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
1006  &undi_info, sizeof ( undi_info ) ) ) != 0 )
1007  goto err_undi_get_information;
1008  memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
1009  memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
1010  undinic->irq = undi_info.IntNumber;
1011  if ( undinic->irq > IRQ_MAX ) {
1012  DBGC ( undinic, "UNDINIC %p ignoring invalid IRQ %d\n",
1013  undinic, undinic->irq );
1014  undinic->irq = 0;
1015  }
1016  DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
1017  undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
1018  if ( undinic->irq ) {
1019  /* Sanity check - prefix should have disabled the IRQ */
1020  assert ( ! irq_enabled ( undinic->irq ) );
1021  }
1022 
1023  /* Get interface information */
1024  memset ( &undi_iface, 0, sizeof ( undi_iface ) );
1025  if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
1026  &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
1027  goto err_undi_get_iface_info;
1028  DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
1029  undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
1030  undi_iface.ServiceFlags );
1031  if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
1032  ( undinic->irq != 0 ) ) {
1033  undinic->irq_supported = 1;
1034  }
1035  DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
1036  ( undinic->irq_supported ? "interrupt" : "polling" ) );
1037  if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
1038  sizeof ( undi_iface.IfaceType ) ) == 0 ) {
1039  DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
1040  undinic );
1041  undinic->hacks |= UNDI_HACK_EB54;
1042  }
1043  if ( undinet_irq_is_broken ( netdev ) ) {
1044  DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
1045  "broken interrupts\n", undinic );
1046  undinic->irq_supported = 0;
1047  }
1048 
1049  /* Register network device */
1050  if ( ( rc = register_netdev ( netdev ) ) != 0 )
1051  goto err_register;
1052 
1053  /* Mark as link up; we don't handle link state */
1054  netdev_link_up ( netdev );
1055 
1056  DBGC ( undinic, "UNDINIC %p added\n", undinic );
1057  return 0;
1058 
1059  err_register:
1060  err_undi_get_iface_info:
1061  err_undi_get_information:
1062  err_undi_initialize:
1063  /* Shut down UNDI stack */
1064  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1065  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
1066  sizeof ( undi_shutdown ) );
1067  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1068  undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
1069  sizeof ( undi_cleanup ) );
1070  undi->flags &= ~UNDI_FL_INITIALIZED;
1071  err_undi_startup:
1072  /* Unhook UNDI stack */
1073  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1074  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1075  sizeof ( stop_undi ) );
1076  undi->flags &= ~UNDI_FL_STARTED;
1077  err_start_undi:
1078  netdev_nullify ( netdev );
1079  netdev_put ( netdev );
1080  undi_set_drvdata ( undi, NULL );
1081  return rc;
1082 }
#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
static int undinet_irq_is_broken(struct net_device *netdev)
Check for devices with broken support for generating interrupts.
Definition: undinet.c:874
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:518
#define ENOMEM
Not enough space.
Definition: errno.h:534
void * memcpy(void *dest, const void *src, size_t len) __nonnull
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:575
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:788
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:531
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
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:827
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:60
#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(), assert(), s_PXENV_START_UNDI::AX, BIOS_SEG, s_PXENV_START_UNDI::BX, s_PXENV_UNDI_GET_INFORMATION::CurrentNodeAddress, DBGC, 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 1089 of file undinet.c.

1089  {
1090  struct net_device *netdev = undi_get_drvdata ( undi );
1091  struct undi_nic *undinic = netdev->priv;
1092  struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
1093  struct s_PXENV_UNDI_CLEANUP undi_cleanup;
1094  struct s_PXENV_STOP_UNDI stop_undi;
1095 
1096  /* Unregister net device */
1098 
1099  /* If we are preparing for an OS boot, or if we cannot exit
1100  * via the PXE stack, then shut down the PXE stack.
1101  */
1102  if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
1103 
1104  /* Shut down UNDI stack */
1105  memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1106  undinet_call ( undinic, PXENV_UNDI_SHUTDOWN,
1107  &undi_shutdown, sizeof ( undi_shutdown ) );
1108  memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1109  undinet_call ( undinic, PXENV_UNDI_CLEANUP,
1110  &undi_cleanup, sizeof ( undi_cleanup ) );
1111  undi->flags &= ~UNDI_FL_INITIALIZED;
1112 
1113  /* Unhook UNDI stack */
1114  memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1115  undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1116  sizeof ( stop_undi ) );
1117  undi->flags &= ~UNDI_FL_STARTED;
1118  }
1119 
1120  /* Clear entry point */
1121  memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
1122 
1123  /* Free network device */
1124  netdev_nullify ( netdev );
1125  netdev_put ( netdev );
1126 
1127  DBGC ( undinic, "UNDINIC %p removed\n", undinic );
1128 }
#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:575
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:531
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 397 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:588
static void undinet_close(struct net_device *netdev)
Close NIC.
Definition: undinet.c:775
static int undinet_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet.
Definition: undinet.c:474
static void undinet_irq(struct net_device *netdev, int enable)
Enable/disable interrupts.
Definition: undinet.c:818
static int undinet_open(struct net_device *netdev)
Open NIC.
Definition: undinet.c:728

UNDI network device operations.

Definition at line 827 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 },
{ 0x8086, 0x1521, 0x1043, PCI_ANY_ID },
}
#define PCI_ANY_ID
Match-anything ID.
Definition: pci.h:186

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

Referenced by undinet_irq_is_broken().