Browse Source

[undi] Move PXE API caller back into UNDI driver

As of commit 10d19bd ("[pxe] Always retrieve cached DHCPACK and apply
to relevant network device"), the UNDI driver has been the only user
of pxeparent_call().  Remove the unnecessary layer of abstraction by
refactoring this code back into undinet.c, and fix the ability of
undiisr.S to fall back to chaining to the original handler if we were
unable to unhook our own ISR.

This effectively reverts commit 337e1ed ("[pxe] Separate parent PXE
API caller from UNDINET driver").

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
7692a8ff02

+ 0
- 1
src/arch/x86/Makefile View File

@@ -13,7 +13,6 @@ SRCDIRS		+= arch/x86/core
13 13
 SRCDIRS		+= arch/x86/image
14 14
 SRCDIRS		+= arch/x86/interface/pcbios
15 15
 SRCDIRS		+= arch/x86/interface/pxe
16
-SRCDIRS		+= arch/x86/interface/pxeparent
17 16
 SRCDIRS		+= arch/x86/interface/efi
18 17
 SRCDIRS		+= arch/x86/interface/vmware
19 18
 SRCDIRS		+= arch/x86/interface/syslinux

+ 2
- 2
src/arch/x86/drivers/net/undiisr.S View File

@@ -31,7 +31,7 @@ undiisr:
31 31
 	movw	%ax, %ds
32 32
 
33 33
 	/* Check that we have an UNDI entry point */
34
-	cmpw	$0, pxeparent_entry_point
34
+	cmpw	$0, undinet_entry_point
35 35
 	je	chain
36 36
 	
37 37
 	/* Issue UNDI API call */
@@ -42,7 +42,7 @@ undiisr:
42 42
 	pushw	%es
43 43
 	pushw	%di
44 44
 	pushw	%bx
45
-	lcall	*pxeparent_entry_point
45
+	lcall	*undinet_entry_point
46 46
 	cli	/* Just in case */
47 47
 	addw	$6, %sp
48 48
 	cmpw	$PXENV_UNDI_ISR_OUT_OURS, funcflag

+ 298
- 66
src/arch/x86/drivers/net/undinet.c View File

@@ -36,7 +36,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
36 36
 #include <ipxe/profile.h>
37 37
 #include <undi.h>
38 38
 #include <undinet.h>
39
-#include <pxeparent.h>
40 39
 
41 40
 /** @file
42 41
  *
@@ -56,6 +55,12 @@ struct undi_nic {
56 55
 	int hacks;
57 56
 };
58 57
 
58
+/* Disambiguate the various error causes */
59
+#define EINFO_EPXECALL							\
60
+	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
61
+			  "External PXE API error" )
62
+#define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status )
63
+
59 64
 /**
60 65
  * @defgroup undi_hacks UNDI workarounds
61 66
  * @{
@@ -80,29 +85,268 @@ struct undi_nic {
80 85
 
81 86
 static void undinet_close ( struct net_device *netdev );
82 87
 
83
-/** Address of UNDI entry point */
84
-static SEGOFF16_t undinet_entry;
85
-
86
-/** Transmit profiler */
87
-static struct profiler undinet_tx_profiler __profiler =
88
-	{ .name = "undinet.tx" };
88
+/**
89
+ * UNDI parameter block
90
+ *
91
+ * Used as the parameter block for all UNDI API calls.  Resides in
92
+ * base memory.
93
+ */
94
+static union u_PXENV_ANY __bss16 ( undinet_params );
95
+#define undinet_params __use_data16 ( undinet_params )
89 96
 
90
-/** Transmit call profiler */
91
-static struct profiler undinet_tx_call_profiler __profiler =
92
-	{ .name = "undinet.tx_call" };
97
+/**
98
+ * UNDI entry point
99
+ *
100
+ * Used as the indirection vector for all UNDI API calls.  Resides in
101
+ * base memory.
102
+ */
103
+SEGOFF16_t __bss16 ( undinet_entry_point );
104
+#define undinet_entry_point __use_data16 ( undinet_entry_point )
93 105
 
94 106
 /** IRQ profiler */
95 107
 static struct profiler undinet_irq_profiler __profiler =
96 108
 	{ .name = "undinet.irq" };
97 109
 
98
-/** ISR call profiler */
99
-static struct profiler undinet_isr_call_profiler __profiler =
100
-	{ .name = "undinet.isr_call" };
101
-
102 110
 /** Receive profiler */
103 111
 static struct profiler undinet_rx_profiler __profiler =
104 112
 	{ .name = "undinet.rx" };
105 113
 
114
+/** A PXE API call breakdown profiler */
115
+struct undinet_profiler {
116
+	/** Total time spent performing REAL_CALL() */
117
+	struct profiler total;
118
+	/** Time spent transitioning to real mode */
119
+	struct profiler p2r;
120
+	/** Time spent in external code */
121
+	struct profiler ext;
122
+	/** Time spent transitioning back to protected mode */
123
+	struct profiler r2p;
124
+};
125
+
126
+/** PXENV_UNDI_TRANSMIT profiler */
127
+static struct undinet_profiler undinet_tx_profiler __profiler = {
128
+	{ .name = "undinet.tx" },
129
+	{ .name = "undinet.tx_p2r" },
130
+	{ .name = "undinet.tx_ext" },
131
+	{ .name = "undinet.tx_r2p" },
132
+};
133
+
134
+/** PXENV_UNDI_ISR profiler
135
+ *
136
+ * Note that this profiler will not see calls to
137
+ * PXENV_UNDI_ISR_IN_START, which are handled by the UNDI ISR and do
138
+ * not go via undinet_call().
139
+ */
140
+static struct undinet_profiler undinet_isr_profiler __profiler = {
141
+	{ .name = "undinet.isr" },
142
+	{ .name = "undinet.isr_p2r" },
143
+	{ .name = "undinet.isr_ext" },
144
+	{ .name = "undinet.isr_r2p" },
145
+};
146
+
147
+/** PXE unknown API call profiler
148
+ *
149
+ * This profiler can be used to measure the overhead of a dummy PXE
150
+ * API call.
151
+ */
152
+static struct undinet_profiler undinet_unknown_profiler __profiler = {
153
+	{ .name = "undinet.unknown" },
154
+	{ .name = "undinet.unknown_p2r" },
155
+	{ .name = "undinet.unknown_ext" },
156
+	{ .name = "undinet.unknown_r2p" },
157
+};
158
+
159
+/** Miscellaneous PXE API call profiler */
160
+static struct undinet_profiler undinet_misc_profiler __profiler = {
161
+	{ .name = "undinet.misc" },
162
+	{ .name = "undinet.misc_p2r" },
163
+	{ .name = "undinet.misc_ext" },
164
+	{ .name = "undinet.misc_r2p" },
165
+};
166
+
167
+/*****************************************************************************
168
+ *
169
+ * UNDI API call
170
+ *
171
+ *****************************************************************************
172
+ */
173
+
174
+/**
175
+ * Name PXE API call
176
+ *
177
+ * @v function		API call number
178
+ * @ret name		API call name
179
+ */
180
+static inline __attribute__ (( always_inline )) const char *
181
+undinet_function_name ( unsigned int function ) {
182
+	switch ( function ) {
183
+	case PXENV_START_UNDI:
184
+		return "PXENV_START_UNDI";
185
+	case PXENV_STOP_UNDI:
186
+		return "PXENV_STOP_UNDI";
187
+	case PXENV_UNDI_STARTUP:
188
+		return "PXENV_UNDI_STARTUP";
189
+	case PXENV_UNDI_CLEANUP:
190
+		return "PXENV_UNDI_CLEANUP";
191
+	case PXENV_UNDI_INITIALIZE:
192
+		return "PXENV_UNDI_INITIALIZE";
193
+	case PXENV_UNDI_RESET_ADAPTER:
194
+		return "PXENV_UNDI_RESET_ADAPTER";
195
+	case PXENV_UNDI_SHUTDOWN:
196
+		return "PXENV_UNDI_SHUTDOWN";
197
+	case PXENV_UNDI_OPEN:
198
+		return "PXENV_UNDI_OPEN";
199
+	case PXENV_UNDI_CLOSE:
200
+		return "PXENV_UNDI_CLOSE";
201
+	case PXENV_UNDI_TRANSMIT:
202
+		return "PXENV_UNDI_TRANSMIT";
203
+	case PXENV_UNDI_SET_MCAST_ADDRESS:
204
+		return "PXENV_UNDI_SET_MCAST_ADDRESS";
205
+	case PXENV_UNDI_SET_STATION_ADDRESS:
206
+		return "PXENV_UNDI_SET_STATION_ADDRESS";
207
+	case PXENV_UNDI_SET_PACKET_FILTER:
208
+		return "PXENV_UNDI_SET_PACKET_FILTER";
209
+	case PXENV_UNDI_GET_INFORMATION:
210
+		return "PXENV_UNDI_GET_INFORMATION";
211
+	case PXENV_UNDI_GET_STATISTICS:
212
+		return "PXENV_UNDI_GET_STATISTICS";
213
+	case PXENV_UNDI_CLEAR_STATISTICS:
214
+		return "PXENV_UNDI_CLEAR_STATISTICS";
215
+	case PXENV_UNDI_INITIATE_DIAGS:
216
+		return "PXENV_UNDI_INITIATE_DIAGS";
217
+	case PXENV_UNDI_FORCE_INTERRUPT:
218
+		return "PXENV_UNDI_FORCE_INTERRUPT";
219
+	case PXENV_UNDI_GET_MCAST_ADDRESS:
220
+		return "PXENV_UNDI_GET_MCAST_ADDRESS";
221
+	case PXENV_UNDI_GET_NIC_TYPE:
222
+		return "PXENV_UNDI_GET_NIC_TYPE";
223
+	case PXENV_UNDI_GET_IFACE_INFO:
224
+		return "PXENV_UNDI_GET_IFACE_INFO";
225
+	/*
226
+	 * Duplicate case value; this is a bug in the PXE specification.
227
+	 *
228
+	 *	case PXENV_UNDI_GET_STATE:
229
+	 *		return "PXENV_UNDI_GET_STATE";
230
+	 */
231
+	case PXENV_UNDI_ISR:
232
+		return "PXENV_UNDI_ISR";
233
+	case PXENV_GET_CACHED_INFO:
234
+		return "PXENV_GET_CACHED_INFO";
235
+	default:
236
+		return "UNKNOWN API CALL";
237
+	}
238
+}
239
+
240
+/**
241
+ * Determine applicable profiler pair (for debugging)
242
+ *
243
+ * @v function		API call number
244
+ * @ret profiler	Profiler
245
+ */
246
+static struct undinet_profiler * undinet_profiler ( unsigned int function ) {
247
+
248
+	/* Determine applicable profiler */
249
+	switch ( function ) {
250
+	case PXENV_UNDI_TRANSMIT:
251
+		return &undinet_tx_profiler;
252
+	case PXENV_UNDI_ISR:
253
+		return &undinet_isr_profiler;
254
+	case PXENV_UNKNOWN:
255
+		return &undinet_unknown_profiler;
256
+	default:
257
+		return &undinet_misc_profiler;
258
+	}
259
+}
260
+
261
+/**
262
+ * Issue UNDI API call
263
+ *
264
+ * @v undinic		UNDI NIC
265
+ * @v function		API call number
266
+ * @v params		PXE parameter block
267
+ * @v params_len	Length of PXE parameter block
268
+ * @ret rc		Return status code
269
+ */
270
+static int undinet_call ( struct undi_nic *undinic, unsigned int function,
271
+			  void *params, size_t params_len ) {
272
+	struct undinet_profiler *profiler = undinet_profiler ( function );
273
+	PXENV_EXIT_t exit;
274
+	uint32_t before;
275
+	uint32_t started;
276
+	uint32_t stopped;
277
+	uint32_t after;
278
+	int discard_D;
279
+	int rc;
280
+
281
+	/* Copy parameter block and entry point */
282
+	assert ( params_len <= sizeof ( undinet_params ) );
283
+	memcpy ( &undinet_params, params, params_len );
284
+
285
+	/* Call real-mode entry point.  This calling convention will
286
+	 * work with both the !PXE and the PXENV+ entry points.
287
+	 */
288
+	profile_start ( &profiler->total );
289
+	__asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
290
+					   "rdtsc\n\t"
291
+					   "pushl %%eax\n\t"
292
+					   "pushw %%es\n\t"
293
+					   "pushw %%di\n\t"
294
+					   "pushw %%bx\n\t"
295
+					   "lcall *undinet_entry_point\n\t"
296
+					   "movw %%ax, %%bx\n\t"
297
+					   "rdtsc\n\t"
298
+					   "addw $6, %%sp\n\t"
299
+					   "popl %%edx\n\t"
300
+					   "popl %%ebp\n\t" /* gcc bug */ )
301
+			       : "=a" ( stopped ), "=d" ( started ),
302
+				 "=b" ( exit ), "=D" ( discard_D )
303
+			       : "b" ( function ),
304
+			         "D" ( __from_data16 ( &undinet_params ) )
305
+			       : "ecx", "esi" );
306
+	profile_stop ( &profiler->total );
307
+	before = profile_started ( &profiler->total );
308
+	after = profile_stopped ( &profiler->total );
309
+	profile_start_at ( &profiler->p2r, before );
310
+	profile_stop_at ( &profiler->p2r, started );
311
+	profile_start_at ( &profiler->ext, started );
312
+	profile_stop_at ( &profiler->ext, stopped );
313
+	profile_start_at ( &profiler->r2p, stopped );
314
+	profile_stop_at ( &profiler->r2p, after );
315
+
316
+	/* Determine return status code based on PXENV_EXIT and
317
+	 * PXENV_STATUS
318
+	 */
319
+	rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
320
+	       0 : -EPXECALL ( undinet_params.Status ) );
321
+
322
+	/* If anything goes wrong, print as much debug information as
323
+	 * it's possible to give.
324
+	 */
325
+	if ( rc != 0 ) {
326
+		SEGOFF16_t rm_params = {
327
+			.segment = rm_ds,
328
+			.offset = __from_data16 ( &undinet_params ),
329
+		};
330
+
331
+		DBGC ( undinic, "UNDINIC %p %s failed: %s\n", undinic,
332
+		       undinet_function_name ( function ), strerror ( rc ) );
333
+		DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
334
+		       "%#02zx, entry point at %04x:%04x\n", undinic,
335
+		       rm_params.segment, rm_params.offset, params_len,
336
+		       undinet_entry_point.segment,
337
+		       undinet_entry_point.offset );
338
+		DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
339
+		DBGC_HDA ( undinic, rm_params, params, params_len );
340
+		DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
341
+		DBGC_HDA ( undinic, rm_params, &undinet_params, params_len );
342
+	}
343
+
344
+	/* Copy parameter block back */
345
+	memcpy ( params, &undinet_params, params_len );
346
+
347
+	return rc;
348
+}
349
+
106 350
 /*****************************************************************************
107 351
  *
108 352
  * UNDI interrupt service routine
@@ -216,9 +460,6 @@ static int undinet_transmit ( struct net_device *netdev,
216 460
 	size_t len;
217 461
 	int rc;
218 462
 
219
-	/* Start profiling */
220
-	profile_start ( &undinet_tx_profiler );
221
-
222 463
 	/* Technically, we ought to make sure that the previous
223 464
 	 * transmission has completed before we re-use the buffer.
224 465
 	 * However, many PXE stacks (including at least some Intel PXE
@@ -281,16 +522,12 @@ static int undinet_transmit ( struct net_device *netdev,
281 522
 	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
282 523
 
283 524
 	/* Issue PXE API call */
284
-	profile_start ( &undinet_tx_call_profiler );
285
-	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
286
-				     &undi_transmit,
287
-				     sizeof ( undi_transmit ) ) ) != 0 )
525
+	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_TRANSMIT, &undi_transmit,
526
+				   sizeof ( undi_transmit ) ) ) != 0 )
288 527
 		goto done;
289
-	profile_stop ( &undinet_tx_call_profiler );
290 528
 
291 529
 	/* Free I/O buffer */
292 530
 	netdev_tx_complete ( netdev, iobuf );
293
-	profile_stop ( &undinet_tx_profiler );
294 531
  done:
295 532
 	return rc;
296 533
 }
@@ -369,14 +606,11 @@ static void undinet_poll ( struct net_device *netdev ) {
369 606
 
370 607
 	/* Run through the ISR loop */
371 608
 	while ( quota ) {
372
-		profile_start ( &undinet_isr_call_profiler );
373
-		if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
374
-					     &undi_isr,
375
-					     sizeof ( undi_isr ) ) ) != 0 ) {
609
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
610
+					   sizeof ( undi_isr ) ) ) != 0 ) {
376 611
 			netdev_rx_err ( netdev, NULL, rc );
377 612
 			break;
378 613
 		}
379
-		profile_stop ( &undinet_isr_call_profiler );
380 614
 		switch ( undi_isr.FuncFlag ) {
381 615
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
382 616
 			/* We don't care about transmit completions */
@@ -480,8 +714,8 @@ static int undinet_open ( struct net_device *netdev ) {
480 714
 	 */
481 715
 	memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
482 716
 		 sizeof ( undi_set_address.StationAddress ) );
483
-	pxeparent_call ( undinet_entry, PXENV_UNDI_SET_STATION_ADDRESS,
484
-			 &undi_set_address, sizeof ( undi_set_address ) );
717
+	undinet_call ( undinic, PXENV_UNDI_SET_STATION_ADDRESS,
718
+		       &undi_set_address, sizeof ( undi_set_address ) );
485 719
 
486 720
 	/* Open NIC.  We ask for promiscuous operation, since it's the
487 721
 	 * only way to ask for all multicast addresses.  On any
@@ -490,8 +724,8 @@ static int undinet_open ( struct net_device *netdev ) {
490 724
 	 */
491 725
 	memset ( &undi_open, 0, sizeof ( undi_open ) );
492 726
 	undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
493
-	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_OPEN,
494
-				     &undi_open, sizeof ( undi_open ) ) ) != 0 )
727
+	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_OPEN, &undi_open,
728
+				   sizeof ( undi_open ) ) ) != 0 )
495 729
 		goto err;
496 730
 
497 731
 	DBGC ( undinic, "UNDINIC %p opened\n", undinic );
@@ -516,9 +750,8 @@ static void undinet_close ( struct net_device *netdev ) {
516 750
 	/* Ensure ISR has exited cleanly */
517 751
 	while ( undinic->isr_processing ) {
518 752
 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
519
-		if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_ISR,
520
-					     &undi_isr,
521
-					     sizeof ( undi_isr ) ) ) != 0 )
753
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
754
+					   sizeof ( undi_isr ) ) ) != 0 )
522 755
 			break;
523 756
 		switch ( undi_isr.FuncFlag ) {
524 757
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
@@ -533,8 +766,8 @@ static void undinet_close ( struct net_device *netdev ) {
533 766
 	}
534 767
 
535 768
 	/* Close NIC */
536
-	pxeparent_call ( undinet_entry, PXENV_UNDI_CLOSE,
537
-			 &undi_close, sizeof ( undi_close ) );
769
+	undinet_call ( undinic, PXENV_UNDI_CLOSE, &undi_close,
770
+		       sizeof ( undi_close ) );
538 771
 
539 772
 	/* Disable interrupt and unhook ISR if applicable */
540 773
 	if ( undinic->irq ) {
@@ -647,7 +880,7 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
647 880
 	undi_set_drvdata ( undi, netdev );
648 881
 	netdev->dev = dev;
649 882
 	memset ( undinic, 0, sizeof ( *undinic ) );
650
-	undinet_entry = undi->entry;
883
+	undinet_entry_point = undi->entry;
651 884
 	DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
652 885
 
653 886
 	/* Hook in UNDI stack */
@@ -658,9 +891,9 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
658 891
 		start_undi.DX = undi->isapnp_read_port;
659 892
 		start_undi.ES = BIOS_SEG;
660 893
 		start_undi.DI = find_pnp_bios();
661
-		if ( ( rc = pxeparent_call ( undinet_entry, PXENV_START_UNDI,
662
-					     &start_undi,
663
-					     sizeof ( start_undi ) ) ) != 0 )
894
+		if ( ( rc = undinet_call ( undinic, PXENV_START_UNDI,
895
+					   &start_undi,
896
+					   sizeof ( start_undi ) ) ) != 0 )
664 897
 			goto err_start_undi;
665 898
 	}
666 899
 	undi->flags |= UNDI_FL_STARTED;
@@ -668,9 +901,9 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
668 901
 	/* Bring up UNDI stack */
669 902
 	if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
670 903
 		memset ( &undi_startup, 0, sizeof ( undi_startup ) );
671
-		if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_STARTUP,
672
-					     &undi_startup,
673
-					     sizeof ( undi_startup ) ) ) != 0 )
904
+		if ( ( rc = undinet_call ( undinic, PXENV_UNDI_STARTUP,
905
+					   &undi_startup,
906
+					   sizeof ( undi_startup ) ) ) != 0 )
674 907
 			goto err_undi_startup;
675 908
 		/* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
676 909
 		 * due to a transient condition (e.g. media test
@@ -680,10 +913,10 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
680 913
 		 */
681 914
 		for ( retry = 0 ; ; ) {
682 915
 			memset ( &undi_init, 0, sizeof ( undi_init ) );
683
-			if ( ( rc = pxeparent_call ( undinet_entry,
684
-						     PXENV_UNDI_INITIALIZE,
685
-						     &undi_init,
686
-						     sizeof ( undi_init ))) ==0)
916
+			if ( ( rc = undinet_call ( undinic,
917
+						   PXENV_UNDI_INITIALIZE,
918
+						   &undi_init,
919
+						   sizeof ( undi_init ) ) ) ==0)
687 920
 				break;
688 921
 			if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
689 922
 				goto err_undi_initialize;
@@ -698,8 +931,8 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
698 931
 
699 932
 	/* Get device information */
700 933
 	memset ( &undi_info, 0, sizeof ( undi_info ) );
701
-	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_INFORMATION,
702
-				     &undi_info, sizeof ( undi_info ) ) ) != 0 )
934
+	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION,
935
+				   &undi_info, sizeof ( undi_info ) ) ) != 0 )
703 936
 		goto err_undi_get_information;
704 937
 	memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
705 938
 	memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
