📄 vt82c686pciibc.c
字号:
/* vt82c686PciIbc.c - via vt82c686 PCI-ISA Bridge Controller (IBC) driver */
/* Copyright 2007 evoc. */
#include "copyright_wrs.h"
/*
modification history
2007.11.08 creat by kuangyaowen,evoc.
--------------------
*/
/*
DESCRIPTION
This module implements the via vt82c686 ISA Bridge Controller (IBC)
driver.
The vt82c686 Chip is a highly integrated ASIC providing PCI-ISA interface
chip. It provides following major capabilities:
PCI Bus Master capability for ISA DMA.
PCI Arbiter capability
PCI Power management control
64 byte PCI bus FIFO for burst capability
Standard ISA interrupt controllers (82C59)
Standard ISA timer/counter (82C54)
This driver is limited to the interrupt controller feature of the chip.
This driver does not interact with any other drivers supporting the
vt82c686 chip.
The chip implements a standard ISA bus interrupt system consisting of
two 82C59A interrupt controller units. The two units are cascaded
together to provide 15 actual interrupt lines. The first unit implements
interrupt number 0 thru 7. Interrupt number 2 is the cascaded input
from the second 82C59A controller, so it functionally does not exist
as a user input. The inputs on the second controller are numbered 8 through
15. Since they are cascaded into interrupt number 2 on the first unit,
their actual priority is higher than inputs 3 through 7 on the first
unit. The true priority heirarchy (from high to low) is: 0, 1, 8, 9,
10, 11, 12, 13, 14, 15, 3, 4, 5, 6, 7. The highest priority input that
is active is the unit that shall receive service first.
The actual vector number corresponding to IRQ0 is determined by the value
in sysVectorIRQ0 at initialization time.
Based on the IBM-PC legacy system, this driver supports 16 levels, each
of which maps to a single vector. Since PCI interrupt lines are shared, this
driver does provide for overloading of interrupt routines (i.e. there is
a list of interrupt routines for each interrupt vector (level)). To service
a vector requires that all connected interrupt routines be called in order
of their connection.
.SH INITIALIZATION
This driver is initialized from the BSP, usually as part of sysHwInit().
The first routine to be called is sysPicInit(). The routine verifies the type
of device and then initializes the interrupt pins routine to IRQ numbers.
Typical device initialization looks like this:
.CS
/@ Initialize the extended portion of the IBC's PCI Header. @/
int pciBusNum;
int pciDevNum;
int pciFuncNum;
if (pciFindDevice ((PCI_ID_IBC & 0xFFFF), (PCI_ID_IBC >> 16) & 0xFFFF, 0,
&pciBusNum, &pciDevNum, &pciFuncNum) != ERROR)
{
sysPicInit ();
}
.CE
.SH CUSTOMIZING THIS DRIVER
The macros PIC_BYTE_OUT and PIC_BYTE_IN provide the hardware access methods.
By default they call the routines sysOutByte() and sysInByte(), which are
presumed to be defined by the BSP with the appropriate memory map offsets.
The user may redefine these macros as needed.
The macros CPU_INT_LOCK() and CPU_INT_UNLOCK provide the access
to the CPU level interrupt lock/unlock routines. We presume that there
is a single interrupt line to the CPU. By default these macros call
intLock() and intUnlock() respectively.
*/
/* includes */
#include "vxWorks.h"
#include "config.h"
#include "errno.h"
#include "sp.h"
#include "vt82c686PciIbc.h"
#include "sysEpic.h"
#ifdef INCLUDE_WINDVIEW
#include "private/eventP.h"
#endif
/* defines */
#ifndef CPU_INT_LOCK
# define CPU_INT_LOCK(pData) \
(*pData = intLock ())
#endif
#ifndef CPU_INT_UNLOCK
# define CPU_INT_UNLOCK(data) \
(intUnlock (data))
#endif
/* externs */
IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
IMPORT void sysOutByte (ULONG, UCHAR);
IMPORT UCHAR sysInByte (ULONG);
IMPORT void sysEpicIntHandlerExec (UCHAR intVec);
IMPORT UINT sysVectorIRQ0; /* vector for IRQ0 */
/* forward declarations */
LOCAL int sysPciIbcIntEnable (int intLevel);
LOCAL int sysPciIbcIntDisable (int intLevel);
LOCAL UCHAR sysPicPhantomInt (UCHAR *intNum, int lvl7Int, int lvl15Int);
LOCAL void sysPicEndOfInt (int intLevel);
void sysPicIntLevelSet(int intLevel);
void sysPicIntHandler (void);
#if FALSE /* defined(INCLUDE_WINDVIEW) || defined(INCLUDE_INSTRUMENTATION) */
IMPORT int evtTimeStamp; /* Windview 1.0 only */
#endif
/* Mask values are the currently disabled sources */
LOCAL UINT8 sysPicMask1 = 0xfb; /* all levels disabled */
LOCAL UINT8 sysPicMask2 = 0xff;
/* Level values are the interrupt level masks */
LOCAL UINT8 sysPicLevel1 = 0;
LOCAL UINT8 sysPicLevel2 = 0;
LOCAL UINT8 sysPicLevelCur = 16; /* curr intNum is 15, all enabled */
/* level values by real priority */
LOCAL UCHAR sysPicPriMask1[17] =
{
0xFB,0xFA,0xF8,0xF8,0xF0,0xE0,0xC0,0x80,
0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x0
};
LOCAL UCHAR sysPicPriMask2 [17] =
{
0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0
};
#ifndef CPU_INT_LOCK
# define CPU_INT_LOCK(pData) \
(*pData = intLock ())
#endif
#ifndef CPU_INT_UNLOCK
# define CPU_INT_UNLOCK(data) \
(intUnlock (data))
#endif
/*******************************************************************************
*
* sysPicInit - Initialize the PIC (Via ISA bridge Controller
* also known as a PIB (PCI to ISA Bridge)
*
* This routine initializes the non PCI header configuration registers
* of the PIC within the vt82c686 PIC Processor Interrupt Controller.
*
* RETURNS: OK always
*
*/
STATUS sysPicInit (void)
{
UCHAR intNum;
/* Initialize the Interrupt Controller #1 */
PIC_BYTE_OUT (PIC1_ICW1, 0x11); /* ICW1 */
/* bit 4 = 1 -> select ICW1, bit1 SNGL = 0 -> two cascaded,
* bit 0 = 1 -> ICW4 must be intialized, indicates x86 mode,
* indicates that no call opcode is sent to the processor.
*/
PIC_BYTE_OUT (PIC1_ICW2, sysVectorIRQ0); /* ICW2 */
PIC_BYTE_OUT (PIC1_ICW3, 0x04); /* ICW3 */
/* bit 2 = 1 -> cascades this PIC1 is cascaded to PIC2. */
/*中断自动结束*/
PIC_BYTE_OUT (PIC1_ICW4, 0x03/*0x01*/); /* ICW4 */
/* bit 0 = 1 -> x86 system, again no call opcode is generated */
/*
* Mask interrupts IRQ 0, 1, and 3-7 by writing to OCW1 register
* IRQ 2 is the cascade input and is not masked
* ORQs 7654 3210
*/
PIC_BYTE_OUT (PIC1_OCW1, 0xfb); /* OCW1 */
/* Initialize the Interrupt Controller #2 */
PIC_BYTE_OUT (PIC2_ICW1, 0x11); /* ICW1 */
/* bit 4 = 1 -> select ICW1, bit3 SNGL = 0 -> two cascaded,
* bit 0 = 1 -> ICW4 must be intialized, indicates x86 mode,
* indicates that no call opcode is sent to the processor.
*/
PIC_BYTE_OUT (PIC2_ICW2, sysVectorIRQ0 + 8); /* ICW2 */
PIC_BYTE_OUT (PIC2_ICW3 , 0x02); /* ICW3 */
/* bit 1 = 0 -> this is the slave identification code
* i.e. this PIC2 is the cascaded (slave) to PIC1
*/
/*中断自动结束*/
PIC_BYTE_OUT (PIC2_ICW4 , 0x03/*0x01*/); /* ICW4 */
/* bit 0 = 1 -> x86 system, again no call opcode is generated */
/* Mask interrupts IRQ 15-8 by writing to OCW1 register */
PIC_BYTE_OUT (PIC2_OCW1, 0xff);
/* Permanently turn off ISA refresh by never completing init steps */
PIC_BYTE_OUT (vt82c686_TRM1_CMOD, 0x74);/*?????????*/
/*
* Perform PCI Interrupt Ack cycle
* Esentially to ensure that we clear all interrupts
* before we return and start the kernel
*/
MEM_READ(PCI_MSTR_IACK_LOCAL, &intNum);
/* perform the end of interrupt procedure */
sysPicEndOfInt (15);
sysPciIbcIntEnable(2);
sysPicIntLevelSet (16);
return (OK);
} /* end of sysPicInit */
/*******************************************************************************
*
* sysPciIbcIntrInit - initialize the interrupts in the vt82c686 chip
*
* This function initializes the interrupt mechanism for the vt82c686 chip
* The vt82c686 chip supports all local IO devices across the ISA bus. It
* has two cascaded 8259 interrupt controller integrated into it.
*
* NOMANUAL
*
* RETURNS: OK, always.
*/
STATUS sysPciIbcIntrInit
(
int viaIrq /* vt82c686 IRQ */
)
{
(void) intConnect (INUM_TO_IVEC (viaIrq), pciIbcIntHandler, 0);
intEnable (viaIrq);
return (OK);
}
/*******************************************************************************
*
* sysPciIbcIntEnable - enable a PIC interrupt level
*
* This routine enables a specified PIC interrupt level.
*
* NOMANUAL
*
* RETURNS: OK.
*/
LOCAL STATUS sysPciIbcIntEnable
(
int intNum
)
{
if (intNum < VT_MAX_IRQS)
{
if (intNum < 8)
{
sysPicMask1 &= ~(1 << intNum);
PIC_BYTE_OUT (PIC1_OCW1, sysPicMask1 | sysPicLevel1);
}
else
{
sysPicMask2 &= ~(1 << (intNum - 8));
PIC_BYTE_OUT (PIC2_OCW1, sysPicMask2 | sysPicLevel2);
}
return (OK);
}
else
{
return ERROR;
}
}
/*******************************************************************************
*
* sysPciIbcIntDisable - disable a Pic interrupt level
*
* This routine disables a specified Pic interrupt level.
*
* NOMANUAL
*
* RETURNS: OK.
*
*/
LOCAL int sysPciIbcIntDisable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -