Browse Source

Work around Etherboot 5.4 bug when multiple packets are received.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
2dc8ed1eb8
1 changed files with 38 additions and 1 deletions
  1. 38
    1
      src/arch/i386/drivers/net/undinet.c

+ 38
- 1
src/arch/i386/drivers/net/undinet.c View File

45
 	unsigned int irq;
45
 	unsigned int irq;
46
 	/** Currently processing ISR */
46
 	/** Currently processing ISR */
47
 	int isr_processing;
47
 	int isr_processing;
48
+	/** Bug workarounds */
49
+	int hacks;
48
 };
50
 };
49
 
51
 
52
+/**
53
+ * @defgroup undi_hacks UNDI workarounds
54
+ * @{
55
+ */
56
+
57
+/** Work around Etherboot 5.4 bugs */
58
+#define UNDI_HACK_EB54		0x0001
59
+
60
+/** @} */
61
+
50
 static void undinet_close ( struct net_device *netdev );
62
 static void undinet_close ( struct net_device *netdev );
51
 
63
 
52
 /*****************************************************************************
64
 /*****************************************************************************
245
 static volatile uint8_t __text16 ( trigger_count ) = 0;
257
 static volatile uint8_t __text16 ( trigger_count ) = 0;
246
 #define trigger_count __use_text16 ( trigger_count )
258
 #define trigger_count __use_text16 ( trigger_count )
247
 
259
 
260
+/** Last observed trigger count */
261
+static unsigned int last_trigger_count = 0;
262
+
248
 /**
263
 /**
249
  * Hook UNDI interrupt service routine
264
  * Hook UNDI interrupt service routine
250
  *
265
  *
292
  * @ret triggered	ISR has been triggered since last check
307
  * @ret triggered	ISR has been triggered since last check
293
  */
308
  */
294
 static int undinet_isr_triggered ( void ) {
309
 static int undinet_isr_triggered ( void ) {
295
-	static unsigned int last_trigger_count = 0;
296
 	unsigned int this_trigger_count;
310
 	unsigned int this_trigger_count;
297
 
311
 
298
 	/* Read trigger_count.  Do this only once; it is volatile */
312
 	/* Read trigger_count.  Do this only once; it is volatile */
470
 					 undi_isr.Frame.segment,
484
 					 undi_isr.Frame.segment,
471
 					 undi_isr.Frame.offset, frag_len );
485
 					 undi_isr.Frame.offset, frag_len );
472
 			if ( iob_len ( iobuf ) == len ) {
486
 			if ( iob_len ( iobuf ) == len ) {
487
+				/* Whole packet received; deliver it */
473
 				netdev_rx ( netdev, iobuf );
488
 				netdev_rx ( netdev, iobuf );
474
 				iobuf = NULL;
489
 				iobuf = NULL;
475
 				--rx_quota;
490
 				--rx_quota;
491
+				/* Etherboot 5.4 fails to return all packets
492
+				 * under mild load; pretend it retriggered.
493
+				 */
494
+				if ( undinic->hacks & UNDI_HACK_EB54 )
495
+					--last_trigger_count;
476
 			}
496
 			}
477
 			break;
497
 			break;
478
 		case PXENV_UNDI_ISR_OUT_DONE:
498
 		case PXENV_UNDI_ISR_OUT_DONE:
592
 	struct s_PXENV_UNDI_STARTUP undi_startup;
612
 	struct s_PXENV_UNDI_STARTUP undi_startup;
593
 	struct s_PXENV_UNDI_INITIALIZE undi_initialize;
613
 	struct s_PXENV_UNDI_INITIALIZE undi_initialize;
594
 	struct s_PXENV_UNDI_GET_INFORMATION undi_info;
614
 	struct s_PXENV_UNDI_GET_INFORMATION undi_info;
615
+	struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
595
 	struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
616
 	struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
596
 	struct s_PXENV_UNDI_CLEANUP undi_cleanup;
617
 	struct s_PXENV_UNDI_CLEANUP undi_cleanup;
597
 	struct s_PXENV_STOP_UNDI stop_undi;
618
 	struct s_PXENV_STOP_UNDI stop_undi;
649
 	DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
670
 	DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n",
650
 	       undinic, eth_ntoa ( netdev->ll_addr ), undinic->irq );
671
 	       undinic, eth_ntoa ( netdev->ll_addr ), undinic->irq );
651
 
672
 
673
+	/* Get interface information */
674
+	memset ( &undi_iface, 0, sizeof ( undi_iface ) );
675
+	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
676
+				   &undi_iface,
677
+				   sizeof ( undi_iface ) ) ) != 0 )
678
+		goto err_undi_get_iface_info;
679
+	DBGC ( undinic, "UNDINIC %p has type %s and link speed %ld\n",
680
+	       undinic, undi_iface.IfaceType, undi_iface.LinkSpeed );
681
+	if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
682
+		       sizeof ( undi_iface.IfaceType ) ) == 0 ) {
683
+		DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
684
+		       undinic );
685
+		undinic->hacks |= UNDI_HACK_EB54;
686
+	}
687
+
652
 	/* Point to NIC specific routines */
688
 	/* Point to NIC specific routines */
653
 	netdev->open	 = undinet_open;
689
 	netdev->open	 = undinet_open;
654
 	netdev->close	 = undinet_close;
690
 	netdev->close	 = undinet_close;
663
 	return 0;
699
 	return 0;
664
 
700
 
665
  err_register:
701
  err_register:
702
+ err_undi_get_iface_info:
666
  err_bad_irq:
703
  err_bad_irq:
667
  err_undi_get_information:
704
  err_undi_get_information:
668
  err_undi_initialize:
705
  err_undi_initialize:

Loading…
Cancel
Save