@@ -715,9 +948,8 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
715 948
 
716 949
 	/* Get interface information */
717 950
 	memset ( &undi_iface, 0, sizeof ( undi_iface ) );
718
-	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_GET_IFACE_INFO,
719
-				     &undi_iface,
720
-				     sizeof ( undi_iface ) ) ) != 0 )
951
+	if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_IFACE_INFO,
952
+				   &undi_iface, sizeof ( undi_iface ) ) ) != 0 )
721 953
 		goto err_undi_get_iface_info;
722 954
 	DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
723 955
 	       undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
@@ -757,17 +989,17 @@ int undinet_probe ( struct undi_device *undi, struct device *dev ) {
757 989
  err_undi_initialize:
758 990
 	/* Shut down UNDI stack */
759 991
 	memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
760
-	pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
761
-			 sizeof ( undi_shutdown ) );
992
+	undinet_call ( undinic, PXENV_UNDI_SHUTDOWN, &undi_shutdown,
993
+		       sizeof ( undi_shutdown ) );
762 994
 	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
763
-	pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP, &undi_cleanup,
764
-			 sizeof ( undi_cleanup ) );
995
+	undinet_call ( undinic, PXENV_UNDI_CLEANUP, &undi_cleanup,
996
+		       sizeof ( undi_cleanup ) );
765 997
 	undi->flags &= ~UNDI_FL_INITIALIZED;
766 998
  err_undi_startup:
767 999
 	/* Unhook UNDI stack */
768 1000
 	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
