From f6f6f626f7f63269c92932e7701392d619c44312 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 20 Aug 2008 02:02:51 +0100 Subject: [PATCH] [undi] Work around broken UNDI polling behaviour in winBoot/i Some dumb NBPs (e.g. emBoot's winBoot/i) never call PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START; they just sit in a tight polling loop merrily violating the PXE spec with repeated calls to PXENV_UNDI_ISR_IN_PROCESS. Force a extra calls to netdev_poll() to cope with these out-of-spec clients. --- src/interface/pxe/pxe_undi.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/interface/pxe/pxe_undi.c b/src/interface/pxe/pxe_undi.c index 26d1c7f5..aaa892f5 100644 --- a/src/interface/pxe/pxe_undi.c +++ b/src/interface/pxe/pxe_undi.c @@ -221,7 +221,7 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER; return PXENV_EXIT_FAILURE; } - DBG ( " %s", ( net_protocol ? net_protocol->name : "UNKNOWN" ) ); + DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) ); /* Calculate total packet length */ copy_from_real ( &tbd, undi_transmit->TBD.segment, @@ -264,6 +264,7 @@ PXENV_EXIT_t pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT pxe_netdev->ll_protocol->ll_addr_len ); ll_dest = destaddr; } else { + DBG ( " BCAST" ); ll_dest = pxe_netdev->ll_protocol->ll_broadcast; } rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest ); @@ -559,13 +560,25 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS; break; case PXENV_UNDI_ISR_IN_PROCESS : + DBG ( " PROCESS" ); + /* Fall through */ case PXENV_UNDI_ISR_IN_GET_NEXT : - DBG ( " PROCESS/GET_NEXT" ); + DBG ( " GET_NEXT" ); + + /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call + * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START; + * they just sit in a tight polling loop merrily + * violating the PXE spec with repeated calls to + * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to + * cope with these out-of-spec clients. + */ + netdev_poll ( pxe_netdev ); /* If we have not yet marked a TX as complete, and the * netdev TX queue is empty, report the TX completion. */ if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) { + DBG ( " TXC" ); undi_tx_count--; undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT; break; @@ -574,6 +587,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { /* Remove first packet from netdev RX queue */ iobuf = netdev_rx_dequeue ( pxe_netdev ); if ( ! iobuf ) { + DBG ( " DONE" ); /* No more packets remaining */ undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE; /* Re-enable interrupts */ @@ -583,7 +597,7 @@ PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) { /* Copy packet to base memory buffer */ len = iob_len ( iobuf ); - DBG ( " RECEIVE %zd", len ); + DBG ( " RX %zd", len ); if ( len > sizeof ( basemem_packet ) ) { /* Should never happen */ len = sizeof ( basemem_packet );