1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER );
21 
22 #include <string.h>
23 #include <unistd.h>
24 #include <byteswap.h>
25 #include <pxe.h>
26 #include <realmode.h>
27 #include <pic8259.h>
28 #include <biosint.h>
29 #include <pnpbios.h>
30 #include <basemem_packet.h>
31 #include <ipxe/io.h>
32 #include <ipxe/iobuf.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/if_ether.h>
35 #include <ipxe/ethernet.h>
36 #include <ipxe/pci.h>
37 #include <ipxe/profile.h>
38 #include <undi.h>
39 #include <undinet.h>
40 
41 /** @file
42  *
43  * UNDI network device driver
44  *
45  */
46 
47 /** An UNDI NIC */
48 struct undi_nic {
49 	/** Device supports IRQs */
50 	int irq_supported;
51 	/** Assigned IRQ number */
52 	unsigned int irq;
53 	/** Currently processing ISR */
54 	int isr_processing;
55 	/** Bug workarounds */
56 	int hacks;
57 };
58 
59 /* Disambiguate the various error causes */
60 #define EINFO_EPXECALL							\
61 	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
62 			  "External PXE API error" )
63 #define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status )
64 
65 /**
66  * @defgroup undi_hacks UNDI workarounds
67  * @{
68  */
69 
70 /** Work around Etherboot 5.4 bugs */
71 #define UNDI_HACK_EB54		0x0001
72 
73 /** @} */
74 
75 /** Maximum number of times to retry PXENV_UNDI_INITIALIZE */
76 #define UNDI_INITIALIZE_RETRY_MAX 10
77 
78 /** Delay between retries of PXENV_UNDI_INITIALIZE */
79 #define UNDI_INITIALIZE_RETRY_DELAY_MS 200
80 
81 /** Maximum number of received packets per poll */
82 #define UNDI_RX_QUOTA 4
83 
84 /** Alignment of received frame payload */
85 #define UNDI_RX_ALIGN 16
86 
87 static void undinet_close ( struct net_device *netdev );
88 
89 /**
90  * UNDI parameter block
91  *
92  * Used as the parameter block for all UNDI API calls.  Resides in
93  * base memory.
94  */
95 static union u_PXENV_ANY __bss16 ( undinet_params );
96 #define undinet_params __use_data16 ( undinet_params )
97 
98 /**
99  * UNDI entry point
100  *
101  * Used as the indirection vector for all UNDI API calls.  Resides in
102  * base memory.
103  */
104 SEGOFF16_t __bss16 ( undinet_entry_point );
105 #define undinet_entry_point __use_data16 ( undinet_entry_point )
106 
107 /* Read TSC in real mode only when profiling */
108 #if PROFILING
109 #define RDTSC_IF_PROFILING "rdtsc\n\t"
110 #else
111 #define RDTSC_IF_PROFILING ""
112 #endif
113 
114 /** IRQ profiler */
115 static struct profiler undinet_irq_profiler __profiler =
116 	{ .name = "undinet.irq" };
117 
118 /** Receive profiler */
119 static struct profiler undinet_rx_profiler __profiler =
120 	{ .name = "undinet.rx" };
121 
122 /** A PXE API call breakdown profiler */
123 struct undinet_profiler {
124 	/** Total time spent performing REAL_CALL() */
125 	struct profiler total;
126 	/** Time spent transitioning to real mode */
127 	struct profiler p2r;
128 	/** Time spent in external code */
129 	struct profiler ext;
130 	/** Time spent transitioning back to protected mode */
131 	struct profiler r2p;
132 };
133 
134 /** PXENV_UNDI_TRANSMIT profiler */
135 static struct undinet_profiler undinet_tx_profiler __profiler = {
136 	{ .name = "undinet.tx" },
137 	{ .name = "undinet.tx_p2r" },
138 	{ .name = "undinet.tx_ext" },
139 	{ .name = "undinet.tx_r2p" },
140 };
141 
142 /** PXENV_UNDI_ISR profiler
143  *
144  * Note that this profiler will not see calls to
145  * PXENV_UNDI_ISR_IN_START, which are handled by the UNDI ISR and do
146  * not go via undinet_call().
147  */
148 static struct undinet_profiler undinet_isr_profiler __profiler = {
149 	{ .name = "undinet.isr" },
150 	{ .name = "undinet.isr_p2r" },
151 	{ .name = "undinet.isr_ext" },
152 	{ .name = "undinet.isr_r2p" },
153 };
154 
155 /** PXE unknown API call profiler
156  *
157  * This profiler can be used to measure the overhead of a dummy PXE
158  * API call.
159  */
160 static struct undinet_profiler undinet_unknown_profiler __profiler = {
161 	{ .name = "undinet.unknown" },
162 	{ .name = "undinet.unknown_p2r" },
163 	{ .name = "undinet.unknown_ext" },
164 	{ .name = "undinet.unknown_r2p" },
165 };
166 
167 /** Miscellaneous PXE API call profiler */
168 static struct undinet_profiler undinet_misc_profiler __profiler = {
169 	{ .name = "undinet.misc" },
170 	{ .name = "undinet.misc_p2r" },
171 	{ .name = "undinet.misc_ext" },
172 	{ .name = "undinet.misc_r2p" },
173 };
174 
175 /*****************************************************************************
176  *
177  * UNDI API call
178  *
179  *****************************************************************************
180  */
181 
182 /**
183  * Name PXE API call
184  *
185  * @v function		API call number
186  * @ret name		API call name
187  */
188 static inline __attribute__ (( always_inline )) const char *
undinet_function_name(unsigned int function)189 undinet_function_name ( unsigned int function ) {
190 	switch ( function ) {
191 	case PXENV_START_UNDI:
192 		return "PXENV_START_UNDI";
193 	case PXENV_STOP_UNDI:
194 		return "PXENV_STOP_UNDI";
195 	case PXENV_UNDI_STARTUP:
196 		return "PXENV_UNDI_STARTUP";
197 	case PXENV_UNDI_CLEANUP:
198 		return "PXENV_UNDI_CLEANUP";
199 	case PXENV_UNDI_INITIALIZE:
200 		return "PXENV_UNDI_INITIALIZE";
201 	case PXENV_UNDI_RESET_ADAPTER:
202 		return "PXENV_UNDI_RESET_ADAPTER";
203 	case PXENV_UNDI_SHUTDOWN:
204 		return "PXENV_UNDI_SHUTDOWN";
205 	case PXENV_UNDI_OPEN:
206 		return "PXENV_UNDI_OPEN";
207 	case PXENV_UNDI_CLOSE:
208 		return "PXENV_UNDI_CLOSE";
209 	case PXENV_UNDI_TRANSMIT:
210 		return "PXENV_UNDI_TRANSMIT";
211 	case PXENV_UNDI_SET_MCAST_ADDRESS:
212 		return "PXENV_UNDI_SET_MCAST_ADDRESS";
213 	case PXENV_UNDI_SET_STATION_ADDRESS:
214 		return "PXENV_UNDI_SET_STATION_ADDRESS";
215 	case PXENV_UNDI_SET_PACKET_FILTER:
216 		return "PXENV_UNDI_SET_PACKET_FILTER";
217 	case PXENV_UNDI_GET_INFORMATION:
218 		return "PXENV_UNDI_GET_INFORMATION";
219 	case PXENV_UNDI_GET_STATISTICS:
220 		return "PXENV_UNDI_GET_STATISTICS";
221 	case PXENV_UNDI_CLEAR_STATISTICS:
222 		return "PXENV_UNDI_CLEAR_STATISTICS";
223 	case PXENV_UNDI_INITIATE_DIAGS:
224 		return "PXENV_UNDI_INITIATE_DIAGS";
225 	case PXENV_UNDI_FORCE_INTERRUPT:
226 		return "PXENV_UNDI_FORCE_INTERRUPT";
227 	case PXENV_UNDI_GET_MCAST_ADDRESS:
228 		return "PXENV_UNDI_GET_MCAST_ADDRESS";
229 	case PXENV_UNDI_GET_NIC_TYPE:
230 		return "PXENV_UNDI_GET_NIC_TYPE";
231 	case PXENV_UNDI_GET_IFACE_INFO:
232 		return "PXENV_UNDI_GET_IFACE_INFO";
233 	/*
234 	 * Duplicate case value; this is a bug in the PXE specification.
235 	 *
236 	 *	case PXENV_UNDI_GET_STATE:
237 	 *		return "PXENV_UNDI_GET_STATE";
238 	 */
239 	case PXENV_UNDI_ISR:
240 		return "PXENV_UNDI_ISR";
241 	case PXENV_GET_CACHED_INFO:
242 		return "PXENV_GET_CACHED_INFO";
243 	default:
244 		return "UNKNOWN API CALL";
245 	}
246 }
247 
248 /**
249  * Determine applicable profiler pair (for debugging)
250  *
251  * @v function		API call number
252  * @ret profiler	Profiler
253  */
undinet_profiler(unsigned int function)254 static struct undinet_profiler * undinet_profiler ( unsigned int function ) {
255 
256 	/* Determine applicable profiler */
257 	switch ( function ) {
258 	case PXENV_UNDI_TRANSMIT:
259 		return &undinet_tx_profiler;
260 	case PXENV_UNDI_ISR:
261 		return &undinet_isr_profiler;
262 	case PXENV_UNKNOWN:
263 		return &undinet_unknown_profiler;
264 	default:
265 		return &undinet_misc_profiler;
266 	}
267 }
268 
269 /**
270  * Issue UNDI API call
271  *
272  * @v undinic		UNDI NIC
273  * @v function		API call number
274  * @v params		PXE parameter block
275  * @v params_len	Length of PXE parameter block
276  * @ret rc		Return status code
277  */
undinet_call(struct undi_nic * undinic,unsigned int function,void * params,size_t params_len)278 static int undinet_call ( struct undi_nic *undinic, unsigned int function,
279 			  void *params, size_t params_len ) {
280 	struct undinet_profiler *profiler = undinet_profiler ( function );
281 	PXENV_EXIT_t exit;
282 	uint32_t before;
283 	uint32_t started;
284 	uint32_t stopped;
285 	uint32_t after;
286 	int discard_D;
287 	int rc;
288 
289 	/* Copy parameter block and entry point */
290 	assert ( params_len <= sizeof ( undinet_params ) );
291 	memcpy ( &undinet_params, params, params_len );
292 
293 	/* Call real-mode entry point.  This calling convention will
294 	 * work with both the !PXE and the PXENV+ entry points.
295 	 */
296 	profile_start ( &profiler->total );
297 	__asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
298 					   RDTSC_IF_PROFILING
299 					   "pushl %%eax\n\t"
300 					   "pushw %%es\n\t"
301 					   "pushw %%di\n\t"
302 					   "pushw %%bx\n\t"
303 					   "lcall *undinet_entry_point\n\t"
304 					   "movw %%ax, %%bx\n\t"
305 					   RDTSC_IF_PROFILING
306 					   "addw $6, %%sp\n\t"
307 					   "popl %%edx\n\t"
308 					   "popl %%ebp\n\t" /* gcc bug */ )
309 			       : "=a" ( stopped ), "=d" ( started ),
310 				 "=b" ( exit ), "=D" ( discard_D )
311 			       : "b" ( function ),
312 			         "D" ( __from_data16 ( &undinet_params ) )
313 			       : "ecx", "esi" );
314 	profile_stop ( &profiler->total );
315 	before = profile_started ( &profiler->total );
316 	after = profile_stopped ( &profiler->total );
317 	profile_start_at ( &profiler->p2r, before );
318 	profile_stop_at ( &profiler->p2r, started );
319 	profile_start_at ( &profiler->ext, started );
320 	profile_stop_at ( &profiler->ext, stopped );
321 	profile_start_at ( &profiler->r2p, stopped );
322 	profile_stop_at ( &profiler->r2p, after );
323 
324 	/* Determine return status code based on PXENV_EXIT and
325 	 * PXENV_STATUS
326 	 */
327 	rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
328 	       0 : -EPXECALL ( undinet_params.Status ) );
329 
330 	/* If anything goes wrong, print as much debug information as
331 	 * it's possible to give.
332 	 */
333 	if ( rc != 0 ) {
334 		SEGOFF16_t rm_params = {
335 			.segment = rm_ds,
336 			.offset = __from_data16 ( &undinet_params ),
337 		};
338 
339 		DBGC ( undinic, "UNDINIC %p %s failed: %s\n", undinic,
340 		       undinet_function_name ( function ), strerror ( rc ) );
341 		DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
342 		       "%#02zx, entry point at %04x:%04x\n", undinic,
343 		       rm_params.segment, rm_params.offset, params_len,
344 		       undinet_entry_point.segment,
345 		       undinet_entry_point.offset );
346 		DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
347 		DBGC_HDA ( undinic, rm_params, params, params_len );
348 		DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
349 		DBGC_HDA ( undinic, rm_params, &undinet_params, params_len );
350 	}
351 
352 	/* Copy parameter block back */
353 	memcpy ( params, &undinet_params, params_len );
354 
355 	return rc;
356 }
357 
358 /*****************************************************************************
359  *
360  * UNDI interrupt service routine
361  *
362  *****************************************************************************
363  */
364 
365 /**
366  * UNDI interrupt service routine
367  *
368  * The UNDI ISR increments a counter (@c trigger_count) and exits.
369  */
370 extern void undiisr ( void );
371 
372 /** IRQ number */
373 uint8_t __data16 ( undiisr_irq );
374 #define undiisr_irq __use_data16 ( undiisr_irq )
375 
376 /** IRQ chain vector */
377 struct segoff __data16 ( undiisr_next_handler );
378 #define undiisr_next_handler __use_data16 ( undiisr_next_handler )
379 
380 /** IRQ trigger count */
381 volatile uint8_t __data16 ( undiisr_trigger_count ) = 0;
382 #define undiisr_trigger_count __use_data16 ( undiisr_trigger_count )
383 
384 /** Last observed trigger count */
385 static unsigned int last_trigger_count = 0;
386 
387 /**
388  * Hook UNDI interrupt service routine
389  *
390  * @v irq		IRQ number
391  */
undinet_hook_isr(unsigned int irq)392 static void undinet_hook_isr ( unsigned int irq ) {
393 
394 	assert ( irq <= IRQ_MAX );
395 	assert ( undiisr_irq == 0 );
396 
397 	undiisr_irq = irq;
398 	hook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
399 			      &undiisr_next_handler );
400 }
401 
402 /**
403  * Unhook UNDI interrupt service routine
404  *
405  * @v irq		IRQ number
406  */
undinet_unhook_isr(unsigned int irq)407 static void undinet_unhook_isr ( unsigned int irq ) {
408 
409 	assert ( irq <= IRQ_MAX );
410 
411 	unhook_bios_interrupt ( IRQ_INT ( irq ), ( ( intptr_t ) undiisr ),
412 				&undiisr_next_handler );
413 	undiisr_irq = 0;
414 }
415 
416 /**
417  * Test to see if UNDI ISR has been triggered
418  *
419  * @ret triggered	ISR has been triggered since last check
420  */
undinet_isr_triggered(void)421 static int undinet_isr_triggered ( void ) {
422 	unsigned int this_trigger_count;
423 
424 	/* Read trigger_count.  Do this only once; it is volatile */
425 	this_trigger_count = undiisr_trigger_count;
426 
427 	if ( this_trigger_count == last_trigger_count ) {
428 		/* Not triggered */
429 		return 0;
430 	} else {
431 		/* Triggered */
432 		last_trigger_count = this_trigger_count;
433 		return 1;
434 	}
435 }
436 
437 /*****************************************************************************
438  *
439  * UNDI network device interface
440  *
441  *****************************************************************************
442  */
443 
444 /** UNDI transmit buffer descriptor */
445 static struct s_PXENV_UNDI_TBD __data16 ( undinet_tbd );
446 #define undinet_tbd __use_data16 ( undinet_tbd )
447 
448 /** UNDI transmit destination address */
449 static uint8_t __data16_array ( undinet_destaddr, [ETH_ALEN] );
450 #define undinet_destaddr __use_data16 ( undinet_destaddr )
451 
452 /**
453  * Transmit packet
454  *
455  * @v netdev		Network device
456  * @v iobuf		I/O buffer
457  * @ret rc		Return status code
458  */
undinet_transmit(struct net_device * netdev,struct io_buffer * iobuf)459 static int undinet_transmit ( struct net_device *netdev,
460 			      struct io_buffer *iobuf ) {
461 	struct undi_nic *undinic = netdev->priv;
462 	struct s_PXENV_UNDI_TRANSMIT undi_transmit;
463 	const void *ll_dest;
464 	const void *ll_source;
465 	uint16_t net_proto;
466 	unsigned int flags;
467 	uint8_t protocol;
468 	size_t len;
469 	int rc;
470 
471 	/* Technically, we ought to make sure that the previous
472 	 * transmission has completed before we re-use the buffer.
473 	 * However, many PXE stacks (including at least some Intel PXE
474 	 * stacks and Etherboot 5.4) fail to generate TX completions.
475 	 * In practice this won't be a problem, since our TX datapath
476 	 * has a very low packet volume and we can get away with
477 	 * assuming that a TX will be complete by the time we want to
478 	 * transmit the next packet.
479 	 */
480 
481 	/* Some PXE stacks are unable to cope with P_UNKNOWN, and will
482 	 * always try to prepend a link-layer header.  Work around
483 	 * these stacks by stripping the existing link-layer header
484 	 * and allowing the PXE stack to (re)construct the link-layer
485 	 * header itself.
486 	 */
487 	if ( ( rc = eth_pull ( netdev, iobuf, &ll_dest, &ll_source,
488 			       &net_proto, &flags ) ) != 0 ) {
489 		DBGC ( undinic, "UNDINIC %p could not strip Ethernet header: "
490 		       "%s\n", undinic, strerror ( rc ) );
491 		return rc;
492 	}
493 	memcpy ( undinet_destaddr, ll_dest, sizeof ( undinet_destaddr ) );
494 	switch ( net_proto ) {
495 	case htons ( ETH_P_IP ) :
496 		protocol = P_IP;
497 		break;
498 	case htons ( ETH_P_ARP ) :
499 		protocol = P_ARP;
500 		break;
501 	case htons ( ETH_P_RARP ) :
502 		protocol = P_RARP;
503 		break;
504 	default:
505 		/* Unknown protocol; restore the original link-layer header */
506 		iob_push ( iobuf, sizeof ( struct ethhdr ) );
507 		protocol = P_UNKNOWN;
508 		break;
509 	}
510 
511 	/* Copy packet to UNDI I/O buffer */
512 	len = iob_len ( iobuf );
513 	if ( len > sizeof ( basemem_packet ) )
514 		len = sizeof ( basemem_packet );
515 	memcpy ( &basemem_packet, iobuf->data, len );
516 
517 	/* Create PXENV_UNDI_TRANSMIT data structure */
518 	memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
519 	undi_transmit.Protocol = protocol;
520 	undi_transmit.XmitFlag = ( ( flags & LL_BROADCAST ) ?
521 				   XMT_BROADCAST : XMT_DESTADDR );
522 	undi_transmit.DestAddr.segment = rm_ds;
523 	undi_transmit.DestAddr.offset = __from_data16 ( &undinet_destaddr );
524 	undi_transmit.TBD.segment = rm_ds;
525 	undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd );
526 
527 	/* Create PXENV_UNDI_TBD data structure */
528 	undinet_tbd.ImmedLength = len;
529 	undinet_tbd.Xmit.segment = rm_ds;
530 	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
531 
532 	/* Issue PXE API call */
533 	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT, &undi_transmit,
534 				   sizeof ( undi_transmit ) ) ) != 0 )
535 		goto done;
536 
537 	/* Free I/O buffer */
538 	netdev_tx_complete ( netdev, iobuf );
539  done:
540 	return rc;
541 }
542 
543 /**
544  * Poll for received packets
545  *
546  * @v netdev		Network device
547  *
548  * Fun, fun, fun.  UNDI drivers don't use polling; they use
549  * interrupts.  We therefore cheat and pretend that an interrupt has
550  * occurred every time undinet_poll() is called.  This isn't too much
551  * of a hack; PCI devices share IRQs and so the first thing that a
552  * proper ISR should do is call PXENV_UNDI_ISR to determine whether or
553  * not the UNDI NIC generated the interrupt; there is no harm done by
554  * spurious calls to PXENV_UNDI_ISR.  Similarly, we wouldn't be
555  * handling them any more rapidly than the usual rate of
556  * undinet_poll() being called even if we did implement a full ISR.
557  * So it should work.  Ha!
558  *
559  * Addendum (21/10/03).  Some cards don't play nicely with this trick,
560  * so instead of doing it the easy way we have to go to all the hassle
561  * of installing a genuine interrupt service routine and dealing with
562  * the wonderful 8259 Programmable Interrupt Controller.  Joy.
563  *
564  * Addendum (10/07/07).  When doing things such as iSCSI boot, in
565  * which we have to co-operate with a running OS, we can't get away
566  * with the "ISR-just-increments-a-counter-and-returns" trick at all,
567  * because it involves tying up the PIC for far too long, and other
568  * interrupt-dependent components (e.g. local disks) start breaking.
569  * We therefore implement a "proper" ISR which calls PXENV_UNDI_ISR
570  * from within interrupt context in order to deassert the device
571  * interrupt, and sends EOI if applicable.
572  */
undinet_poll(struct net_device * netdev)573 static void undinet_poll ( struct net_device *netdev ) {
574 	struct undi_nic *undinic = netdev->priv;
575 	struct s_PXENV_UNDI_ISR undi_isr;
576 	struct io_buffer *iobuf = NULL;
577 	unsigned int quota = UNDI_RX_QUOTA;
578 	size_t len;
579 	size_t reserve_len;
580 	size_t frag_len;
581 	size_t max_frag_len;
582 	int rc;
583 
584 	if ( ! undinic->isr_processing ) {
585 		/* Allow interrupt to occur.  Do this even if
586 		 * interrupts are not known to be supported, since
587 		 * some cards erroneously report that they do not
588 		 * support interrupts.
589 		 */
590 		if ( ! undinet_isr_triggered() ) {
591 			/* Allow interrupt to occur */
592 			profile_start ( &undinet_irq_profiler );
593 			__asm__ __volatile__ ( "sti\n\t"
594 					       "nop\n\t"
595 					       "nop\n\t"
596 					       "cli\n\t" );
597 			profile_stop ( &undinet_irq_profiler );
598 
599 			/* If interrupts are known to be supported,
600 			 * then do nothing on this poll; wait for the
601 			 * interrupt to be triggered.
602 			 */
603 			if ( undinic->irq_supported )
604 				return;
605 		}
606 
607 		/* Start ISR processing */
608 		undinic->isr_processing = 1;
609 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
610 	} else {
611 		/* Continue ISR processing */
612 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
613 	}
614 
615 	/* Run through the ISR loop */
616 	while ( quota ) {
617 		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
618 					   sizeof ( undi_isr ) ) ) != 0 ) {
619 			netdev_rx_err ( netdev, NULL, rc );
620 			break;
621 		}
622 		switch ( undi_isr.FuncFlag ) {
623 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
624 			/* We don't care about transmit completions */
625 			break;
626 		case PXENV_UNDI_ISR_OUT_RECEIVE:
627 			/* Packet fragment received */
628 			profile_start ( &undinet_rx_profiler );
629 			len = undi_isr.FrameLength;
630 			frag_len = undi_isr.BufferLength;
631 			reserve_len = ( -undi_isr.FrameHeaderLength &
632 					( UNDI_RX_ALIGN - 1 ) );
633 			if ( ( len == 0 ) || ( len < frag_len ) ) {
634 				/* Don't laugh.  VMWare does it. */
635 				DBGC ( undinic, "UNDINIC %p reported insane "
636 				       "fragment (%zd of %zd bytes)\n",
637 				       undinic, frag_len, len );
638 				netdev_rx_err ( netdev, NULL, -EINVAL );
639 				break;
640 			}
641 			if ( ! iobuf ) {
642 				iobuf = alloc_iob ( reserve_len + len );
643 				if ( ! iobuf ) {
644 					DBGC ( undinic, "UNDINIC %p could not "
645 					       "allocate %zd bytes for RX "
646 					       "buffer\n", undinic, len );
647 					/* Fragment will be dropped */
648 					netdev_rx_err ( netdev, NULL, -ENOMEM );
649 					goto done;
650 				}
651 				iob_reserve ( iobuf, reserve_len );
652 			}
653 			max_frag_len = iob_tailroom ( iobuf );
654 			if ( frag_len > max_frag_len ) {
655 				DBGC ( undinic, "UNDINIC %p fragment too big "
656 				       "(%zd+%zd does not fit into %zd)\n",
657 				       undinic, iob_len ( iobuf ), frag_len,
658 				       ( iob_len ( iobuf ) + max_frag_len ) );
659 				frag_len = max_frag_len;
660 			}
661 			copy_from_real ( iob_put ( iobuf, frag_len ),
662 					 undi_isr.Frame.segment,
663 					 undi_isr.Frame.offset, frag_len );
664 			if ( iob_len ( iobuf ) == len ) {
665 				/* Whole packet received; deliver it */
666 				netdev_rx ( netdev, iob_disown ( iobuf ) );
667 				quota--;
668 				/* Etherboot 5.4 fails to return all packets
669 				 * under mild load; pretend it retriggered.
670 				 */
671 				if ( undinic->hacks & UNDI_HACK_EB54 )
672 					--last_trigger_count;
673 			}
674 			profile_stop ( &undinet_rx_profiler );
675 			break;
676 		case PXENV_UNDI_ISR_OUT_DONE:
677 			/* Processing complete */
678 			undinic->isr_processing = 0;
679 			goto done;
680 		default:
681 			/* Should never happen.  VMWare does it routinely. */
682 			DBGC ( undinic, "UNDINIC %p ISR returned invalid "
683 			       "FuncFlag %04x\n", undinic, undi_isr.FuncFlag );
684 			undinic->isr_processing = 0;
685 			goto done;
686 		}
687 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
688 	}
689 
690  done:
691 	if ( iobuf ) {
692 		DBGC ( undinic, "UNDINIC %p returned incomplete packet "
693 		       "(%zd of %zd)\n", undinic, iob_len ( iobuf ),
694 		       ( iob_len ( iobuf ) + iob_tailroom ( iobuf ) ) );
695 		netdev_rx_err ( netdev, iobuf, -EINVAL );
696 	}
697 }
698 
699 /**
700  * Open NIC
701  *
702  * @v netdev		Net device
703  * @ret rc		Return status code
704  */
undinet_open(struct net_device * netdev)705 static int undinet_open ( struct net_device *netdev ) {
706 	struct undi_nic *undinic = netdev->priv;
707 	struct s_PXENV_UNDI_SET_STATION_ADDRESS undi_set_address;
708 	struct s_PXENV_UNDI_OPEN undi_open;
709 	int rc;
710 
711 	/* Hook interrupt service routine and enable interrupt if applicable */
712 	if ( undinic->irq ) {
713 		undinet_hook_isr ( undinic->irq );
714 		enable_irq ( undinic->irq );
715 		send_eoi ( undinic->irq );
716 	}
717 
718 	/* Set station address.  Required for some PXE stacks; will
719 	 * spuriously fail on others.  Ignore failures.  We only ever
720 	 * use it to set the MAC address to the card's permanent value
721 	 * anyway.
722 	 */
723 	memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
724 		 sizeof ( undi_set_address.StationAddress ) );
725 	undinet_call ( undinic, PXENV_UNDI_SET_STATION_ADDRESS,
726 		       &undi_set_address, sizeof ( undi_set_address ) );
727 
728 	/* Open NIC.  We ask for promiscuous operation, since it's the
729 	 * only way to ask for all multicast addresses.  On any
730 	 * switched network, it shouldn't really make a difference to
731 	 * performance.
732 	 */
733 	memset ( &undi_open, 0, sizeof ( undi_open ) );
734 	undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
735 	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
736 				   sizeof ( undi_open ) ) ) != 0 )
737 		goto err;
738 
739 	DBGC ( undinic, "UNDINIC %p opened\n", undinic );
740 	return 0;
741 
742  err:
743 	undinet_close ( netdev );
744 	return rc;
745 }
746 
747 /**
748  * Close NIC
749  *
750  * @v netdev		Net device
751  */
undinet_close(struct net_device * netdev)752 static void undinet_close ( struct net_device *netdev ) {
753 	struct undi_nic *undinic = netdev->priv;
754 	struct s_PXENV_UNDI_ISR undi_isr;
755 	struct s_PXENV_UNDI_CLOSE undi_close;
756 	int rc;
757 
758 	/* Ensure ISR has exited cleanly */
759 	while ( undinic->isr_processing ) {
760 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
761 		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
762 					   sizeof ( undi_isr ) ) ) != 0 )
763 			break;
764 		switch ( undi_isr.FuncFlag ) {
765 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
766 		case PXENV_UNDI_ISR_OUT_RECEIVE:
767 			/* Continue draining */
768 			break;
769 		default:
770 			/* Stop processing */
771 			undinic->isr_processing = 0;
772 			break;
773 		}
774 	}
775 
776 	/* Close NIC */
777 	undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
778 		       sizeof ( undi_close ) );
779 
780 	/* Disable interrupt and unhook ISR if applicable */
781 	if ( undinic->irq ) {
782 		disable_irq ( undinic->irq );
783 		undinet_unhook_isr ( undinic->irq );
784 	}
785 
786 	DBGC ( undinic, "UNDINIC %p closed\n", undinic );
787 }
788 
789 /**
790  * Enable/disable interrupts
791  *
792  * @v netdev		Net device
793  * @v enable		Interrupts should be enabled
794  */
undinet_irq(struct net_device * netdev,int enable)795 static void undinet_irq ( struct net_device *netdev, int enable ) {
796 	struct undi_nic *undinic = netdev->priv;
797 
798 	/* Cannot support interrupts yet */
799 	DBGC ( undinic, "UNDINIC %p cannot %s interrupts\n",
800 	       undinic, ( enable ? "enable" : "disable" ) );
801 }
802 
803 /** UNDI network device operations */
804 static struct net_device_operations undinet_operations = {
805 	.open		= undinet_open,
806 	.close		= undinet_close,
807 	.transmit	= undinet_transmit,
808 	.poll		= undinet_poll,
809 	.irq   		= undinet_irq,
810 };
811 
812 /** A device with broken support for generating interrupts */
813 struct undinet_irq_broken {
814 	/** PCI vendor ID */
815 	uint16_t pci_vendor;
816 	/** PCI device ID */
817 	uint16_t pci_device;
818 	/** PCI subsystem vendor ID */
819 	uint16_t pci_subsys_vendor;
820 	/** PCI subsystem ID */
821 	uint16_t pci_subsys;
822 };
823 
824 /**
825  * List of devices with broken support for generating interrupts
826  *
827  * Some PXE stacks are known to claim that IRQs are supported, but
828  * then never generate interrupts.  No satisfactory solution has been
829  * found to this problem; the workaround is to add the PCI vendor and
830  * device IDs to this list.  This is something of a hack, since it
831  * will generate false positives for identical devices with a working
832  * PXE stack (e.g. those that have been reflashed with iPXE), but it's
833  * an improvement on the current situation.
834  */
835 static const struct undinet_irq_broken undinet_irq_broken_list[] = {
836 	/* HP XX70x laptops */
837 	{ 0x8086, 0x1502, PCI_ANY_ID, PCI_ANY_ID },
838 	{ 0x8086, 0x1503, PCI_ANY_ID, PCI_ANY_ID },
839 	/* HP 745 G3 laptop */
840 	{ 0x14e4, 0x1687, PCI_ANY_ID, PCI_ANY_ID },
841 };
842 
843 /**
844  * Check for devices with broken support for generating interrupts
845  *
846  * @v desc		Device description
847  * @ret irq_is_broken	Interrupt support is broken; no interrupts are generated
848  */
undinet_irq_is_broken(struct device_description * desc)849 static int undinet_irq_is_broken ( struct device_description *desc ) {
850 	const struct undinet_irq_broken *broken;
851 	struct pci_device pci;
852 	uint16_t subsys_vendor;
853 	uint16_t subsys;
854 	unsigned int i;
855 
856 	/* Ignore non-PCI devices */
857 	if ( desc->bus_type != BUS_TYPE_PCI )
858 		return 0;
859 
860 	/* Read subsystem IDs */
861 	pci_init ( &pci, desc->location );
862 	pci_read_config_word ( &pci, PCI_SUBSYSTEM_VENDOR_ID, &subsys_vendor );
863 	pci_read_config_word ( &pci, PCI_SUBSYSTEM_ID, &subsys );
864 
865 	/* Check for a match against the broken device list */
866 	for ( i = 0 ; i < ( sizeof ( undinet_irq_broken_list ) /
867 			    sizeof ( undinet_irq_broken_list[0] ) ) ; i++ ) {
868 		broken = &undinet_irq_broken_list[i];
869 		if ( ( broken->pci_vendor == desc->vendor ) &&
870 		     ( broken->pci_device == desc->device ) &&
871 		     ( ( broken->pci_subsys_vendor == subsys_vendor ) ||
872 		       ( broken->pci_subsys_vendor == PCI_ANY_ID ) ) &&
873 		     ( ( broken->pci_subsys == subsys ) ||
874 		       ( broken->pci_subsys == PCI_ANY_ID ) ) ) {
875 			return 1;
876 		}
877 	}
878 	return 0;
879 }
880 
881 /**
882  * Probe UNDI device
883  *
884  * @v undi		UNDI device
885  * @v dev		Underlying generic device
886  * @ret rc		Return status code
887  */
undinet_probe(struct undi_device * undi,struct device * dev)888 int undinet_probe ( struct undi_device *undi, struct device *dev ) {
889 	struct net_device *netdev;
890 	struct undi_nic *undinic;
891 	struct s_PXENV_START_UNDI start_undi;
892 	struct s_PXENV_UNDI_STARTUP undi_startup;
893 	struct s_PXENV_UNDI_INITIALIZE undi_init;
894 	struct s_PXENV_UNDI_GET_INFORMATION undi_info;
895 	struct s_PXENV_UNDI_GET_IFACE_INFO undi_iface;
896 	struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
897 	struct s_PXENV_UNDI_CLEANUP undi_cleanup;
898 	struct s_PXENV_STOP_UNDI stop_undi;
899 	unsigned int retry;
900 	int rc;
901 
902 	/* Allocate net device */
903 	netdev = alloc_etherdev ( sizeof ( *undinic ) );
904 	if ( ! netdev )
905 		return -ENOMEM;
906 	netdev_init ( netdev, &undinet_operations );
907 	undinic = netdev->priv;
908 	undi_set_drvdata ( undi, netdev );
909 	netdev->dev = dev;
910 	memset ( undinic, 0, sizeof ( *undinic ) );
911 	undinet_entry_point = undi->entry;
912 	DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
913 
914 	/* Hook in UNDI stack */
915 	if ( ! ( undi->flags & UNDI_FL_STARTED ) ) {
916 		memset ( &start_undi, 0, sizeof ( start_undi ) );
917 		start_undi.AX = undi->pci_busdevfn;
918 		start_undi.BX = undi->isapnp_csn;
919 		start_undi.DX = undi->isapnp_read_port;
920 		start_undi.ES = BIOS_SEG;
921 		start_undi.DI = find_pnp_bios();
922 		if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
923 					   &start_undi,
924 					   sizeof ( start_undi ) ) ) != 0 )
925 			goto err_start_undi;
926 	}
927 	undi->flags |= UNDI_FL_STARTED;
928 
929 	/* Bring up UNDI stack */
930 	if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
931 		memset ( &undi_startup, 0, sizeof ( undi_startup ) );
932 		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
933 					   &undi_startup,
934 					   sizeof ( undi_startup ) ) ) != 0 )
935 			goto err_undi_startup;
936 		/* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
937 		 * due to a transient condition (e.g. media test
938 		 * failing because the link has only just come out of
939 		 * reset).  We may therefore need to retry this call
940 		 * several times.
941 		 */
942 		for ( retry = 0 ; ; ) {
943 			memset ( &undi_init, 0, sizeof ( undi_init ) );
944 			if ( ( rc = undinet_call ( undinic,
945 						   PXENV_UNDI_INITIALIZE,
946 						   &undi_init,
947 						   sizeof ( undi_init ) ) ) ==0)
948 				break;
949 			if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
950 				goto err_undi_initialize;
951 			DBGC ( undinic, "UNDINIC %p retrying "
952 			       "PXENV_UNDI_INITIALIZE (retry %d)\n",
953 			       undinic, retry );
954 			/* Delay to allow link to settle if necessary */
955 			mdelay ( UNDI_INITIALIZE_RETRY_DELAY_MS );
956 		}
957 	}
958 	undi->flags |= UNDI_FL_INITIALIZED;
959 
960 	/* Get device information */
961 	memset ( &undi_info, 0, sizeof ( undi_info ) );
962 	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
963 				   &undi_info, sizeof ( undi_info ) ) ) != 0 )
964 		goto err_undi_get_information;
965 	memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
966 	memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
967 	undinic->irq = undi_info.IntNumber;
968 	if ( undinic->irq > IRQ_MAX ) {
969 		DBGC ( undinic, "UNDINIC %p ignoring invalid IRQ %d\n",
970 		       undinic, undinic->irq );
971 		undinic->irq = 0;
972 	}
973 	DBGC ( undinic, "UNDINIC %p has MAC address %s and IRQ %d\n",
974 	       undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq );
975 
976 	/* Get interface information */
977 	memset ( &undi_iface, 0, sizeof ( undi_iface ) );
978 	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
979 				   &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
980 		goto err_undi_get_iface_info;
981 	DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
982 	       undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
983 	       undi_iface.ServiceFlags );
984 	if ( ( undi_iface.ServiceFlags & SUPPORTED_IRQ ) &&
985 	     ( undinic->irq != 0 ) ) {
986 		undinic->irq_supported = 1;
987 	}
988 	DBGC ( undinic, "UNDINIC %p using %s mode\n", undinic,
989 	       ( undinic->irq_supported ? "interrupt" : "polling" ) );
990 	if ( strncmp ( ( ( char * ) undi_iface.IfaceType ), "Etherboot",
991 		       sizeof ( undi_iface.IfaceType ) ) == 0 ) {
992 		DBGC ( undinic, "UNDINIC %p Etherboot 5.4 workaround enabled\n",
993 		       undinic );
994 		undinic->hacks |= UNDI_HACK_EB54;
995 	}
996 	if ( undinet_irq_is_broken ( &dev->desc ) ) {
997 		DBGC ( undinic, "UNDINIC %p forcing polling mode due to "
998 		       "broken interrupts\n", undinic );
999 		undinic->irq_supported = 0;
1000 	}
1001 
1002 	/* Register network device */
1003 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
1004 		goto err_register;
1005 
1006 	/* Mark as link up; we don't handle link state */
1007 	netdev_link_up ( netdev );
1008 
1009 	DBGC ( undinic, "UNDINIC %p added\n", undinic );
1010 	return 0;
1011 
1012  err_register:
1013  err_undi_get_iface_info:
1014  err_undi_get_information:
1015  err_undi_initialize:
1016 	/* Shut down UNDI stack */
1017 	memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1018 	undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
1019 		       sizeof ( undi_shutdown ) );
1020 	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1021 	undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
1022 		       sizeof ( undi_cleanup ) );
1023 	undi->flags &= ~UNDI_FL_INITIALIZED;
1024  err_undi_startup:
1025 	/* Unhook UNDI stack */
1026 	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1027 	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1028 		       sizeof ( stop_undi ) );
1029 	undi->flags &= ~UNDI_FL_STARTED;
1030  err_start_undi:
1031 	netdev_nullify ( netdev );
1032 	netdev_put ( netdev );
1033 	undi_set_drvdata ( undi, NULL );
1034 	return rc;
1035 }
1036 
1037 /**
1038  * Remove UNDI device
1039  *
1040  * @v undi		UNDI device
1041  */
undinet_remove(struct undi_device * undi)1042 void undinet_remove ( struct undi_device *undi ) {
1043 	struct net_device *netdev = undi_get_drvdata ( undi );
1044 	struct undi_nic *undinic = netdev->priv;
1045 	struct s_PXENV_UNDI_SHUTDOWN undi_shutdown;
1046 	struct s_PXENV_UNDI_CLEANUP undi_cleanup;
1047 	struct s_PXENV_STOP_UNDI stop_undi;
1048 
1049 	/* Unregister net device */
1050 	unregister_netdev ( netdev );
1051 
1052 	/* If we are preparing for an OS boot, or if we cannot exit
1053 	 * via the PXE stack, then shut down the PXE stack.
1054 	 */
1055 	if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
1056 
1057 		/* Shut down UNDI stack */
1058 		memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
1059 		undinet_call ( undinic, PXENV_UNDI_SHUTDOWN,
1060 			       &undi_shutdown, sizeof ( undi_shutdown ) );
1061 		memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
1062 		undinet_call ( undinic, PXENV_UNDI_CLEANUP,
1063 			       &undi_cleanup, sizeof ( undi_cleanup ) );
1064 		undi->flags &= ~UNDI_FL_INITIALIZED;
1065 
1066 		/* Unhook UNDI stack */
1067 		memset ( &stop_undi, 0, sizeof ( stop_undi ) );
1068 		undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1069 			       sizeof ( stop_undi ) );
1070 		undi->flags &= ~UNDI_FL_STARTED;
1071 	}
1072 
1073 	/* Clear entry point */
1074 	memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
1075 
1076 	/* Free network device */
1077 	netdev_nullify ( netdev );
1078 	netdev_put ( netdev );
1079 
1080 	DBGC ( undinic, "UNDINIC %p removed\n", undinic );
1081 }
1082