769
-	pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
770
-			 sizeof ( stop_undi ) );
1001
+	undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1002
+		       sizeof ( stop_undi ) );
771 1003
 	undi->flags &= ~UNDI_FL_STARTED;
772 1004
  err_start_undi:
773 1005
 	netdev_nullify ( netdev );
@@ -798,22 +1030,22 @@ void undinet_remove ( struct undi_device *undi ) {
798 1030
 
799 1031
 		/* Shut down UNDI stack */
800 1032
 		memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
801
-		pxeparent_call ( undinet_entry, PXENV_UNDI_SHUTDOWN,
802
-				 &undi_shutdown, sizeof ( undi_shutdown ) );
1033
+		undinet_call ( undinic, PXENV_UNDI_SHUTDOWN,
1034
+			       &undi_shutdown, sizeof ( undi_shutdown ) );
803 1035
 		memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
804
-		pxeparent_call ( undinet_entry, PXENV_UNDI_CLEANUP,
805
-				 &undi_cleanup, sizeof ( undi_cleanup ) );
1036
+		undinet_call ( undinic, PXENV_UNDI_CLEANUP,
1037
+			       &undi_cleanup, sizeof ( undi_cleanup ) );
806 1038
 		undi->flags &= ~UNDI_FL_INITIALIZED;
807 1039
 
808 1040
 		/* Unhook UNDI stack */
809 1041
 		memset ( &stop_undi, 0, sizeof ( stop_undi ) );
810
-		pxeparent_call ( undinet_entry, PXENV_STOP_UNDI, &stop_undi,
811
-				 sizeof ( stop_undi ) );
1042
+		undinet_call ( undinic, PXENV_STOP_UNDI, &stop_undi,
1043
+			       sizeof ( stop_undi ) );
812 1044
 		undi->flags &= ~UNDI_FL_STARTED;
813 1045
 	}
814 1046
 
815 1047
 	/* Clear entry point */
816
-	memset ( &undinet_entry, 0, sizeof ( undinet_entry ) );
1048
+	memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
817 1049
 
818 1050
 	/* Free network device */
819 1051
 	netdev_nullify ( netdev );

+ 0
- 11
src/arch/x86/include/pxeparent.h View File

@@ -1,11 +0,0 @@
1
-#ifndef PXEPARENT_H
2
-#define PXEPARENT_H
3
-
4
-FILE_LICENCE ( GPL2_OR_LATER );
5
-
6
-#include <pxe_types.h>
7
-
8
-extern int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
9
-			    void *params, size_t params_len );
10
-
11
-#endif

+ 0
- 287
src/arch/x86/interface/pxeparent/pxeparent.c View File

