"Fossies" - the Fresh Open Source Software archive 
Member "netboot-0.10.2/include/romconfig.i86" of archive netboot-0.10.2.tar.gz:
/*
* romconfig.i86 - Configuration definitions for the bootrom
*
* Copyright (C) 2003-2007 Gero Kuhlmann <gero@gkminix.han.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: romconfig.i86,v 1.6 2007/01/06 18:30:52 gkminix Exp $
*/
#ifndef HEADERS_ROMCONFIG_I86
#define HEADERS_ROMCONFIG_I86
/*
* Include the main C header file
*/
#define GAS_INCLUDE
#include <romconfig.h86>
/*
*****************************************************************************
*
* According to the UNDI specification, the kernel or protocol driver handles
* the hardware interrupt of the network card initially. It will then call
* UNDI to check if this interrupt really came from the network card. Upon
* return, it will then send an EOI to the PICs and calls UNDI again to finally
* process the interrupt. On the first call, UNDI has to disable the network
* card interrupts. Lateron, with the second call, UNDI has to reenable the
* network card interrupt.
*
* The problem here is that with precompiled network drivers (like packet
* drivers or NDIS drivers) the EOI will be sent to the PICs by the driver
* itself. Therefore, the kernel or protocol driver will issue a second EOI
* upon return from this call. Normally, when this routine gets executed
* no other ISR bit is set but ours, which will get reset by the driver EOI.
* Therefore the kernel EOI remains without effect. This is because in a normal
* system, any interrupt service routine should send an EOI before enabling
* interrupts at the processor level which means that low-priority interrupts
* can get interrupted by higher level interrupts only after EOI. When the
* higher-priority interrupt executes, no lower-level ISR bit remains set.
* There is just one possible situation where this double-EOI can cause
* problems. In this situation the following conditions have to apply:
*
* 1.) An interrupt service routine with lower priority than our
* network interrupt gets called and enables interrupts at the
* processor level _before_ sending its own EOI. This really is
* a serious software bug, especially since there exist 8259-
* clones (especially within C&T chipsets) which incorrectly handle
* a non-specific EOI by resetting all ISR bits instead of just
* the one with the highest priority.
* 2.) The network card produces an interrupt in the time between
* enabling interrupts and the lower-priority interrupt service
* routine sending its EOI.
* 3.) The kernel or protocol driver uses a non-specific EOI instead
* of a specific EOI. The network card ISR bit has already been
* reset by the network card driver, so the highest priority ISR
* bit seen by the PIC when it receives a non-specific EOI is that
* of the interrupt with the lower-than-ours priority.
*
* There are three solutions for this problem:
*
* 1.) We simply ignore it and assume that all hardware interrupt
* handlers are written correctly. This should be pretty safe,
* but if you have buggy software and the kernel or protocol driver
* uses non-specific EOI, you might experience occasional hangups.
* 2.) We check that we are the only routine with an ISR bit set (which
* should always be true as long as all interrupt service routines
* are written correctly). If thats not true, we have to ignore the
* network card interrupt. As with option 1 this should be pretty
* safe, but with buggy software we are going to loose network
* packets - independent of the kernel using specific or non-specific
* EOI. At least it doesnt hang the system.
* 3.) We mask out all interrupts with a set ISR bit and then enter
* special mask mode on both PICs. When the kernel or protocol
* driver sends a non-specific EOI the PIC will not be able to
* find a set ISR bit. In special mask mode, masked ISR bits are
* invisible to the PIC according to the Intel 8259A data sheet.
* Unfortunately we dont know if all higher level interrupts can
* safely deal with the special mask mode. Also this would not
* prevent the EOI to reset the ISR bits on buggy chips like with
* those C&T chipsets.
*
* All three solutions have their individual draw-backs. I think option 1
* will be the safest (as at least our own network kernel will use specific
* EOI), so we make it the default. The INTMODE value set in romconfig.h86
* specifies one of the options mentioned above.
*
* Another problem is the UNDI requirement of disabling the interrupt line of
* the network card. This can be done at two positions: directly at the network
* card chip set, or by masking the interrupt at the PIC. The first case is
* not suitable for us because only the network driver (e.g. packet or NDIS
* driver) has access to the network card chipset. However, the second case
* is unsafe when using a PCI network card, because the PCI bus allows shared
* interrupts. If another card uses the same interrupt as the network card,
* it wont receive its own interrupt while it has been masked out at the PIC.
* In addition, we can run into a race condition with disabling interrupts at
* the PIC: the base code starts its second call to the UNDI ISR routine
* independently from the actual hardware interrupt. If the base code just
* started a transmit operation, and a network interrupt appears before the
* network driver disables interrupts, the second UNDI call cant get initiated
* by the base code. This means that during the transmit operation, interrupts
* are masked off at the PIC. Many network chip sets are still able to send
* the packet, but some network drivers wait until they receive the transmit
* interrupt - which will never appear because interrupts are masked. This
* problem gets even worse when there are many PCI devices shared by the
* same interrupt line. The MASKINT values defines the masking behaviour.
* It has always to be set for interrupt mode 3. For the other two modes
* we turn it off by default. However, if masking has been turned on, the
* network driver interface has to make sure that they cant get masked again
* before a transmit operation has been finished. This will likely fail with
* interrupt mode 3!
*
* The third selectable parameter is INTCHECK. It defines if we should check
* the ISR bit before calling the network driver interrupt service routine.
* With mode 1 this is usually not necessary. If the first UNDI interrupt
* service API gets called, we can be pretty sure that the corresponding ISR
* bit is set. However, with interrupt mode 2, we check that the network card
* interrupt is the only currently serviced interrupt, and therefore INTCHECK
* should be turned on.
*
* All the logic for these values can be found in the file
* bootrom/netdrvr/lib/interrupt.S86 and in the corresponding network driver
* interface files packet.S86 and ndis.S86. You should probably never change
* any of the values defined here!
*
* Note that the original definitions for these values appear in the file
* romconfig.h86.
*/
#ifndef INTMODE
# define INTMODE 1
#endif
#if INTMODE == 1
# define DEFAULT_INTCHECK 0
# define DEFAULT_MASKINT 0
#else
# if INTMODE == 2
# define DEFAULT_INTCHECK 1
# define DEFAULT_MASKINT 0
# else
# if INTMODE == 3
# define DEFAULT_INTCHECK 1
# define DEFAULT_MASKINT 1
# else
# error Invalid INTMODE value
# endif
# endif
#endif
#ifndef INTCHECK
# define INTCHECK DEFAULT_INTCHECK
#else
# if INTCHECK != 0 && INTCHECK != 1
# error Invalid INTCHECK value
# endif
#endif
#ifndef MASKINT
# define MASKINT DEFAULT_MASKINT
#else
# if MASKINT != 0 && MASKINT != 1
# error Invalid MASKINT value
# endif
#endif
#endif