Data Structures | |
| struct | s_PXENV_UNDI_ISR |
| Parameter block for pxenv_undi_isr(). More... | |
Defines | |
| #define | PXENV_UNDI_ISR 0x0014 |
| PXE API function code for pxenv_undi_isr(). | |
| #define | PXENV_UNDI_ISR_IN_START 1 |
| Determine whether or not this is our interrupt. | |
| #define | PXENV_UNDI_ISR_IN_PROCESS 2 |
| Start processing interrupt. | |
| #define | PXENV_UNDI_ISR_IN_GET_NEXT 3 |
| Continue processing interrupt. | |
| #define | PXENV_UNDI_ISR_OUT_OURS 0 |
| This interrupt was ours. | |
| #define | PXENV_UNDI_ISR_OUT_NOT_OURS 1 |
| This interrupt was not ours. | |
| #define | PXENV_UNDI_ISR_OUT_DONE 0 |
| Finished processing interrupt. | |
| #define | PXENV_UNDI_ISR_OUT_TRANSMIT 2 |
| A packet transmission has completed. | |
| #define | PXENV_UNDI_ISR_OUT_RECEIVE 3 |
| A packet has been received. | |
| #define | PXENV_UNDI_ISR_OUT_BUSY 4 |
| We are already in the middle of processing an interrupt. | |
| #define | P_DIRECTED 0 |
| Unicast packet (or packet captured in promiscuous mode). | |
| #define | P_BROADCAST 1 |
| Broadcast packet. | |
| #define | P_MULTICAST 2 |
| Multicast packet. | |
Typedefs | |
| typedef struct s_PXENV_UNDI_ISR | PXENV_UNDI_ISR_t |
Functions | |
| PXENV_EXIT_t | pxenv_undi_isr (struct s_PXENV_UNDI_ISR *undi_isr) |
| #define PXENV_UNDI_ISR 0x0014 |
PXE API function code for pxenv_undi_isr().
Definition at line 1540 of file pxe_api.h.
Referenced by pxe_api_call(), pxeparent_function_name(), undinet_close(), and undinet_poll().
| #define PXENV_UNDI_ISR_IN_START 1 |
Determine whether or not this is our interrupt.
Definition at line 1543 of file pxe_api.h.
Referenced by pxenv_undi_isr().
| #define PXENV_UNDI_ISR_IN_PROCESS 2 |
Start processing interrupt.
Definition at line 1545 of file pxe_api.h.
Referenced by pxenv_undi_isr(), and undinet_poll().
| #define PXENV_UNDI_ISR_IN_GET_NEXT 3 |
Continue processing interrupt.
Definition at line 1547 of file pxe_api.h.
Referenced by pxenv_undi_isr(), undinet_close(), and undinet_poll().
| #define PXENV_UNDI_ISR_OUT_OURS 0 |
| #define PXENV_UNDI_ISR_OUT_NOT_OURS 1 |
This interrupt was not ours.
Definition at line 1551 of file pxe_api.h.
Referenced by pxenv_undi_isr().
| #define PXENV_UNDI_ISR_OUT_DONE 0 |
Finished processing interrupt.
Definition at line 1553 of file pxe_api.h.
Referenced by pxenv_undi_isr(), and undinet_poll().
| #define PXENV_UNDI_ISR_OUT_TRANSMIT 2 |
A packet transmission has completed.
Definition at line 1555 of file pxe_api.h.
Referenced by pxenv_undi_isr(), undinet_close(), and undinet_poll().
| #define PXENV_UNDI_ISR_OUT_RECEIVE 3 |
A packet has been received.
Definition at line 1557 of file pxe_api.h.
Referenced by pxenv_undi_isr(), undinet_close(), and undinet_poll().
| #define PXENV_UNDI_ISR_OUT_BUSY 4 |
| #define P_DIRECTED 0 |
| typedef struct s_PXENV_UNDI_ISR PXENV_UNDI_ISR_t |
| PXENV_EXIT_t pxenv_undi_isr | ( | struct s_PXENV_UNDI_ISR * | undi_isr | ) |
Definition at line 642 of file pxe_undi.c.
References __from_data16, arp_protocol, basemem_packet, s_PXENV_UNDI_ISR::BufferLength, io_buffer::data, DBGC2, ETH_P_ARP, ETH_P_IP, ETH_P_RARP, s_PXENV_UNDI_ISR::Frame, s_PXENV_UNDI_ISR::FrameHeaderLength, s_PXENV_UNDI_ISR::FrameLength, free_iob(), s_PXENV_UNDI_ISR::FuncFlag, htons, iob_len(), ipv4_protocol, list_empty(), net_device::ll_protocol, memcpy, net_protocol::name, netdev_irq(), netdev_irq_enabled(), netdev_poll(), netdev_rx_dequeue(), NULL, s_SEGOFF16::offset, P_ARP, P_IP, P_RARP, P_UNKNOWN, s_PXENV_UNDI_ISR::PktType, s_PXENV_UNDI_ISR::ProtType, ll_protocol::pull, PXENV_EXIT_FAILURE, PXENV_EXIT_SUCCESS, PXENV_STATUS_SUCCESS, PXENV_STATUS_UNDI_INVALID_PARAMETER, pxenv_undi_isr(), PXENV_UNDI_ISR_IN_GET_NEXT, PXENV_UNDI_ISR_IN_PROCESS, PXENV_UNDI_ISR_IN_START, PXENV_UNDI_ISR_OUT_DONE, PXENV_UNDI_ISR_OUT_NOT_OURS, PXENV_UNDI_ISR_OUT_OURS, PXENV_UNDI_ISR_OUT_RECEIVE, PXENV_UNDI_ISR_OUT_TRANSMIT, rarp_protocol, rm_ds, s_SEGOFF16::segment, s_PXENV_UNDI_ISR::Status, net_device::tx_queue, undi_tx_count, and XMT_DESTADDR.
Referenced by pxe_api_call(), and pxenv_undi_isr().
00642 { 00643 struct io_buffer *iobuf; 00644 size_t len; 00645 struct ll_protocol *ll_protocol; 00646 const void *ll_dest; 00647 const void *ll_source; 00648 uint16_t net_proto; 00649 size_t ll_hlen; 00650 struct net_protocol *net_protocol; 00651 unsigned int prottype; 00652 int rc; 00653 00654 /* Use coloured debug, since UNDI ISR messages are likely to 00655 * be interspersed amongst other UNDI messages. 00656 */ 00657 DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" ); 00658 00659 /* Just in case some idiot actually looks at these fields when 00660 * we weren't meant to fill them in... 00661 */ 00662 undi_isr->BufferLength = 0; 00663 undi_isr->FrameLength = 0; 00664 undi_isr->FrameHeaderLength = 0; 00665 undi_isr->ProtType = 0; 00666 undi_isr->PktType = 0; 00667 00668 switch ( undi_isr->FuncFlag ) { 00669 case PXENV_UNDI_ISR_IN_START : 00670 DBGC2 ( &pxenv_undi_isr, " START" ); 00671 00672 /* Call poll(). This should acknowledge the device 00673 * interrupt and queue up any received packet. 00674 */ 00675 netdev_poll ( pxe_netdev ); 00676 00677 /* A 100% accurate determination of "OURS" vs "NOT 00678 * OURS" is difficult to achieve without invasive and 00679 * unpleasant changes to the driver model. We settle 00680 * for always returning "OURS" if interrupts are 00681 * currently enabled. 00682 * 00683 * Returning "NOT OURS" when interrupts are disabled 00684 * allows us to avoid a potential interrupt storm when 00685 * we are on a shared interrupt line; if we were to 00686 * always return "OURS" then the other device's ISR 00687 * may never be called. 00688 */ 00689 if ( netdev_irq_enabled ( pxe_netdev ) ) { 00690 DBGC2 ( &pxenv_undi_isr, " OURS" ); 00691 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS; 00692 } else { 00693 DBGC2 ( &pxenv_undi_isr, " NOT OURS" ); 00694 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_NOT_OURS; 00695 } 00696 00697 /* Disable interrupts */ 00698 netdev_irq ( pxe_netdev, 0 ); 00699 00700 break; 00701 case PXENV_UNDI_ISR_IN_PROCESS : 00702 case PXENV_UNDI_ISR_IN_GET_NEXT : 00703 DBGC2 ( &pxenv_undi_isr, " %s", 00704 ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ? 00705 "PROCESS" : "GET_NEXT" ) ); 00706 00707 /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call 00708 * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START; 00709 * they just sit in a tight polling loop merrily 00710 * violating the PXE spec with repeated calls to 00711 * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to 00712 * cope with these out-of-spec clients. 00713 */ 00714 netdev_poll ( pxe_netdev ); 00715 00716 /* If we have not yet marked a TX as complete, and the 00717 * netdev TX queue is empty, report the TX completion. 00718 */ 00719 if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) { 00720 DBGC2 ( &pxenv_undi_isr, " TXC" ); 00721 undi_tx_count--; 00722 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT; 00723 break; 00724 } 00725 00726 /* Remove first packet from netdev RX queue */ 00727 iobuf = netdev_rx_dequeue ( pxe_netdev ); 00728 if ( ! iobuf ) { 00729 DBGC2 ( &pxenv_undi_isr, " DONE" ); 00730 /* No more packets remaining */ 00731 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; 00732 /* Re-enable interrupts */ 00733 netdev_irq ( pxe_netdev, 1 ); 00734 break; 00735 } 00736 00737 /* Copy packet to base memory buffer */ 00738 len = iob_len ( iobuf ); 00739 DBGC2 ( &pxenv_undi_isr, " RX" ); 00740 if ( len > sizeof ( basemem_packet ) ) { 00741 /* Should never happen */ 00742 DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len ); 00743 len = sizeof ( basemem_packet ); 00744 } 00745 memcpy ( basemem_packet, iobuf->data, len ); 00746 00747 /* Strip link-layer header */ 00748 ll_protocol = pxe_netdev->ll_protocol; 00749 if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest, 00750 &ll_source, &net_proto )) !=0){ 00751 /* Assume unknown net_proto and no ll_source */ 00752 net_proto = 0; 00753 ll_source = NULL; 00754 } 00755 ll_hlen = ( len - iob_len ( iobuf ) ); 00756 00757 /* Determine network-layer protocol */ 00758 switch ( net_proto ) { 00759 case htons ( ETH_P_IP ): 00760 net_protocol = &ipv4_protocol; 00761 prottype = P_IP; 00762 break; 00763 case htons ( ETH_P_ARP ): 00764 net_protocol = &arp_protocol; 00765 prottype = P_ARP; 00766 break; 00767 case htons ( ETH_P_RARP ): 00768 net_protocol = &rarp_protocol; 00769 prottype = P_RARP; 00770 break; 00771 default: 00772 net_protocol = NULL; 00773 prottype = P_UNKNOWN; 00774 break; 00775 } 00776 00777 /* Fill in UNDI_ISR structure */ 00778 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE; 00779 undi_isr->BufferLength = len; 00780 undi_isr->FrameLength = len; 00781 undi_isr->FrameHeaderLength = ll_hlen; 00782 undi_isr->Frame.segment = rm_ds; 00783 undi_isr->Frame.offset = __from_data16 ( basemem_packet ); 00784 undi_isr->ProtType = prottype; 00785 undi_isr->PktType = XMT_DESTADDR; 00786 DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d", 00787 undi_isr->Frame.segment, undi_isr->Frame.offset, 00788 undi_isr->BufferLength, undi_isr->FrameLength, 00789 ( net_protocol ? net_protocol->name : "RAW" ), 00790 undi_isr->FrameHeaderLength ); 00791 00792 /* Free packet */ 00793 free_iob ( iobuf ); 00794 break; 00795 default : 00796 DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n", 00797 undi_isr->FuncFlag ); 00798 00799 /* Should never happen */ 00800 undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; 00801 undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; 00802 return PXENV_EXIT_FAILURE; 00803 } 00804 00805 DBGC2 ( &pxenv_undi_isr, "\n" ); 00806 undi_isr->Status = PXENV_STATUS_SUCCESS; 00807 return PXENV_EXIT_SUCCESS; 00808 }
1.5.7.1