PXENV_UNDI_ISR
[PXE UNDI API]

UNDI ISR. More...


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)


Detailed Description

UNDI ISR.

Define Documentation

#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

This interrupt was ours.

Definition at line 1549 of file pxe_api.h.

Referenced by pxenv_undi_isr().

#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

We are already in the middle of processing an interrupt.

Definition at line 1559 of file pxe_api.h.

#define P_DIRECTED   0

Unicast packet (or packet captured in promiscuous mode).

Definition at line 1562 of file pxe_api.h.

#define P_BROADCAST   1

Broadcast packet.

Definition at line 1564 of file pxe_api.h.

#define P_MULTICAST   2

Multicast packet.

Definition at line 1566 of file pxe_api.h.


Typedef Documentation

Definition at line 1596 of file pxe_api.h.


Function Documentation

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 }


Generated on Tue Apr 6 20:01:59 2010 for gPXE by  doxygen 1.5.7.1