/* sysLib.c - PC 386/486/Pentium/Pentiumpro system-dependent library */ /* Copyright 1984-1999 Wind River Systems, Inc. */ #include "copyright_wrs.h" /* modification history -------------------- 03m,21apr99,hdn added conditional tffsDrv.h inclusion (SPR# 26922) 03l,12mar99,cn added support for el3c90xEnd driver (SPR# 25327). 03k,09mar99,sbs added support for ne2000End driver added support for ultraEnd driver added support for elt3c509End driver 03j,01feb99,jkf added END support for AMD 7997x PCI card. 03i,26jan99,jkf changed sysHwInit2 to use INCLUDE_ADD_BOOTMEM and removed ATA_MEM_DOSFS from sysToMonitor. SPR#21338 03h,31mar98,cn Added Enhanced Network Driver support. 03g,04jun98,hdn made sysIntLevel() faster. added sysIntCount[] for debug. 03f,28may98,hdn added support for APIC. 03e,12may98,hdn merged with pcPentium/sysLib.c. obsolete INCLUDE_IDE. 03d,23apr98,yp merged TrueFFS support. 03c,16apr98,hdn added sysCpuid[] for sysCpuProbe(). 03b,17mar98,sbs using macro for dummy mmu entry. added forward declaration for sysMmuMapAdd(). changed sysIntIdtType and sysWarmType to use macros. documentation update. 03a,12mar98,sbs moved PCI initialization from sysPhysMemTop() to sysHwInit(). changed the PCI library calls to the new updated library API. moved sys557PciInit() from sysPhysMemTop() to sysHwInit(). added sysAic7880PciInit(). 02z,02mar98,sbs removed device specific mmu entries and added dynamic entries in sysPhysMemDesc table. added sysMmuMapAdd(). added initialization of sysPhysMemDescNumEnt in sysHwInit(). 02y,06jan98,hdn included tffsDrv.h. 02x,15dec97,hdn added support for warm start from TFFS device. 02w,10jul97,dds added SCSI-2 support. 02v,24mar97,mas added sysPhysMemTop(); removed NOMANUAL from sysHwInit2(); parameterized the sysWarm* reboot variables (SPR 7806, 7850). 02u,03dec96,hdn added sys557PciInit(). moved PCI initialization from sysHwInit2() to sysMemTop(). 02t,22nov96,dat added sysNetif.c, for all network support rtns. (if_eex32.c and if_i82557 were combined into sysNetif.c) 02s,20nov96,db conditionally defined INCLUDE_EEX32 for man page(SPR #6190). 02r,20nov96,hdn added support for PRO100B. 02q,01nov96,hdn added support for PCMCIA. 02p,21oct96,hdn removed lptTimeout, added lptResources[]. 02o,14oct96,dat removed ref to i8253TimerTS.c, merged from windview102. 02n,24sep96,hdn fixed by removing IMPORT ATA_RESOURCE ataResources[]. 02m,03sep96,hdn added the compression support. changed constants to ROM_WARM_HIGH and ROM_WARM_LOW. 02l,09aug96,hdn renamed INT_VEC_IRQ0 to INT_NUM_IRQ0. 02k,26jul96,hdn shut off warning message: "implicit declaration of function" 02j,18jul96,hdn added support for INCLUDE_ATA. 02i,19jul96,wlf doc: cleanup. 02h,25jun96,hdn added support for TIMESTAMP timer. 02g,17jun96,hdn initialized sysProcessor to NONE 02f,14jun96,hdn added support for PCI bus. 02e,28may96,hdn renamed PIT_INT_xxx to PIT0_INT_xxx. 02d,28sep95,dat new BSP revision id 02c,27sep95,hdn fixed a typo by changing IO_ADRS_ULTRA to IO_ADRS_ELC. 02b,14jun95,hdn added a global variable sysCodeSelector. added a local function sysIntVecSetEnt(), sysIntVecSetExit(). renamed pSysEndOfInt to intEOI. moved global function declarations to sysLib.h. 02a,14jun95,myz moved serial configuration to sysSerial.c 01z,07jan95,hdn added an accurate memory size checking. 01y,31oct94,hdn changed sysMemTop() to find out a memory size. deleted sysGDT and used sysGdt in sysALib.s. added the Intel EtherExpress32 driver. deleted a conditional macro for INCLUDE_LPT. swapped 1st and 2nd parameter of fdDevCreate(). imported globals to timeout IDE and LPT. 01x,12oct94,hdn deleted sysBootType. added a conditional macro for INCLUDE_LPT. 01w,29may94,hdn moved sysCpuProbe() to cacheArchLib.c. added open and read bootrom.dat in sysToMonitor(). 01v,22apr94,hdn moved sysVectorIRQ0 from i8259Pic.c. made new globals sysFdBuf and sysFdBufSize. supported the warm start from the EPROM. 01u,06apr94,hdn added sysCpuProbe(). 01t,17feb94,hdn deleted memAddToPool() in sysHwInit2(). added a conditional statement in sysMemTop(). changed sysWarmType 0 to 1. 01s,03feb94,hdn added MMU conditional macro for the limit in the GDT. 01r,29nov93,hdn added sysBspRev () routine. 01q,22nov93,hdn added xxdetach () routine for warm start. 01p,16nov93,hdn added sysWarmType which controls warm start device. 01o,09nov93,hdn added warm start (control X). 01n,08nov93,vin added support pc console drivers. 01m,27oct93,hdn added memAddToPool stuff to sysHwInit2(). 01l,12oct93,hdn changed PIT_INT_VEC_NUM to PIT_INT_VEC. 01k,05sep93,hdn moved PIC related functions to intrCtl/i8259Pic.c. added sysDelay (). 01j,12aug93,hdn changed a global descriptor table sysGDT. deleted sysGDTSet. 01i,11aug93,hdn added a global sysVectorIRQ0. 01h,03aug93,hdn changed a mapping IRQ to Vector Table. 01g,26jul93,hdn added a memory descriptor table sysPhysMemDesc[]. 01f,25jun93,hdn changed sysToMonitor() to call sysReboot. 01e,24jun93,hdn changed the initialization of PIC. 01d,17jun93,hdn updated to 5.1. 01c,08apr93,jdi doc cleanup. 01d,07apr93,hdn renamed Compaq to PC. 01c,26mar93,hdn added the global descriptor table, memAddToPool. moved enabling A20 to romInit.s. added cacheClear for 486. 01b,18nov92,hdn supported nested interrupt. 01a,15may92,hdn written based on frc386 version. */ /* DESCRIPTION This library provides board-specific routines. The chip drivers included are: i8250Sio.c - Intel 8250 UART tty driver i8253Timer.c - Intel 8253 timer driver i8259Intr.c - Intel 8259 Programmable Interrupt Controller (PIC) library nullNvRam.c - null NVRAM library nullVme.c - null VMEbus library if_eex32.c - Intel Ether Express (EISA) Ethernet network interface driver pciConfigLib.c - PCI configuration space access support for PCI drivers pciIntLib.c - PCI shared interrupt support pciConfigShow.c - Show routines for PCI configuration library if_fei.c - Intel 82557 Ethernet network interface driver aic7880Lib.c - Adaptec 7880 SCSI Host Adapter Library sysEl3c90xEnd.c - system configuration module for el3c90xEnd driver INCLUDE FILES: sysLib.h SEE ALSO: .pG "Configuration" */ /* includes */ #include "vxWorks.h" #include "vme.h" #include "memLib.h" #include "sysLib.h" #include "string.h" #include "intLib.h" #include "config.h" #include "logLib.h" #include "taskLib.h" #include "vxLib.h" #include "errnoLib.h" #include "dosFsLib.h" #include "stdio.h" #include "cacheLib.h" #include "private/vmLibP.h" #include "arch/i86/pentiumLib.h" #ifdef INCLUDE_TFFS #include "tffs/tffsDrv.h" #endif /* INCLUDE_TFFS */ /* To make man pages for network support routines */ #ifdef DOC #define INCLUDE_EEX32 #define INCLUDE_FEI #define INCLUDE_FEI_END #endif /* imports */ IMPORT char end; /* end of system, created by ld */ IMPORT GDT sysGdt[]; /* the global descriptor table */ IMPORT void elcdetach (int unit); IMPORT void ultradetach (int unit); IMPORT VOIDFUNCPTR intEoiGet; /* function used in intConnect() for B/EOI */ IMPORT void intEnt (void); STATUS sysMmuMapAdd(void *address, UINT len, UINT initialStateMask, UINT initialState); /* globals */ PHYS_MEM_DESC sysPhysMemDesc [] = { /* adrs and length parameters must be page-aligned (multiples of 4KB/4MB) */ #if (VM_PAGE_SIZE == PAGE_SIZE_4KB) /* lower memory */ { (void *) LOCAL_MEM_LOCAL_ADRS, (void *) LOCAL_MEM_LOCAL_ADRS, 0xa0000, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_MEM_OS }, /* video ram, etc */ { (void *) 0xa0000, (void *) 0xa0000, 0x60000, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO }, /* upper memory for OS */ { (void *) 0x100000, (void *) 0x100000, 0x080000, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_MEM_OS }, /* upper memory for Application */ { (void *) 0x180000, (void *) 0x180000, LOCAL_MEM_SIZE - 0x180000, /* it is changed in sysMemTop() */ VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_MEM_APPLICATION }, /* SBS */ /* entry for the Bt878 PCI MMIO */ { (void *) 0x04000000, (void *) 0x04000000, 0x00001000, /* length */ VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE, VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT }, /* SBS */ /* SBS */ /* entry for the Bt878 PCI MMIO */ { (void *) 0x05000000, (void *) 0x05000000, 0x00001000, /* length */ VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE, VM_STATE_VALID | VM_STATE_WRITABLE | VM_STATE_CACHEABLE_NOT }, /* SBS */ /* entries for dynamic mappings - create sufficient entries */ DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, #else /* (VM_PAGE_SIZE == PAGE_SIZE_4KB) */ /* 1st 4MB: lower memory + video ram etc + upper memory for OS */ { (void *) LOCAL_MEM_LOCAL_ADRS, (void *) LOCAL_MEM_LOCAL_ADRS, 0x400000, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_MEM_OS }, /* 2nd 4MB: upper memory for Application */ { (void *) 0x400000, (void *) 0x400000, LOCAL_MEM_SIZE - 0x400000, /* it is changed in sysMemTop() */ VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_MEM_APPLICATION }, /* entries for dynamic mappings - create sufficient entries */ DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, DUMMY_MMU_ENTRY, #endif /* (VM_PAGE_SIZE == PAGE_SIZE_4KB) */ }; int sysPhysMemDescNumEnt; /* number Mmu entries to be mapped */ #ifdef INCLUDE_PC_CONSOLE PC_CON_DEV pcConDv [N_VIRTUAL_CONSOLES] = { {{{{NULL}}}, FALSE, NULL, NULL}, {{{{NULL}}}, FALSE, NULL, NULL} }; #endif /* INCLUDE_PC_CONSOLE */ #ifdef INCLUDE_FD IMPORT STATUS usrFdConfig (int type, int drive, char *fileName); FD_TYPE fdTypes[] = { {2880,18,2,80,2,0x1b,0x54,0x00,0x0c,0x0f,0x02,1,1,"1.44M"}, {2400,15,2,80,2,0x24,0x50,0x00,0x0d,0x0f,0x02,1,1,"1.2M"}, }; UINT sysFdBuf = FD_DMA_BUF_ADDR; /* floppy disk DMA buffer address */ UINT sysFdBufSize = FD_DMA_BUF_SIZE; /* floppy disk DMA buffer size */ #endif /* INCLUDE_FD */ #ifdef INCLUDE_ATA IMPORT STATUS usrAtaConfig (int ctrl, int drive, char *fileName); ATA_TYPE ataTypes[ATA_MAX_CTRLS][ATA_MAX_DRIVES] = { {{761, 8, 39, 512, 0xff}, /* ctrl 0 drive 0 */ {761, 8, 39, 512, 0xff}}, /* ctrl 0 drive 1 */ {{761, 8, 39, 512, 0xff}, /* ctrl 1 drive 0 */ {761, 8, 39, 512, 0xff}}, /* ctrl 1 drive 1 */ }; ATA_RESOURCE ataResources[ATA_MAX_CTRLS] = { { { 5, 0, {ATA0_IO_START0, ATA0_IO_START1}, {ATA0_IO_STOP0, ATA0_IO_STOP1}, 0, 0, 0, 0, 0, 0 }, IDE_LOCAL, 1, ATA0_INT_VEC, ATA0_INT_LVL, ATA0_CONFIG, ATA_SEM_TIMEOUT, ATA_WDG_TIMEOUT, 0, 0 }, /* ctrl 0 */ { { 5, 0, {ATA1_IO_START0, ATA1_IO_START1}, {ATA1_IO_STOP0, ATA1_IO_STOP1}, 0, 0, 0, 0, 0, 0 }, ATA_PCMCIA, 1, ATA1_INT_VEC, ATA1_INT_LVL, ATA1_CONFIG, ATA_SEM_TIMEOUT, ATA_WDG_TIMEOUT, 0, 0 } /* ctrl 1 */ }; #endif /* INCLUDE_ATA */ #ifdef INCLUDE_LPT LPT_RESOURCE lptResources[LPT_CHANNELS] = { {LPT0_BASE_ADRS, LPT_INT_VEC, LPT_INT_LVL, TRUE, 10000, 10000, 1, 1}, }; #endif /* INCLUDE_LPT */ int sysBus = BUS; /* system bus type (VME_BUS, etc) */ int sysCpu = CPU; /* system cpu type (MC680x0) */ char *sysBootLine = BOOT_LINE_ADRS; /* address of boot line */ char *sysExcMsg = EXC_MSG_ADRS; /* catastrophic message area */ int sysProcNum; /* processor number of this cpu */ int sysFlags; /* boot flags */ char sysBootHost [BOOT_FIELD_LEN]; /* name of host from which we booted */ char sysBootFile [BOOT_FIELD_LEN]; /* name of file from which we booted */ UINT sysIntIdtType = SYS_INT_TRAPGATE; /* IDT entry type */ UINT sysProcessor = NONE; /* 0=386, 1=486, 2=P5, 3=ns486, 4=P6 */ UINT sysCoprocessor = 0; /* 0=none, 1=387, 2=487 */ int sysWarmType = SYS_WARM_TYPE; /* system warm boot type */ int sysWarmFdDrive = SYS_WARM_FD_DRIVE; /* 0 = drive a:, 1 = b: */ int sysWarmFdType = SYS_WARM_FD_TYPE; /* 0 = 3.5" 2HD, 1 = 5.25" 2HD */ int sysWarmAtaCtrl = SYS_WARM_ATA_CTRL; /* controller 0 or 1 */ int sysWarmAtaDrive = SYS_WARM_ATA_DRIVE; /* Hd drive 0 (c:), 1 (d:) */ int sysWarmTffsDrive= SYS_WARM_TFFS_DRIVE; /* TFFS drive 0 (DOC) */ UINT sysStrayIntCount = 0; /* Stray interrupt count */ char *memTopPhys = NULL; /* top of memory */ GDT *pSysGdt = (GDT *)(LOCAL_MEM_LOCAL_ADRS + GDT_BASE_OFFSET); int sysCodeSelector = CODE_SELECTOR;/* code selector for context switch */ CPUID sysCpuId = {0,0,{0}}; /* CPUID version and feature */ /* locals */ LOCAL short *sysRomBase[] = { (short *)0xce000, (short *)0xce800, (short *)0xcf000, (short *)0xcf800 }; #define ROM_SIGNATURE_SIZE 16 LOCAL char sysRomSignature[ROM_SIGNATURE_SIZE] = { 0x55,0xaa,0x01,0x90,0x90,0x90,0x90,0x90, 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 }; #if (CPU == PENTIUM) /* * The cache control flags and MTRRs operate hierarchically for restricting * caching. That is, if the CD flag is set, caching is prevented globally. * If the CD flag is clear, either the PCD flags and/or the MTRRs can be * used to restrict caching. If there is an overlap of page-level caching * control and MTRR caching control, the mechanism that prevents caching * has precedence. For example, if an MTRR makes a region of system memory * uncachable, a PCD flag cannot be used to enable caching for a page in * that region. The converse is also true; that is, if the PCD flag is * set, an MTRR cannot be used to make a region of system memory cacheable. * If there is an overlap in the assignment of the write-back and write- * through caching policies to a page and a region of memory, the write- * through policy takes precedence. The write-combining policy takes * precedence over either write-through or write-back. */ LOCAL MTRR sysMtrr = { /* MTRR table */ {0,0}, /* MTRR_CAP register */ {0,0}, /* MTRR_DEFTYPE register */ /* Fixed Range MTRRs */ {{{MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB}}, {{MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB, MTRR_WB}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_WC, MTRR_WC, MTRR_WC, MTRR_WC}}, {{MTRR_WP, MTRR_WP, MTRR_WP, MTRR_WP, MTRR_WP, MTRR_WP, MTRR_WP, MTRR_WP}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}, {{MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC, MTRR_UC}}}, {{0LL, 0LL}, /* Variable Range MTRRs */ {0LL, 0LL}, {0LL, 0LL}, {0LL, 0LL}, {0LL, 0LL}, {0LL, 0LL}, {0LL, 0LL}, {0LL, 0LL}} }; #endif /* (CPU == PENTIUM) */ /* forward declarations */ LOCAL void sysStrayInt (void); char *sysPhysMemTop (void); STATUS sysMmuMapAdd (void *address, UINT len, UINT initialStateMask, UINT initialState); LOCAL void sysIntInitPIC (void); LOCAL void sysIntEoiGet (VOIDFUNCPTR * vector, VOIDFUNCPTR * routineBoi, int * parameterBoi, VOIDFUNCPTR * routineEoi, int * parameterEoi); /* includes (source file) */ #include "mem/nullNvRam.c" #include "vme/nullVme.c" #include "sysSerial.c" #if defined(VIRTUAL_WIRE_MODE) # include "intrCtl/loApicIntr.c" # include "intrCtl/i8259Intr.c" # ifdef INCLUDE_APIC_TIMER # include "timer/loApicTimer.c" /* includes timestamp driver */ # else # include "timer/i8253Timer.c" /* includes timestamp driver */ # endif /* INCLUDE_APIC_TIMER */ #elif defined(SYMMETRIC_IO_MODE) # include "intrCtl/loApicIntr.c" # include "intrCtl/i8259Intr.c" # include "intrCtl/ioApicIntr.c" # ifdef INCLUDE_APIC_TIMER # include "timer/loApicTimer.c" /* includes timestamp driver */ # else # include "timer/i8253Timer.c" /* includes timestamp driver */ # endif /* INCLUDE_APIC_TIMER */ #else # include "intrCtl/i8259Intr.c" # include "timer/i8253Timer.c" /* includes timestamp driver */ #endif /* defined(VIRTUAL_WIRE_MODE) */ #ifdef INCLUDE_PCI # include "pci/pciConfigLib.c" # include "pci/pciIntLib.c" # ifdef INCLUDE_SHOW_ROUTINES # include "pci/pciConfigShow.c" # endif /* INCLUDE_SHOW_ROUTINES */ #endif /* INCLUDE_PCI */ #ifdef INCLUDE_PCMCIA # include "pcmcia/pccardLib.c" # include "pcmcia/pccardShow.c" #endif /* INCLUDE_PCMCIA */ /* include ultraEnd driver support routines */ #ifdef INCLUDE_ULTRA_END #include "sysUltraEnd.c" #endif /* INCLUDE_ULTRA_END */ /* include elt3c509End driver support routines */ #ifdef INCLUDE_ELT_3C509_END #include "sysElt3c509End.c" #endif /* INCLUDE_ELT_3C509_END */ /* include ne2000End driver support routines */ #ifdef INCLUDE_ENE_END #include "sysNe2000End.c" #endif /* INCLUDE_ENE_END */ /* include el3c90xEnd driver support routines */ #ifdef INCLUDE_EL_3C90X_END # include "sysEl3c90xEnd.c" #endif /* INCLUDE_EL_3C90X_END */ #include "sysNetif.c" /* network driver support */ #include "sysScsi.c" /* scsi support */ /******************************************************************************* * * sysModel - return the model name of the CPU board * * This routine returns the model name of the CPU board. * * RETURNS: A pointer to the string "PC 386, 486, PENTIUM or PENTIUMPRO". */ char *sysModel (void) { #if (CPU == I80386) return ("PC 386"); #elif (CPU == I80486) return ("PC 486"); #elif (CPU_VARIANT == PENTIUM) return ("PC PENTIUM"); #elif (CPU_VARIANT == PENTIUMPRO) return ("PC PENTIUMPRO"); #endif /* (CPU == I80386) */ } /******************************************************************************* * * sysBspRev - return the BSP version and revision number * * This routine returns a pointer to a BSP version and revision number, for * example, 1.1/0. BSP_REV is concatenated to BSP_VERSION and returned. * * RETURNS: A pointer to the BSP version/revision string. */ char * sysBspRev (void) { return (BSP_VERSION BSP_REV); } /******************************************************************************* * * sysHwInit - initialize the system hardware * * This routine initializes various features of the i386/i486 board. * It is called from usrInit() in usrConfig.c. * * NOTE: This routine should not be called directly by the user application. * * RETURNS: N/A */ void sysHwInit (void) { PHYS_MEM_DESC *pMmu; int ix = 0; #if (CPU == PENTIUM) /* enable MTRR (Memory Type Range Registers) */ if ((sysCpuId.feature & CPUID_MTRR) == CPUID_MTRR) { pentiumMtrrDisable (); /* disable MTRR */ #ifdef INCLUDE_MTRR_GET (void) pentiumMtrrGet (&sysMtrr); /* get MTRR initialized by BIOS */ #else (void) pentiumMtrrSet (&sysMtrr); /* set your own MTRR */ #endif /* INCLUDE_MTRR_GET */ pentiumMtrrEnable (); /* enable MTRR */ } #ifdef INCLUDE_PMC /* enable PMC (Performance Monitoring Counters) */ if ((sysProcessor == X86CPU_PENTIUMPRO) && ((sysCpuId.feature & CPUID_MSR) == CPUID_MSR)) { pentiumPmcStop (); /* stop PMC0 and PMC1 */ pentiumPmcReset (); /* reset PMC0 and PMC1 */ /* * select events of your interest, such as: * PMC_HW_INT_RX - number of hardware interrupts received * PMC_MISALIGN_MEM_REF - number of misaligned data memory references */ (void) pentiumPmcStart (PMC_EN | PMC_OS | PMC_UMASK_00 | PMC_HW_INT_RX, PMC_EN | PMC_OS | PMC_UMASK_00 | PMC_MISALIGN_MEM_REF); } #endif /* INCLUDE_PMC */ /* enable MCA (Machine Check Architecture) */ if ((sysCpuId.feature & CPUID_MCE) == CPUID_MCE) { #ifdef INCLUDE_SHOW_ROUTINES IMPORT FUNCPTR excMcaInfoShow; /* * if excMcaInfoShow is not NULL, it is called in the default * exception handler when Machine Check Exception happened */ excMcaInfoShow = (FUNCPTR) pentiumMcaShow; #endif /* INCLUDE_SHOW_ROUTINES */ if ((sysCpuId.feature & CPUID_MCA) == CPUID_MCA) { UINT32 zero[2] = {0x00000000,0x00000000}; UINT32 one[2] = {0xffffffff,0xffffffff}; UINT32 cap[2]; int mcaBanks; int ix; /* enable all MCA features if MCG_CTL register is present */ pentiumMsrGet (MSR_MCG_CAP, (long long int *)&cap); if (cap[0] & MCG_CTL_P) pentiumMsrSet (MSR_MCG_CTL, (long long int *)&one); mcaBanks = cap[0] & MCG_COUNT; /* get number of banks */ /* enable logging of all errors except for the MC0_CTL register */ for (ix = 1; ix < mcaBanks; ix++) pentiumMsrSet (MSR_MC0_CTL+(ix * 4), (long long int *)&one); /* clear all errors */ for (ix = 0; ix < mcaBanks; ix++) pentiumMsrSet (MSR_MC0_STATUS+(ix * 4), (long long int *)&zero); } pentiumCr4Set (pentiumCr4Get () | CR4_MCE); /* enable MC exception */ } #endif /* (CPU == PENTIUM) */ /* initialize the number of active mappings (sysPhysMemDescNumEnt) */ pMmu = &sysPhysMemDesc[0]; for (ix = 0; ix < NELEMENTS (sysPhysMemDesc); ix++) if (pMmu->virtualAddr != (void *)DUMMY_VIRT_ADDR) pMmu++; else break; sysPhysMemDescNumEnt = ix; /* initialize the PIC (Programmable Interrupt Controller) */ sysIntInitPIC (); intEoiGet = sysIntEoiGet; /* function pointer used in intConnect () */ /* initialize PCI and related devices */ #ifdef INCLUDE_PCI pciConfigLibInit (PCI_MECHANISM_1, PCI_CONFIG_ADDR, PCI_CONFIG_DATA, NONE); pciIntLibInit (); /* * PCI-to-PCI bridge initialization should be done here, if it is. * It is not necessary for Intel 430HX PCISET, which splits * the extended memory area as follows: * - Flash BIOS area from 4GByte to (4GB - 512KB) * - DRAM memory from 1MB to a maximum of 512MB * - PCI memory space from the top of DRAM to (4GB - 512KB) */ #if defined (INCLUDE_FEI) || defined (INCLUDE_FEI_END) sys557PciInit (); #endif /* INCLUDE_FEI || INCLUDE_FEI_END */ #ifdef INCLUDE_LN_97X_END sysLan97xPciInit (); #endif /* INCLUDE_LN_97X_END */ #ifdef INCLUDE_EL_3C90X_END sysEl3c90xPciInit (); #endif /* INCLUDE_EL_3C90X_END */ #ifdef INCLUDE_SCSI #ifdef INCLUDE_AIC_7880 sysAic7880PciInit (); #endif /* INCLUDE_AIC_7880 */ #endif /* INCLUDE_SCSI */ #endif /* INCLUDE_PCI */ /* initializes the serial devices */ sysSerialHwInit (); /* initialize serial data structure */ } /******************************************************************************* * * sysHwInit2 - additional system configuration and initialization * * This routine connects system interrupts and does any additional * configuration necessary. * * RETURNS: N/A */ void sysHwInit2 (void) { #if defined (INCLUDE_ADD_BOOTMEM) /* * We memAddToPool some upper memory into any low memory * x86 "rom" images pool. The x86 low memory images reside * from 0x8000 to 0xa0000. By memAddToPool'ing some upper * memory here, we allow devices a larger pool to swim within. * (SPR#21338). This is no longer performed in bootConfig.c */ #if (ADDED_BOOTMEM_SIZE != 0x0) /* * if &end (compiler symbol) is in lower memory, then we assume * this is a low memory image, and add some upper memory to the pool. */ if ((int)&end < 0x100000) { /* Only do this if there is enough memory. Default is 4MB min. */ if ((int)memTopPhys >= (0x00200000 + ADDED_BOOTMEM_SIZE)) { memAddToPool ((char *)memTopPhys - ADDED_BOOTMEM_SIZE, ADDED_BOOTMEM_SIZE); } } #endif /* (ADDED_BOOTMEM_SIZE !=0) */ #endif /* INCLUDE_ADD_BOOTMEM defined */ /* connect sys clock interrupt and auxiliary clock interrupt*/ #ifdef INCLUDE_APIC_TIMER (void)intConnect (INUM_TO_IVEC (TIMER_INT_VEC), sysClkInt, 0); #ifdef PIT0_FOR_AUX (void)intConnect (INUM_TO_IVEC (PIT0_INT_VEC), sysAuxClkInt, 0); #else (void)intConnect (INUM_TO_IVEC (RTC_INT_VEC), sysAuxClkInt, 0); #endif /* PIT0_FOR_AUX */ #else (void)intConnect (INUM_TO_IVEC (PIT0_INT_VEC), sysClkInt, 0); (void)intConnect (INUM_TO_IVEC (RTC_INT_VEC), sysAuxClkInt, 0); #endif /* INCLUDE_APIC_TIMER */ /* connect serial interrupt */ sysSerialHwInit2(); /* connect stray(spurious/phantom) interrupt */ #if defined(VIRTUAL_WIRE_MODE) (void)intConnect (INUM_TO_IVEC (SPURIOUS_INT_VEC), sysStrayInt, 0); (void)intConnect (INUM_TO_IVEC (LPT_INT_VEC), sysStrayInt, 0); #elif defined(SYMMETRIC_IO_MODE) (void)intConnect (INUM_TO_IVEC (SPURIOUS_INT_VEC), sysStrayInt, 0); #else (void)intConnect (INUM_TO_IVEC (LPT_INT_VEC), sysStrayInt, 0); #endif /* defined(VIRTUAL_WIRE_MODE) */ #ifdef INCLUDE_PC_CONSOLE /* connect keyboard Controller 8042 chip interrupt */ (void) intConnect (INUM_TO_IVEC (KBD_INT_VEC), kbdIntr, 0); #endif /* INCLUDE_PC_CONSOLE */ } /******************************************************************************* * * sysPhysMemTop - get the address of the top of physical memory * * This routine returns the address of the first missing byte of memory, * which indicates the top of physical memory. * * Memory probing begins at the end of BSS; at every 4K boundary a byte * is read until it finds one that cannot be read, or 4MB have been probed, * whichever is first. * * RETURNS: The address of the top of physical memory. * * INTERNAL * This routine is used by sysHwInit() to differentiate between models. * It is highly questionable whether vxMemProbe() can be used during the * initial stage of booting. */ char *sysPhysMemTop (void) { #define TEST_PATTERN 0x12345678 #define SYS_PAGE_SIZE 0x10000 #define N_TIMES 3 static char *memTop = NULL; /* top of memory */ int delta = SYS_PAGE_SIZE; BOOL found = FALSE; PHYS_MEM_DESC *pMmu; int temp[N_TIMES]; char gdtr[6]; char *p; int ix; if (memTop != NULL) return (memTop); /* if (&end) is in upper memory, we assume it is VxWorks image. * if not, it is Boot image */ if ((int)&end > 0x100000) p = (char *)(((int)&end + (delta - 1)) & (~ (delta - 1))); else p = (char *)0x100000; /* find out the actual size of the memory (max 1GB) */ for (; (int)p < 0x40000000; p += delta) { for (ix=0; ixlimit00 = limit & 0x0ffff; pGdt->limit01 = ((limit & 0xf0000) >> 16) | (pGdt->limit01 & 0xf0); } } #endif /* INCLUDE_PCI */ /* load the global descriptor table. set the MMU table */ sysLoadGdt (gdtr); #if (VM_PAGE_SIZE == PAGE_SIZE_4KB) pMmu = &sysPhysMemDesc[3]; /* 4th entry: above 1.5MB upper memory */ pMmu->len = (UINT)memTop - (UINT)pMmu->physicalAddr; #else /* (VM_PAGE_SIZE == PAGE_SIZE_4KB) */ pMmu = &sysPhysMemDesc[1]; /* 2nd entry: above 4MB upper memory */ pMmu->len = (UINT)memTop - (UINT)pMmu->physicalAddr; #endif /* (VM_PAGE_SIZE == PAGE_SIZE_4KB) */ memTopPhys = memTop; /* set the real memory size */ return (memTop); } /******************************************************************************* * * sysMemTop - get the address of the top of VxWorks memory * * This routine returns a pointer to the first byte of memory not * controlled or used by VxWorks. * * The user can reserve memory space by defining the macro USER_RESERVED_MEM * in config.h. This routine returns the address of the reserved memory * area. The value of USER_RESERVED_MEM is in bytes. * * RETURNS: The address of the top of VxWorks memory. */ char * sysMemTop (void) { static char * memTop = NULL; if (memTop == NULL) { memTop = sysPhysMemTop () - USER_RESERVED_MEM; if ((int)&end < 0x100000) /* this is for bootrom */ memTop = (char *)0xa0000; } return (memTop); } /******************************************************************************* * * sysToMonitor - transfer control to the ROM monitor * * This routine transfers control to the ROM monitor. It is usually called * only by reboot() -- which services ^X -- and by bus errors at interrupt * level. However, in some circumstances, the user may wish to introduce a * new to enable special boot ROM facilities. * * RETURNS: Does not return. */ STATUS sysToMonitor ( int startType /* passed to ROM to tell it how to boot */ ) { FUNCPTR pEntry; int ix; int iy; int iz; char buf[ROM_SIGNATURE_SIZE]; short *pSrc; short *pDst; VM_ENABLE (FALSE); /* disbale MMU */ /* decide a destination RAM address and the entry point */ if ((int)&end > 0x100000) { pDst = (short *)RAM_HIGH_ADRS; /* copy it in lower mem */ pEntry = (FUNCPTR)(RAM_HIGH_ADRS + ROM_WARM_HIGH); } else { pDst = (short *)RAM_LOW_ADRS; /* copy it in upper mem */ pEntry = (FUNCPTR)(RAM_LOW_ADRS + ROM_WARM_LOW); } /* disable 16-bit memory access */ #ifdef INCLUDE_ULTRA sysOutByte (IO_ADRS_ULTRA + 4, sysInByte (IO_ADRS_ULTRA + 4) | 0x80); sysOutByte (IO_ADRS_ULTRA + 5, sysInByte (IO_ADRS_ULTRA + 5) & ~0x80); #endif /* INCLUDE_ULTRA */ #ifdef INCLUDE_ELC sysOutByte (IO_ADRS_ELC + 5, sysInByte (IO_ADRS_ELC + 5) & ~0x80); #endif /* INCLUDE_ELC */ /* copy EPROM to RAM and jump, if there is a VxWorks EPROM */ for (ix = 0; ix < NELEMENTS(sysRomBase); ix++) { bcopyBytes ((char *)sysRomBase[ix], buf, ROM_SIGNATURE_SIZE); if (strncmp (sysRomSignature, buf, ROM_SIGNATURE_SIZE) == 0) { for (iy = 0; iy < 1024; iy++) { *sysRomBase[ix] = iy; /* map the moveable window */ pSrc = (short *)((int)sysRomBase[ix] + 0x200); for (iz = 0; iz < 256; iz++) *pDst++ = *pSrc++; } sysClkDisable (); /* disable the system clock interrupt */ sysIntInitPIC (); /* reset the used interrupt controllers */ (*pEntry) (startType); } } #ifdef INCLUDE_FD if (sysWarmType == SYS_WARM_FD) { IMPORT int dosFsDrvNum; fdDrv (FD_INT_VEC, FD_INT_LVL); /* initialize floppy disk */ if (dosFsDrvNum == ERROR) dosFsInit (NUM_DOSFS_FILES); /* initialize DOS-FS */ if (usrFdConfig (sysWarmFdDrive, sysWarmFdType, "/vxboot/") == ERROR) { printErr ("usrFdConfig failed.\n"); return (ERROR); } } #endif /* INCLUDE_FD */ #ifdef INCLUDE_ATA if (sysWarmType == SYS_WARM_ATA) { ATA_RESOURCE *pAtaResource = &ataResources[sysWarmAtaCtrl]; IMPORT int dosFsDrvNum; if (ataDrv (sysWarmAtaCtrl, pAtaResource->drives, pAtaResource->intVector, pAtaResource->intLevel, pAtaResource->configType, pAtaResource->semTimeout, pAtaResource->wdgTimeout) == ERROR) /* initialize ATA/IDE disk */ { printErr ("Could not initialize.\n"); return (ERROR); } if (dosFsDrvNum == ERROR) dosFsInit (NUM_DOSFS_FILES); /* initialize DOS-FS */ if (usrAtaConfig (sysWarmAtaCtrl, sysWarmAtaDrive, "/vxboot/") == ERROR) { printErr ("usrAtaConfig failed.\n"); return (ERROR); } } #endif /* INCLUDE_ATA */ #ifdef INCLUDE_TFFS if (sysWarmType == SYS_WARM_TFFS) { IMPORT int dosFsDrvNum; tffsDrv (); /* initialize TFFS */ if (dosFsDrvNum == ERROR) dosFsInit (NUM_DOSFS_FILES); /* initialize DOS-FS */ if (usrTffsConfig (sysWarmTffsDrive, FALSE, "/vxboot/") == ERROR) { printErr ("usrTffsConfig failed.\n"); return (ERROR); } } #endif /* INCLUDE_TFFS */ #if (defined(INCLUDE_FD) || defined(INCLUDE_ATA) || defined(INCLUDE_TFFS)) if ((sysWarmType == SYS_WARM_FD) || (sysWarmType == SYS_WARM_ATA) || (sysWarmType == SYS_WARM_TFFS)) { int fd; if ((fd = open ("/vxboot/bootrom.sys", O_RDWR, 0644)) == ERROR) { if ((fd = open ("/vxboot/bootrom.dat", O_RDWR, 0644)) == ERROR) { printErr ("Can't open \"%s\"\n", "bootrom.{sys,dat}"); return (ERROR); } if (read (fd, (char *)pDst, 0x20) == ERROR) /* a.out header */ { printErr ("Error during read file: %x\n", errnoGet ()); return (ERROR); } } /* read text and data, write them to the memory */ if (read (fd, (char *)pDst, 0x98000) == ERROR) { printErr ("Error during read file: %x\n", errnoGet ()); return (ERROR); } close (fd); sysClkDisable (); /* disable the system clock interrupt */ sysIntInitPIC (); /* reset the used interrupt controllers */ (*pEntry) (startType); } #endif /* (INCLUDE_FD) || (INCLUDE_ATA) || (INCLUDE_TFFS) */ intLock (); #ifdef INCLUDE_ELC elcdetach (0); #endif /* INCLUDE_ELC */ #ifdef INCLUDE_ULTRA ultradetach (0); #endif /* INCLUDE_ULTRA */ sysClkDisable (); sysWait (); sysOutByte (COMMAND_8042, 0xfe); /* assert SYSRESET */ sysWait (); sysOutByte (COMMAND_8042, 0xff); /* NULL command */ sysReboot (); /* crash the global descriptor table */ return (OK); /* in case we ever continue from ROM monitor */ } /******************************************************************************* * * sysIntInitPIC - initialize the interrupt controller * * This routine initializes the interrupt controller. * * RETURNS: N/A * * ARGSUSED0 */ LOCAL void sysIntInitPIC (void) { #if defined(VIRTUAL_WIRE_MODE) { int addrLo; /* page aligned Local APIC Base Address */ int lengthLo; /* length of Local APIC registers */ loApicInit (); i8259Init (); /* add an entry to the sysMmuPhysDesc[] for Local APIC */ addrLo = ((int)loApicBase / PAGE_SIZE) * PAGE_SIZE; lengthLo = (int)loApicBase - addrLo + LOAPIC_LENGTH; if ((lengthLo % PAGE_SIZE) != 0) lengthLo = (lengthLo / PAGE_SIZE + 1) * PAGE_SIZE; sysMmuMapAdd ((void *)addrLo, lengthLo, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); } #elif defined(SYMMETRIC_IO_MODE) { int addrLo; /* page aligned Local APIC Base Address */ int addrIo; /* page aligned IO APIC Base Address */ int lengthLo; /* length of Local APIC registers */ int lengthIo; /* length of IO APIC registers */ loApicInit (); i8259Init (); ioApicInit (); /* add an entry to the sysMmuPhysDesc[] for Local APIC and IO APIC */ addrLo = ((int)loApicBase / PAGE_SIZE) * PAGE_SIZE; lengthLo = (int)loApicBase - addrLo + LOAPIC_LENGTH; if ((lengthLo % PAGE_SIZE) != 0) lengthLo = (lengthLo / PAGE_SIZE + 1) * PAGE_SIZE; addrIo = ((int)ioApicBase / PAGE_SIZE) * PAGE_SIZE; lengthIo = (int)ioApicBase - addrIo + IOAPIC_LENGTH; if ((lengthIo % PAGE_SIZE) != 0) lengthIo = (lengthIo / PAGE_SIZE + 1) * PAGE_SIZE; if (addrLo == addrIo) { sysMmuMapAdd ((void *)addrLo, max (lengthLo, lengthIo), VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); } else if ((addrLo < addrIo) && ((addrLo + lengthLo) >= addrIo)) { sysMmuMapAdd ((void *)addrLo, max ((addrLo + lengthLo), (addrIo + lengthIo)) - addrLo, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); } else if ((addrIo < addrLo) && ((addrIo + lengthIo) >= addrLo)) { sysMmuMapAdd ((void *)addrIo, max ((addrLo + lengthLo), (addrIo + lengthIo)) - addrIo, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); } else { sysMmuMapAdd ((void *)addrLo, lengthLo, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); sysMmuMapAdd ((void *)addrIo, lengthIo, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_IO); } } #else i8259Init (); #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntLock - lock out all interrupts * * This routine saves the mask and locks out all interrupts. * It should be called in the interrupt disable state(IF bit is 0). * * SEE ALSO: sysIntUnlock() * * ARGSUSED0 */ VOID sysIntLock (void) { #if defined(VIRTUAL_WIRE_MODE) loApicIntLock (); i8259IntLock (); #elif defined(SYMMETRIC_IO_MODE) loApicIntLock (); ioApicIntLock (); #else i8259IntLock (); #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntUnlock - unlock the PIC interrupts * * This routine restores the mask and unlocks the PIC interrupts * It should be called in the interrupt disable state(IF bit is 0). * * SEE ALSO: sysIntLock() * * ARGSUSED0 */ VOID sysIntUnlock (void) { #if defined(VIRTUAL_WIRE_MODE) loApicIntUnlock (); i8259IntUnlock (); #elif defined(SYMMETRIC_IO_MODE) loApicIntUnlock (); ioApicIntUnlock (); #else i8259IntUnlock (); #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntDisablePIC - disable a bus interrupt level * * This routine disables a specified bus interrupt level. * * RETURNS: OK, or ERROR if failed. * * ARGSUSED0 */ STATUS sysIntDisablePIC ( int irqNo /* IRQ(PIC) or INTIN(APIC) number to disable */ ) { #if defined(VIRTUAL_WIRE_MODE) return (i8259IntDisable (irqNo)); #elif defined(SYMMETRIC_IO_MODE) return (ioApicIntDisable (irqNo)); #else return (i8259IntDisable (irqNo)); #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntEnablePIC - enable a bus interrupt level * * This routine enables a specified bus interrupt level. * * RETURNS: OK, or ERROR if failed. * * ARGSUSED0 */ STATUS sysIntEnablePIC ( int irqNo /* IRQ(PIC) or INTIN(APIC) number to enable */ ) { #if defined(VIRTUAL_WIRE_MODE) return (i8259IntEnable (irqNo)); #elif defined(SYMMETRIC_IO_MODE) return (ioApicIntEnable (irqNo)); #else return (i8259IntEnable (irqNo)); #endif /* defined(VIRTUAL_WIRE_MODE) */ } STATUS sysIntEnable ( int irqNo /* IRQ(PIC) or INTIN(APIC) number to enable */ ) { #if defined(VIRTUAL_WIRE_MODE) return (i8259IntEnable (irqNo)); #elif defined(SYMMETRIC_IO_MODE) return (ioApicIntEnable (irqNo)); #else return (i8259IntEnable (irqNo)); #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntEoiGet - get EOI/BOI function and its parameter * * This routine gets EOI function and its parameter for the interrupt controller. * If returned EOI/BOI function is NULL, intHandlerCreateX86() replaces * "call _routineBoi/Eoi" in intConnectCode[] with NOP instruction. * * RETURNS: N/A * * ARGSUSED0 */ LOCAL void sysIntEoiGet ( VOIDFUNCPTR * vector, /* interrupt vector to attach to */ VOIDFUNCPTR * routineBoi, /* BOI function */ int * parameterBoi, /* a parameter of the BOI function */ VOIDFUNCPTR * routineEoi, /* EOI function */ int * parameterEoi /* a parameter of the EOI function */ ) { int vectorNo = IVEC_TO_INUM (vector); int irqNo; *routineBoi = NULL; /* set the default value */ *parameterBoi = 0; /* set the default value */ #if defined(VIRTUAL_WIRE_MODE) if (vectorNo == TIMER_INT_VEC) { *routineEoi = loApicIntEoi; *parameterEoi = TIMER_INT_LVL; } else if (vectorNo == SPURIOUS_INT_VEC) { *routineEoi = NULL; /* no EOI is necessary */ *parameterEoi = SPURIOUS_INT_LVL; } else if (vectorNo == ERROR_INT_VEC) { *routineEoi = loApicIntEoi; *parameterEoi = ERROR_INT_LVL; } else { irqNo = vectorNo - INT_NUM_IRQ0; if ((irqNo == 7) || (irqNo == 15)) { *routineBoi = i8259IntBoi; *parameterBoi = irqNo; } if (irqNo < 8) *routineEoi = i8259IntEoiMaster; else *routineEoi = i8259IntEoiSlave; *parameterEoi = irqNo; } #elif defined(SYMMETRIC_IO_MODE) if (vectorNo == TIMER_INT_VEC) { *routineEoi = loApicIntEoi; *parameterEoi = TIMER_INT_LVL; } else if (vectorNo == SPURIOUS_INT_VEC) { *routineEoi = NULL; /* no EOI is necessary */ *parameterEoi = SPURIOUS_INT_LVL; } else if (vectorNo == ERROR_INT_VEC) { *routineEoi = loApicIntEoi; *parameterEoi = ERROR_INT_LVL; } else { for (irqNo = 0; irqNo < NELEMENTS (redTable); irqNo++) if (redTable [irqNo].vectorNo == vectorNo) break; *routineEoi = ioApicIntEoi; *parameterEoi = irqNo; } #else irqNo = vectorNo - INT_NUM_IRQ0; if ((irqNo == 7) || (irqNo == 15)) { *routineBoi = i8259IntBoi; *parameterBoi = irqNo; } if (irqNo < 8) *routineEoi = i8259IntEoiMaster; else *routineEoi = i8259IntEoiSlave; *parameterEoi = irqNo; #endif /* defined(VIRTUAL_WIRE_MODE) */ } /******************************************************************************* * * sysIntLevel - get an IRQ(PIC) or INTIN(APIC) number in service * * This routine gets an IRQ(PIC) or INTIN(APIC) number in service. * We assume followings: * - this function is called in intEnt() * - IRQ number of the interrupt is at intConnectCode [29] * * RETURNS: 0 - (NUMBER_OF_IRQS - 1), or NUMBER_OF_IRQS if we failed to get it. * * ARGSUSED0 */ #ifdef SYS_INT_DEBUG UINT32 sysIntCount[NUMBER_OF_IRQS + 1]; #endif /* SYS_INT_DEBUG */ int sysIntLevel ( int arg /* parameter to get the stack pointer */ ) { UINT32 * pStack; UCHAR * pInst; int ix; int irqNo = NUMBER_OF_IRQS; /* return NUMBER_OF_IRQS if we failed */ pStack = &arg; /* get the stack pointer */ pStack += 3; /* skip pushed volitile registers */ /* * we are looking for a return address on the stack which point * to the next instruction of "call _intEnt" in the malloced stub. * Then get the irqNo at intConnectCode [29]. */ for (ix = 0; ix < 10; ix++, pStack++) { pInst = (UCHAR *)*pStack; /* return address */ if ((*pInst == 0x50) && /* intConnectCode [5] */ ((*(int *)(pInst - 4) + (int)pInst) == (int)intEnt)) { irqNo = *(int *)(pInst + 24); /* intConnectCode [29] */ break; } } #ifdef SYS_INT_DEBUG sysIntCount[irqNo]++; #endif /* SYS_INT_DEBUG */ return (irqNo); } /**************************************************************************** * * sysProcNumGet - get the processor number * * This routine returns the processor number for the CPU board, which is * set with sysProcNumSet(). * * RETURNS: The processor number for the CPU board. * * SEE ALSO: sysProcNumSet() */ int sysProcNumGet (void) { return (sysProcNum); } /**************************************************************************** * * sysProcNumSet - set the processor number * * Set the processor number for the CPU board. Processor numbers should be * unique on a single backplane. * * NOTE: By convention, only Processor 0 should dual-port its memory. * * RETURNS: N/A * * SEE ALSO: sysProcNumGet() */ void sysProcNumSet ( int procNum /* processor number */ ) { sysProcNum = procNum; } /******************************************************************************* * * sysDelay - allow recovery time for port accesses * * This routine provides a brief delay used between accesses to the same serial * port chip. * * RETURNS: N/A */ void sysDelay (void) { char ix; ix = sysInByte (UNUSED_ISA_IO_ADDRESS); /* it takes 720ns */ } /******************************************************************************* * * sysStrayInt - Do nothing for stray interrupts. * * Do nothing for stray interrupts. */ LOCAL void sysStrayInt (void) { sysStrayIntCount++; } /******************************************************************************* * * sysMmuMapAdd - insert a new mmu mapping * * This routine adds a new mmu mapping entry to allow dynamic mappings. * * RETURNS: OK or ERROR depending on availability of free mappings. */ STATUS sysMmuMapAdd ( void *address, UINT length, UINT initialStateMask, UINT initialState ) { PHYS_MEM_DESC *pMmu; STATUS result = OK; pMmu = &sysPhysMemDesc[sysPhysMemDescNumEnt]; if(pMmu->virtualAddr != (void *)DUMMY_VIRT_ADDR) result = ERROR; else { pMmu->virtualAddr = address; pMmu->physicalAddr = address; pMmu->len = length; pMmu->initialStateMask = initialStateMask; pMmu->initialState = initialState; sysPhysMemDescNumEnt += 1; } return (result); }