iPXE
pxe_undi.c
Go to the documentation of this file.
1 /** @file
2  *
3  * PXE UNDI API
4  *
5  */
6 
7 /*
8  * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of the
13  * License, or any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301, USA.
24  *
25  * You can also choose to distribute this program under the terms of
26  * the Unmodified Binary Distribution Licence (as given in the file
27  * COPYING.UBDL), provided that you have satisfied its requirements.
28  */
29 
30 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
31 
32 #include <stdint.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <byteswap.h>
36 #include <basemem_packet.h>
37 #include <ipxe/netdevice.h>
38 #include <ipxe/iobuf.h>
39 #include <ipxe/device.h>
40 #include <ipxe/pci.h>
41 #include <ipxe/if_ether.h>
42 #include <ipxe/ip.h>
43 #include <ipxe/arp.h>
44 #include <ipxe/rarp.h>
45 #include <ipxe/profile.h>
46 #include "pxe.h"
47 
48 /**
49  * Count of outstanding transmitted packets
50  *
51  * This is incremented each time PXENV_UNDI_TRANSMIT is called, and
52  * decremented each time that PXENV_UNDI_ISR is called with the TX
53  * queue empty, stopping when the count reaches zero. This allows us
54  * to provide a pessimistic approximation of TX completion events to
55  * the PXE NBP simply by monitoring the netdev's TX queue.
56  */
57 static int undi_tx_count = 0;
58 
60 
61 /** Transmit profiler */
62 static struct profiler undi_tx_profiler __profiler = { .name = "undi.tx" };
63 
64 /**
65  * Set network device as current PXE network device
66  *
67  * @v netdev Network device, or NULL
68  */
69 void pxe_set_netdev ( struct net_device *netdev ) {
70 
71  if ( pxe_netdev ) {
74  }
75 
76  pxe_netdev = NULL;
77 
78  if ( netdev )
80 }
81 
82 /**
83  * Open PXE network device
84  *
85  * @ret rc Return status code
86  */
87 static int pxe_netdev_open ( void ) {
88  int rc;
89 
90  assert ( pxe_netdev != NULL );
91 
92  if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
93  return rc;
94 
96  netdev_irq ( pxe_netdev, 1 );
97 
98  return 0;
99 }
100 
101 /**
102  * Close PXE network device
103  *
104  */
105 static void pxe_netdev_close ( void ) {
106 
107  assert ( pxe_netdev != NULL );
109  netdev_irq ( pxe_netdev, 0 );
111  undi_tx_count = 0;
112 }
113 
114 /**
115  * Dump multicast address list
116  *
117  * @v mcast PXE multicast address list
118  */
119 static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) {
121  unsigned int i;
122 
123  for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) {
124  DBGC ( &pxe_netdev, " %s",
125  ll_protocol->ntoa ( mcast->McastAddr[i] ) );
126  }
127 }
128 
129 /* PXENV_UNDI_STARTUP
130  *
131  * Status: working
132  */
133 static PXENV_EXIT_t
134 pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
135  DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" );
136 
137  /* Sanity check */
138  if ( ! pxe_netdev ) {
139  DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP called with no "
140  "network device\n" );
141  undi_startup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
142  return PXENV_EXIT_FAILURE;
143  }
144 
145  undi_startup->Status = PXENV_STATUS_SUCCESS;
146  return PXENV_EXIT_SUCCESS;
147 }
148 
149 /* PXENV_UNDI_CLEANUP
150  *
151  * Status: working
152  */
153 static PXENV_EXIT_t
154 pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
155  DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" );
156 
157  /* Sanity check */
158  if ( ! pxe_netdev ) {
159  DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP called with no "
160  "network device\n" );
161  undi_cleanup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
162  return PXENV_EXIT_FAILURE;
163  }
164 
165  /* Close network device */
167 
168  undi_cleanup->Status = PXENV_STATUS_SUCCESS;
169  return PXENV_EXIT_SUCCESS;
170 }
171 
172 /* PXENV_UNDI_INITIALIZE
173  *
174  * Status: working
175  */
176 static PXENV_EXIT_t
177 pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE *undi_initialize ) {
178  DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n",
179  undi_initialize->ProtocolIni );
180 
181  /* Sanity check */
182  if ( ! pxe_netdev ) {
183  DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE called with no "
184  "network device\n" );
185  undi_initialize->Status = PXENV_STATUS_UNDI_INVALID_STATE;
186  return PXENV_EXIT_FAILURE;
187  }
188 
189  undi_initialize->Status = PXENV_STATUS_SUCCESS;
190  return PXENV_EXIT_SUCCESS;
191 }
192 
193 /* PXENV_UNDI_RESET_ADAPTER
194  *
195  * Status: working
196  */
197 static PXENV_EXIT_t
198 pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET *undi_reset_adapter ) {
199  int rc;
200 
201  DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER" );
202  pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
203  DBGC ( &pxe_netdev, "\n" );
204 
205  /* Sanity check */
206  if ( ! pxe_netdev ) {
207  DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER called with no "
208  "network device\n" );
209  undi_reset_adapter->Status = PXENV_STATUS_UNDI_INVALID_STATE;
210  return PXENV_EXIT_FAILURE;
211  }
212 
213  /* Close and reopen network device */
215  if ( ( rc = pxe_netdev_open() ) != 0 ) {
216  DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not "
217  "reopen %s: %s\n", pxe_netdev->name, strerror ( rc ) );
218  undi_reset_adapter->Status = PXENV_STATUS ( rc );
219  return PXENV_EXIT_FAILURE;
220  }
221 
222  undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
223  return PXENV_EXIT_SUCCESS;
224 }
225 
226 /* PXENV_UNDI_SHUTDOWN
227  *
228  * Status: working
229  */
230 static PXENV_EXIT_t
231 pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown ) {
232  DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" );
233 
234  /* Sanity check */
235  if ( ! pxe_netdev ) {
236  DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN called with no "
237  "network device\n" );
238  undi_shutdown->Status = PXENV_STATUS_UNDI_INVALID_STATE;
239  return PXENV_EXIT_FAILURE;
240  }
241 
242  /* Close network device */
244 
245  undi_shutdown->Status = PXENV_STATUS_SUCCESS;
246  return PXENV_EXIT_SUCCESS;
247 }
248 
249 /* PXENV_UNDI_OPEN
250  *
251  * Status: working
252  */
253 static PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
254  int rc;
255 
256  DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN flag %04x filter %04x",
257  undi_open->OpenFlag, undi_open->PktFilter );
258  pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
259  DBGC ( &pxe_netdev, "\n" );
260 
261  /* Sanity check */
262  if ( ! pxe_netdev ) {
263  DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN called with no "
264  "network device\n" );
266  return PXENV_EXIT_FAILURE;
267  }
268 
269  /* Open network device */
270  if ( ( rc = pxe_netdev_open() ) != 0 ) {
271  DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n",
272  pxe_netdev->name, strerror ( rc ) );
273  undi_open->Status = PXENV_STATUS ( rc );
274  return PXENV_EXIT_FAILURE;
275  }
276 
277  undi_open->Status = PXENV_STATUS_SUCCESS;
278  return PXENV_EXIT_SUCCESS;
279 }
280 
281 /* PXENV_UNDI_CLOSE
282  *
283  * Status: working
284  */
285 static PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
286  DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" );
287 
288  /* Sanity check */
289  if ( ! pxe_netdev ) {
290  DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE called with no "
291  "network device\n" );
293  return PXENV_EXIT_FAILURE;
294  }
295 
296  /* Close network device */
298 
299  undi_close->Status = PXENV_STATUS_SUCCESS;
300  return PXENV_EXIT_SUCCESS;
301 }
302 
303 /* PXENV_UNDI_TRANSMIT
304  *
305  * Status: working
306  */
307 static PXENV_EXIT_t
308 pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) {
309  struct s_PXENV_UNDI_TBD tbd;
310  struct DataBlk *datablk;
311  struct io_buffer *iobuf;
312  struct net_protocol *net_protocol;
313  struct ll_protocol *ll_protocol;
314  char destaddr[MAX_LL_ADDR_LEN];
315  const void *ll_dest;
316  size_t len;
317  unsigned int i;
318  int rc;
319 
320  /* Start profiling */
321  profile_start ( &undi_tx_profiler );
322 
323  /* Sanity check */
324  if ( ! pxe_netdev ) {
325  DBGC ( &pxe_netdev, "PXENV_UNDI_TRANSMIT called with no "
326  "network device\n" );
327  undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_STATE;
328  return PXENV_EXIT_FAILURE;
329  }
330 
331  DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" );
332 
333  /* Forcibly enable interrupts and freeze receive queue
334  * processing at this point, to work around callers that never
335  * call PXENV_UNDI_OPEN before attempting to use the UNDI API.
336  */
337  if ( ! netdev_rx_frozen ( pxe_netdev ) ) {
339  netdev_irq ( pxe_netdev, 1 );
340  }
341 
342  /* Identify network-layer protocol */
343  switch ( undi_transmit->Protocol ) {
344  case P_IP: net_protocol = &ipv4_protocol; break;
345  case P_ARP: net_protocol = &arp_protocol; break;
346  case P_RARP: net_protocol = &rarp_protocol; break;
347  case P_UNKNOWN:
348  net_protocol = NULL;
349  break;
350  default:
351  DBGC2 ( &pxe_netdev, " %02x invalid protocol\n",
352  undi_transmit->Protocol );
354  return PXENV_EXIT_FAILURE;
355  }
356  DBGC2 ( &pxe_netdev, " %s",
357  ( net_protocol ? net_protocol->name : "RAW" ) );
358 
359  /* Calculate total packet length */
360  copy_from_real ( &tbd, undi_transmit->TBD.segment,
361  undi_transmit->TBD.offset, sizeof ( tbd ) );
362  len = tbd.ImmedLength;
363  DBGC2 ( &pxe_netdev, " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset,
364  tbd.ImmedLength );
365  for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
366  datablk = &tbd.DataBlock[i];
367  len += datablk->TDDataLen;
368  DBGC2 ( &pxe_netdev, " %04x:%04x+%x",
369  datablk->TDDataPtr.segment, datablk->TDDataPtr.offset,
370  datablk->TDDataLen );
371  }
372 
373  /* Allocate and fill I/O buffer */
374  iobuf = alloc_iob ( MAX_LL_HEADER_LEN +
375  ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) );
376  if ( ! iobuf ) {
377  DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" );
378  undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
379  return PXENV_EXIT_FAILURE;
380  }
381  iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
382  copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment,
383  tbd.Xmit.offset, tbd.ImmedLength );
384  for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
385  datablk = &tbd.DataBlock[i];
386  copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ),
387  datablk->TDDataPtr.segment,
388  datablk->TDDataPtr.offset,
389  datablk->TDDataLen );
390  }
391 
392  /* Add link-layer header, if required to do so */
393  if ( net_protocol != NULL ) {
394 
395  /* Calculate destination address */
397  if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
398  copy_from_real ( destaddr,
399  undi_transmit->DestAddr.segment,
400  undi_transmit->DestAddr.offset,
402  ll_dest = destaddr;
403  DBGC2 ( &pxe_netdev, " DEST %s",
404  ll_protocol->ntoa ( ll_dest ) );
405  } else {
406  ll_dest = pxe_netdev->ll_broadcast;
407  DBGC2 ( &pxe_netdev, " BCAST" );
408  }
409 
410  /* Add link-layer header */
411  if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest,
413  net_protocol->net_proto ))!=0){
414  DBGC2 ( &pxe_netdev, " could not add link-layer "
415  "header: %s\n", strerror ( rc ) );
416  free_iob ( iobuf );
417  undi_transmit->Status = PXENV_STATUS ( rc );
418  return PXENV_EXIT_FAILURE;
419  }
420  }
421 
422  /* Flag transmission as in-progress. Do this before starting
423  * to transmit the packet, because the ISR may trigger before
424  * we return from netdev_tx().
425  */
426  undi_tx_count++;
427 
428  /* Transmit packet */
429  DBGC2 ( &pxe_netdev, "\n" );
430  if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
431  DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT could not transmit: "
432  "%s\n", strerror ( rc ) );
433  undi_tx_count--;
434  undi_transmit->Status = PXENV_STATUS ( rc );
435  return PXENV_EXIT_FAILURE;
436  }
437 
438  profile_stop ( &undi_tx_profiler );
439  undi_transmit->Status = PXENV_STATUS_SUCCESS;
440  return PXENV_EXIT_SUCCESS;
441 }
442 
443 /* PXENV_UNDI_SET_MCAST_ADDRESS
444  *
445  * Status: working (for NICs that support receive-all-multicast)
446  */
447 static PXENV_EXIT_t
449  *undi_set_mcast_address ) {
450  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS" );
451  pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
452  DBGC ( &pxe_netdev, "\n" );
453 
454  /* Sanity check */
455  if ( ! pxe_netdev ) {
456  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS called with "
457  "no network device\n" );
458  undi_set_mcast_address->Status =
460  return PXENV_EXIT_FAILURE;
461  }
462 
463  undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
464  return PXENV_EXIT_SUCCESS;
465 }
466 
467 /* PXENV_UNDI_SET_STATION_ADDRESS
468  *
469  * Status: working
470  */
471 static PXENV_EXIT_t
473  *undi_set_station_address ) {
474  struct ll_protocol *ll_protocol;
475 
476  /* Sanity check */
477  if ( ! pxe_netdev ) {
478  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS called "
479  "with no network device\n" );
480  undi_set_station_address->Status =
482  return PXENV_EXIT_FAILURE;
483  }
484 
486  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s",
487  ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
488 
489  /* If adapter is open, the change will have no effect; return
490  * an error
491  */
492  if ( netdev_is_open ( pxe_netdev ) ) {
493  DBGC ( &pxe_netdev, " failed: netdev is open\n" );
494  undi_set_station_address->Status =
496  return PXENV_EXIT_FAILURE;
497  }
498 
499  /* Update MAC address */
501  &undi_set_station_address->StationAddress,
503 
504  DBGC ( &pxe_netdev, "\n" );
505  undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
506  return PXENV_EXIT_SUCCESS;
507 }
508 
509 /* PXENV_UNDI_SET_PACKET_FILTER
510  *
511  * Status: won't implement (would require driver API changes for no
512  * real benefit)
513  */
514 static PXENV_EXIT_t
516  *undi_set_packet_filter ) {
517 
518  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
519  undi_set_packet_filter->filter );
520 
521  /* Sanity check */
522  if ( ! pxe_netdev ) {
523  DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER called with "
524  "no network device\n" );
525  undi_set_packet_filter->Status =
527  return PXENV_EXIT_FAILURE;
528  }
529 
530  /* Pretend that we succeeded, otherwise the 3Com DOS UNDI
531  * driver refuses to load. (We ignore the filter value in the
532  * PXENV_UNDI_OPEN call anyway.)
533  */
534  undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS;
535 
536  return PXENV_EXIT_SUCCESS;
537 }
538 
539 /* PXENV_UNDI_GET_INFORMATION
540  *
541  * Status: working
542  */
543 static PXENV_EXIT_t
545  *undi_get_information ) {
546  struct device *dev;
547  struct ll_protocol *ll_protocol;
548 
549  /* Sanity check */
550  if ( ! pxe_netdev ) {
551  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION called with no "
552  "network device\n" );
553  undi_get_information->Status = PXENV_STATUS_UNDI_INVALID_STATE;
554  return PXENV_EXIT_FAILURE;
555  }
556 
557  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" );
558 
559  /* Fill in information */
560  dev = pxe_netdev->dev;
562  undi_get_information->BaseIo = dev->desc.ioaddr;
563  undi_get_information->IntNumber =
564  ( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 );
565  /* Cheat: assume all cards can cope with this */
566  undi_get_information->MaxTranUnit = ETH_MAX_MTU;
567  undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
568  undi_get_information->HwAddrLen = ll_protocol->ll_addr_len;
570  sizeof ( undi_get_information->CurrentNodeAddress ) );
571  memcpy ( &undi_get_information->CurrentNodeAddress,
573  sizeof ( undi_get_information->CurrentNodeAddress ) );
575  &undi_get_information->PermNodeAddress );
576  undi_get_information->ROMAddress = 0;
577  /* nic.rom_info->rom_segment; */
578  /* We only provide the ability to receive or transmit a single
579  * packet at a time. This is a bootloader, not an OS.
580  */
581  undi_get_information->RxBufCt = 1;
582  undi_get_information->TxBufCt = 1;
583 
584  DBGC ( &pxe_netdev, " io %04x irq %d mtu %d %s %s\n",
585  undi_get_information->BaseIo, undi_get_information->IntNumber,
586  undi_get_information->MaxTranUnit, ll_protocol->name,
587  ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress ));
588  undi_get_information->Status = PXENV_STATUS_SUCCESS;
589  return PXENV_EXIT_SUCCESS;
590 }
591 
592 /* PXENV_UNDI_GET_STATISTICS
593  *
594  * Status: working
595  */
596 static PXENV_EXIT_t
598  *undi_get_statistics ) {
599 
600  /* Sanity check */
601  if ( ! pxe_netdev ) {
602  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS called with no "
603  "network device\n" );
604  undi_get_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
605  return PXENV_EXIT_FAILURE;
606  }
607 
608  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" );
609 
610  /* Report statistics */
611  undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
612  undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
613  undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
614  undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
615  DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n",
616  undi_get_statistics->XmtGoodFrames,
617  undi_get_statistics->RcvGoodFrames,
618  undi_get_statistics->RcvCRCErrors,
619  undi_get_statistics->RcvResourceErrors );
620 
621  undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
622  return PXENV_EXIT_SUCCESS;
623 }
624 
625 /* PXENV_UNDI_CLEAR_STATISTICS
626  *
627  * Status: working
628  */
629 static PXENV_EXIT_t
631  *undi_clear_statistics ) {
632  DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" );
633 
634  /* Sanity check */
635  if ( ! pxe_netdev ) {
636  DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS called with "
637  "no network device\n" );
638  undi_clear_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
639  return PXENV_EXIT_FAILURE;
640  }
641 
642  /* Clear statistics */
643  memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
644  memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
645 
646  undi_clear_statistics->Status = PXENV_STATUS_SUCCESS;
647  return PXENV_EXIT_SUCCESS;
648 }
649 
650 /* PXENV_UNDI_INITIATE_DIAGS
651  *
652  * Status: won't implement (would require driver API changes for no
653  * real benefit)
654  */
655 static PXENV_EXIT_t
657  *undi_initiate_diags ) {
658  DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
659 
660  /* Sanity check */
661  if ( ! pxe_netdev ) {
662  DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS called with no "
663  "network device\n" );
664  undi_initiate_diags->Status = PXENV_STATUS_UNDI_INVALID_STATE;
665  return PXENV_EXIT_FAILURE;
666  }
667 
668  undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
669  return PXENV_EXIT_FAILURE;
670 }
671 
672 /* PXENV_UNDI_FORCE_INTERRUPT
673  *
674  * Status: won't implement (would require driver API changes for no
675  * perceptible benefit)
676  */
677 static PXENV_EXIT_t
679  *undi_force_interrupt ) {
680  DBGC ( &pxe_netdev,
681  "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
682 
683  /* Sanity check */
684  if ( ! pxe_netdev ) {
685  DBGC ( &pxe_netdev, "PXENV_UNDI_FORCE_INTERRUPT called with no "
686  "network device\n" );
687  undi_force_interrupt->Status = PXENV_STATUS_UNDI_INVALID_STATE;
688  return PXENV_EXIT_FAILURE;
689  }
690 
691  undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
692  return PXENV_EXIT_FAILURE;
693 }
694 
695 /* PXENV_UNDI_GET_MCAST_ADDRESS
696  *
697  * Status: working
698  */
699 static PXENV_EXIT_t
701  *undi_get_mcast_address ) {
702  struct ll_protocol *ll_protocol;
703  struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
704  int rc;
705 
706  /* Sanity check */
707  if ( ! pxe_netdev ) {
708  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS called with "
709  "no network device\n" );
710  undi_get_mcast_address->Status =
712  return PXENV_EXIT_FAILURE;
713  }
714 
715  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s",
716  inet_ntoa ( ip ) );
717 
718  /* Hash address using the network device's link-layer protocol */
720  if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
721  undi_get_mcast_address->MediaAddr ))!=0){
722  DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) );
723  undi_get_mcast_address->Status = PXENV_STATUS ( rc );
724  return PXENV_EXIT_FAILURE;
725  }
726  DBGC ( &pxe_netdev, "=>%s\n",
727  ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) );
728 
729  undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS;
730  return PXENV_EXIT_SUCCESS;
731 }
732 
733 /* PXENV_UNDI_GET_NIC_TYPE
734  *
735  * Status: working
736  */
738  *undi_get_nic_type ) {
739  struct device *dev;
740 
741  /* Sanity check */
742  if ( ! pxe_netdev ) {
743  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE called with "
744  "no network device\n" );
745  undi_get_nic_type->Status = PXENV_STATUS_UNDI_INVALID_STATE;
746  return PXENV_EXIT_FAILURE;
747  }
748 
749  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" );
750 
751  /* Fill in information */
752  memset ( &undi_get_nic_type->info, 0,
753  sizeof ( undi_get_nic_type->info ) );
754  dev = pxe_netdev->dev;
755  switch ( dev->desc.bus_type ) {
756  case BUS_TYPE_PCI: {
757  struct pci_nic_info *info = &undi_get_nic_type->info.pci;
758 
759  undi_get_nic_type->NicType = PCI_NIC;
760  info->Vendor_ID = dev->desc.vendor;
761  info->Dev_ID = dev->desc.device;
762  info->Base_Class = PCI_BASE_CLASS ( dev->desc.class );
763  info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class );
764  info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class );
765  info->BusDevFunc = dev->desc.location;
766  /* Earlier versions of the PXE specification do not
767  * have the SubVendor_ID and SubDevice_ID fields. It
768  * is possible that some NBPs will not provide space
769  * for them, and so we must not fill them in.
770  */
771  DBGC ( &pxe_netdev, " PCI %02x:%02x.%x %04x:%04x "
772  "('%04x:%04x') %02x%02x%02x rev %02x\n",
773  PCI_BUS ( info->BusDevFunc ),
774  PCI_SLOT ( info->BusDevFunc ),
775  PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID,
776  info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID,
777  info->Base_Class, info->Sub_Class, info->Prog_Intf,
778  info->Rev );
779  break; }
780  case BUS_TYPE_ISAPNP: {
781  struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
782 
783  undi_get_nic_type->NicType = PnP_NIC;
784  info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) |
785  dev->desc.device );
786  info->CardSelNum = dev->desc.location;
787  /* Cheat: remaining fields are probably unnecessary,
788  * and would require adding extra code to isapnp.c.
789  */
790  DBGC ( &pxe_netdev, " ISAPnP CSN %04x %08x %02x%02x%02x\n",
791  info->CardSelNum, info->EISA_Dev_ID,
792  info->Base_Class, info->Sub_Class, info->Prog_Intf );
793  break; }
794  default:
795  DBGC ( &pxe_netdev, " failed: unknown bus type\n" );
796  undi_get_nic_type->Status = PXENV_STATUS_FAILURE;
797  return PXENV_EXIT_FAILURE;
798  }
799 
800  undi_get_nic_type->Status = PXENV_STATUS_SUCCESS;
801  return PXENV_EXIT_SUCCESS;
802 }
803 
804 /* PXENV_UNDI_GET_IFACE_INFO
805  *
806  * Status: working
807  */
808 static PXENV_EXIT_t
810  *undi_get_iface_info ) {
811 
812  /* Sanity check */
813  if ( ! pxe_netdev ) {
814  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO called with "
815  "no network device\n" );
816  undi_get_iface_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
817  return PXENV_EXIT_FAILURE;
818  }
819 
820  DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" );
821 
822  /* Just hand back some info, doesn't really matter what it is.
823  * Most PXE stacks seem to take this approach.
824  */
825  snprintf ( ( char * ) undi_get_iface_info->IfaceType,
826  sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" );
827  undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
828  undi_get_iface_info->ServiceFlags =
833  undi_get_iface_info->ServiceFlags |= SUPPORTED_IRQ;
834  memset ( undi_get_iface_info->Reserved, 0,
835  sizeof(undi_get_iface_info->Reserved) );
836 
837  DBGC ( &pxe_netdev, " %s %dbps flags %08x\n",
838  undi_get_iface_info->IfaceType, undi_get_iface_info->LinkSpeed,
839  undi_get_iface_info->ServiceFlags );
840  undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
841  return PXENV_EXIT_SUCCESS;
842 }
843 
844 /* PXENV_UNDI_GET_STATE
845  *
846  * Status: impossible due to opcode collision
847  */
848 
849 /* PXENV_UNDI_ISR
850  *
851  * Status: working
852  */
853 static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
854  struct io_buffer *iobuf;
855  size_t len;
856  struct ll_protocol *ll_protocol;
857  const void *ll_dest;
858  const void *ll_source;
859  uint16_t net_proto;
860  unsigned int flags;
861  size_t ll_hlen;
862  struct net_protocol *net_protocol;
863  unsigned int prottype;
864  int rc;
865 
866  /* Use a different debug colour, since UNDI ISR messages are
867  * likely to be interspersed amongst other UNDI messages.
868  */
869 
870  /* Sanity check */
871  if ( ! pxe_netdev ) {
872  DBGC ( &pxenv_undi_isr, "PXENV_UNDI_ISR called with "
873  "no network device\n" );
875  return PXENV_EXIT_FAILURE;
876  }
877 
878  DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
879 
880  /* Just in case some idiot actually looks at these fields when
881  * we weren't meant to fill them in...
882  */
883  undi_isr->BufferLength = 0;
884  undi_isr->FrameLength = 0;
885  undi_isr->FrameHeaderLength = 0;
886  undi_isr->ProtType = 0;
887  undi_isr->PktType = 0;
888 
889  switch ( undi_isr->FuncFlag ) {
891  DBGC2 ( &pxenv_undi_isr, " START" );
892 
893  /* Call poll(). This should acknowledge the device
894  * interrupt and queue up any received packet.
895  */
896  net_poll();
897 
898  /* A 100% accurate determination of "OURS" vs "NOT
899  * OURS" is difficult to achieve without invasive and
900  * unpleasant changes to the driver model. We settle
901  * for always returning "OURS" if interrupts are
902  * currently enabled.
903  *
904  * Returning "NOT OURS" when interrupts are disabled
905  * allows us to avoid a potential interrupt storm when
906  * we are on a shared interrupt line; if we were to
907  * always return "OURS" then the other device's ISR
908  * may never be called.
909  */
910  if ( netdev_irq_enabled ( pxe_netdev ) ) {
911  DBGC2 ( &pxenv_undi_isr, " OURS" );
912  undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
913  } else {
914  DBGC2 ( &pxenv_undi_isr, " NOT OURS" );
916  }
917 
918  /* Disable interrupts */
919  netdev_irq ( pxe_netdev, 0 );
920 
921  break;
924  DBGC2 ( &pxenv_undi_isr, " %s",
925  ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ?
926  "PROCESS" : "GET_NEXT" ) );
927 
928  /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call
929  * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START;
930  * they just sit in a tight polling loop merrily
931  * violating the PXE spec with repeated calls to
932  * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to
933  * cope with these out-of-spec clients.
934  */
935  net_poll();
936 
937  /* If we have not yet marked a TX as complete, and the
938  * netdev TX queue is empty, report the TX completion.
939  */
940  if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
941  DBGC2 ( &pxenv_undi_isr, " TXC" );
942  undi_tx_count--;
944  break;
945  }
946 
947  /* Remove first packet from netdev RX queue */
948  iobuf = netdev_rx_dequeue ( pxe_netdev );
949  if ( ! iobuf ) {
950  DBGC2 ( &pxenv_undi_isr, " DONE" );
951  /* No more packets remaining */
952  undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
953  /* Re-enable interrupts */
954  netdev_irq ( pxe_netdev, 1 );
955  break;
956  }
957 
958  /* Copy packet to base memory buffer */
959  len = iob_len ( iobuf );
960  DBGC2 ( &pxenv_undi_isr, " RX" );
961  if ( len > sizeof ( basemem_packet ) ) {
962  /* Should never happen */
963  DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len );
964  len = sizeof ( basemem_packet );
965  }
966  memcpy ( basemem_packet, iobuf->data, len );
967 
968  /* Strip link-layer header */
970  if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest,
971  &ll_source, &net_proto,
972  &flags ) ) != 0 ) {
973  /* Assume unknown net_proto and no ll_source */
974  net_proto = 0;
975  ll_source = NULL;
976  }
977  ll_hlen = ( len - iob_len ( iobuf ) );
978 
979  /* Determine network-layer protocol */
980  switch ( net_proto ) {
981  case htons ( ETH_P_IP ):
982  net_protocol = &ipv4_protocol;
983  prottype = P_IP;
984  break;
985  case htons ( ETH_P_ARP ):
986  net_protocol = &arp_protocol;
987  prottype = P_ARP;
988  break;
989  case htons ( ETH_P_RARP ):
990  net_protocol = &rarp_protocol;
991  prottype = P_RARP;
992  break;
993  default:
994  net_protocol = NULL;
995  prottype = P_UNKNOWN;
996  break;
997  }
998 
999  /* Fill in UNDI_ISR structure */
1001  undi_isr->BufferLength = len;
1002  undi_isr->FrameLength = len;
1003  undi_isr->FrameHeaderLength = ll_hlen;
1004  undi_isr->Frame.segment = rm_ds;
1005  undi_isr->Frame.offset = __from_data16 ( basemem_packet );
1006  undi_isr->ProtType = prottype;
1007  if ( flags & LL_BROADCAST ) {
1008  undi_isr->PktType = P_BROADCAST;
1009  } else if ( flags & LL_MULTICAST ) {
1010  undi_isr->PktType = P_MULTICAST;
1011  } else {
1012  undi_isr->PktType = P_DIRECTED;
1013  }
1014  DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
1015  undi_isr->Frame.segment, undi_isr->Frame.offset,
1016  undi_isr->BufferLength, undi_isr->FrameLength,
1017  ( net_protocol ? net_protocol->name : "RAW" ),
1018  undi_isr->FrameHeaderLength );
1019 
1020  /* Free packet */
1021  free_iob ( iobuf );
1022  break;
1023  default :
1024  DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n",
1025  undi_isr->FuncFlag );
1026 
1027  /* Should never happen */
1028  undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
1030  return PXENV_EXIT_FAILURE;
1031  }
1032 
1033  DBGC2 ( &pxenv_undi_isr, "\n" );
1034  undi_isr->Status = PXENV_STATUS_SUCCESS;
1035  return PXENV_EXIT_SUCCESS;
1036 }
1037 
1038 /** PXE UNDI API */
1039 struct pxe_api_call pxe_undi_api[] __pxe_api_call = {
1041  struct s_PXENV_UNDI_STARTUP ),
1043  struct s_PXENV_UNDI_CLEANUP ),
1045  struct s_PXENV_UNDI_INITIALIZE ),
1047  struct s_PXENV_UNDI_RESET ),
1049  struct s_PXENV_UNDI_SHUTDOWN ),
1051  struct s_PXENV_UNDI_OPEN ),
1053  struct s_PXENV_UNDI_CLOSE ),
1055  struct s_PXENV_UNDI_TRANSMIT ),
1068  struct s_PXENV_UNDI_GET_STATISTICS ),
1072  struct s_PXENV_UNDI_INITIATE_DIAGS ),
1079  struct s_PXENV_UNDI_GET_NIC_TYPE ),
1081  struct s_PXENV_UNDI_GET_IFACE_INFO ),
1083  struct s_PXENV_UNDI_ISR ),
1084 };
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition: netdevice.h:105
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1109
#define PCI_FUNC(busdevfn)
Definition: pci.h:281
Address Resolution Protocol.
IP4_t InetAddr
Multicast IP address.
Definition: pxe_api.h:1283
#define PXENV_STATUS_OUT_OF_RESOURCES
Definition: pxe_error.h:25
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown()
Definition: pxe_api.h:922
#define SUPPORTED_OPEN_CLOSE
Open / Close Adapter supported.
Definition: pxe_api.h:1376
#define PCI_BUS(busdevfn)
Definition: pci.h:279
Parameter block for pxenv_undi_isr()
Definition: pxe_api.h:1479
#define PXENV_UNDI_FORCE_INTERRUPT
PXE API function code for pxenv_undi_force_interrupt()
Definition: pxe_api.h:1259
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
const char * name
Protocol name.
Definition: netdevice.h:66
UINT16_t TDDataLen
Length of this transmit buffer.
Definition: pxe_api.h:72
#define iob_put(iobuf, len)
Definition: iobuf.h:120
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1263
Parameter block for pxenv_undi_clear_statistics()
Definition: pxe_api.h:1224
A transmit buffer descriptor, as pointed to by s_PXENV_UNDI_TRANSMIT::TBD.
Definition: pxe_api.h:1025
#define PCI_NIC
PCI network card.
Definition: pxe_api.h:1301
u32 info
Definition: ar9003_mac.h:67
struct pnp_nic_info pnp
NIC information (if NicType==PnP_NIC)
Definition: pxe_api.h:1343
#define PXENV_EXIT_FAILURE
An error occurred.
Definition: pxe_types.h:46
uint8_t ll_addr_len
Link-layer address length.
Definition: netdevice.h:198
#define SUPPORTED_IRQ
Interrupt Request supported.
Definition: pxe_api.h:1378
Parameter block for pxenv_undi_force_interrupt()
Definition: pxe_api.h:1262
#define P_IP
IP protocol.
Definition: pxe_api.h:1012
List of multicast MAC addresses.
Definition: pxe_api.h:894
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup()
Definition: pxe_api.h:841
UINT32_t RcvGoodFrames
Successful reception count.
Definition: pxe_api.h:1204
UINT16_t IntNumber
IRQ number.
Definition: pxe_api.h:1169
#define PXENV_UNDI_SET_STATION_ADDRESS
PXE API function code for pxenv_undi_set_station_address()
Definition: pxe_api.h:1105
UINT16_t RxBufCt
Receive queue length.
Definition: pxe_api.h:1182
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:845
#define SUPPORTED_SET_STATION_ADDRESS
Software settable station address.
Definition: pxe_api.h:1370
void net_poll(void)
Poll the network stack.
Definition: netdevice.c:1126
static PXENV_EXIT_t pxenv_undi_open(struct s_PXENV_UNDI_OPEN *undi_open)
Definition: pxe_undi.c:253
UINT16_t BaseIo
I/O base address.
Definition: pxe_api.h:1168
#define PXENV_UNDI_CLEAR_STATISTICS
PXE API function code for pxenv_undi_clear_statistics()
Definition: pxe_api.h:1221
static PXENV_EXIT_t pxenv_undi_reset_adapter(struct s_PXENV_UNDI_RESET *undi_reset_adapter)
Definition: pxe_undi.c:198
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1480
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1050
UINT8_t PktType
Packet type.
Definition: pxe_api.h:1503
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
Multicast MAC addresses.
Definition: pxe_api.h:907
MAC_ADDR_t MediaAddr
Multicast MAC address.
Definition: pxe_api.h:1284
#define PXENV_UNDI_GET_MCAST_ADDRESS
PXE API function code for pxenv_undi_get_mcast_address()
Definition: pxe_api.h:1278
unsigned long ioaddr
I/O address.
Definition: device.h:37
static PXENV_EXIT_t pxenv_undi_get_nic_type(struct s_PXENV_UNDI_GET_NIC_TYPE *undi_get_nic_type)
Definition: pxe_undi.c:737
#define SUPPORTED_RESET
Reset MAC supported.
Definition: pxe_api.h:1374
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1088
#define ETH_P_IP
Definition: if_ether.h:18
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:926
#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 PXENV_STATUS_UNDI_INVALID_PARAMETER
Definition: pxe_error.h:83
static PXENV_EXIT_t pxenv_undi_isr(struct s_PXENV_UNDI_ISR *undi_isr)
Definition: pxe_undi.c:853
Parameter block for pxenv_undi_transmit()
Definition: pxe_api.h:1049
UINT32_t RcvResourceErrors
Receive queue overflow count.
Definition: pxe_api.h:1206
const uint8_t * ll_broadcast
Link-layer broadcast address.
Definition: netdevice.h:389
unsigned long class
Device class.
Definition: device.h:35
#define PXENV_UNDI_SET_MCAST_ADDRESS
PXE API function code for pxenv_undi_set_mcast_address()
Definition: pxe_api.h:1084
SEGSEL_t ROMAddress
Real-mode ROM segment address.
Definition: pxe_api.h:1181
IP protocol.
Parameter block for pxenv_undi_set_packet_filter()
Definition: pxe_api.h:1128
#define ETH_MAX_MTU
Definition: if_ether.h:14
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define P_DIRECTED
Unicast packet (or packet captured in promiscuous mode)
Definition: pxe_api.h:1472
#define ntohs(value)
Definition: byteswap.h:136
Parameter block for pxenv_undi_get_nic_type()
Definition: pxe_api.h:1329
struct s_PXENV_UNDI_TBD::DataBlk DataBlock[MAX_DATA_BLKS]
static PXENV_EXIT_t pxenv_undi_force_interrupt(struct s_PXENV_UNDI_FORCE_INTERRUPT *undi_force_interrupt)
Definition: pxe_undi.c:678
UINT32_t ServiceFlags
Service flags.
Definition: pxe_api.h:1401
A data structure for storing profiling information.
Definition: profile.h:26
#define rm_ds
Definition: libkir.h:39
UINT16_t PktFilter
Receive packet filter.
Definition: pxe_api.h:973
#define PXENV_UNDI_GET_NIC_TYPE
PXE API function code for pxenv_undi_get_nic_type()
Definition: pxe_api.h:1299
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition: profile.h:171
union s_PXENV_UNDI_GET_NIC_TYPE::nic_type_info info
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
List of multicast addresses.
Definition: pxe_api.h:1090
static PXENV_EXIT_t pxenv_undi_get_information(struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information)
Definition: pxe_undi.c:544
UINT32_t RcvCRCErrors
Receive CRC error count.
Definition: pxe_api.h:1205
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:129
UINT16_t FuncFlag
Function flag.
Definition: pxe_api.h:1489
unsigned int vendor
Vendor ID.
Definition: device.h:31
UINT32_t LinkSpeed
Link speed, in bits per second.
Definition: pxe_api.h:1394
struct net_device_stats tx_stats
TX statistics.
Definition: netdevice.h:423
void(* init_addr)(const void *hw_addr, void *ll_addr)
Initialise link-layer address.
Definition: netdevice.h:150
struct pci_nic_info pci
NIC information (if NicType==PCI_NIC)
Definition: pxe_api.h:1339
A link-layer protocol.
Definition: netdevice.h:114
static PXENV_EXIT_t pxenv_undi_get_mcast_address(struct s_PXENV_UNDI_GET_MCAST_ADDRESS *undi_get_mcast_address)
Definition: pxe_undi.c:700
#define PCI_BASE_CLASS(class)
Definition: pci.h:285
#define PXE_API_CALL(_opcode, _entry, _params_type)
Define a PXE API call.
Definition: pxe.h:108
#define PXENV_UNDI_ISR_OUT_RECEIVE
A packet has been received.
Definition: pxe_api.h:1467
int(* push)(struct net_device *netdev, struct io_buffer *iobuf, const void *ll_dest, const void *ll_source, uint16_t net_proto)
Add link-layer header.
Definition: netdevice.h:127
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1244
Parameter block for pxenv_undi_close()
Definition: pxe_api.h:993
static PXENV_EXIT_t pxenv_undi_initialize(struct s_PXENV_UNDI_INITIALIZE *undi_initialize)
Definition: pxe_undi.c:177
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
const char * name
Protocol name.
Definition: netdevice.h:116
UINT32_t XmtGoodFrames
Successful transmission count.
Definition: pxe_api.h:1203
#define PXENV_UNDI_ISR_IN_PROCESS
Start processing interrupt.
Definition: pxe_api.h:1455
A hardware device.
Definition: device.h:73
#define PnP_NIC
ISAPnP network card.
Definition: pxe_api.h:1302
void * memcpy(void *dest, const void *src, size_t len) __nonnull
UINT16_t PXENV_EXIT_t
A PXE exit code.
Definition: pxe_types.h:44
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1282
const char * name
Name.
Definition: profile.h:28
struct pxe_api_call pxe_undi_api [] __pxe_api_call
PXE UNDI API.
Definition: pxe_undi.c:1039
static PXENV_EXIT_t pxenv_undi_set_station_address(struct s_PXENV_UNDI_SET_STATION_ADDRESS *undi_set_station_address)
Definition: pxe_undi.c:472
static PXENV_EXIT_t pxenv_undi_set_packet_filter(struct s_PXENV_UNDI_SET_PACKET_FILTER *undi_set_packet_filter)
Definition: pxe_undi.c:515
UINT16_t FrameLength
Total frame length.
Definition: pxe_api.h:1491
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
MAC_ADDR_t PermNodeAddress
Permanent (EEPROM) MAC address.
Definition: pxe_api.h:1180
#define PXENV_UNDI_ISR_IN_START
Determine whether or not this is our interrupt.
Definition: pxe_api.h:1453
#define BUS_TYPE_PCI
PCI bus type.
Definition: device.h:43
#define MAX_LL_ADDR_LEN
Maximum length of a link-layer address.
Definition: netdevice.h:36
SEGOFF16_t TDDataPtr
Address of this transmit buffer.
Definition: pxe_api.h:73
#define PXENV_UNDI_CLOSE
PXE API function code for pxenv_undi_close()
Definition: pxe_api.h:990
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:572
unsigned int irq
IRQ.
Definition: device.h:39
UINT8_t Protocol
Protocol.
Definition: pxe_api.h:1057
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1167
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1330
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:994
SEGOFF16_t DestAddr
Destination MAC address.
Definition: pxe_api.h:1063
UINT8_t XmitFlag
Unicast/broadcast flag.
Definition: pxe_api.h:1062
UINT32_t Reserved[4]
Must be zero.
Definition: pxe_api.h:1402
Parameter block for pxenv_undi_set_station_address()
Definition: pxe_api.h:1108
Information for an ISAPnP or equivalent NIC.
Definition: pxe_api.h:1319
struct list_head tx_queue
TX packet queue.
Definition: netdevice.h:417
#define P_MULTICAST
Multicast packet.
Definition: pxe_api.h:1476
#define SUPPORTED_BROADCAST
Broadcast supported.
Definition: pxe_api.h:1362
static struct net_device * netdev
Definition: gdbudp.c:52
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition: netdevice.h:45
SEGOFF16_t Frame
Data buffer address.
Definition: pxe_api.h:1493
UINT16_t MaxTranUnit
Adapter MTU.
Definition: pxe_api.h:1170
Parameter block for pxenv_undi_shutdown()
Definition: pxe_api.h:925
void pxe_set_netdev(struct net_device *netdev)
Set network device as current PXE network device.
Definition: pxe_undi.c:69
Parameter block for pxenv_undi_get_mcast_address()
Definition: pxe_api.h:1281
static void profile_start(struct profiler *profiler)
Start profiling.
Definition: profile.h:158
UINT8_t filter
Receive packet filter.
Definition: pxe_api.h:1140
Profiling.
unsigned int location
Location.
Definition: device.h:29
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1225
#define PXENV_UNDI_ISR_OUT_TRANSMIT
A packet transmission has completed.
Definition: pxe_api.h:1465
static PXENV_EXIT_t pxenv_undi_get_statistics(struct s_PXENV_UNDI_GET_STATISTICS *undi_get_statistics)
Definition: pxe_undi.c:597
static struct profiler undi_tx_profiler __profiler
Transmit profiler.
Definition: pxe_undi.c:62
Parameter block for pxenv_undi_startup()
Definition: pxe_api.h:825
#define PXENV_UNDI_TRANSMIT
PXE API function code for pxenv_undi_transmit()
Definition: pxe_api.h:1009
static int netdev_irq_enabled(struct net_device *netdev)
Check whether or not network device interrupts are currently enabled.
Definition: netdevice.h:681
#define basemem_packet
static void pxe_netdev_close(void)
Close PXE network device.
Definition: pxe_undi.c:105
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
UINT8_t ProtType
Protocol type.
Definition: pxe_api.h:1498
Parameter block for pxenv_undi_set_mcast_address()
Definition: pxe_api.h:1087
UINT8_t NicType
NIC type.
Definition: pxe_api.h:1335
struct net_device * pxe_netdev
Definition: pxe_undi.c:59
IP address structure.
Definition: in.h:39
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:959
#define SUPPORTED_MULTICAST
Multicast supported.
Definition: pxe_api.h:1364
#define PCI_SLOT(busdevfn)
Definition: pci.h:280
PCI bus.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
struct net_device_stats rx_stats
RX statistics.
Definition: netdevice.h:425
Reverse Address Resolution Protocol.
MAC_ADDR_t McastAddr[MAXNUM_MCADDR]
List of up to MAXNUM_MCADDR multicast MAC addresses.
Definition: pxe_api.h:898
unsigned int bad
Count of error completions.
Definition: netdevice.h:295
void netdev_irq(struct net_device *netdev, int enable)
Enable or disable interrupts.
Definition: netdevice.c:970
A network device.
Definition: netdevice.h:352
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:658
IP4_t ip
Destination IP address.
Definition: pxe_api.h:58
SEGOFF16_t Xmit
Address of the transmit buffer.
Definition: pxe_api.h:1027
int netdev_tx(struct net_device *netdev, struct io_buffer *iobuf)
Transmit raw packet via network device.
Definition: netdevice.c:334
static PXENV_EXIT_t pxenv_undi_set_mcast_address(struct s_PXENV_UNDI_SET_MCAST_ADDRESS *undi_set_mcast_address)
Definition: pxe_undi.c:448
Parameter block for pxenv_undi_get_information()
Definition: pxe_api.h:1166
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1202
#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_STATUS_UNSUPPORTED
Definition: pxe_error.h:22
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:561
#define PXENV_UNDI_OPEN
PXE API function code for pxenv_undi_open()
Definition: pxe_api.h:941
#define XMT_DESTADDR
Unicast packet.
Definition: pxe_api.h:1017
MAC_ADDR_t StationAddress
Station MAC address.
Definition: pxe_api.h:1110
#define PXENV_UNDI_ISR_OUT_NOT_OURS
This interrupt was not ours.
Definition: pxe_api.h:1461
uint16_t net_proto
Network-layer protocol.
Definition: netdevice.h:99
uint16_t ll_proto
Link-layer protocol.
Definition: netdevice.h:194
#define PXENV_UNDI_ISR_IN_GET_NEXT
Continue processing interrupt.
Definition: pxe_api.h:1457
int(* mc_hash)(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition: netdevice.h:172
static PXENV_EXIT_t pxenv_undi_cleanup(struct s_PXENV_UNDI_CLEANUP *undi_cleanup)
Definition: pxe_undi.c:154
UINT16_t HwAddrLen
MAC address length.
Definition: pxe_api.h:1178
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
ADDR32_t ProtocolIni
NDIS 2.0 configuration information, or NULL.
Definition: pxe_api.h:872
#define LL_BROADCAST
Packet is a broadcast packet.
Definition: netdevice.h:108
void netdev_close(struct net_device *netdev)
Close network device.
Definition: netdevice.c:895
void netdev_rx_freeze(struct net_device *netdev)
Freeze network device receive queue processing.
Definition: netdevice.c:178
A network-layer protocol.
Definition: netdevice.h:64
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
void netdev_rx_unfreeze(struct net_device *netdev)
Unfreeze network device receive queue processing.
Definition: netdevice.c:192
Network device management.
Parameter block for pxenv_undi_cleanup()
Definition: pxe_api.h:844
#define copy_from_real
Definition: libkir.h:79
#define P_BROADCAST
Broadcast packet.
Definition: pxe_api.h:1474
MAC_ADDR_t CurrentNodeAddress
Current MAC address.
Definition: pxe_api.h:1179
#define iob_reserve(iobuf, len)
Definition: iobuf.h:67
UINT16_t TxBufCt
Transmit queue length.
Definition: pxe_api.h:1183
static void pxe_dump_mcast_list(struct s_PXENV_UNDI_MCAST_ADDRESS *mcast)
Dump multicast address list.
Definition: pxe_undi.c:119
unsigned int good
Count of successful completions.
Definition: netdevice.h:293
int(* pull)(struct net_device *netdev, struct io_buffer *iobuf, const void **ll_dest, const void **ll_source, uint16_t *net_proto, unsigned int *flags)
Remove link-layer header.
Definition: netdevice.h:141
unsigned int bus_type
Bus type.
Definition: device.h:24
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
#define PCI_PROG_INTF(class)
Definition: pci.h:287
uint32_t len
Length.
Definition: ena.h:14
A PXE API call.
Definition: pxe.h:81
Parameter block for pxenv_undi_reset_adapter()
Definition: pxe_api.h:904
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1129
#define PXENV_UNDI_RESET_ADAPTER
PXE API function code for pxenv_undi_reset_adapter()
Definition: pxe_api.h:888
#define DBGC2(...)
Definition: compiler.h:522
Parameter block for pxenv_undi_initiate_diags()
Definition: pxe_api.h:1243
UINT16_t DataBlkCount
Definition: pxe_api.h:1028
unsigned int device
Device ID.
Definition: device.h:33
#define __from_data16(pointer)
Definition: libkir.h:22
static PXENV_EXIT_t pxenv_undi_initiate_diags(struct s_PXENV_UNDI_INITIATE_DIAGS *undi_initiate_diags)
Definition: pxe_undi.c:656
SEGOFF16_t TBD
Address of the Transmit Buffer Descriptor.
Definition: pxe_api.h:1068
#define IOB_ZLEN
Minimum I/O buffer length.
Definition: iobuf.h:24
void * data
Start of data.
Definition: iobuf.h:48
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition: pxe_api.h:1450
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:826
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:905
Array of up to MAX_DATA_BLKS additional transmit buffers.
Definition: pxe_api.h:61
Parameter block for pxenv_undi_get_iface_info()
Definition: pxe_api.h:1381
static PXENV_EXIT_t pxenv_undi_shutdown(struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown)
Definition: pxe_undi.c:231
UINT16_t ImmedLength
Length of the transmit buffer.
Definition: pxe_api.h:1026
struct device_description desc
Device description.
Definition: device.h:79
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition: netdevice.h:163
static PXENV_EXIT_t pxenv_undi_clear_statistics(struct s_PXENV_UNDI_CLEAR_STATISTICS *undi_clear_statistics)
Definition: pxe_undi.c:630
#define P_RARP
RARP protocol.
Definition: pxe_api.h:1014
UINT16_t HwType
Hardware type.
Definition: pxe_api.h:1177
Device model.
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
#define PXENV_UNDI_ISR_OUT_DONE
Finished processing interrupt.
Definition: pxe_api.h:1463
UINT16_t OpenFlag
Open flags as defined in NDIS 2.0.
Definition: pxe_api.h:966
static PXENV_EXIT_t pxenv_undi_close(struct s_PXENV_UNDI_CLOSE *undi_close)
Definition: pxe_undi.c:285
static PXENV_EXIT_t pxenv_undi_get_iface_info(struct s_PXENV_UNDI_GET_IFACE_INFO *undi_get_iface_info)
Definition: pxe_undi.c:809
#define ETH_P_ARP
Definition: if_ether.h:19
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
UINT8_t IfaceType[16]
Interface type.
Definition: pxe_api.h:1393
#define ETH_P_RARP
Definition: if_ether.h:20
#define P_ARP
ARP protocol.
Definition: pxe_api.h:1013
#define PXENV_UNDI_GET_INFORMATION
PXE API function code for pxenv_undi_get_information()
Definition: pxe_api.h:1155
static int undi_tx_count
Count of outstanding transmitted packets.
Definition: pxe_undi.c:57
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define P_UNKNOWN
Media header already filled in.
Definition: pxe_api.h:1011
static PXENV_EXIT_t pxenv_undi_startup(struct s_PXENV_UNDI_STARTUP *undi_startup)
Definition: pxe_undi.c:134
#define PXENV_UNDI_STARTUP
PXE API function code for pxenv_undi_startup()
Definition: pxe_api.h:815
static int netdev_rx_frozen(struct net_device *netdev)
Check whether or not network device receive queue processing is frozen.
Definition: netdevice.h:692
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:864
#define PXENV_UNDI_INITIALIZE
PXE API function code for pxenv_undi_initialize()
Definition: pxe_api.h:860
UINT16_t FrameHeaderLength
Frame header length.
Definition: pxe_api.h:1492
PXENV_STATUS_t Status
PXE status code.
Definition: pxe_api.h:1382
#define PXENV_UNDI_ISR_OUT_OURS
This interrupt was ours.
Definition: pxe_api.h:1459
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition: netdevice.h:381
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
Parameter block for pxenv_undi_get_statistics()
Definition: pxe_api.h:1201
static int pxe_netdev_open(void)
Open PXE network device.
Definition: pxe_undi.c:87
String functions.
static int netdev_irq_supported(struct net_device *netdev)
Check whether or not network device supports interrupts.
Definition: netdevice.h:669
UINT16_t BufferLength
Data buffer length.
Definition: pxe_api.h:1490
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
#define htons(value)
Definition: byteswap.h:135
#define PXENV_STATUS(rc)
Derive PXENV_STATUS code from iPXE error number.
Definition: pxe_error.h:121
Parameter block for pxenv_undi_open()
Definition: pxe_api.h:958
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63
#define PXENV_STATUS_FAILURE
Definition: pxe_error.h:20
struct ll_protocol * ll_protocol
Link-layer protocol.
Definition: netdevice.h:372
#define PXENV_STATUS_UNDI_INVALID_STATE
Definition: pxe_error.h:81
UINT16_t MCastAddrCount
Number of multicast MAC addresses.
Definition: pxe_api.h:896
Information for a PCI or equivalent NIC.
Definition: pxe_api.h:1306
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition: device.h:46
void * memset(void *dest, int character, size_t len) __nonnull
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition: netdevice.c:637
A persistent I/O buffer.
Definition: iobuf.h:33
uint8_t flags
Flags.
Definition: ena.h:18
static PXENV_EXIT_t pxenv_undi_transmit(struct s_PXENV_UNDI_TRANSMIT *undi_transmit)
Definition: pxe_undi.c:308
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
Multicast MAC addresses.
Definition: pxe_api.h:975
#define PCI_SUB_CLASS(class)
Definition: pci.h:286