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
 SRCDIRS		+= arch/x86/image
13
 SRCDIRS		+= arch/x86/image
14
 SRCDIRS		+= arch/x86/interface/pcbios
14
 SRCDIRS		+= arch/x86/interface/pcbios
15
 SRCDIRS		+= arch/x86/interface/pxe
15
 SRCDIRS		+= arch/x86/interface/pxe
16
-SRCDIRS		+= arch/x86/interface/pxeparent
17
 SRCDIRS		+= arch/x86/interface/efi
16
 SRCDIRS		+= arch/x86/interface/efi
18
 SRCDIRS		+= arch/x86/interface/vmware
17
 SRCDIRS		+= arch/x86/interface/vmware
19
 SRCDIRS		+= arch/x86/interface/syslinux
18
 SRCDIRS		+= arch/x86/interface/syslinux

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

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

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

36
 #include <ipxe/profile.h>
36
 #include <ipxe/profile.h>
37
 #include <undi.h>
37
 #include <undi.h>
38
 #include <undinet.h>
38
 #include <undinet.h>
39
-#include <pxeparent.h>
40
 
39
 
41
 /** @file
40
 /** @file
42
  *
41
  *
56
 	int hacks;
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
  * @defgroup undi_hacks UNDI workarounds
65
  * @defgroup undi_hacks UNDI workarounds
61
  * @{
66
  * @{
80
 
85
 
81
 static void undinet_close ( struct net_device *netdev );
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
 /** IRQ profiler */
106
 /** IRQ profiler */
95
 static struct profiler undinet_irq_profiler __profiler =
107
 static struct profiler undinet_irq_profiler __profiler =
96
 	{ .name = "undinet.irq" };
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
 /** Receive profiler */
110
 /** Receive profiler */
103
 static struct profiler undinet_rx_profiler __profiler =
111
 static struct profiler undinet_rx_profiler __profiler =
104
 	{ .name = "undinet.rx" };
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
  * UNDI interrupt service routine
352
  * UNDI interrupt service routine
216
 	size_t len;
460
 	size_t len;
217
 	int rc;
461
 	int rc;
218
 
462
 
219
-	/* Start profiling */
220
-	profile_start ( &undinet_tx_profiler );
221
-
222
 	/* Technically, we ought to make sure that the previous
463
 	/* Technically, we ought to make sure that the previous
223
 	 * transmission has completed before we re-use the buffer.
464
 	 * transmission has completed before we re-use the buffer.
224
 	 * However, many PXE stacks (including at least some Intel PXE
465
 	 * However, many PXE stacks (including at least some Intel PXE
281
 	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
522
 	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );
282
 
523
 
283
 	/* Issue PXE API call */
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
 		goto done;
527
 		goto done;
289
-	profile_stop ( &undinet_tx_call_profiler );
290
 
528
 
291
 	/* Free I/O buffer */
529
 	/* Free I/O buffer */
292
 	netdev_tx_complete ( netdev, iobuf );
530
 	netdev_tx_complete ( netdev, iobuf );
293
-	profile_stop ( &undinet_tx_profiler );
294
  done:
531
  done:
295
 	return rc;
532
 	return rc;
296
 }
533
 }
369
 
606
 
370
 	/* Run through the ISR loop */
607
 	/* Run through the ISR loop */
371
 	while ( quota ) {
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
 			netdev_rx_err ( netdev, NULL, rc );
611
 			netdev_rx_err ( netdev, NULL, rc );
377
 			break;
612
 			break;
378
 		}
613
 		}
