|
@@ -39,8 +39,6 @@
|
39
|
39
|
|
40
|
40
|
/** An UNDI NIC */
|
41
|
41
|
struct undi_nic {
|
42
|
|
- /** Entry point */
|
43
|
|
- SEGOFF16_t entry;
|
44
|
42
|
/** Assigned IRQ number */
|
45
|
43
|
unsigned int irq;
|
46
|
44
|
/** Currently processing ISR */
|
|
@@ -167,7 +165,6 @@ static int undinet_call ( struct undi_nic *undinic, unsigned int function,
|
167
|
165
|
/* Copy parameter block and entry point */
|
168
|
166
|
assert ( params_len <= sizeof ( undinet_params ) );
|
169
|
167
|
memcpy ( &undinet_params, params, params_len );
|
170
|
|
- undinet_entry_point = undinic->entry;
|
171
|
168
|
|
172
|
169
|
/* Call real-mode entry point. This calling convention will
|
173
|
170
|
* work with both the !PXE and the PXENV+ entry points.
|
|
@@ -222,7 +219,8 @@ static int undinet_call ( struct undi_nic *undinic, unsigned int function,
|
222
|
219
|
DBGC ( undinic, "UNDINIC %p parameters at %04x:%04x length "
|
223
|
220
|
"%#02x, entry point at %04x:%04x\n", undinic,
|
224
|
221
|
rm_params.segment, rm_params.offset, params_len,
|
225
|
|
- undinic->entry.segment, undinic->entry.offset );
|
|
222
|
+ undinet_entry_point.segment,
|
|
223
|
+ undinet_entry_point.offset );
|
226
|
224
|
DBGC ( undinic, "UNDINIC %p parameters provided:\n", undinic );
|
227
|
225
|
DBGC_HDA ( undinic, rm_params, params, params_len );
|
228
|
226
|
DBGC ( undinic, "UNDINIC %p parameters returned:\n", undinic );
|
|
@@ -268,13 +266,6 @@ static unsigned int last_trigger_count = 0;
|
268
|
266
|
* Hook UNDI interrupt service routine
|
269
|
267
|
*
|
270
|
268
|
* @v irq IRQ number
|
271
|
|
- *
|
272
|
|
- * The UNDI ISR specifically does @b not chain to the previous
|
273
|
|
- * interrupt handler. BIOSes seem to install somewhat perverse
|
274
|
|
- * default interrupt handlers; some do nothing other than an iret (and
|
275
|
|
- * so will cause a screaming interrupt if there really is another
|
276
|
|
- * interrupting device) and some disable the interrupt at the PIC (and
|
277
|
|
- * so will bring our own interrupts to a shuddering halt).
|
278
|
269
|
*/
|
279
|
270
|
static void undinet_hook_isr ( unsigned int irq ) {
|
280
|
271
|
|
|
@@ -411,6 +402,15 @@ static int undinet_transmit ( struct net_device *netdev,
|
411
|
402
|
* so instead of doing it the easy way we have to go to all the hassle
|
412
|
403
|
* of installing a genuine interrupt service routine and dealing with
|
413
|
404
|
* the wonderful 8259 Programmable Interrupt Controller. Joy.
|
|
405
|
+ *
|
|
406
|
+ * Addendum (10/07/07). When doing things such as iSCSI boot, in
|
|
407
|
+ * which we have to co-operate with a running OS, we can't get away
|
|
408
|
+ * with the "ISR-just-increments-a-counter-and-returns" trick at all,
|
|
409
|
+ * because it involves tying up the PIC for far too long, and other
|
|
410
|
+ * interrupt-dependent components (e.g. local disks) start breaking.
|
|
411
|
+ * We therefore implement a "proper" ISR which calls PXENV_UNDI_ISR
|
|
412
|
+ * from within interrupt context in order to deassert the device
|
|
413
|
+ * interrupt, and sends EOI if applicable.
|
414
|
414
|
*/
|
415
|
415
|
static void undinet_poll ( struct net_device *netdev ) {
|
416
|
416
|
struct undi_nic *undinic = netdev->priv;
|
|
@@ -425,28 +425,6 @@ static void undinet_poll ( struct net_device *netdev ) {
|
425
|
425
|
if ( ! undinet_isr_triggered() )
|
426
|
426
|
return;
|
427
|
427
|
|
428
|
|
-#if 0
|
429
|
|
- /* See if this was our interrupt */
|
430
|
|
- memset ( &undi_isr, 0, sizeof ( undi_isr ) );
|
431
|
|
- undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
|
432
|
|
- if ( ( rc = undinet_call ( undinic, PXENV_UNDI_ISR, &undi_isr,
|
433
|
|
- sizeof ( undi_isr ) ) ) != 0 )
|
434
|
|
- return;
|
435
|
|
-
|
436
|
|
- /* Send EOI to the PIC. In an ideal world, we'd do
|
437
|
|
- * this only for interrupts which the UNDI stack
|
438
|
|
- * reports as "ours". However, since we don't (can't)
|
439
|
|
- * chain to the previous interrupt handler, we have to
|
440
|
|
- * acknowledge all interrupts. See undinet_hook_isr()
|
441
|
|
- * for more background.
|
442
|
|
- */
|
443
|
|
- send_eoi ( undinic->irq );
|
444
|
|
-
|
445
|
|
- /* If this wasn't our interrupt, exit now */
|
446
|
|
- if ( undi_isr.FuncFlag != PXENV_UNDI_ISR_OUT_OURS )
|
447
|
|
- return;
|
448
|
|
-#endif
|
449
|
|
-
|
450
|
428
|
/* Start ISR processing */
|
451
|
429
|
undinic->isr_processing = 1;
|
452
|
430
|
undi_isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
|
|
@@ -651,7 +629,7 @@ int undinet_probe ( struct undi_device *undi ) {
|
651
|
629
|
undi_set_drvdata ( undi, netdev );
|
652
|
630
|
netdev->dev = &undi->dev;
|
653
|
631
|
memset ( undinic, 0, sizeof ( *undinic ) );
|
654
|
|
- undinic->entry = undi->entry;
|
|
632
|
+ undinet_entry_point = undi->entry;
|
655
|
633
|
DBGC ( undinic, "UNDINIC %p using UNDI %p\n", undinic, undi );
|
656
|
634
|
|
657
|
635
|
/* Hook in UNDI stack */
|
|
@@ -770,6 +748,9 @@ void undinet_remove ( struct undi_device *undi ) {
|
770
|
748
|
sizeof ( stop_undi ) );
|
771
|
749
|
undi->flags &= ~UNDI_FL_STARTED;
|
772
|
750
|
|
|
751
|
+ /* Clear entry point */
|
|
752
|
+ memset ( &undinet_entry_point, 0, sizeof ( undinet_entry_point ) );
|
|
753
|
+
|
773
|
754
|
/* Free network device */
|
774
|
755
|
netdev_nullify ( netdev );
|
775
|
756
|
netdev_put ( netdev );
|