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
30FILE_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 */
57static int undi_tx_count = 0;
58
60
61/** Transmit profiler */
62static 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 */
70
71 if ( pxe_netdev ) {
74 }
75
77
78 if ( netdev )
80}
81
82/**
83 * Open PXE network device
84 *
85 * @ret rc Return status code
86 */
87static 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
97
98 return 0;
99}
100
101/**
102 * Close PXE network device
103 *
104 */
105static 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 */
119static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) {
120 struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
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 */
133static PXENV_EXIT_t
134pxenv_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" );
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 */
153static PXENV_EXIT_t
154pxenv_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" );
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 */
176static PXENV_EXIT_t
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 */
197static PXENV_EXIT_t
198pxenv_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 */
230static PXENV_EXIT_t
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" );
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 */
253static 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 */
285static 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 */
307static PXENV_EXIT_t
309 struct s_PXENV_UNDI_TBD tbd;
310 struct DataBlk *datablk;
311 struct io_buffer *iobuf;
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" );
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:
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 }
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 */
396 ll_protocol = pxe_netdev->ll_protocol;
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,
412 pxe_netdev->ll_addr,
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 */
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 ) );
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 */
447static 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 */
471static 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
485 ll_protocol = pxe_netdev->ll_protocol;
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 */
500 memcpy ( pxe_netdev->ll_addr,
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 */
514static 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 */
543static 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;
561 ll_protocol = pxe_netdev->ll_protocol;
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,
572 pxe_netdev->ll_addr,
573 sizeof ( undi_get_information->CurrentNodeAddress ) );
574 ll_protocol->init_addr ( pxe_netdev->hw_addr,
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 */
596static 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 */
629static 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 */
655static 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 */
677static 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 */
699static 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 */
719 ll_protocol = pxe_netdev->ll_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 */
808static 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 */
853static 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;
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" );
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" );
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 */
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 */
969 ll_protocol = pxe_netdev->ll_protocol;
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:
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 */
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 */
1039struct 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 ),
1083 struct s_PXENV_UNDI_ISR ),
1084};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u32 info
Definition ar9003_mac.h:0
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
Address Resolution Protocol.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
#define basemem_packet
Device model.
#define BUS_TYPE_PCI
PCI bus type.
Definition device.h:44
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition device.h:47
ring len
Length.
Definition dwmac.h:226
uint8_t flags
Flags.
Definition ena.h:7
static struct net_device * netdev
Definition gdbudp.c:53
#define AF_INET
IPv4 Internet addresses.
Definition socket.h:64
#define DBGC2(...)
Definition compiler.h:522
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define PXENV_EXIT_FAILURE
An error occurred.
Definition pxe_types.h:46
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition pxe_types.h:45
UINT16_t PXENV_EXIT_t
A PXE exit code.
Definition pxe_types.h:44
#define PXENV_STATUS_UNSUPPORTED
Definition pxe_error.h:22
#define PXENV_STATUS_FAILURE
Definition pxe_error.h:20
#define PXENV_STATUS_SUCCESS
Definition pxe_error.h:19
#define PXENV_STATUS_UNDI_INVALID_PARAMETER
Definition pxe_error.h:83
#define PXENV_STATUS_UNDI_INVALID_STATE
Definition pxe_error.h:81
#define PXENV_STATUS_OUT_OF_RESOURCES
Definition pxe_error.h:25
#define PXENV_UNDI_CLEANUP
PXE API function code for pxenv_undi_cleanup()
Definition pxe_api.h:841
#define PXENV_UNDI_CLEAR_STATISTICS
PXE API function code for pxenv_undi_clear_statistics()
Definition pxe_api.h:1221
#define PXENV_UNDI_CLOSE
PXE API function code for pxenv_undi_close()
Definition pxe_api.h:990
#define PXENV_UNDI_FORCE_INTERRUPT
PXE API function code for pxenv_undi_force_interrupt()
Definition pxe_api.h:1259
#define SUPPORTED_SET_STATION_ADDRESS
Software settable station address.
Definition pxe_api.h:1370
#define SUPPORTED_OPEN_CLOSE
Open / Close Adapter supported.
Definition pxe_api.h:1376
#define SUPPORTED_BROADCAST
Broadcast supported.
Definition pxe_api.h:1362
#define SUPPORTED_MULTICAST
Multicast supported.
Definition pxe_api.h:1364
#define SUPPORTED_RESET
Reset MAC supported.
Definition pxe_api.h:1374
#define PXENV_UNDI_GET_IFACE_INFO
PXE API function code for pxenv_undi_get_iface_info()
Definition pxe_api.h:1359
#define SUPPORTED_IRQ
Interrupt Request supported.
Definition pxe_api.h:1378
#define PXENV_UNDI_GET_INFORMATION
PXE API function code for pxenv_undi_get_information()
Definition pxe_api.h:1155
#define PXENV_UNDI_GET_MCAST_ADDRESS
PXE API function code for pxenv_undi_get_mcast_address()
Definition pxe_api.h:1278
#define PCI_NIC
PCI network card.
Definition pxe_api.h:1301
#define PXENV_UNDI_GET_NIC_TYPE
PXE API function code for pxenv_undi_get_nic_type()
Definition pxe_api.h:1299
#define PnP_NIC
ISAPnP network card.
Definition pxe_api.h:1302
#define PXENV_UNDI_GET_STATISTICS
PXE API function code for pxenv_undi_get_statistics()
Definition pxe_api.h:1198
#define PXENV_UNDI_INITIALIZE
PXE API function code for pxenv_undi_initialize()
Definition pxe_api.h:860
#define PXENV_UNDI_INITIATE_DIAGS
PXE API function code for pxenv_undi_initiate_diags()
Definition pxe_api.h:1240
#define PXENV_UNDI_ISR_OUT_NOT_OURS
This interrupt was not ours.
Definition pxe_api.h:1461
#define PXENV_UNDI_ISR_OUT_DONE
Finished processing interrupt.
Definition pxe_api.h:1463
#define PXENV_UNDI_ISR_IN_GET_NEXT
Continue processing interrupt.
Definition pxe_api.h:1457
#define P_MULTICAST
Multicast packet.
Definition pxe_api.h:1476
#define PXENV_UNDI_ISR_OUT_RECEIVE
A packet has been received.
Definition pxe_api.h:1467
#define PXENV_UNDI_ISR
PXE API function code for pxenv_undi_isr()
Definition pxe_api.h:1450
#define P_DIRECTED
Unicast packet (or packet captured in promiscuous mode)
Definition pxe_api.h:1472
#define PXENV_UNDI_ISR_OUT_TRANSMIT
A packet transmission has completed.
Definition pxe_api.h:1465
#define PXENV_UNDI_ISR_OUT_OURS
This interrupt was ours.
Definition pxe_api.h:1459
#define PXENV_UNDI_ISR_IN_PROCESS
Start processing interrupt.
Definition pxe_api.h:1455
#define PXENV_UNDI_ISR_IN_START
Determine whether or not this is our interrupt.
Definition pxe_api.h:1453
#define P_BROADCAST
Broadcast packet.
Definition pxe_api.h:1474
#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_SET_MCAST_ADDRESS
PXE API function code for pxenv_undi_set_mcast_address()
Definition pxe_api.h:1084
#define PXENV_UNDI_SET_PACKET_FILTER
PXE API function code for pxenv_undi_set_packet_filter()
Definition pxe_api.h:1125
#define PXENV_UNDI_SET_STATION_ADDRESS
PXE API function code for pxenv_undi_set_station_address()
Definition pxe_api.h:1105
#define PXENV_UNDI_SHUTDOWN
PXE API function code for pxenv_undi_shutdown()
Definition pxe_api.h:922
#define PXENV_UNDI_STARTUP
PXE API function code for pxenv_undi_startup()
Definition pxe_api.h:815
#define P_RARP
RARP protocol.
Definition pxe_api.h:1014
#define PXENV_UNDI_TRANSMIT
PXE API function code for pxenv_undi_transmit()
Definition pxe_api.h:1009
#define P_IP
IP protocol.
Definition pxe_api.h:1012
#define XMT_DESTADDR
Unicast packet.
Definition pxe_api.h:1017
#define P_UNKNOWN
Media header already filled in.
Definition pxe_api.h:1011
#define P_ARP
ARP protocol.
Definition pxe_api.h:1013
#define ETH_MAX_MTU
Definition if_ether.h:15
#define ETH_P_RARP
Definition if_ether.h:21
#define ETH_P_IP
Definition if_ether.h:19
#define ETH_P_ARP
Definition if_ether.h:20
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
Profiling.
#define __profiler
Declare a profiler.
Definition profile.h:61
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition profile.h:174
static void profile_start(struct profiler *profiler)
Start profiling.
Definition profile.h:161
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define IOB_ZLEN
Minimum I/O buffer length and alignment.
Definition iobuf.h:29
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
IP protocol.
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition ipv4.c:814
#define rm_ds
Definition libkir.h:39
#define __from_data16(pointer)
Definition libkir.h:22
#define copy_from_real
Definition libkir.h:79
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
void netdev_rx_unfreeze(struct net_device *netdev)
Unfreeze network device receive queue processing.
Definition netdevice.c:193
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition netdevice.c:638
void netdev_rx_freeze(struct net_device *netdev)
Freeze network device receive queue processing.
Definition netdevice.c:179
int netdev_open(struct net_device *netdev)
Open network device.
Definition netdevice.c:862
void netdev_close(struct net_device *netdev)
Close network device.
Definition netdevice.c:896
void net_poll(void)
Poll the network stack.
Definition netdevice.c:1127
void netdev_irq(struct net_device *netdev, int enable)
Enable or disable interrupts.
Definition netdevice.c:971
int netdev_tx(struct net_device *netdev, struct io_buffer *iobuf)
Transmit raw packet via network device.
Definition netdevice.c:335
Network device management.
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
static int netdev_irq_enabled(struct net_device *netdev)
Check whether or not network device interrupts are currently enabled.
Definition netdevice.h:685
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition netdevice.h:662
static int netdev_irq_supported(struct net_device *netdev)
Check whether or not network device supports interrupts.
Definition netdevice.h:673
#define LL_MULTICAST
Packet is a multicast (including broadcast) packet.
Definition netdevice.h:106
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
static int netdev_rx_frozen(struct net_device *netdev)
Check whether or not network device receive queue processing is frozen.
Definition netdevice.h:696
#define LL_BROADCAST
Packet is a broadcast packet.
Definition netdevice.h:109
#define MAX_LL_HEADER_LEN
Maximum length of a link-layer header.
Definition netdevice.h:46
#define MAX_LL_ADDR_LEN
Maximum length of a link-layer address.
Definition netdevice.h:37
PCI bus.
#define PCI_FUNC(busdevfn)
Definition pci.h:286
#define PCI_BUS(busdevfn)
Definition pci.h:284
#define PCI_SUB_CLASS(class)
Definition pci.h:291
#define PCI_BASE_CLASS(class)
Definition pci.h:290
#define PCI_PROG_INTF(class)
Definition pci.h:292
#define PCI_SLOT(busdevfn)
Definition pci.h:285
#define PXE_API_CALL(_opcode, _entry, _params_type)
Define a PXE API call.
Definition pxe.h:106
#define __pxe_api_call
Declare a PXE API call.
Definition pxe.h:96
IP4_t ip
Destination IP address.
Definition pxe_api.h:1
#define PXENV_STATUS(rc)
Derive PXENV_STATUS code from iPXE error number.
Definition pxe_error.h:121
static PXENV_EXIT_t pxenv_undi_clear_statistics(struct s_PXENV_UNDI_CLEAR_STATISTICS *undi_clear_statistics)
Definition pxe_undi.c:630
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
static PXENV_EXIT_t pxenv_undi_get_information(struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information)
Definition pxe_undi.c:544
void pxe_set_netdev(struct net_device *netdev)
Set network device as current PXE network device.
Definition pxe_undi.c:69
static void pxe_dump_mcast_list(struct s_PXENV_UNDI_MCAST_ADDRESS *mcast)
Dump multicast address list.
Definition pxe_undi.c:119
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_transmit(struct s_PXENV_UNDI_TRANSMIT *undi_transmit)
Definition pxe_undi.c:308
static PXENV_EXIT_t pxenv_undi_shutdown(struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown)
Definition pxe_undi.c:231
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_startup(struct s_PXENV_UNDI_STARTUP *undi_startup)
Definition pxe_undi.c:134
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
static PXENV_EXIT_t pxenv_undi_reset_adapter(struct s_PXENV_UNDI_RESET *undi_reset_adapter)
Definition pxe_undi.c:198
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
static PXENV_EXIT_t pxenv_undi_initiate_diags(struct s_PXENV_UNDI_INITIATE_DIAGS *undi_initiate_diags)
Definition pxe_undi.c:656
static void pxe_netdev_close(void)
Close PXE network device.
Definition pxe_undi.c:105
static PXENV_EXIT_t pxenv_undi_get_statistics(struct s_PXENV_UNDI_GET_STATISTICS *undi_get_statistics)
Definition pxe_undi.c:597
static int pxe_netdev_open(void)
Open PXE network device.
Definition pxe_undi.c:87
static PXENV_EXIT_t pxenv_undi_isr(struct s_PXENV_UNDI_ISR *undi_isr)
Definition pxe_undi.c:853
static PXENV_EXIT_t pxenv_undi_open(struct s_PXENV_UNDI_OPEN *undi_open)
Definition pxe_undi.c:253
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
struct net_device * pxe_netdev
Definition pxe_undi.c:59
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
static PXENV_EXIT_t pxenv_undi_initialize(struct s_PXENV_UNDI_INITIALIZE *undi_initialize)
Definition pxe_undi.c:177
static int undi_tx_count
Count of outstanding transmitted packets.
Definition pxe_undi.c:57
static PXENV_EXIT_t pxenv_undi_force_interrupt(struct s_PXENV_UNDI_FORCE_INTERRUPT *undi_force_interrupt)
Definition pxe_undi.c:678
static PXENV_EXIT_t pxenv_undi_cleanup(struct s_PXENV_UNDI_CLEANUP *undi_cleanup)
Definition pxe_undi.c:154
Reverse Address Resolution Protocol.
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
Array of up to MAX_DATA_BLKS additional transmit buffers.
Definition pxe_api.h:4
UINT16_t TDDataLen
Length of this transmit buffer.
Definition pxe_api.h:15
SEGOFF16_t TDDataPtr
Address of this transmit buffer.
Definition pxe_api.h:16
unsigned int bus_type
Bus type.
Definition device.h:25
unsigned int device
Device ID.
Definition device.h:34
unsigned int vendor
Vendor ID.
Definition device.h:32
unsigned long class
Device class.
Definition device.h:36
unsigned int location
Location.
Definition device.h:30
unsigned int irq
IRQ.
Definition device.h:40
unsigned long ioaddr
I/O address.
Definition device.h:38
A hardware device.
Definition device.h:77
struct device_description desc
Device description.
Definition device.h:83
IP address structure.
Definition in.h:42
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A link-layer protocol.
Definition netdevice.h:115
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:128
const char * name
Protocol name.
Definition netdevice.h:117
void(* init_addr)(const void *hw_addr, void *ll_addr)
Initialise link-layer address.
Definition netdevice.h:151
const char *(* ntoa)(const void *ll_addr)
Transcribe link-layer address.
Definition netdevice.h:164
int(* mc_hash)(unsigned int af, const void *net_addr, void *ll_addr)
Hash multicast address.
Definition netdevice.h:173
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:142
uint8_t ll_addr_len
Link-layer address length.
Definition netdevice.h:199
uint16_t ll_proto
Link-layer protocol.
Definition netdevice.h:195
A network device.
Definition netdevice.h:353
A network-layer protocol.
Definition netdevice.h:65
const char * name
Protocol name.
Definition netdevice.h:67
uint16_t net_proto
Network-layer protocol.
Definition netdevice.h:100
Information for a PCI or equivalent NIC.
Definition pxe_api.h:1306
Information for an ISAPnP or equivalent NIC.
Definition pxe_api.h:1319
A data structure for storing profiling information.
Definition profile.h:27
A PXE API call.
Definition pxe.h:81
Parameter block for pxenv_undi_cleanup()
Definition pxe_api.h:844
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:845
Parameter block for pxenv_undi_clear_statistics()
Definition pxe_api.h:1224
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1225
Parameter block for pxenv_undi_close()
Definition pxe_api.h:993
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:994
Parameter block for pxenv_undi_force_interrupt()
Definition pxe_api.h:1262
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1263
Parameter block for pxenv_undi_get_iface_info()
Definition pxe_api.h:1381
UINT32_t LinkSpeed
Link speed, in bits per second.
Definition pxe_api.h:1394
UINT32_t ServiceFlags
Service flags.
Definition pxe_api.h:1401
UINT32_t Reserved[4]
Must be zero.
Definition pxe_api.h:1402
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1382
UINT8_t IfaceType[16]
Interface type.
Definition pxe_api.h:1393
Parameter block for pxenv_undi_get_information()
Definition pxe_api.h:1166
UINT16_t RxBufCt
Receive queue length.
Definition pxe_api.h:1182
UINT16_t BaseIo
I/O base address.
Definition pxe_api.h:1168
UINT16_t HwAddrLen
MAC address length.
Definition pxe_api.h:1178
SEGSEL_t ROMAddress
Real-mode ROM segment address.
Definition pxe_api.h:1181
MAC_ADDR_t CurrentNodeAddress
Current MAC address.
Definition pxe_api.h:1179
UINT16_t TxBufCt
Transmit queue length.
Definition pxe_api.h:1183
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1167
UINT16_t MaxTranUnit
Adapter MTU.
Definition pxe_api.h:1170
MAC_ADDR_t PermNodeAddress
Permanent (EEPROM) MAC address.
Definition pxe_api.h:1180
UINT16_t HwType
Hardware type.
Definition pxe_api.h:1177
UINT16_t IntNumber
IRQ number.
Definition pxe_api.h:1169
Parameter block for pxenv_undi_get_mcast_address()
Definition pxe_api.h:1281
IP4_t InetAddr
Multicast IP address.
Definition pxe_api.h:1283
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1282
MAC_ADDR_t MediaAddr
Multicast MAC address.
Definition pxe_api.h:1284
Parameter block for pxenv_undi_get_nic_type()
Definition pxe_api.h:1329
UINT8_t NicType
NIC type.
Definition pxe_api.h:1335
union s_PXENV_UNDI_GET_NIC_TYPE::nic_type_info info
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1330
Parameter block for pxenv_undi_get_statistics()
Definition pxe_api.h:1201
UINT32_t RcvCRCErrors
Receive CRC error count.
Definition pxe_api.h:1205
UINT32_t RcvResourceErrors
Receive queue overflow count.
Definition pxe_api.h:1206
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1202
UINT32_t RcvGoodFrames
Successful reception count.
Definition pxe_api.h:1204
UINT32_t XmtGoodFrames
Successful transmission count.
Definition pxe_api.h:1203
Parameter block for pxenv_undi_initialize()
Definition pxe_api.h:863
ADDR32_t ProtocolIni
NDIS 2.0 configuration information, or NULL.
Definition pxe_api.h:872
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:864
Parameter block for pxenv_undi_initiate_diags()
Definition pxe_api.h:1243
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1244
Parameter block for pxenv_undi_isr()
Definition pxe_api.h:1479
UINT16_t FrameHeaderLength
Frame header length.
Definition pxe_api.h:1492
UINT16_t FrameLength
Total frame length.
Definition pxe_api.h:1491
UINT16_t BufferLength
Data buffer length.
Definition pxe_api.h:1490
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1480
UINT8_t PktType
Packet type.
Definition pxe_api.h:1503
UINT8_t ProtType
Protocol type.
Definition pxe_api.h:1498
UINT16_t FuncFlag
Function flag.
Definition pxe_api.h:1489
SEGOFF16_t Frame
Data buffer address.
Definition pxe_api.h:1493
List of multicast MAC addresses.
Definition pxe_api.h:894
MAC_ADDR_t McastAddr[MAXNUM_MCADDR]
List of up to MAXNUM_MCADDR multicast MAC addresses.
Definition pxe_api.h:898
UINT16_t MCastAddrCount
Number of multicast MAC addresses.
Definition pxe_api.h:896
Parameter block for pxenv_undi_open()
Definition pxe_api.h:958
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:959
UINT16_t PktFilter
Receive packet filter.
Definition pxe_api.h:973
UINT16_t OpenFlag
Open flags as defined in NDIS 2.0.
Definition pxe_api.h:966
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
Multicast MAC addresses.
Definition pxe_api.h:975
Parameter block for pxenv_undi_reset_adapter()
Definition pxe_api.h:904
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
Multicast MAC addresses.
Definition pxe_api.h:907
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:905
Parameter block for pxenv_undi_set_mcast_address()
Definition pxe_api.h:1087
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1088
struct s_PXENV_UNDI_MCAST_ADDRESS R_Mcast_Buf
List of multicast addresses.
Definition pxe_api.h:1090
Parameter block for pxenv_undi_set_packet_filter()
Definition pxe_api.h:1128
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1129
UINT8_t filter
Receive packet filter.
Definition pxe_api.h:1140
Parameter block for pxenv_undi_set_station_address()
Definition pxe_api.h:1108
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1109
MAC_ADDR_t StationAddress
Station MAC address.
Definition pxe_api.h:1110
Parameter block for pxenv_undi_shutdown()
Definition pxe_api.h:925
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:926
Parameter block for pxenv_undi_startup()
Definition pxe_api.h:825
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:826
A transmit buffer descriptor, as pointed to by s_PXENV_UNDI_TRANSMIT::TBD.
Definition pxe_api.h:1025
SEGOFF16_t Xmit
Address of the transmit buffer.
Definition pxe_api.h:1027
struct s_PXENV_UNDI_TBD::DataBlk DataBlock[MAX_DATA_BLKS]
UINT16_t DataBlkCount
Definition pxe_api.h:1028
UINT16_t ImmedLength
Length of the transmit buffer.
Definition pxe_api.h:1026
Parameter block for pxenv_undi_transmit()
Definition pxe_api.h:1049
UINT8_t Protocol
Protocol.
Definition pxe_api.h:1057
SEGOFF16_t TBD
Address of the Transmit Buffer Descriptor.
Definition pxe_api.h:1068
PXENV_STATUS_t Status
PXE status code.
Definition pxe_api.h:1050
UINT8_t XmitFlag
Unicast/broadcast flag.
Definition pxe_api.h:1062
SEGOFF16_t DestAddr
Destination MAC address.
Definition pxe_api.h:1063
struct pci_nic_info pci
NIC information (if NicType==PCI_NIC)
Definition pxe_api.h:1339
struct pnp_nic_info pnp
NIC information (if NicType==PnP_NIC)
Definition pxe_api.h:1343
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383