379
-		profile_stop ( &undinet_isr_call_profiler );
380
 		switch ( undi_isr.FuncFlag ) {
614
 		switch ( undi_isr.FuncFlag ) {
381
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
615
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
382
 			/* We don't care about transmit completions */
616
 			/* We don't care about transmit completions */
480
 	 */
714
 	 */
481
 	memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
715
 	memcpy ( undi_set_address.StationAddress, netdev->ll_addr,
482
 		 sizeof ( undi_set_address.StationAddress ) );
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
 	/* Open NIC.  We ask for promiscuous operation, since it's the
720
 	/* Open NIC.  We ask for promiscuous operation, since it's the
487
 	 * only way to ask for all multicast addresses.  On any
721
 	 * only way to ask for all multicast addresses.  On any
490
 	 */
724
 	 */
491
 	memset ( &undi_open, 0, sizeof ( undi_open ) );
725
 	memset ( &undi_open, 0, sizeof ( undi_open ) );
492
 	undi_open.PktFilter = ( FLTR_DIRECTED | FLTR_BRDCST | FLTR_PRMSCS );
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
 		goto err;
729
 		goto err;
496
 
730
 
497
 	DBGC ( undinic, "UNDINIC %p opened\n", undinic );
731
 	DBGC ( undinic, "UNDINIC %p opened\n", undinic );
516
 	/* Ensure ISR has exited cleanly */
750
 	/* Ensure ISR has exited cleanly */
517
 	while ( undinic->isr_processing ) {
751
 	while ( undinic->isr_processing ) {
518
 		undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
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
 			break;
755
 			break;
523
 		switch ( undi_isr.FuncFlag ) {
756
 		switch ( undi_isr.FuncFlag ) {
524
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
757
 		case PXENV_UNDI_ISR_OUT_TRANSMIT:
533
 	}
766
 	}
534
 
767
 
535
 	/* Close NIC */
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
 	/* Disable interrupt and unhook ISR if applicable */
772
 	/* Disable interrupt and unhook ISR if applicable */
540
 	if ( undinic->irq ) {
773
 	if ( undinic->irq ) {
647
 	undi_set_drvdata ( undi, netdev );
880
 	undi_set_drvdata ( undi, netdev );
648
 	netdev->dev = dev;
881
 	netdev->dev = dev;
649
 	memset ( undinic, 0, sizeof ( *undinic ) );
882
 	memset ( undinic, 0, sizeof ( *undinic ) );
650
-	undinet_entry = undi->entry;
883
+	undinet_entry_point = undi->entry;
651
 	DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
884
 	DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
652
 
885
 
653
 	/* Hook in UNDI stack */
886
 	/* Hook in UNDI stack */
658
 		start_undi.DX = undi->isapnp_read_port;
891
 		start_undi.DX = undi->isapnp_read_port;
659
 		start_undi.ES = BIOS_SEG;
892
 		start_undi.ES = BIOS_SEG;
660
 		start_undi.DI = find_pnp_bios();
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
 			goto err_start_undi;
897
 			goto err_start_undi;
665
 	}
898
 	}
666
 	undi->flags |= UNDI_FL_STARTED;
899
 	undi->flags |= UNDI_FL_STARTED;
668
 	/* Bring up UNDI stack */
901
 	/* Bring up UNDI stack */
669
 	if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
902
 	if ( ! ( undi->flags & UNDI_FL_INITIALIZED ) ) {
670
 		memset ( &undi_startup, 0, sizeof ( undi_startup ) );
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
 			goto err_undi_startup;
907
 			goto err_undi_startup;
675
 		/* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
908
 		/* On some PXE stacks, PXENV_UNDI_INITIALIZE may fail
676
 		 * due to a transient condition (e.g. media test
909
 		 * due to a transient condition (e.g. media test
680
 		 */
913
 		 */
681
 		for ( retry = 0 ; ; ) {
914
 		for ( retry = 0 ; ; ) {
682
 			memset ( &undi_init, 0, sizeof ( undi_init ) );
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
 				break;
920
 				break;
688
 			if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
921
 			if ( ++retry > UNDI_INITIALIZE_RETRY_MAX )
689
 				goto err_undi_initialize;
922
 				goto err_undi_initialize;
698
 
931
 
699
 	/* Get device information */
932
 	/* Get device information */
700
 	memset ( &undi_info, 0, sizeof ( undi_info ) );
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
 		goto err_undi_get_information;
936
 		goto err_undi_get_information;
704
 	memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
937
 	memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN );
705
 	memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
938
 	memcpy ( netdev->ll_addr, undi_info.CurrentNodeAddress, ETH_ALEN );
715
 
948
 
716
 	/* Get interface information */
949
 	/* Get interface information */
717
 	memset ( &undi_iface, 0, sizeof ( undi_iface ) );
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
 		goto err_undi_get_iface_info;
953
 		goto err_undi_get_iface_info;
722
 	DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
954
 	DBGC ( undinic, "UNDINIC %p has type %s, speed %d, flags %08x\n",
723
 	       undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
955
 	       undinic, undi_iface.IfaceType, undi_iface.LinkSpeed,
757
  err_undi_initialize:
989
  err_undi_initialize:
758
 	/* Shut down UNDI stack */
990
 	/* Shut down UNDI stack */
759
 	memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
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
 	memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
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
 	undi->flags &= ~UNDI_FL_INITIALIZED;
997
 	undi->flags &= ~UNDI_FL_INITIALIZED;
766
  err_undi_startup:
998
  err_undi_startup:
767
 	/* Unhook UNDI stack */
999
 	/* Unhook UNDI stack */
768
 	memset ( &stop_undi, 0, sizeof ( stop_undi ) );
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
 	undi->flags &= ~UNDI_FL_STARTED;
1003
 	undi->flags &= ~UNDI_FL_STARTED;
772
  err_start_undi:
1004
  err_start_undi:
773
 	netdev_nullify ( netdev );
1005
 	netdev_nullify ( netdev );
798
 
1030
 
799
 		/* Shut down UNDI stack */
1031
 		/* Shut down UNDI stack */
800
 		memset ( &undi_shutdown, 0, sizeof ( undi_shutdown ) );
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
 		memset ( &undi_cleanup, 0, sizeof ( undi_cleanup ) );
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
 		undi->flags &= ~UNDI_FL_INITIALIZED;
1038
 		undi->flags &= ~UNDI_FL_INITIALIZED;
807
 
1039
 
808
 		/* Unhook UNDI stack */
1040
 		/* Unhook UNDI stack */
809
 		memset ( &stop_undi, 0, sizeof ( stop_undi ) );
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
 		undi->flags &= ~UNDI_FL_STARTED;
1044
 		undi->flags &= ~UNDI_FL_STARTED;
813
 	}
1045
 	}
814
 
1046
 
815
 	/* Clear entry point */
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
 	/* Free network device */
1050
 	/* Free network device */
819
 	netdev_nullify ( netdev );
1051
 	netdev_nullify ( netdev );

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

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
-/*
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