@@ -1,287 +0,0 @@
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 <ipxe/dhcp.h>
23
-#include <ipxe/profile.h>
24
-#include <pxeparent.h>
25
-#include <pxe_api.h>
26
-#include <pxe_types.h>
27
-#include <pxe.h>
28
-
29
-/** @file
30
- *
31
- * Call interface to parent PXE stack
32
- *
33
- */
34
-
35
-/* Disambiguate the various error causes */
36
-#define EINFO_EPXECALL							\
37
-	__einfo_uniqify ( EINFO_EPLATFORM, 0x01,			\
38
-			  "External PXE API error" )
39
-#define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status )
40
-
41
-/** A parent PXE API call profiler */
42
-struct pxeparent_profiler {
43
-	/** Total time spent performing REAL_CALL() */
44
-	struct profiler total;
45
-	/** Time spent transitioning to real mode */
46
-	struct profiler p2r;
47
-	/** Time spent in external code */
48
-	struct profiler ext;
49
-	/** Time spent transitioning back to protected mode */
50
-	struct profiler r2p;
51
-};
52
-
53
-/** PXENV_UNDI_TRANSMIT profiler */
54
-static struct pxeparent_profiler pxeparent_tx_profiler __profiler = {
55
-	{ .name = "pxeparent.tx" },
56
-	{ .name = "pxeparent.tx_p2r" },
57
-	{ .name = "pxeparent.tx_ext" },
58
-	{ .name = "pxeparent.tx_r2p" },
59
-};
60
-
61
-/** PXENV_UNDI_ISR profiler
62
- *
63
- * Note that this profiler will not see calls to
64
- * PXENV_UNDI_ISR_IN_START, which are handled by the UNDI ISR and do
65
- * not go via pxeparent_call().
66
- */
67
-static struct pxeparent_profiler pxeparent_isr_profiler __profiler = {
68
-	{ .name = "pxeparent.isr" },
69
-	{ .name = "pxeparent.isr_p2r" },
70
-	{ .name = "pxeparent.isr_ext" },
71
-	{ .name = "pxeparent.isr_r2p" },
72
-};
73
-
74
-/** PXE unknown API call profiler
75
- *
76
- * This profiler can be used to measure the overhead of a dummy PXE
77
- * API call.
78
- */
79
-static struct pxeparent_profiler pxeparent_unknown_profiler __profiler = {
80
-	{ .name = "pxeparent.unknown" },
81
-	{ .name = "pxeparent.unknown_p2r" },
82
-	{ .name = "pxeparent.unknown_ext" },
83
-	{ .name = "pxeparent.unknown_r2p" },
84
-};
85
-
86
-/** Miscellaneous PXE API call profiler */
87
-static struct pxeparent_profiler pxeparent_misc_profiler __profiler = {
88
-	{ .name = "pxeparent.misc" },
89
-	{ .name = "pxeparent.misc_p2r" },
90
-	{ .name = "pxeparent.misc_ext" },
91
-	{ .name = "pxeparent.misc_r2p" },
92
-};
93
-
94
-/**
95
- * Name PXE API call
96
- *
97
- * @v function		API call number
98
- * @ret name		API call name
99
- */
100
-static inline __attribute__ (( always_inline )) const char *
101
-pxeparent_function_name ( unsigned int function ) {
102
-	switch ( function ) {
103
-	case PXENV_START_UNDI:
104
-		return "PXENV_START_UNDI";
105
-	case PXENV_STOP_UNDI:
106
-		return "PXENV_STOP_UNDI";
107
-	case PXENV_UNDI_STARTUP:
108
-		return "PXENV_UNDI_STARTUP";
109
-	case PXENV_UNDI_CLEANUP:
110
-		return "PXENV_UNDI_CLEANUP";
111
-	case PXENV_UNDI_INITIALIZE:
112
-		return "PXENV_UNDI_INITIALIZE";
113
-	case PXENV_UNDI_RESET_ADAPTER:
114
-		return "PXENV_UNDI_RESET_ADAPTER";
115
-	case PXENV_UNDI_SHUTDOWN:
116
-		return "PXENV_UNDI_SHUTDOWN";
117
-	case PXENV_UNDI_OPEN:
118
-		return "PXENV_UNDI_OPEN";
119
-	case PXENV_UNDI_CLOSE:
120
-		return "PXENV_UNDI_CLOSE";
121
-	case PXENV_UNDI_TRANSMIT:
122
-		return "PXENV_UNDI_TRANSMIT";
123
-	case PXENV_UNDI_SET_MCAST_ADDRESS:
124
-		return "PXENV_UNDI_SET_MCAST_ADDRESS";
125
-	case PXENV_UNDI_SET_STATION_ADDRESS:
126
-		return "PXENV_UNDI_SET_STATION_ADDRESS";
127
-	case PXENV_UNDI_SET_PACKET_FILTER:
128
-		return "PXENV_UNDI_SET_PACKET_FILTER";
129
-	case PXENV_UNDI_GET_INFORMATION:
130
-		return "PXENV_UNDI_GET_INFORMATION";
131
-	case PXENV_UNDI_GET_STATISTICS:
132
-		return "PXENV_UNDI_GET_STATISTICS";
133
-	case PXENV_UNDI_CLEAR_STATISTICS:
134
-		return "PXENV_UNDI_CLEAR_STATISTICS";
135
-	case PXENV_UNDI_INITIATE_DIAGS:
136
-		return "PXENV_UNDI_INITIATE_DIAGS";
137
-	case PXENV_UNDI_FORCE_INTERRUPT:
138
-		return "PXENV_UNDI_FORCE_INTERRUPT";
139
-	case PXENV_UNDI_GET_MCAST_ADDRESS:
140
-		return "PXENV_UNDI_GET_MCAST_ADDRESS";
141
-	case PXENV_UNDI_GET_NIC_TYPE:
142
-		return "PXENV_UNDI_GET_NIC_TYPE";
143
-	case PXENV_UNDI_GET_IFACE_INFO:
144
-		return "PXENV_UNDI_GET_IFACE_INFO";
145
-	/*
146
-	 * Duplicate case value; this is a bug in the PXE specification.
147
-	 *
148
-	 *	case PXENV_UNDI_GET_STATE:
149
-	 *		return "PXENV_UNDI_GET_STATE";
150
-	 */
151
-	case PXENV_UNDI_ISR:
152
-		return "PXENV_UNDI_ISR";
153
-	case PXENV_GET_CACHED_INFO:
154
-		return "PXENV_GET_CACHED_INFO";
155
-	default:
156
-		return "UNKNOWN API CALL";
157
-	}
158
-}
159
-
160
-/**
161
- * Determine applicable profiler pair (for debugging)
162
- *
163
- * @v function		API call number
164
- * @ret profiler	Profiler
165
- */
166
-static struct pxeparent_profiler * pxeparent_profiler ( unsigned int function ){
167
-
168
-	/* Determine applicable profiler */
169
-	switch ( function ) {
170
-	case PXENV_UNDI_TRANSMIT:
171
-		return &pxeparent_tx_profiler;
172
-	case PXENV_UNDI_ISR:
173
-		return &pxeparent_isr_profiler;
174
-	case PXENV_UNKNOWN:
175
-		return &pxeparent_unknown_profiler;
176
-	default:
177
-		return &pxeparent_misc_profiler;
178
-	}
179
-}
180
-
181
-/**
182
- * PXE parent parameter block
183
- *
184
- * Used as the parameter block for all parent PXE API calls.  Resides
185
- * in base memory.
186
- */
187
-static union u_PXENV_ANY __bss16 ( pxeparent_params );
188
-#define pxeparent_params __use_data16 ( pxeparent_params )
189
-
190
-/** PXE parent entry point
191
- *
192
- * Used as the indirection vector for all parent PXE API calls.  Resides in
193
- * base memory.
194
- */
195
-SEGOFF16_t __bss16 ( pxeparent_entry_point );
196
-#define pxeparent_entry_point __use_data16 ( pxeparent_entry_point )
197
-
198
-/**
199
- * Issue parent PXE API call
200
- *
201
- * @v entry		Parent PXE stack entry point
202
- * @v function		API call number
203
- * @v params		PXE parameter block
204
- * @v params_len	Length of PXE parameter block
205
- * @ret rc		Return status code
206
- */
207
-int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
208
-		     void *params, size_t params_len ) {
209
-	struct pxeparent_profiler *profiler = pxeparent_profiler ( function );
210
-	PXENV_EXIT_t exit;
211
-	uint32_t before;
212
-	uint32_t started;
213
-	uint32_t stopped;
214
-	uint32_t after;
215
-	int discard_D;
216
-	int rc;
217
-
218
-	/* Copy parameter block and entry point */
219
-	assert ( params_len <= sizeof ( pxeparent_params ) );
220
-	memcpy ( &pxeparent_params, params, params_len );
221
-	memcpy ( &pxeparent_entry_point, &entry, sizeof ( entry ) );
222
-
223
-	/* Call real-mode entry point.  This calling convention will
224
-	 * work with both the !PXE and the PXENV+ entry points.
225
-	 */
226
-	profile_start ( &profiler->total );
227
-	__asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
228
-					   "rdtsc\n\t"
229
-					   "pushl %%eax\n\t"
230
-					   "pushw %%es\n\t"
231
-					   "pushw %%di\n\t"
232
-					   "pushw %%bx\n\t"
233
-					   "lcall *pxeparent_entry_point\n\t"
234
-					   "movw %%ax, %%bx\n\t"
235
-					   "rdtsc\n\t"
236
-					   "addw $6, %%sp\n\t"
237
-					   "popl %%edx\n\t"
238
-					   "popl %%ebp\n\t" /* gcc bug */ )
239
-			       : "=a" ( stopped ), "=d" ( started ),
240
-				 "=b" ( exit ), "=D" ( discard_D )
241
-			       : "b" ( function ),
242
-			         "D" ( __from_data16 ( &pxeparent_params ) )
243
-			       : "ecx", "esi" );
244
-	profile_stop ( &profiler->total );
245
-	before = profile_started ( &profiler->total );
246
-	after = profile_stopped ( &profiler->total );
247
-	profile_start_at ( &profiler->p2r, before );
248
-	profile_stop_at ( &profiler->p2r, started );
249
-	profile_start_at ( &profiler->ext, started );
250
-	profile_stop_at ( &profiler->ext, stopped );
251
-	profile_start_at ( &profiler->r2p, stopped );
252
-	profile_stop_at ( &profiler->r2p, after );
253
-
254
-	/* Determine return status code based on PXENV_EXIT and
255
-	 * PXENV_STATUS
256
-	 */
257
-	rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
258
-	       0 : -EPXECALL ( pxeparent_params.Status ) );
259
-
260
-	/* If anything goes wrong, print as much debug information as
261
-	 * it's possible to give.
262
-	 */
263
-	if ( rc != 0 ) {
264
-		SEGOFF16_t rm_params = {
265
-			.segment = rm_ds,
266
-			.offset = __from_data16 ( &pxeparent_params ),
267
-		};
268
-
269
-		DBG ( "PXEPARENT %s failed: %s\n",
270
-		       pxeparent_function_name ( function ), strerror ( rc ) );
271
-		DBG ( "PXEPARENT parameters at %04x:%04x length "
272
-		       "%#02zx, entry point at %04x:%04x\n",
273
-		       rm_params.segment, rm_params.offset, params_len,
274
-		       pxeparent_entry_point.segment,
275
-		       pxeparent_entry_point.offset );
276
-		DBG ( "PXEPARENT parameters provided:\n" );
277
-		DBG_HDA ( rm_params, params, params_len );
278
-		DBG ( "PXEPARENT parameters returned:\n" );
279
-		DBG_HDA ( rm_params, &pxeparent_params, params_len );
280
-	}
281
-
282
-	/* Copy parameter block back */
283
-	memcpy ( params, &pxeparent_params, params_len );
284
-
285
-	return rc;
286
-}
287
-

Loading…
Cancel
Save