From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halr96b/mips/allstart.c | 272 ++ private/ntos/nthals/halr96b/mips/busdat.c | 1231 ++++++++ private/ntos/nthals/halr96b/mips/cacherr.s | 11 + private/ntos/nthals/halr96b/mips/cirrus.h | 281 ++ private/ntos/nthals/halr96b/mips/cmdcnst.h | 105 + private/ntos/nthals/halr96b/mips/esm.c | 1182 ++++++++ private/ntos/nthals/halr96b/mips/esmnvram.h | 688 +++++ private/ntos/nthals/halr96b/mips/glint.h | 580 ++++ private/ntos/nthals/halr96b/mips/halp.h | 365 +++ private/ntos/nthals/halr96b/mips/j4cache.s | 11 + private/ntos/nthals/halr96b/mips/j4flshbf.s | 11 + private/ntos/nthals/halr96b/mips/j4flshio.c | 236 ++ private/ntos/nthals/halr96b/mips/j4prof.c | 11 + private/ntos/nthals/halr96b/mips/jxbeep.c | 215 ++ private/ntos/nthals/halr96b/mips/jxdisp.c | 3605 ++++++++++++++++++++++ private/ntos/nthals/halr96b/mips/jxdmadsp.s | 11 + private/ntos/nthals/halr96b/mips/jxebsup.c | 1398 +++++++++ private/ntos/nthals/halr96b/mips/jxenvirv.c | 800 +++++ private/ntos/nthals/halr96b/mips/jxhalp.h | 224 ++ private/ntos/nthals/halr96b/mips/jxhwsup.c | 4265 +++++++++++++++++++++++++++ private/ntos/nthals/halr96b/mips/jxmapio.c | 11 + private/ntos/nthals/halr96b/mips/jxmaptb.c | 11 + private/ntos/nthals/halr96b/mips/jxport.c | 11 + private/ntos/nthals/halr96b/mips/jxreturn.c | 258 ++ private/ntos/nthals/halr96b/mips/jxsysint.c | 355 +++ private/ntos/nthals/halr96b/mips/jxtime.c | 377 +++ private/ntos/nthals/halr96b/mips/jxusage.c | 510 ++++ private/ntos/nthals/halr96b/mips/mipsdat.c | 145 + private/ntos/nthals/halr96b/mips/mode542x.h | 1302 ++++++++ private/ntos/nthals/halr96b/mips/modeset.h | 85 + private/ntos/nthals/halr96b/mips/pcibrd.c | 1020 +++++++ private/ntos/nthals/halr96b/mips/pcibus.c | 3585 ++++++++++++++++++++++ private/ntos/nthals/halr96b/mips/pciint.c | 376 +++ private/ntos/nthals/halr96b/mips/pcip.h | 200 ++ private/ntos/nthals/halr96b/mips/pcisup.c | 632 ++++ private/ntos/nthals/halr96b/mips/r94adbg.c | 157 + private/ntos/nthals/halr96b/mips/r94adef.h | 266 ++ private/ntos/nthals/halr96b/mips/r94adma.h | 433 +++ private/ntos/nthals/halr96b/mips/r94ainfo.c | 99 + private/ntos/nthals/halr96b/mips/r94aint.h | 35 + private/ntos/nthals/halr96b/mips/r94aio.s | 149 + private/ntos/nthals/halr96b/mips/r94anmi.s | 621 ++++ private/ntos/nthals/halr96b/mips/rgb525.h | 468 +++ private/ntos/nthals/halr96b/mips/tga.h | 93 + private/ntos/nthals/halr96b/mips/x4clock.s | 433 +++ private/ntos/nthals/halr96b/mips/x4tb.s | 11 + private/ntos/nthals/halr96b/mips/x86bios.c | 1261 ++++++++ private/ntos/nthals/halr96b/mips/xxcalstl.c | 302 ++ private/ntos/nthals/halr96b/mips/xxclock.c | 11 + private/ntos/nthals/halr96b/mips/xxidle.s | 11 + private/ntos/nthals/halr96b/mips/xxinithl.c | 934 ++++++ private/ntos/nthals/halr96b/mips/xxinitnt.c | 11 + private/ntos/nthals/halr96b/mips/xxipiint.s | 11 + private/ntos/nthals/halr96b/mips/xxmvmem.s | 264 ++ 54 files changed, 29950 insertions(+) create mode 100644 private/ntos/nthals/halr96b/mips/allstart.c create mode 100644 private/ntos/nthals/halr96b/mips/busdat.c create mode 100644 private/ntos/nthals/halr96b/mips/cacherr.s create mode 100644 private/ntos/nthals/halr96b/mips/cirrus.h create mode 100644 private/ntos/nthals/halr96b/mips/cmdcnst.h create mode 100644 private/ntos/nthals/halr96b/mips/esm.c create mode 100644 private/ntos/nthals/halr96b/mips/esmnvram.h create mode 100644 private/ntos/nthals/halr96b/mips/glint.h create mode 100644 private/ntos/nthals/halr96b/mips/halp.h create mode 100644 private/ntos/nthals/halr96b/mips/j4cache.s create mode 100644 private/ntos/nthals/halr96b/mips/j4flshbf.s create mode 100644 private/ntos/nthals/halr96b/mips/j4flshio.c create mode 100644 private/ntos/nthals/halr96b/mips/j4prof.c create mode 100644 private/ntos/nthals/halr96b/mips/jxbeep.c create mode 100644 private/ntos/nthals/halr96b/mips/jxdisp.c create mode 100644 private/ntos/nthals/halr96b/mips/jxdmadsp.s create mode 100644 private/ntos/nthals/halr96b/mips/jxebsup.c create mode 100644 private/ntos/nthals/halr96b/mips/jxenvirv.c create mode 100644 private/ntos/nthals/halr96b/mips/jxhalp.h create mode 100644 private/ntos/nthals/halr96b/mips/jxhwsup.c create mode 100644 private/ntos/nthals/halr96b/mips/jxmapio.c create mode 100644 private/ntos/nthals/halr96b/mips/jxmaptb.c create mode 100644 private/ntos/nthals/halr96b/mips/jxport.c create mode 100644 private/ntos/nthals/halr96b/mips/jxreturn.c create mode 100644 private/ntos/nthals/halr96b/mips/jxsysint.c create mode 100644 private/ntos/nthals/halr96b/mips/jxtime.c create mode 100644 private/ntos/nthals/halr96b/mips/jxusage.c create mode 100644 private/ntos/nthals/halr96b/mips/mipsdat.c create mode 100644 private/ntos/nthals/halr96b/mips/mode542x.h create mode 100644 private/ntos/nthals/halr96b/mips/modeset.h create mode 100644 private/ntos/nthals/halr96b/mips/pcibrd.c create mode 100644 private/ntos/nthals/halr96b/mips/pcibus.c create mode 100644 private/ntos/nthals/halr96b/mips/pciint.c create mode 100644 private/ntos/nthals/halr96b/mips/pcip.h create mode 100644 private/ntos/nthals/halr96b/mips/pcisup.c create mode 100644 private/ntos/nthals/halr96b/mips/r94adbg.c create mode 100644 private/ntos/nthals/halr96b/mips/r94adef.h create mode 100644 private/ntos/nthals/halr96b/mips/r94adma.h create mode 100644 private/ntos/nthals/halr96b/mips/r94ainfo.c create mode 100644 private/ntos/nthals/halr96b/mips/r94aint.h create mode 100644 private/ntos/nthals/halr96b/mips/r94aio.s create mode 100644 private/ntos/nthals/halr96b/mips/r94anmi.s create mode 100644 private/ntos/nthals/halr96b/mips/rgb525.h create mode 100644 private/ntos/nthals/halr96b/mips/tga.h create mode 100644 private/ntos/nthals/halr96b/mips/x4clock.s create mode 100644 private/ntos/nthals/halr96b/mips/x4tb.s create mode 100644 private/ntos/nthals/halr96b/mips/x86bios.c create mode 100644 private/ntos/nthals/halr96b/mips/xxcalstl.c create mode 100644 private/ntos/nthals/halr96b/mips/xxclock.c create mode 100644 private/ntos/nthals/halr96b/mips/xxidle.s create mode 100644 private/ntos/nthals/halr96b/mips/xxinithl.c create mode 100644 private/ntos/nthals/halr96b/mips/xxinitnt.c create mode 100644 private/ntos/nthals/halr96b/mips/xxipiint.s create mode 100644 private/ntos/nthals/halr96b/mips/xxmvmem.s (limited to 'private/ntos/nthals/halr96b/mips') diff --git a/private/ntos/nthals/halr96b/mips/allstart.c b/private/ntos/nthals/halr96b/mips/allstart.c new file mode 100644 index 000000000..8363d1dcc --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/allstart.c @@ -0,0 +1,272 @@ +/* #pragma comment(exestr, "@(#) NEC(MIPS) allstart.c 1.2 95/10/17 01:17:28" ) */ +/*++ + +Copyright (c) 1995 NEC Corporation +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + allstart.c + +Abstract: + + + This module implements the platform specific operations that must be + performed after all processors have been started. + +Author: + + David N. Cutler (davec) 19-Jun-1994 + +Environment: + + Kernel mode only. + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Mon Oct 17 09:29:01 JST 1994 kbnes!kishimoto + -chg function name HalpCreateEisaStructures() + changed for HalpCreateEisaPCIStructures() + H001 Mon Oct 17 19:09:23 JST 1994 kbnes!kishimoto + -del Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX() + M002 Tue Jan 31 17:51:41 JST 1995 kbnes!A.Kuriyama + -add set NMI Handle routine to FW + M003 Tue Jan 31 18:41:45 JST 1995 kbnes!A.Kuriyama + -add NMI Handle valiable + S004 Tue Jan 31 19:05:16 JST 1995 kbnes!A.Kuriyama + - compile error clear + M005 Fri Feb 17 15:57:02 JST 1995 kbnes!A.Kuriyama + - set NMI routine at KSEG1_BASE + S006 Tue Feb 21 21:04:42 JST 1995 kbnes!A.Kuriyama + - disable dump nmi untill dump support. + M007 Wed Feb 22 11:27:18 JST 1995 kbnes!kuriyama (A) + - change NMI dumpflag + - add display NMI register + M008 Wed Feb 22 14:14:19 JST 1995 kbnes!kuriyama (A) + - compile error clear + S009 Wed Feb 22 14:34:31 JST 1995 kbnes!kuriyama (A) + - warning clear + S010 Tue Mar 07 14:13:41 JST 1995 kbnes!kuriyama (A) + - warning clear + S011 Sat Mar 18 20:19:57 JST 1995 kbnes!kuriyaam (A) + - enable dump nmi + M012 Sat Mar 18 20:24:58 JST 1995 kbnes!kuriyama (A) + - change nmi logic + M013 Mon May 08 23:20:10 JST 1995 kbnes!kuriyama (A) + - EISA/PCI interrupt change to CPU-A on MultiProcessor + S014 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:55:08 JST 1995 + - Set Panic Flag for esm + M015 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 03:08:04 JST 1995 + - Change NMI interface address to HalpNMIInterfaceAddress + S016 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 04:49:24 JST 1995 + - NMI Interface bug fix + M017 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 20:26:09 JST 1995 + - add Enable Ecc 1bit error exception + S018 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 13:23:19 JST 1995 + - add set dump switch flag for esm + M019 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 18:50:42 JST 1995 + - change ecc 1bit was not set enable + if nvram is not initialize. + M020 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 14:11:16 1995 + - clear M013. delete test code, dump switch interface. + + S021 kuriyama@oa2.kbnes.nec.co.jp Tue Oct 17 00:51:42 JST 1995 + - change length of NMISave + +--*/ + +#include "halp.h" +#include "esmnvram.h" // M019 +#include // S010 + +ULONG HalpNMIFlag = 0; +ULONG HalpDumpNMIFlag = 0; // S006, M008 +ULONG HalpNMISave0[0x80 / 4]; // S021 +ULONG HalpNMISave1[0x80 / 4]; // S021 + +extern ULONG HalpNMIInterfaceAddress; + +VOID +HalpNMIDispatch( + VOID + ); + +BOOLEAN +HalAllProcessorsStarted ( + VOID + ) + +/*++ + +Routine Description: + + This function executes platform specific operations that must be + performed after all processors have been started. It is called + for each processor in the host configuration. + +Arguments: + + None. + +Return Value: + + If platform specific operations are successful, then return TRUE. + Otherwise, return FALSE. + +--*/ + +{ + + // + // M002,M005,M015,S016,M020 + // set NMI Handle routine to firmware interface. + // + + if (HalpNMIInterfaceAddress) { + *(PVOID *)(KSEG0_BASE|HalpNMIInterfaceAddress) = (PVOID)(KSEG1_BASE | (ULONG)HalpNMIDispatch); + } + + // + // M017,M019 + // Enable and clear ECC 1bit error. + // + + { + ULONG DataWord; + KIRQL OldIrql; + UCHAR dataBuf[36]; + UCHAR tempBuf[24]; + + #define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag) + #define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic) + #define NVRAM_VALID 3 + #define NVRAM_MAGIC 0xff651026 + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf ); + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + KeRaiseIrql(HIGH_LEVEL,&OldIrql); + KiAcquireSpinLock(&Ecc1bitDisableLock); + DataWord = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart; + + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.LowPart = + 0xffddffff & DataWord; + KeFlushWriteBuffer(); + + KiReleaseSpinLock(&Ecc1bitDisableLock); + KeLowerIrql(OldIrql); + } + + } + + // + // If the number of processors in the host configuration is one, + // then connect EISA interrupts to that processor zero. Otherwise, + // connect EISA interrupts to processor one. + // + + if (**((PULONG *)(&KeNumberProcessors)) == 1) { + return HalpCreateEisaStructures(); + +#if defined(_INT_LIMIT_) + } else if (PCR->Number == 0) { +#else + } else if (PCR->Number == 1) { +#endif // _INT_LIMIT_ + return HalpCreateEisaStructures(); + + } else { + return TRUE; + } +} + +VOID +HalpNMIInterrupt( + ULONG DumpStatus + ) + +/*++ + +Routine Description: + + This routine was called when dump swich was pressed or Fatal NMI occued. + We call KeBugCheckEx() in order to Dump. + +Arguments: + + DumpStatus: Dump Switch Status + + 0 Dump Switch was not pressed. + 1 Dump Switch was pressed. + +Return Value: + + None. + +--*/ + +{ + ULONG NMISource; + ULONG MemoryFailed; + LARGE_INTEGER InvalidAddressValue; + LARGE_INTEGER EccDiagnosticValue; + UCHAR Buffer[100]; + + HalpChangePanicFlag(16, (UCHAR)(0x01 | (4 * DumpStatus)), 0x10); // S014,S018 + + // + // M007,M012 + // Check DumpStatus.and Display NMI status. + // + + if (DumpStatus == 1) { + HalDisplayString("HAL:Dump Switch Pressed!\n"); + } else { + HalDisplayString("HAL:NMI occured\n"); + } + + // + // Display NMI registers + // + + NMISource = READ_REGISTER_ULONG(&DMA_CONTROL->NmiSource.Long); + sprintf(Buffer, "HAL:NmiSource register = %x\n",NMISource); + HalDisplayString((UCHAR *)Buffer); + + MemoryFailed = READ_REGISTER_ULONG( + &((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long); + sprintf(Buffer, + "HAL:MemoryFailedAddress register = %x\n", + MemoryFailed); + HalDisplayString((UCHAR *)Buffer); + + READ_REGISTER_DWORD( + (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, + &InvalidAddressValue); + sprintf(Buffer, + "HAL:Processor Invalid Address register = %x %x\n", + InvalidAddressValue.HighPart,InvalidAddressValue.LowPart); + HalDisplayString((UCHAR *)Buffer); + + READ_REGISTER_DWORD( + (PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, + &EccDiagnosticValue); + sprintf(Buffer, + "HAL:EccDiagnostic register = %x %x\n", + EccDiagnosticValue.HighPart,EccDiagnosticValue.LowPart); + HalDisplayString((UCHAR *)Buffer); + + // + // M007,M008 + // call KeBugCheckEx() for dump. + // + + KeBugCheckEx(NMI_HARDWARE_FAILURE,DumpStatus,NMISource,0,0); + + return; + +} diff --git a/private/ntos/nthals/halr96b/mips/busdat.c b/private/ntos/nthals/halr96b/mips/busdat.c new file mode 100644 index 000000000..1218588b8 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/busdat.c @@ -0,0 +1,1231 @@ +// #pragma comment(exestr, "@(#) busdat.c 1.1 95/09/28 15:30:19 nec") +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixhwsup.c + +Abstract: + + This module contains the IoXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would reside in the iosubs.c module. + +Author: + + Ken Reneris (kenr) July-28-1994 + +Environment: + + Kernel mode + +Revision History: + +Modification History: + + H001 Fri Jun 30 02:57:29 1995 kbnes!kisimoto + - Merge build 1057 + H002 Sat Jul 1 19:53:41 1995 kbnes!kisimoto + - change 'Base' and 'Limit' value on Internal + +--*/ + +#include "halp.h" +#include "string.h" // H001 + +UCHAR HalName[] = "NEC MIPS HAL"; // H001 + +VOID HalpInitializePciBus (VOID); // H001 +VOID HalpInitOtherBuses (VOID); + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +#if !defined(_R94A_) +ULONG HalpcGetCmosData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG HalpcSetCmosData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG HalpGetCmosData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ); + +ULONG HalpSetCmosData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ); +#endif // !_R94A_ + +HalpGetEisaData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +// +// Prototype for system bus handlers +// + +NTSTATUS +HalpAdjustEisaResourceList ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +ULONG +HalpGetSystemInterruptVector ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetEisaInterruptVector ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +#if defined(_R94A_) // H001 +ULONG +HalpGetPCIInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); +#endif + +BOOLEAN +HalpTranslateSystemBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +BOOLEAN +HalpTranslateIsaBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +BOOLEAN +HalpTranslateEisaBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + +NTSTATUS +HalpHibernateHal ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler + ); + +NTSTATUS +HalpResumeHal ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler + ); + +#ifdef MCA +// +// Default functionality of MCA handlers is the same as the Eisa handlers, +// just use them +// + +#define HalpGetMCAInterruptVector HalpGetEisaInterruptVector +#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList; + +HalpGetPosData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +#endif + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers) +#pragma alloc_text(INIT,HalpAllocateBusHandler) +#endif + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ) +{ + PBUS_HANDLER Bus; + + if (KeGetCurrentPrcb()->Number) { + // only need to do this once + return ; + } + + // + // Initalize BusHandler data before registering any handlers + // + + HalpInitBusHandler (); + + // + // Build internal-bus 0, or system level bus + // + + Bus = HalpAllocateBusHandler ( + Internal, + ConfigurationSpaceUndefined, + 0, // Internal BusNumber 0 + InterfaceTypeUndefined, // no parent bus + 0, + 0 // no bus specfic data + ); + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build internal-bus 0, or system level bus + // + // H001: kugi Internal Bus was called with bus-no. 2, We have no idea. + + Bus = HalpAllocateBusHandler ( + Internal, + ConfigurationSpaceUndefined, + 1, // Internal BusNumber 1 + InterfaceTypeUndefined, // no parent bus + 0, + 0 // no bus specfic data + ); + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build Isa/Eisa bus #0 + // + + Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0); + Bus->GetBusData = HalpGetEisaData; + Bus->GetInterruptVector = HalpGetEisaInterruptVector; + Bus->AdjustResourceList = HalpAdjustEisaResourceList; + Bus->TranslateBusAddress = HalpTranslateEisaBusAddress; + + Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0); + Bus->GetBusData = HalpNoBusData; + Bus->BusAddresses->Memory.Limit = 0xFFFFFF; + Bus->TranslateBusAddress = HalpTranslateIsaBusAddress; + HalpInitOtherBuses (); +} + + + +PBUS_HANDLER +HalpAllocateBusHandler ( + IN INTERFACE_TYPE InterfaceType, + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN INTERFACE_TYPE ParentBusInterfaceType, + IN ULONG ParentBusNumber, + IN ULONG BusSpecificData + ) +/*++ + +Routine Description: + + Stub function to map old style code into new HalRegisterBusHandler code. + + Note we can add our specific bus handler functions after this bus + handler structure has been added since this is being done during + hal initialization. + +--*/ +{ + PBUS_HANDLER Bus; + + + // + // Create bus handler - new style + // + + HaliRegisterBusHandler ( + InterfaceType, + BusDataType, + BusNumber, + ParentBusInterfaceType, + ParentBusNumber, + BusSpecificData, + NULL, + &Bus + ); + + if (InterfaceType != InterfaceTypeUndefined) { + Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES)); + RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES)); + Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION; + Bus->BusAddresses->Dma.Limit = 7; +// Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF; // H001 + Bus->BusAddresses->IO.Limit = 0xFFFF; + Bus->BusAddresses->IO.SystemAddressSpace = 0; // H001 + Bus->BusAddresses->PrefetchMemory.Base = 1; + + // + // start H001, H002 + // configurate the bus specific data + // + + switch(InterfaceType) { + + case Internal: + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->LowPart + = 0x80000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart + = 0x800FFFFF; + Bus->BusAddresses->Memory.SystemBase + = 0x00000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->LowPart + = 0x80000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart + = 0x800FFFFF; + Bus->BusAddresses->IO.SystemBase + = 0x00000000; + break; + + case Eisa: + Bus->BusAddresses->Memory.Base = 0x00000000; + Bus->BusAddresses->Memory.Limit = 0x03FFFFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = EISA_MEMORY_VERSION2_LOW; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart + = EISA_MEMORY_VERSION2_HIGH; + Bus->BusAddresses->IO.Base = 0x00000000; + Bus->BusAddresses->IO.Limit = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = EISA_CONTROL_PHYSICAL_BASE; + break; + + case Isa: + Bus->BusAddresses->Memory.Base = 0x00000000; + Bus->BusAddresses->Memory.Limit = 0x00FFFFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = EISA_MEMORY_VERSION2_LOW; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart + = EISA_MEMORY_VERSION2_HIGH; + Bus->BusAddresses->IO.Base = 0x00000000; + Bus->BusAddresses->IO.Limit = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = EISA_CONTROL_PHYSICAL_BASE; + break; + + case PCIBus: + Bus->BusAddresses->Memory.Base = 0x04000000; // from 64MB + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart + = 0xFFFFFFFF; // up to 4GB + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = PCI_MEMORY_PHYSICAL_BASE_LOW; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart + = PCI_MEMORY_PHYSICAL_BASE_HIGH; + Bus->BusAddresses->IO.Base = 0x00000000; + Bus->BusAddresses->IO.Limit = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = PCI_CONTROL_PHYSICAL_BASE; + break; + } + } + + return Bus; +} + + +#if !defined(_R94A_) + +// +// C to Asm thunks for CMos +// + +ULONG HalpcGetCmosData ( + IN PBUS_HANDLER BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + // bugbug: this interface should be rev'ed to support non-zero offsets + if (Offset != 0) { + return 0; + } + + return HalpGetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length); +} + + +ULONG HalpcSetCmosData ( + IN PBUS_HANDLER BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + // bugbug: this interface should be rev'ed to support non-zero offsets + if (Offset != 0) { + return 0; + } + + return HalpSetCmosData (BusHandler->BusNumber, SlotNumber, Buffer, Length); +} + +#endif // !_R94A_ + +#if defined(_R94A_) + +VOID +HalReportResourceUsage ( + VOID + ) +{ + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + +#if 0 // H001: support next version + HalpRegisterAddressUsage (&HalpDefaultPcIoSpace); + HalpRegisterAddressUsage (&HalpEisaIoSpace); + HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace); +#endif + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + HalpReportResourceUsage ( + &UHalName, // descriptive name + Internal // device space interface type + ); + + RtlFreeUnicodeString (&UHalName); + + // + // Registry is now intialized, see if there are any PCI buses + // + + HalpInitializePciBus (); + +} + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + // no other internal buses supported +} + +ULONG +HalpGetEisaInterruptVector( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified bus interrupt level and/or vector. The + system interrupt vector and IRQL are suitable for use in a subsequent call + to KeInitializeInterrupt. + +Arguments: + + BusHandle - Per bus specific structure + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + // + // Jazz and Duo only have one I/O bus which is an EISA, so the bus + // number and the bus interrupt vector are unused. + // + // The IRQL level is always equal to the EISA level. + // + + *Affinity = HalpEisaBusAffinity; + + *Irql = EISA_DEVICE_LEVEL; + + // + // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa + // hardware. + // + + if (BusInterruptLevel == 2) { + BusInterruptLevel = 9; + } + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + return(BusInterruptLevel + EISA_VECTORS); +} + +ULONG +HalpGetPCIInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + + This function returns the system interrupt vector and IRQL level + corresponding to the specified bus interrupt level and/or vector. The + system interrupt vector and IRQL are suitable for use in a subsequent call + to KeInitializeInterrupt. + +Arguments: + + BusHandle - Per bus specific structure + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + *Affinity = HalpEisaBusAffinity; + *Irql = EISA_DEVICE_LEVEL; + + return(BusInterruptVector + PCI_VECTORS); +} + +HalpGetEisaData ( + IN PBUS_HANDLER BusHandler, // H001 + IN PBUS_HANDLER RootHandler, // H001 + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Eisa bus data for a slot or address. + +Arguments: + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + OBJECT_ATTRIBUTES ObjectAttributes; + OBJECT_ATTRIBUTES BusObjectAttributes; + PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter"; + PWSTR ConfigData = L"Configuration Data"; + ANSI_STRING TmpString; + ULONG BusNumber; + UCHAR BusString[] = "00"; + UNICODE_STRING RootName, BusName; + UNICODE_STRING ConfigDataName; + NTSTATUS NtStatus; + PKEY_VALUE_FULL_INFORMATION ValueInformation; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource; + PCM_EISA_SLOT_INFORMATION SlotInformation; + ULONG PartialCount; + ULONG TotalDataSize, SlotDataSize; + HANDLE EisaHandle, BusHandle; + ULONG BytesWritten, BytesNeeded; + PUCHAR KeyValueBuffer; + ULONG i; + ULONG DataLength = 0; + PUCHAR DataBuffer = Buffer; + BOOLEAN Found = FALSE; + + PAGED_CODE (); // H001 + + + RtlInitUnicodeString( + &RootName, + EisaPath + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &RootName, + OBJ_CASE_INSENSITIVE, + (HANDLE)NULL, + NULL + ); + + // + // Open the EISA root + // + + NtStatus = ZwOpenKey( + &EisaHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + DbgPrint("HAL: Open Status = %x\n",NtStatus); + return(0); + } + + // + // Init bus number path + // + + BusNumber = BusHandler->BusNumber; + if (BusNumber > 99) { + return (0); + } + + if (BusNumber > 9) { + BusString[0] += (UCHAR) (BusNumber/10); + BusString[1] += (UCHAR) (BusNumber % 10); + } else { + BusString[0] += (UCHAR) BusNumber; + BusString[1] = '\0'; + } + + RtlInitAnsiString( + &TmpString, + BusString + ); + + RtlAnsiStringToUnicodeString( + &BusName, + &TmpString, + TRUE + ); + + + InitializeObjectAttributes( + &BusObjectAttributes, + &BusName, + OBJ_CASE_INSENSITIVE, + (HANDLE)EisaHandle, + NULL + ); + + // + // Open the EISA root + Bus Number + // + + NtStatus = ZwOpenKey( + &BusHandle, + KEY_READ, + &BusObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus); + return(0); + } + + // + // opening the configuration data. This first call tells us how + // much memory we need to allocate + // + + RtlInitUnicodeString( + &ConfigDataName, + ConfigData + ); + + // + // This should fail. We need to make this call so we can + // get the actual size of the buffer to allocate. + // + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i; + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + 0, + &BytesNeeded + ); + + KeyValueBuffer = ExAllocatePool( + NonPagedPool, + BytesNeeded + ); + + if (KeyValueBuffer == NULL) { +#if DBG + DbgPrint("HAL: Cannot allocate Key Value Buffer\n"); +#endif + ZwClose(BusHandle); + return(0); + } + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer; + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + BytesNeeded, + &BytesWritten + ); + + + ZwClose(BusHandle); + + if (!NT_SUCCESS(NtStatus)) { +#if DBG + DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus); +#endif + ExFreePool(KeyValueBuffer); + return(0); + } + + + // + // We get back a Full Resource Descriptor List + // + + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation + + ValueInformation->DataOffset); + + PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) + &(Descriptor->PartialResourceList.PartialDescriptors); + PartialCount = Descriptor->PartialResourceList.Count; + + for (i = 0; i < PartialCount; i++) { + + // + // Do each partial Resource + // + + switch (PartialResource->Type) { + case CmResourceTypeNull: + case CmResourceTypePort: + case CmResourceTypeInterrupt: + case CmResourceTypeMemory: + case CmResourceTypeDma: + + // + // We dont care about these. + // + + PartialResource++; + + break; + + case CmResourceTypeDeviceSpecific: + + // + // Bingo! + // + + TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)PartialResource + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + + while (((LONG)TotalDataSize) > 0) { + + if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION); + + } else { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) + + SlotInformation->NumberFunctions * + sizeof(CM_EISA_FUNCTION_INFORMATION); + } + + if (SlotDataSize > TotalDataSize) { + + // + // Something is wrong again + // + + ExFreePool(KeyValueBuffer); + return(0); + + } + + if (SlotNumber != 0) { + + SlotNumber--; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)SlotInformation + SlotDataSize); + + TotalDataSize -= SlotDataSize; + + continue; + + } + + // + // This is our slot + // + + Found = TRUE; + break; + + } + + // + // End loop + // + + i = PartialCount; + + break; + + default: + +#if DBG + DbgPrint("Bad Data in registry!\n"); +#endif + + ExFreePool(KeyValueBuffer); + return(0); + + } + + } + + if (Found) { + i = Length + Offset; + if (i > SlotDataSize) { + i = SlotDataSize; + } + + DataLength = i - Offset; + RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength); + } + + ExFreePool(KeyValueBuffer); + return DataLength; +} + +// from ixsysbus.c +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + PSUPPORTED_RANGE pRange; + + pRange = NULL; + switch (*AddressSpace) { + case 0: + // verify memory address is within buses memory limits + for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) { + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + + if (!pRange) { + for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) { + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + } + + break; + + case 1: + // verify IO address is within buses IO limits + for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) { + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + break; + } + + if (pRange) { + TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase; + *AddressSpace = pRange->SystemAddressSpace; + return TRUE; + } + + // + // + // PCI Translate Bus Address workaround + // + // + + if (((BusHandler->InterfaceType == PCIBus)) && + (*AddressSpace == 0) && + (BusAddress.QuadPart >= 0) && + (BusAddress.QuadPart <= 0xffffffff )) { + TranslatedAddress->QuadPart = BusAddress.QuadPart + 0x100000000; + return TRUE; + } + + + return FALSE; +} + +ULONG +HalpGetSystemInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) + +/*++ + +Routine Description: + +Arguments: + + BusInterruptLevel - Supplies the bus specific interrupt level. + + BusInterruptVector - Supplies the bus specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the system wide irq affinity. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ +{ + *Affinity = 1; + *Irql = (KIRQL)BusInterruptLevel; + + if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision) == 0 ){ + + // + // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt + // Enable register is zero origin. + // + // N.B. This obstruction is limiteded to beta-version of STORM chipset. + // + + return(BusInterruptVector + DEVICE_VECTORS); + + }else{ + + return(BusInterruptVector); + + } +} + +BOOLEAN +HalpTranslateEisaBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + BOOLEAN Status; + + // + // Translated normally + // + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddress, + AddressSpace, + TranslatedAddress + ); + + + // + // If it could not be translated, and it's in the 640k - 1m + // range then (for compatibility) try translating it on the + // Internal bus for + // + + if (Status == FALSE && + *AddressSpace == 0 && + BusAddress.HighPart == 0 && + BusAddress.LowPart >= 0xA0000 && + BusAddress.LowPart < 0xFFFFF) { + + Status = HalTranslateBusAddress ( + Internal, + 0, + BusAddress, + AddressSpace, + TranslatedAddress + ); + } + + return Status; +} + +BOOLEAN +HalpTranslateIsaBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + BOOLEAN Status; + + // + // Translated normally + // + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddress, + AddressSpace, + TranslatedAddress + ); + + + // + // If it could not be translated, and it's memory space + // then we allow the translation as it would occur on it's + // corrisponding EISA bus. We're allowing this because + // many VLBus drivers are claiming to be ISA devices. + // (yes, they should claim to be VLBus devices, but VLBus is + // run by video cards and like everything else about video + // there's no hope of fixing it. (At least according to + // Andre)) + // + + if (Status == FALSE && *AddressSpace == 0) { + Status = HalTranslateBusAddress ( + Eisa, + BusHandler->BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress + ); + } + + return Status; +} + +NTSTATUS +HalpAdjustEisaResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +{ + SUPPORTED_RANGE InterruptRange; + + RtlZeroMemory (&InterruptRange, sizeof InterruptRange); + InterruptRange.Base = 0; + InterruptRange.Limit = 15; + + return HaliAdjustResourceListRange ( + BusHandler->BusAddresses, + &InterruptRange, + pResourceList + ); +} + +#endif // _R94A_ diff --git a/private/ntos/nthals/halr96b/mips/cacherr.s b/private/ntos/nthals/halr96b/mips/cacherr.s new file mode 100644 index 000000000..0b3cdf5ce --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/cacherr.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\cacherr.s" diff --git a/private/ntos/nthals/halr96b/mips/cirrus.h b/private/ntos/nthals/halr96b/mips/cirrus.h new file mode 100644 index 000000000..d827568cf --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/cirrus.h @@ -0,0 +1,281 @@ +// #pragma comment(exestr, "@(#) cirrus.h 1.1 95/09/28 15:31:10 nec") +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + cirrus.h + +Abstract: + + This module contains the definitions for the code that implements the + Cirrus Logic VGA 6410/6420/542x device driver. + +Environment: + + Kernel mode + +Notes: + + This module based on Cirrus Minport Driver. And modify for R96 MIPS + R4400 HAL Cirrus display initialize. + +Revision History: + + +--*/ + +/* + * M001 1993.19.28 A. Kuriyama @ oa2 + * + * - Modify for R96 MIPS R4400 HAL + * + * Delete : Miniport Driver Interface + * + * + * Revision History in Cirrus Miniport Driver as follows: + * + * L001 1993.10.15 Kuroki + * + * - Modify for R96 MIPS R4400 * + * Delete : Micro channel Bus Initialize. + * VDM & Text, Fullscreen mode support. + * Banking routine. + * CL64xx Chip support. + * 16-color mode. + * + * Add : Liner Addressing. + * + * L002 1993.10.21 Kuroki + * + * - Warniing clear + * + * S003 1993.1.13 kbnes!A.Kuriyama + * + * - VGA Address was changed + * + */ + +// +// Change Ushort to Uchar, because R96 is mips machine. +// + + +// +// Base address of VGA memory range. Also used as base address of VGA +// memory when loading a font, which is done with the VGA mapped at A0000. +// + +/* START L001 */ + +#define LA_MASK 0xE /* S003 */ +#define MEM_VGA (LA_MASK << 20) +#define MEM_VGA_SIZE 0x100000 + +/* END L001 */ + +// +// Port definitions for filling the ACCSES_RANGES structure in the miniport +// information, defines the range of I/O ports the VGA spans. +// There is a break in the IO ports - a few ports are used for the parallel +// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped +// so all VGA ports are in one address range. +// + +#define VGA_BASE_IO_PORT 0x000003B0 +#define VGA_START_BREAK_PORT 0x000003BB +#define VGA_END_BREAK_PORT 0x000003C0 +#define VGA_MAX_IO_PORT 0x000003DF + +// +// VGA port-related definitions. +// + +// +// VGA register definitions +// + // ports in monochrome mode +#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and +#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode +#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port + // in mono mode +#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read + // port in mono mode +#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO + // Register to read to reset + // Attribute Controller index/data +#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and +#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port + // for writes, but only Address is + // readable at 0x010 +#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is + // readable here +#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write + // port +#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read + // port +#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the + // entire VGA subsystem +#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and +#define SEQ_DATA_PORT 0x0015 // Data registers +#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg +#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg, + // write-only +#define DAC_STATE_PORT 0x0017 // DAC state (read/write), + // read-only +#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg +#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg +#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port +#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read + // port +#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address +#define GRAPH_DATA_PORT 0x001F // and Data registers + + // ports in color mode +#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and +#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode +#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port +#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read + // port in color mode +#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR + // Register to read to reset + // Attribute Controller index/data + // toggle in color mode + +// +// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed +// VGA registers. +// + +#define CRTC_ADDRESS_MONO_OFFSET 0x04 +#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A +#define ATT_ADDRESS_OFFSET 0x10 +#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12 +#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13 +#define SEQ_ADDRESS_OFFSET 0x14 +#define DAC_PIXEL_MASK_OFFSET 0x16 +#define DAC_STATE_OFFSET 0x17 +#define DAC_ADDRESS_WRITE_OFFSET 0x18 +#define GRAPH_ADDRESS_OFFSET 0x1E +#define CRTC_ADDRESS_COLOR_OFFSET 0x24 +#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A + +// toggle in color mode +// +// VGA indexed register indexes. +// + +// CL-GD542x specific registers: +// +#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts +#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad +#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register +// +#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start +#define IND_CURSOR_END 0x0B // and End registers +#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location +#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers +#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync + // End register, which has the bit + // that protects/unprotects CRTC + // index registers 0-7 +#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC +#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC +#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr +#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr +#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr +#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr +#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq +#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer +#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq +#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in + // CRTC +#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg + // in CRTC +#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start + // synchronous reset +#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end + // synchronous reset + +// +// Values for Attribute Controller Index register to turn video off +// and on, by setting bit 5 to 0 (off) or 1 (on). +// + +#define VIDEO_DISABLE 0 +#define VIDEO_ENABLE 0x20 + +// Masks to keep only the significant bits of the Graphics Controller and +// Sequencer Address registers. Masking is necessary because some VGAs, such +// as S3-based ones, don't return unused bits set to 0, and some SVGAs use +// these bits if extensions are enabled. +// + +#define GRAPH_ADDR_MASK 0x0F +#define SEQ_ADDR_MASK 0x07 + +// +// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register. +// + +#define CHAIN4_MASK 0x08 + +// +// Value written to the Read Map register when identifying the existence of +// a VGA in VgaInitialize. This value must be different from the final test +// value written to the Bit Mask in that routine. +// + +#define READ_MAP_TEST_SETTING 0x03 + +// +// Default text mode setting for various registers, used to restore their +// states if VGA detection fails after they've been modified. +// + +#define MEMORY_MODE_TEXT_DEFAULT 0x02 +#define BIT_MASK_DEFAULT 0xFF +#define READ_MAP_DEFAULT 0x00 + + +// +// Palette-related info. +// + +// +// Highest valid DAC color register index. +// + +#define VIDEO_MAX_COLOR_REGISTER 0xFF + +// +// Indices for type of memory mapping; used in ModesVGA[], must match +// MemoryMap[]. +// + +typedef enum _VIDEO_MEMORY_MAP { + MemMap_Mono, + MemMap_CGA, + MemMap_VGA +} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP; + +// +// For a mode, the type of banking supported. Controls the information +// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking. +// + +typedef enum _BANK_TYPE { + NoBanking = 0, + NormalBanking, + PlanarHCBanking +} BANK_TYPE, *PBANK_TYPE; + +#define CL6410 0x0001 +#define CL6420 0x0002 +#define CL542x 0x0004 + +// bitfields for the DisplayType +#define crt 0x0001 +#define panel 0x0002 +#define simulscan 0x0004 // this means both, but is unused for now. diff --git a/private/ntos/nthals/halr96b/mips/cmdcnst.h b/private/ntos/nthals/halr96b/mips/cmdcnst.h new file mode 100644 index 000000000..ea2bba221 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/cmdcnst.h @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + cmdcnst.h + +Abstract: + + This is the command string interpreter definitions + +Environment: + + kernel mode only + +Notes: + + This module is same file on Cirrus Minport Driver. + +Revision History: + +--*/ + +//-------------------------------------------------------------------------- +// Definition of the set/clear mode command language. +// +// Each command is composed of a major portion and a minor portion. +// The major portion of a command can be found in the most significant +// nibble of a command byte, while the minor portion is in the least +// significant portion of a command byte. +// +// maj minor Description +// ---- ----- -------------------------------------------- +// 00 End of data +// +// 10 in and out type commands as described by flags +// flags: +// +// xxxx +// |||| +// |||+-------- unused +// ||+--------- 0/1 single/multiple values to output (in's are always +// |+---------- 0/1 8/16 bit operation single) +// +----------- 0/1 out/in instruction +// +// Outs +// ---------------------------------------------- +// 0 reg:W val:B +// 2 reg:W cnt:W val1:B val2:B...valN:B +// 4 reg:W val:W +// 6 reg:W cnt:W val1:W val2:W...valN:W +// +// Ins +// ---------------------------------------------- +// 8 reg:W +// a reg:W cnt:W +// c reg:W +// e reg:W cnt:W +// +// 20 Special purpose outs +// 00 do indexed outs for seq, crtc, and gdc +// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B +// 01 do indexed outs for atc +// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B +// 02 do masked outs +// indexreg:W andmask:B xormask:B +// +// F0 Nop +// +//--------------------------------------------------------------------------- + +// some useful equates - major commands + +#define EOD 0x000 // end of data +#define INOUT 0x010 // do ins or outs +#define METAOUT 0x020 // do special types of outs +#define NCMD 0x0f0 // Nop command + + +// flags for INOUT major command + +//#define UNUSED 0x01 // reserved +#define MULTI 0x02 // multiple or single outs +#define BW 0x04 // byte/word size of operation +#define IO 0x08 // out/in instruction + +// minor commands for metout + +#define INDXOUT 0x00 // do indexed outs +#define ATCOUT 0x01 // do indexed outs for atc +#define MASKOUT 0x02 // do masked outs using and-xor masks + + +// composite inout type commands + +#define OB (INOUT) // output 8 bit value +#define OBM (INOUT+MULTI) // output multiple bytes +#define OW (INOUT+BW) // output single word value +#define OWM (INOUT+BW+MULTI) // output multiple words + +#define IB (INOUT+IO) // input byte +#define IBM (INOUT+IO+MULTI) // input multiple bytes +#define IW (INOUT+IO+BW) // input word +#define IWM (INOUT+IO+BW+MULTI) // input multiple words diff --git a/private/ntos/nthals/halr96b/mips/esm.c b/private/ntos/nthals/halr96b/mips/esm.c new file mode 100644 index 000000000..f15acb3c6 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/esm.c @@ -0,0 +1,1182 @@ +// #pragma comment(exestr, "@(#) esm.c 1.1 95/09/28 15:31:51 nec") +/*++ + +Copyright (c) 1995 Kobe NEC Software + +Module Name: + + esm.c + +Abstract: + + This module implements the ESM service routine + +Author: + +Environment: + + Kernel mode + +Revision History: + + L001 kuriyama@oa2.kb.nec.co.jp Thu Jun 15 14:57:14 JST 1995 + -Change HalpEccError() for support J94C ECC error + + M002 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 14:31:57 JST 1995 + - add ecc 1bit safety flag + + M003 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 20:40:52 JST 1995 + - add serialize ecc 1bit routine + + S004 kuriyama@oa2.kb.nec.co.jp Fri Jun 23 16:55:12 JST 1995 + - bug fix ecc 2bit error +--*/ +#include "halp.h" +#include "esmnvram.h" +#include "bugcodes.h" +#include "stdio.h" + +// +// define offset. +// + +#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag) +#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic) +#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr) +#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest) +#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr) +#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest) +#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr) +#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest) + + +#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description) +#define TIME_STAMP_SIZE 14 + +// +// define value +// + +#define NVRAM_VALID 3 +#define NVRAM_MAGIC 0xff651026 +#define ECC_LOG_VALID_FLG 1 + +// L001++ +#define STORM_ECC_1BIT_ERROR 1 +#define STORM_ECC_2BIT_ERROR 2 +#define STORM_OTHER_ERROR 0 +// L001--- + +//#define SDCR_SET0_ADDR 0xb9100030 +//#define SDCR_SET1_ADDR 0xb9120030 + +#define STRING_BUFFER_SIZE 512 + +#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10 + +// M002 +++ + +// +// Define Ecc safety flags +// + +#define CHECKED 1 +#define NOT_CHECKED 0 +#define RUNNING 1 +#define NOT_RUNNING 0 +// M002 --- + +// +// Define global variable. This variable use in display string into nvram. +// + +ULONG CallCountOfInitDisplay = 0; +ULONG HalpNvramValid=FALSE; +USHORT ErrBufferLatest; +USHORT ErrBufferArea; +USHORT ErrBufferStart; +USHORT ErrBufferEnd; +USHORT ErrBufferCurrent; +ULONG HalpPanicFlg=0; +UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE]; +ULONG HalpNvramStringBufferCounter=0; + +// L001+++ +//LONG HalpECC1bitDisableFlag=1; // S001 +//LONG HalpECC1bitDisableTime=0; // S003 +//ULONG HalpECC1bitScfrBuffer=0; // S003 +ULONG HalpEcc1bitCount[2] = {0,0}; +ULONG HalpOldMemoryFailed[2] = {0,0}; +ULONG HalpEcc2bitErrorFlag = 0; +// L001--- + +// M002 +++ + +// ecc 1bit total count +ULONG HalpEcc1bitTotalCount = 0; + +// variables for ecc1bit safety flag +extern ULONG HalpAnotherRunningECC; +extern ULONG HalpAnotherCheckedECC; +// M002 --- + + +UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002 + +// +// Define macro +// +#if 0 +#define GET_PADDR(addr,sts2,SicSet) { \ + (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \ + + ( (SicSet) << 30 ) ); \ +} +#endif // 0 + +#define GET_TIME(Buffer) { \ + TIME_FIELDS timeBuffer; \ + HalQueryRealTimeClock( &timeBuffer ); \ + sprintf( (Buffer), \ + "%04d%02d%02d%02d%02d%02d", \ + timeBuffer.Year, \ + timeBuffer.Month, \ + timeBuffer.Day, \ + timeBuffer.Hour, \ + timeBuffer.Minute, \ + timeBuffer.Second \ + ); \ +} + +// S002, S003 vvv +#if 0 +#define NOTIFY_ECC1BIT(Scfr) { \ + ULONG buffer; \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer &= DPCM_ENABLE_MASK; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \ + if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer &= DPCM_ENABLE_MASK; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \ + buffer); \ + } \ +} + +#define DONT_NOTIFY_ECC1BIT(Scfr) { \ + ULONG buffer; \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer |= DPCM_ECC1BIT_BIT; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \ + buffer); \ + if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer |= DPCM_ECC1BIT_BIT; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \ + buffer); \ + } \ +} +#endif // 0 +// S002, S003 ^^^ + +VOID +HalpInitDisplayStringIntoNvram( + VOID + ) + +/*++ + +Routine Description: + + This routine is initialize variable of use when write display data in + HalDisplayString into NVRAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + SYSTEM_ERR_AREA_INFO infoBuf; + UCHAR recordFlg; + UCHAR buf[8]; + UCHAR buf2[8]; + + CallCountOfInitDisplay++; + if(CallCountOfInitDisplay == 1){ + + // + // Check NVRAM status + // + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 ); + + if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){ + HalpNvramValid=FALSE; + return; + } + + HalpNvramValid=TRUE; + + // + // Get log area infomation. + // + + HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET, + sizeof(SYSTEM_ERR_AREA_INFO), + &infoBuf); + + ErrBufferLatest = infoBuf.offset_latest; + + HalNvramRead( infoBuf.offset_latest, 1, &recordFlg); + + // + // Check current record flg. + // + + if( (recordFlg & 0x01) == 1 ) { + infoBuf.offset_latest += infoBuf.size_rec; + if( infoBuf.offset_latest >= + infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){ + infoBuf.offset_latest = infoBuf.offset_systemerr; + } + HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, + 2, + &infoBuf.offset_latest); + } + + // + // initialize variable. this value use log area access. + // + + ErrBufferArea = infoBuf.offset_latest; + ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE; + ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1; + ErrBufferCurrent = ErrBufferStart; + + // + // status flg set. + // + + HalpPanicFlg = 0; + + recordFlg = 0x11; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + + // + // buffer initialize. + // + + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + + } else { + + // + // start Panic log. + // + + HalpChangePanicFlag( 1, 1, 0); + } +} + +// L001 +++ + +UCHAR +HalpFindMemoryGroup( + IN ULONG MemoryFailed + ) + +/*++ + +Routine Description: + + This routine finds MemoryGroup of MemoryFaled address + +Arguments: + + MemoryFailed - MemoryFailed Register value + + +Return Value: + + if MemoryFaied is within any Goup, return MemoryGroup Number. + + Otherwise, return 0xff + +--*/ + +{ + UCHAR returnValue = 0xff; + UCHAR i; + ULONG startAddr; + ULONG length; + ULONG simmType; + ULONG dataWord; + + // + // find MemoryGroup from MemoryGroup[0:3] register. + // + // MemoryGroup[0:3] register + // + // [31] Reserved + // [30:22] Starting address + // [21:04] Reserved + // [03:02] SIMM type + // 01=Single-sided 11=Double-sided other=Reserved + // [01:00] SIMM size + // 00= 1M 01=4M 10=16M 11=64M SIMM + // + // note: 1 memory group is have 4 SIMM's + // + + for (i = 0; i < 4; i++) { + dataWord = READ_REGISTER_ULONG(&DMA_CONTROL->MemoryConfig[i]); + + // check SIMM type is valid + + switch (dataWord & 0xc) { + + case 4: + simmType = 1; + break; + + case 0xc: + simmType = 2; + break; + + default: + simmType = 3; + } + + if (simmType == 3) { + continue; + } + + // compute amount of MemoryGoup SIMM length; + + length = (0x400000 << ((dataWord & 3) * 2)) * simmType; + + // compute MemoryGoup SIMM start address; + + startAddr = dataWord & 0x7fc00000; + + // check if MemoryFailed is within this MemoryGroup + + if ( (startAddr <= MemoryFailed) + && (MemoryFailed < (length + startAddr))) { + returnValue = i; + break; + } + } + return returnValue; + +} + + +ULONG +HalpEccError( + IN ULONG EccDiagnostic, + IN ULONG MemoryFailed + ) + +/*++ + +Routine Description: + + This routine check ecc error and error log put in NVRAM. + +Arguments: + + EccDiagnostic - EccDiagnostic Register value + MemoryFailed - MemoryFailed Register value + + +Return Value: + + return value is the following error occured. + 1: ecc 1bit error. + 2: ecc 2bit error. + 0: other error. + +--*/ + +{ + ULONG returnValue; + USHORT infoOffset; + USHORT writeOffset; + ULONG buffer; // S001 + ULONG i; // S002 + UCHAR dataBuf[36]; + UCHAR infoBuf[24]; + UCHAR tempBuf[24]; + KIRQL OldIrql; + ULONG DataWord; + ULONG Number; + + // + // Check for Ecc 2bit/1bit error + // + + if (EccDiagnostic & 0x44000000) { + returnValue = STORM_ECC_2BIT_ERROR; + infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET; + } else if (EccDiagnostic & 0x22000000) { + returnValue = STORM_ECC_1BIT_ERROR; + infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET; + } else { + return 0; // Probably Error bit was disappered. + } + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf ); + + // S002 vvv + switch(returnValue) { + + case STORM_ECC_2BIT_ERROR: + + // + // Disable and clear ECC 1bit error. + // + + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00ee0000; + KeFlushWriteBuffer(); + + // set Flag indicate ECC 2bit error. + + HalpEcc2bitErrorFlag = 1; + + // + // Log to NVRAM + // + + // check for nvram was valid. + + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG; + + ((pECC2_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0; + // Error Address was 16Byte Alined. + + GET_TIME(tempBuf); + RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ), + (PVOID)tempBuf, + TIME_STAMP_SIZE + ); + + ((pECC2_ERR_REC)dataBuf)->syndrome = EccDiagnostic; + + ((pECC2_ERR_REC)dataBuf)->specified_group = + HalpFindMemoryGroup(MemoryFailed); + + ((pECC2_ERR_REC)dataBuf)->specified_simm = 0; + + writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest + +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec; + + if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr + +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec + *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) { + writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr; + } + + HalNvramWrite( (ULONG)writeOffset, + sizeof(ECC2_ERR_REC), + (PVOID)dataBuf); + + HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET, + sizeof(USHORT), + (PVOID)&writeOffset); + } + return returnValue; // S004 + + case STORM_ECC_1BIT_ERROR: + + // + // If MemoryFailed address + // is over 512M Nothing can do. + // + if ((MemoryFailed & 0xfffffff0) > 0x1fffffff) { + return returnValue; + } + + // + // Disable and clear ECC 1bit error. + // + + Number = KeGetCurrentPrcb()->Number; + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00ee0000; + KeFlushWriteBuffer(); +// M003 +++ + // + // serialize ecc 1bit logging routine + // + + for (;;) { + KiAcquireSpinLock(&Ecc1bitRoutineLock); + if (HalpEcc1bitCount[!Number] == 0) { + + // + // Increment HalpEcc1bitCount + // + + HalpEcc1bitCount[Number]++; + KiReleaseSpinLock(&Ecc1bitRoutineLock); + break; + } + KiReleaseSpinLock(&Ecc1bitRoutineLock); + } +// M003 --- + + switch(HalpEcc1bitCount[Number]) { + + case 1: + + HalpEcc1bitTotalCount++; // M002 + + + HalpOldMemoryFailed[Number] = MemoryFailed; + + // + // ReWrite error address + // if error address is over 512M + // Nothing can do. + // + + KiAcquireSpinLock(&Ecc1bitDisableLock); + + // disable ecc 1bit error again. + + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00ee0000; + KeFlushWriteBuffer(); + + DataWord = READ_REGISTER_ULONG( + KSEG1_BASE + | (MemoryFailed & 0xfffffff0) + ); + WRITE_REGISTER_ULONG( + KSEG1_BASE + | (MemoryFailed & 0xfffffff0), + DataWord + ); + + KiReleaseSpinLock(&Ecc1bitDisableLock); + + // + // Wait 20 us. + // + + KeStallExecutionProcessor(20); + + // + // Enable and clear ECC 1bit error. + // + + KiAcquireSpinLock(&Ecc1bitDisableLock); + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00cc0000; + KeFlushWriteBuffer(); + KiReleaseSpinLock(&Ecc1bitDisableLock); + + // + // ReRead error address + // if error address is over 512M + // Nothing can do. + // + // if Ecc 1bit error occur again , DataBusError will occur. + // + + DataWord = READ_REGISTER_ULONG( + KSEG1_BASE + | (MemoryFailed & 0xfffffff0) + ); + + // decrement ecc 1bit count + + HalpEcc1bitCount[Number]--; + + return(returnValue); + + case 2: + + if (HalpOldMemoryFailed[Number] != MemoryFailed) { + break; + } + if (MemoryFailed & 2) { + + // if multi error + // nothing can do. + + break; + } + + + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + + // + // Search for wheather error address was already logged + // + + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) { + HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)-> + size_rec * i + +((pECC1_ERR_AREA_INFO)infoBuf)-> + offset_1biterr), + sizeof(ECC1_ERR_REC), + (PVOID)dataBuf); + if ( ((MemoryFailed & 0xfffffff0) + == ((pECC1_ERR_REC)dataBuf)->err_address) && + ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) { + break; + } + } + + if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) { + break; + } + + // + // Log to NVRAM + // + + // check for nvram was valid. + + ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG; + + ((pECC1_ERR_REC)dataBuf)->err_address = MemoryFailed & 0xfffffff0; + // Error Address was 16Byte Alined. + + GET_TIME(tempBuf); + RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ), + (PVOID)tempBuf, + TIME_STAMP_SIZE + ); + + ((pECC1_ERR_REC)dataBuf)->syndrome = EccDiagnostic; + + ((pECC1_ERR_REC)dataBuf)->specified_group = + HalpFindMemoryGroup(MemoryFailed); + + ((pECC1_ERR_REC)dataBuf)->specified_simm = 0; + + writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest + +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec; + + if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr + +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec + *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) { + writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr; + } + + HalNvramWrite( (ULONG)writeOffset, + sizeof(ECC1_ERR_REC), + (PVOID)dataBuf); + HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET, + sizeof(USHORT), + (PVOID)&writeOffset); + } + + + // disable ecc 1bit error again. + + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00ee0000; + KeFlushWriteBuffer(); + + // decrement ecc 1bit count + + HalpEcc1bitCount[Number]--; + + return(returnValue); + } + + // + // Enable and clear ECC 1bit error. + // + + KiAcquireSpinLock(&Ecc1bitDisableLock); + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)-> + EccDiagnostic.u.LargeInteger.LowPart + = 0x00cc0000; + KeFlushWriteBuffer(); + KiReleaseSpinLock(&Ecc1bitDisableLock); + + + // decrement ecc 1bit count + + HalpEcc1bitCount[Number]--; + + return(returnValue); + } +} + +// L001 --- + + +VOID +HalpSetInitDisplayTimeStamp( + VOID + ) +{ + UCHAR buf[24]; + + // + // Set time stamp on initialize display. + // + + if(HalpNvramValid == TRUE) { + GET_TIME(buf); + HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf ); + } +} + + +VOID +HalpSuccessOsStartUp( + VOID + ) +{ + UCHAR recordFlg; + + if(HalpNvramValid == TRUE) { + recordFlg = 0; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest ); + } +} + + +VOID +HalpChangePanicFlag( + IN ULONG NewPanicFlg, + IN UCHAR NewLogFlg, + IN UCHAR CurrentLogFlgMask + ) +{ + UCHAR recordFlg; + UCHAR buf[24]; + + if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) { + return; + } + + HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, + 2, + &ErrBufferArea); + + // + // initialize currernt buffer address + // + + ErrBufferCurrent = ErrBufferStart; + + // + // set panic flag + // + + HalNvramRead( ErrBufferArea, 1, &recordFlg ); + recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + + GET_TIME(buf); + HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf ); + + // + // set new flag of panic level + // + + HalpPanicFlg = NewPanicFlg; + + // + // initialize log buffer. + // + + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); +} + + +// S002 vvv +VOID +HalStringIntoBuffer( + IN UCHAR Character + ) +{ + if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) { + HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character; + } +} + + +VOID +HalStringIntoBufferStart( + IN ULONG Column, + IN ULONG Row + ) +{ + ULONG i; + + // + // Initialize buffer + // + + for(i=0; i ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) { + return; + } else { + if( HalpPanicFlg == 0 ) { + ErrBufferCurrent = ErrBufferStart; + goto loop; + } else if(ErrBufferCurrent >= ErrBufferEnd){ + return; + } + + for(count=0;;count++) { + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count ); + } + ErrBufferCurrent++; + if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) { + break; + } + } + + buf[0]=0xff; + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + } +} + +#if 0 +VOID +HalpStringIntoNvram( + IN ULONG Column, + IN ULONG Row, + IN PUCHAR String + ) +{ + UCHAR buf[4]; + USHORT count; + + // + // check nvram status. + // + + if(HalpNvramValid == FALSE) { + return; + } + + // + // check panic message + // + + for(count=0; 1; count++) { + if( KernelPanicMessage[count] == '\0' ){ + HalpChangePanicFlag( 8, 0x01, 0x10); + break; + } + if( KernelPanicMessage[count] != String[count] ){ + break; + } + } + + // + // check message length + // + + for(count=0;;count++) { + if(String[count]=='\0'){ + count++; + break; + } + } + +loop: + if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) { + buf[0]=(UCHAR)Column; + buf[1]=(UCHAR)Row; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + ErrBufferCurrent += 2; + HalNvramWrite( ErrBufferCurrent, count, String ); + ErrBufferCurrent += count; + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + + } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) { + return; + } else { + if( HalpPanicFlg == 0 ) { + ErrBufferCurrent = ErrBufferStart; + goto loop; + } else if(ErrBufferCurrent >= ErrBufferEnd){ + return; + } + + buf[0]=(UCHAR)Column; + buf[1]=(UCHAR)Row; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + ErrBufferCurrent += 2; + + for(count=0;;count++) { + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent, 1, String+count ); + } + ErrBufferCurrent++; + if(String[count]=='\0') { + break; + } + } + + buf[0]=0xff; + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + } +} +#endif +// S002 ^^^ + + +// +// test code +// + +int +printNvramData(void) +{ + UCHAR buf[256]; + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf ); + DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf ); + buf[14]=0; + DbgPrint("Nvram TimeStamp: %s\n", buf); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err), + sizeof(ECC1_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err), + sizeof(ECC2_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err), + sizeof(SYSTEM_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + return(0); +} + + +int +TmpInitNvram(void) +{ + UCHAR buf[256]; + ULONG i; + + buf[0]=0xff; + for(i=0; i<8*1024; i++) + HalNvramWrite( i, 1, buf); + + // + // Make nvram flg + // + + buf[0]=0x03; + HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf); + + i = NVRAM_MAGIC; + HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 4, (PUCHAR)&i); + + // + // Make 1bit err log info + // + + ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768; + ((pECC1_ERR_AREA_INFO)buf)->size_rec=25; + ((pECC1_ERR_AREA_INFO)buf)->num_rec=16; + ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768; + + ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0; + + ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0; + + HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET, + sizeof(ECC1_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=768; i<768+25*16; i++) + HalNvramWrite( i, 1, buf); + + // + // Make 2bit err log info + // + + ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400; + ((pECC2_ERR_AREA_INFO)buf)->size_rec=25; + ((pECC2_ERR_AREA_INFO)buf)->num_rec=4; + ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400; + + ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0; + + HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET, + sizeof(ECC2_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=768+400; i<768+400+25*4; i++) + HalNvramWrite( i, 1, buf); + + // + // Make system err log info + // + + ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280; + ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512; + ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4; + ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280; + + HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET, + sizeof(ECC2_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=1280; i<1280+512*4; i++) + HalNvramWrite( i, 1, buf); + + return(0); +} + diff --git a/private/ntos/nthals/halr96b/mips/esmnvram.h b/private/ntos/nthals/halr96b/mips/esmnvram.h new file mode 100644 index 000000000..2392671e9 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/esmnvram.h @@ -0,0 +1,688 @@ +// #pragma comment(exestr, "@(#) esmnvram.h 1.1 95/09/28 15:32:22 nec") + +/**************************************************************** + ******* Copyright (C) 1994 NEC Corporation ******* + ****************************************************************/ + +/******* + + File Name: + + envram.h + + Abstract: + + This module contains the definitions for the extended NVRAM. + + Author: + + Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994 + + Modification History: + + - M000 12/22/94 - + created. + +*******/ + + + +/******************************************************************************* + ******** NVRAM¡Ê8K¥Ð¥¤¥È¡Ë¤ÎÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤ò°Ê²¼¤Ëµ­½Ò¤¹¤ë¡£ ******** + ******************************************************************************* + * + * S001 11/22/94 + * ¥ì¥³¡¼¥É¤ÎÍ­¸ú/̵¸ú¥Õ¥é¥°¡¢Check̤/ºÑ¥Õ¥é¥°¤ò³Æ¥ì¥³¡¼¥É¤ÎÀèƬ¤Ë¤ª¤¯¤« + * ¤Þ¤È¤á¤Æ¥ì¥³¡¼¥É¥ê¡¼¥¸¥ç¥ó¤ÎÀèƬ¤Ë¤ª¤¯¤«¤Ç¡¢¥ì¥³¡¼¥É¤Î½èÍýÊýË¡¤¬ÊѤï¤Ã¤Æ + * ¤¯¤ë¡£¸å¼Ô¤Ï¥é¥ó¥À¥à¥¢¥¯¥»¥¹¡¢Á°¼Ô¤Ï¥·¡¼¥±¥ó¥·¥ã¥ë¥¢¥¯¥»¥¹¤Ë¤à¤¯¡£ + * º£²ó¤ÏÁ°¼Ô¤òºÎÍÑ¡£ + * + * ¹Ô¤ÎÀèƬ¤Ë¤¢¤ë¿ô»ú¤Ï³ä¤êÅö¤Æ¤ë¥Ð¥¤¥È¿ô¤ò¤¢¤é¤ï¤¹¡£ + * + * ËÜ»ÅÍͤˤ·¤¿¤¬¤Ã¤Æ¹½Â¤ÂΤòºîÀ®Í½Äê¡£ + * + * S002 11/26/94 + * ³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°´ØÏ¢¡¢etc.¡Ë + * ¤ÎÀèƬ¤Î¥Ø¥Ã¥ÀÉô¤òÁ´¤ÆNVRAM¤ÎÀèƬ¤Ë°Ü¤¹¡£NVRAM¤ÎÀèƬ¤Ë¤¢¤ë¥Ø¥Ã¥ÀÆâ¤Ë + * ³ÆÎΰè¤Î¥ì¥³¡¼¥É¤òľÀÜ¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥ª¥Õ¥»¥Ã¥È¤ò¤â¤Ä¤è¤¦¤Ë¤¹¤ë¡£ + * + * NVRAM¤Î¥¢¥¯¥»¥¹»þ¤Ë¤Ï256¥Ð¥¤¥Èñ°Ì¤Ç¥Ð¥ó¥¯Àڤ괹¤¨¤¬¤ª¤³¤Ê¤ï¤ì¤ë¤¿¤á + * ³Æ¥Ç¡¼¥¿¡Ê256¥Ð¥¤¥ÈĹ°Ê²¼¤Î¤â¤Î¡Ë¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤ò¤Þ¤¿¤¬¤é¤Ê¤¤¤è¤¦ + * ¤ËÇÛθ¡£³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢etc.¡Ë¤ÎÀèƬ¤¬É¬¤º256¥Ð¥¤¥È + * ¥Ð¥¦¥ó¥À¥ê¤«¤é³«»Ï¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë¡£ + * + * ECC¥¨¥é¡¼¥í¥°Æâ¤ÎSIMMÆÃÄê²½¾ðÊó¤ò2¥Ð¥¤¥È¤«¤é1¥Ð¥¤¥È¤ØÊѹ¹¡£ + * + * ¡É¥ª¥Õ¥»¥Ã¥È ¡É¤Ï¤¹¤Ù¤ÆNVRAM¤ÎÀèƬ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¡£ + * + * S003 12/13/94 + * NW¥¨¡¼¥¸¥§¥ó¥È¤È¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ò¶¦Ä̲½¤¹¤ë¤¿¤áÀèƬ512¥Ð¥¤¥È¤ò + * ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤È¤·¡¢¥Õ¥©¡¼¥Þ¥Ã¥È¤òNW¥¨¡¼¥¸¥§¥ó¥È¤ÈÅý°ì¤¹¤ë¡£ + * + * STEP1¤Ç¤Ï¥á¥â¥ê½ÌÂà¤ò¹Ô¤ï¤Ê¤¤¤¿¤áËÜ¥¨¥ê¥¢¤Ï»ÈÍѤ·¤Ê¤¤¡£ + * ËÜ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ÏNW¥¨¡¼¥¸¥§¥ó¥È¤È¤Î¶¦Ä̲½¤Î¤¿¤á¤Ë¿·¤¿¤ËÀߤ±¤ë + * ¤â¤Î¤Ç¤¢¤ê¡¢°ÊÁ°¤«¤é¤ÎECC¥¨¥é¡¼¾ðÊóÎΰè¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£ + * + * 512¥Ð¥¤¥È¤Î¥¨¥ê¥¢¤òÀèƬ¤ËÀߤ±¤ë¤¿¤á¡¢°ÊÁ°¤«¤é¤Î¤½¤Î¾Á´¤Æ¤Î¾ðÊóÎΰè¤Ï + * 512¥Ð¥¤¥È¥ª¥Õ¥»¥Ã¥È¤¬Â礭¤¯¤Ê¤ë¤³¤È¤Ë¤Ê¤ë¡£ + * + * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È2¥Ð¥¤¥È¤òÄɲᣠ+ * + * ¥ª¥Õ¥»¥Ã¥È¤ÎºÆ·×»»¡£ + * + * S004 12/14/94 + * ¹½Â¤ÂκîÀ®¡£ + * + * ¡Ç¥Ñ¥Ë¥Ã¥¯ ¡Ç¤ò¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£ + * + * S005 12/23/94 + * 4byte alignment¤Ë¤½¤Ê¤¨¤Æ¥Ñ¥Ç¥£¥ó¥°¤ò°ìÉôÊѹ¹¡£ + * + * ¥¹¥È¥Ã¥×¥¨¥é¡¼¤Î¥Õ¥é¥°¤Î2¥Ó¥Ã¥È¤Ë¿·¤¿¤ËÄêµÁÄɲᣠ+ * + * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤òNVRAM¥Ø¥Ã¥À¤Ë¤È¤ê¤³¤à¡£ + * ¤³¤ì¤Ë¤È¤â¤Ê¤¤¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ÏÉÔÍפȤʤ뤿¤á + * 2¥Ð¥¤¥Èʬ̤»ÈÍѤȤ¹¤ë¡£ + * + * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ë¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤òÄɲá£ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ¤ò + * ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤È¥Õ¥é¥°¤Ç¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¤¹¤ë¡£¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤Ï + * 0xFF651026¤È¤¹¤ë¡£ + * + * ¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ò¡Ç¥·¥¹¥Æ¥à¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£ + * + * S006 12/27/94 + * #pragma pack() ¤òÄɲà + * + * char reserved[49] ¤ò char reserved[49] ¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ïharmless¤Ç¤¢¤ë + * ¤È¿®¤¸¤ë... (^_^; + * + * unsigned short offset_ecc2err ¤ò offset_2biterr¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ï + * harmless¤Ç¤¢¤ë¤È¿®¤¸¤ë... (^_^; + * + ****************************************************************************** + + + ################### + # NVRAM¥Ø¥Ã¥ÀÉô # + ################### + + ###################################################### + # F/WÍÑ¥á¥â¥ê¡¼¥¨¥é¡¼¥¨¥ê¥¢ (NW¥¨¡¼¥¸¥§¥ó¥È¤È¶¦ÄÌ) # + ###################################################### + + 512 ¥á¥â¥ê¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(2¥Ð¥¤¥È) ¡ß 256 + + #################### + # ¥ì¥³¡¼¥É¤ÎÆâÍÆ # + #################### + + ¡¡¡¡1 ¥¹¥Æ¡¼¥¿¥¹ 0:Àµ¾ï 1:°Û¾ï(2bit¥¨¥é¡¼Í­Ìµ) + 1 1bit¥¨¥é¡¼¥«¥¦¥ó¥È + +¡¡¡¡ ###################### + # Á´ÂΤ˴ؤ¹¤ë¤â¤Î # + ###################### + + 1 NVRAM¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥° + + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 NVRAMÁ´ÂÎÍ­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú + ¡¡1 ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ 0:̵ 1:Í­ + ¡¡¡¡2 READ-ONLY 0:NO 1:YES + ¡¡¡¡3 LOCK 0:NO 1:YES + ¡¡¡¡4 [reserved] + ¡¡¡¡5 ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7 ¡¡¡¡¢¬ + 14 NVRAM¤¬¥Õ¥©¡¼¥Þ¥Ã¥È¤µ¤ì¤¿¥¿¥¤¥à¥¹¥¿¥ó¥× + + 3 [ reserved ] + +¡¡¡¡ ############################### + # ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ############################### + + 2 ALIVE¾ðÊóÎΰè¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + +¡¡¡¡ ####################################### + # ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ####################################### + + 2 ECC 1bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + ¡¡ 2 ECC 1bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º + 2 ECC 1bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô + 2 ECC 1bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + 4 °ìÈֺǸå¤ÎECC1bit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿ + ¡¡ 8 ECC 1bit¥¨¥é¡¼¥«¥¦¥ó¥È ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô8 + +¡¡¡¡ ####################################### + # ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ####################################### + + 2 ECC 2bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + ¡¡ 2 ECC 2bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º + 2 ECC 2bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô + 2 ECC 2bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + 4 °ìÈֺǸå¤ÎECCÊ£¿ôbit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿ + 4 SIMM¸ò´¹¥Õ¥é¥° ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô4 + + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 ¥°¥ë¡¼¥×NÆâSIMM #0 (N=1¡Á4) 0:OK 1:NG(Í׸ò´¹) + ¡¡¡¡1 ¥°¥ë¡¼¥×NÆâSIMM #1 ¢¬ + ¡¡¡¡2 ¥°¥ë¡¼¥×NÆâSIMM #2¡¡¡¡ ¢¬ + ¡¡¡¡3 ¥°¥ë¡¼¥×NÆâSIMM #3¡¡¡¡ ¢¬ + ¡¡¡¡4 [reserved] + ¡¡¡¡5 ¢¬ + ¡¡¡¡6 ¢¬ + ¡¡¡¡7¡¡¡¡¡¡¢¬ + 4 [reserved] + +¡¡¡¡ ######################################## + ¡¡¡¡# ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ¡¡¡¡######################################## + + 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + ¡¡ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó1¥ì¥³¡¼¥É¥µ¥¤¥º + 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É¿ô + 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + +¡¡¡¡ ############################################ + ¡¡¡¡# ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Îΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ############################################ + + 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + ¡¡ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º + 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô + 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + +¡¡¡¡ ################################## + ¡¡¡¡# ¤·¤­¤¤Ã;ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ################################## + + 2 ¤·¤­¤¤Ã;ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + +¡¡¡¡ ############################## + ¡¡¡¡# ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î # + ############################## + + 2 ¥ê¥¶¡¼¥ÖÎΰè¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È + + + ######################## + # ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ # + ######################## + +¡¡¡¡¡¡¡¡ 1 ¥·¥¹¥Æ¥à¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥° + + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + 0 [reserved] + ¡¡¡¡1 ¡¡¡¡¢¬ + ¡¡¡¡2 ¡¡¡¡¢¬ + ¡¡¡¡3 ¡¡¡¡¢¬ + ¡¡¡¡4 ¡¡¡¡¢¬ + ¡¡¡¡5 ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7 ¡¡¡¡¢¬ + 3 [reserved] + 32 ¥·¥¹¥Æ¥à¤Î¾ðÊó¡Ê¥·¥¹¥Æ¥à̾¡Ë + 4 ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ + 4 ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ + 4 [reserved] + +----------------------------------------------------------------------------- +TOTAL 640 ¥Ð¥¤¥È + + + ####################################### + # ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ # + ####################################### + + 1 ¸½ºß¤ÎÄÌÊó¥ì¥Ù¥ë + 16 ALIVE°ì¼¡ÄÌÊóÀè + 16 ALIVEÆó¼¡ÄÌÊóÀè + 47 [reserved for pager call] + +----------------------------------------------------------------------------- +TOTAL 80 ¥Ð¥¤¥È + + + ############################################################################## + # ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë # + # 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ # + ############################################################################## + + 48 [reserved] + + + ####################### + # ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô # + ####################### + + 400 1bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 16 + + #################### + # ¥ì¥³¡¼¥É¤ÎÆâÍÆ # + #################### + + 1¡¡¡¡¥Õ¥é¥° + + ¡¡¡¡ ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú + ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ + ¡¡¡¡2 [reserved] + ¡¡¡¡3 ¡¡¡¡¢¬ + ¡¡¡¡4 ¡¡¡¡¢¬ + ¡¡¡¡5 ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7¡¡¡¡ ¡¡¢¬ + ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹ + 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× + 4 ¥·¥ó¥É¥í¡¼¥à + ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥× + 1 SIMMÆÃÄê¾ðÊó + 100 2bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 4 + + #################### + # ¥ì¥³¡¼¥É¤ÎÆâÍÆ # + #################### + + 1 ¥Õ¥é¥° + + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú + ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ + ¡¡¡¡2 [reserved] + ¡¡¡¡3 ¡¡¡¡¢¬ + ¡¡¡¡4 ¡¡¡¡¢¬ + ¡¡¡¡5¡¡ ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7 ¡¡¡¡¢¬ + ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹ + 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× + 4 ¥·¥ó¥É¥í¡¼¥à + ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥× + 1 SIMMÆÃÄê¾ðÊó + +----------------------------------------------------------------------------- +TOTAL 500 ¥Ð¥¤¥È + + + ############################################################################### + # ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë # + # 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ # + ############################################################################### + + 12 [reserved] + + + ########################## + # ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô # + ########################## + + 2048 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô (1¥ì¥³¡¼¥É512¥Ð¥¤¥È ¡ß 4 ¡á 2K) + + #################### + # ¥ì¥³¡¼¥É¤ÎÆâÍÆ # + #################### + + 1 ¥Õ¥é¥° + + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú + ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ + ¡¡¡¡2 Dump/Dump SW 0:D 1:D SW + ¡¡¡¡3 ÄÌÊó¤Î̵ͭ 0:̤ 1:ºÑ + ¡¡¡¡4 boot·ë²Ì 0:Àµ¾ï 1:°Û¾ï + ¡¡¡¡5 ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7 ¡¡¡¡¢¬ + 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× + 496 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó + 1 [reserved] + +----------------------------------------------------------------------------- +TOTAL 2048 ¥Ð¥¤¥È + + + ####################################################### + # ¢¬¤³¤³¤Þ¤Ç3328¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê # + ####################################################### + + + ############################################################### + # ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) # + ############################################################### + + 4096 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) + + #################### + # ¥ì¥³¡¼¥É¤ÎÆâÍÆ # + #################### + + 1 ¥Õ¥é¥° + ################## + # ¥Õ¥é¥°¤ÎÆâÍÆ # + ################## + + ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú + ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ + ¡¡¡¡2 Panic/Shutdown 0:P 1:S + ¡¡¡¡3 [reserved] + ¡¡¡¡4 ¡¡¡¡¢¬ + ¡¡¡¡5 ¡¡¡¡¢¬ + ¡¡¡¡6 ¡¡¡¡¢¬ + ¡¡¡¡7 ¡¡¡¡¢¬ + 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× + 20 ¥½¡¼¥¹Ì¾ + 80 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó + 13 [reserved] + +----------------------------------------------------------------------------- +TOTAL 4096 ¥Ð¥¤¥È + + + ####################################################### + # ¢¬¤³¤³¤Þ¤Ç7424¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê # + ####################################################### + + + ############################## + # ¤·¤­¤¤ÃÍȽÄêÍѥǡ¼¥¿Îΰè # + ############################## + + ¡¡ 256 [reserved] + +----------------------------------------------------------------------------- +TOTAL 256 ¥Ð¥¤¥È + + + ############################################################### + # ¢¬¤³¤³¤Þ¤Ç7680(7K+512)¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê # + ############################################################### + + + ############################## + # ¥ê¥¶¡¼¥ÖÎΰè (512¥Ð¥¤¥È) # + ############################## + + 512 PAiNTSÍÑ? + +----------------------------------------------------------------------------- +TOTAL 512 ¥Ð¥¤¥È + + + ############################################# + # ¢¬¤³¤³¤Þ¤Ç8192(8K)¥Ð¥¤¥È¡£NVRAM¤Î¤·¤Ã¤Ý # + ############################################# + +******************************************************************************/ + + +#pragma pack(1) + +/******************** + * * + * ¡¡¹½Â¤ÂÎÄêµÁ * + * * + ********************/ + + +/* + * WAS & PS¶¦ÄÌFWÍÑ¥á¥â¥ê¥¨¥é¡¼¾ðÊóÎΰè + */ +typedef struct _MEM_ERR_REC { + unsigned char mem_status; /* ¥¹¥Æ¡¼¥¿¥¹ */ + unsigned char err_count; /* 1bit¥¨¥é¡¼¥«¥¦¥ó¥È */ +} MEM_ERR_REC, *pMEM_ERR_REC; + + +/* + * ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _ALIVE_AREA_INFO { + unsigned short offset_alive; + /* ALIVE¾ðÊ󥨥ꥢ¥ª¥Õ¥»¥Ã¥È */ +} ALIVE_AREA_INFO, *pALIVE_AREA_INFO; + + +/* + * ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _ECC1_ERR_AREA_INFO { + unsigned short offset_1biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */ + unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */ + unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */ + unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */ + unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */ + unsigned char err_count_group0; /* ¥á¥â¥êG#0 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group1; /* ¥á¥â¥êG#1 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group2; /* ¥á¥â¥êG#2 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group3; /* ¥á¥â¥êG#3 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group4; /* ¥á¥â¥êG#4 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group5; /* ¥á¥â¥êG#5 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group6; /* ¥á¥â¥êG#6 ¥¨¥é¡¼¥«¥¦¥ó¥È */ + unsigned char err_count_group7; /* ¥á¥â¥êG#7 ¥¨¥é¡¼¥«¥¦¥ó¥È */ +} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO; + + +/* + * ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _ECC2_ERR_AREA_INFO { + unsigned short offset_2biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */ + unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */ + unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */ + unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */ + unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */ + unsigned char simm_flag_group1; /* ¥á¥â¥êG#1ÆâSIMM¥Õ¥é¥° */ + unsigned char simm_flag_group2; /* ¥á¥â¥êG#2ÆâSIMM¥Õ¥é¥° */ + unsigned char simm_flag_group3; /* ¥á¥â¥êG#3ÆâSIMM¥Õ¥é¥° */ + unsigned char simm_flag_group4; /* ¥á¥â¥êG#4ÆâSIMM¥Õ¥é¥° */ + char reserved[4]; /* reserved */ +} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO; + + +/* + * ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _SYSTEM_ERR_AREA_INFO { + unsigned short offset_systemerr;/* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */ + unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */ + unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */ + unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */ +} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO; + + +/* + * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _CRITICAL_ERR_AREA_INFO { + unsigned short offset_critical; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */ + unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */ + unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */ + unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */ +} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO; + + +/* + * ¤·¤­¤¤ÃÍÅù¤½¤Î¾¤Î¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _MISC_AREA_INFO { + unsigned short offset_misc; + /* ¤·¤­¤¤¤ÁÅù¤Î¾ðÊ󥨥ꥢÀèƬ¥ª¥Õ¥»¥Ã¥È */ +} MISC_AREA_INFO, *pMISC_AREA_INFO; + + +/* + * ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î + */ +typedef struct _RESERVE_AREA_INFO { + unsigned short offset_reserve; + /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢ÀèƬ¥ª¥Õ¥»¥Ã¥È */ +} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO; + + +/* + * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ + * 49¥Ð¥¤¥È + */ + +typedef struct _SYS_INFO { + unsigned char system_flag; /* ¥·¥¹¥Æ¥à¾õÂ֥ե饰 */ + char reserved1[3]; /* 4byte alignment¤Ë¤½¤Ê¤¨¤Æ */ + char sys_description[32]; /* ¥·¥¹¥Æ¥à¤Î¾ðÊó */ + unsigned long serical_num; /* ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ */ + unsigned long magic; /* ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ */ + char reserved2[4]; /* reserved */ +} SYS_INFO, *pSYS_INFO; + + + +/* + * NVRAM¥Ø¥Ã¥ÀÉô + * 640¥Ð¥¤¥È + */ + +typedef struct _NVRAM_HEADER { + MEM_ERR_REC mem_err_map[256]; /* ¥á¥â¥ê¥¨¥é¡¼¾ðÊóNT&NW¶¦ÄÌ¥¨¥ê¥¢ */ + unsigned char nvram_flag; /* nvram¤Î¾õÂ֥ե饰 */ + char when_formatted[14]; /* ¥Õ¥©¡¼¥Þ¥Ã¥È¥¿¥¤¥à¥¹¥¿¥ó¥× */ + char reserved[3]; /* 4byte alignment ¤Ë¤½¤Ê¤¨¤Æ */ + ALIVE_AREA_INFO alive; /* ALIVE¾ðÊ󥨥ꥢ */ + ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */ + ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */ + SYSTEM_ERR_AREA_INFO system_err;/* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊ󥨥ꥢ */ + CRITICAL_ERR_AREA_INFO critical_err_log; + /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥¨¥ê¥¢ */ + MISC_AREA_INFO misc; /* ¤·¤­¤¤¤Á¾ðÊ󥨥ꥢ */ + RESERVE_AREA_INFO reserve; /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢¥ª¥Õ¥»¥Ã¥È */ + SYS_INFO system; /* ¥·¥¹¥Æ¥à¾ðÊó */ +} NVRAM_HEADER, *pNVRAM_HEADER; + + + +/* + * ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ + * 80¥Ð¥¤¥È + */ + +typedef struct _ALIVE_INFO { + unsigned char alert_level; /* ÄÌÊó¥ì¥Ù¥ë¥° */ + char primary_destination[16]; /* °ì¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */ + char secondary_destinaiton[16]; /* Æó¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */ + char reserved[47]; /* reserved for pager call */ +} ALIVE_INFO, *pALIVE_INFO; + + +/* + * ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë + * 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ + */ + +char reserved[48]; + + +typedef struct _ECC1_ERR_REC { + unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */ + unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */ + char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */ + unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */ + unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */ + unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */ +} ECC1_ERR_REC, *pECC1_ERR_REC; + + +typedef struct _ECC2_ERR_REC { + unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */ + unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */ + char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */ + unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */ + unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */ + unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */ +} ECC2_ERR_REC, *pECC2_ERR_REC; + + +/* + * ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô + * 500 ¥Ð¥¤¥È + */ + +ECC1_ERR_REC ecc1_err_rec_log[16]; + +ECC2_ERR_REC ecc2_err_rec_log[4]; + + +/* + * ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë + * 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ + */ + +char reserved2[12]; + + +typedef struct _STOP_ERR_REC { + unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */ + char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */ + char err_description[496]; /* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó */ + char reserved[1]; /* reserved */ +} STOP_ERR_REC, *pSTOP_ERR_REC; + +/* + * ¥¹¥Ã¥È¥×¥¨¥é¡¼¾ðÊóÉô + * 2048 ¥Ð¥¤¥È + */ + +STOP_ERR_REC stop_err_rec_log[4]; + + +typedef struct _CRITICAL_ERR_REC { + unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */ + char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */ + char source[14]; /* ¥½¡¼¥¹Ì¾ */ + char err_description[496]; /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó */ + char reserved[13]; /* reserved */ +} CRITICAL_ERR_REC, *pCRITICAL; + + +/* ¡¡ + * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) + * 4096¥Ð¥¤¥È + */ + +CRITICAL_ERR_REC critical_err_rec_log[32]; + + +/* + * ¤·¤­¤¤ÃÍȽÄêÍÑÅù¥Ç¡¼¥¿Îΰè. + * 256¥Ð¥¤¥È + */ + +char reserved3[256]; /* reserved */ + + +/* + * ¥ê¥¶¡¼¥ÖÎΰè(PAiNTSÍÑ?) + * 512¥Ð¥¤¥È + */ + +char reserved4[512]; /* reserved for paints ? */ + +#pragma pack(4) diff --git a/private/ntos/nthals/halr96b/mips/glint.h b/private/ntos/nthals/halr96b/mips/glint.h new file mode 100644 index 000000000..ac8c6e07a --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/glint.h @@ -0,0 +1,580 @@ +// #pragma comment(exestr, "@(#) glint.h 1.1 95/09/28 15:32:57 nec") +/************************************************************************ + * * + * Copyright (c) 1994 3Dlabs Inc. Ltd. * + * All rights reserved * + * * + * This software and its associated documentation contains proprietary, * + * confidential and trade secret information of 3Dlabs Inc. Ltd. and * + * except as provided by written agreement with 3Dlabs Inc. Ltd. * + * * + * a) no part may be disclosed, distributed, reproduced, transmitted, * + * transcribed, stored in a retrieval system, adapted or translated * + * in any form or by any means electronic, mechanical, magnetic, * + * optical, chemical, manual or otherwise, * + * * + * and * + * * + * b) the recipient is not entitled to discover through reverse * + * engineering or reverse compiling or other such techniques or * + * processes the trade secrets contained therein or in the * + * documentation. * + * * + ************************************************************************/ + +#ifndef __GLINT_H__ +#define __GLINT_H__ + +typedef unsigned long DWORD; + +/************************************************************************/ +/* PCI CONFIGURATION REGION */ +/************************************************************************/ + +#define __GLINT_CFGVendorId PCI_CS_VENDOR_ID +#define __GLINT_CFGDeviceId PCI_CS_DEVICE_ID +#define __GLINT_CFGRevisionId PCI_CS_REVISION_ID +#define __GLINT_CFGClassCode PCI_CS_CLASS_CODE +#define __GLINT_CFGHeaderType PCI_CS_HEADER_TYPE +#define __GLINT_CFGCommand PCI_CS_COMMAND +#define __GLINT_CFGStatus PCI_CS_STATUS +#define __GLINT_CFGBist PCI_CS_BIST +#define __GLINT_CFGLatTimer PCI_CS_MASTER_LATENCY +#define __GLINT_CFGCacheLine PCI_CS_CACHE_LINE_SIZE +#define __GLINT_CFGMaxLat PCI_CS_MAX_LAT +#define __GLINT_CFGMinGrant PCI_CS_MIN_GNT +#define __GLINT_CFGIntPin PCI_CS_INTERRUPT_PIN +#define __GLINT_CFGIntLine PCI_CS_INTERRUPT_LINE + +#define __GLINT_CFGBaseAddr0 PCI_CS_BASE_ADDRESS_0 +#define __GLINT_CFGBaseAddr1 PCI_CS_BASE_ADDRESS_1 +#define __GLINT_CFGBaseAddr2 PCI_CS_BASE_ADDRESS_2 +#define __GLINT_CFGBaseAddr3 PCI_CS_BASE_ADDRESS_3 +#define __GLINT_CFGBaseAddr4 PCI_CS_BASE_ADDRESS_4 +#define __GLINT_CFGRomAddr PCI_CS_EXPANSION_ROM + +/* CFGVendorId[15:0] - 3Dlabs Vendor ID Value */ + +#define GLINT_VENDOR_ID (0x3D3D) + +/* CFGDeviceId[15:0] - GLINT 300SX Device ID */ + +#define GLINT_DEVICE_ID (0x0001) + +/* CFGRevisionID[7:0] - GLINT Revision Code */ + +#define GLINT_REVISION_A (0x00) +#define GLINT_REVISION_B (0x01) + +/* CFGClassCode[23:0] - Other Display Controller */ + +#define GLINT_CLASS_CODE ((DWORD) 0x00038000) + +/* CFGHeaderType[7:0] - Single Function Device */ + +#define GLINT_HEADER_TYPE (0x00) + +/* CFGCommand[15:0] - Reset Value Zero */ + +#define GLINT_COMMAND_RESET_VALUE (0x0000) + +/* CFGCommand[1] - Memory Access Enable */ + +#define GLINT_MEMORY_ACCESS_MASK (1 << 0) +#define GLINT_MEMORY_ACCESS_DISABLE (0 << 0) +#define GLINT_MEMORY_ACCESS_ENABLE (1 << 1) + +/* CFGCommand[2] - Master Enable */ + +#define GLINT_MASTER_ENABLE_MASK (1 << 2) +#define GLINT_MASTER_DISABLE (0 << 2) +#define GLINT_MASTER_ENABLE (1 << 2) + +/* CFGStatus[15:0] - Reset Value Zero */ + +#define GLINT_STATUS_RESET_VALUE (0x0000) + +/* CFGBist - Built In Self Test Unsupported */ + +#define GLINT_BIST (0x00) + +/* CFGCacheLine - Cache Line Size Unsupported */ + +#define GLINT_CACHE_LINE (0x00) + +/* CFGIntPin - Interrupt Pin INTA# */ + +#define GLINT_INTERRUPT_PIN (0x01) + +/********************/ + +#define GLINT_CONTROL_BASE __GLINT_CFGBaseAddr0 +#define GLINT_LOCAL_0_BASE __GLINT_CFGBaseAddr1 +#define GLINT_FRAME_0_BASE __GLINT_CFGBaseAddr2 +#define GLINT_LOCAL_1_BASE __GLINT_CFGBaseAddr3 +#define GLINT_FRAME_1_BASE __GLINT_CFGBaseAddr4 +#define GLINT_EPROM_BASE __GLINT_CFGRomAddr + +#define GLINT_EPROM_SIZE ((DWORD)(64L * 1024L)) + +/************************************************************************/ +/* CONTROL AND STATUS REGISTERS */ +/************************************************************************/ + +#define GLINT_REGION_0_SIZE ((DWORD)(128L * 1024L)) + +#define __GLINT_ResetStatus 0x0000 +#define __GLINT_IntEnable 0x0008 +#define __GLINT_IntFlags 0x0010 +#define __GLINT_InFIFOSpace 0x0018 +#define __GLINT_OutFIFOWords 0x0020 +#define __GLINT_DMAAddress 0x0028 +#define __GLINT_DMACount 0x0030 +#define __GLINT_ErrorFlags 0x0038 +#define __GLINT_VClkCtl 0x0040 +#define __GLINT_TestRegister 0x0048 +#define __GLINT_Aperture0 0x0050 +#define __GLINT_Aperture1 0x0058 +#define __GLINT_DMAControl 0x0060 + +/* ResetStatus[31] - Software Reset Flag */ + +#define GLINT_RESET_STATUS_MASK ((DWORD) 1 << 31) +#define GLINT_READY_FOR_USE ((DWORD) 0 << 31) +#define GLINT_RESET_IN_PROGRESS ((DWORD) 1 << 31) + +/* IntEnable[4:0] - Interrupt Enable Register */ + +#define GLINT_INT_ENABLE_DMA ((DWORD) 1 << 0) +#define GLINT_INT_ENABLE_SYNC ((DWORD) 1 << 1) +#define GLINT_INT_ENABLE_EXTERNAL ((DWORD) 1 << 2) +#define GLINT_INT_ENABLE_ERROR ((DWORD) 1 << 3) +#define GLINT_INT_ENABLE_VERTICAL ((DWORD) 1 << 4) + +/* IntFlags[4:0] - Interrupt Flags Register */ + +#define GLINT_INT_FLAG_DMA ((DWORD) 1 << 0) +#define GLINT_INT_FLAG_SYNC ((DWORD) 1 << 1) +#define GLINT_INT_FLAG_EXTERNAL ((DWORD) 1 << 2) +#define GLINT_INT_FLAG_ERROR ((DWORD) 1 << 3) +#define GLINT_INT_FLAG_VERTICAL ((DWORD) 1 << 4) + +/* ErrorFlags[2:0] - Error Flags Register */ + +#define GLINT_ERROR_INPUT_FIFO ((DWORD) 1 << 0) +#define GLINT_ERROR_OUTPUT_FIFO ((DWORD) 1 << 1) +#define GLINT_ERROR_COMMAND ((DWORD) 1 << 2) + +/* ApertureX[1:0] - Framebuffer Byte Control */ + +#define GLINT_FB_BYTE_CONTROL_MASK ((DWORD) 3 << 0) +#define GLINT_FB_LITTLE_ENDIAN ((DWORD) 0 << 0) +#define GLINT_FB_BIG_ENDIAN ((DWORD) 1 << 0) +#define GLINT_FB_GIB_ENDIAN ((DWORD) 2 << 0) +#define GLINT_FB_BYTE_RESERVED ((DWORD) 3 << 0) + +/* ApertureX[2] - Localbuffer Byte Control */ + +#define GLINT_LB_BYTE_CONTROL_MASK ((DWORD) 1 << 2) +#define GLINT_LB_LITTLE_ENDIAN ((DWORD) 0 << 2) +#define GLINT_LB_BIG_ENDIAN ((DWORD) 1 << 2) + +/* DMAControl[0] - DMA Byte Swap Control */ + +#define GLINT_DMA_CONTROL_MASK ((DWORD) 1 << 0) +#define GLINT_DMA_LITTLE_ENDIAN ((DWORD) 0 << 0) +#define GLINT_DMA_BIG_ENDIAN ((DWORD) 1 << 0) + +/************************************************************************/ +/* LOCALBUFFER REGISTERS */ +/************************************************************************/ + +#define __GLINT_LBMemoryCtl 0x1000 + +/* LBMemoryCtl[0] - Number of Localbuffer Banks */ + +#define GLINT_LB_BANK_MASK ((DWORD) 1 << 0) +#define GLINT_LB_ONE_BANK ((DWORD) 0 << 0) +#define GLINT_LB_TWO_BANKS ((DWORD) 1 << 0) + +/* LBMemoryCtl[2:1] - Localbuffer Page Size */ + +#define GLINT_LB_PAGE_SIZE_MASK ((DWORD) 2 << 1) +#define GLINT_LB_PAGE_SIZE_256_PIXELS ((DWORD) 0 << 1) +#define GLINT_LB_PAGE_SIZE_512_PIXELS ((DWORD) 1 << 1) +#define GLINT_LB_PAGE_SIZE_1024_PIXELS ((DWORD) 2 << 1) +#define GLINT_LB_PAGE_SIZE_2048_PIXELS ((DWORD) 3 << 1) + +/* LBMemoryCtl[4:3] - Localbuffer RAS-CAS Low */ + +#define GLINT_LB_RAS_CAS_LOW_MASK ((DWORD) 3 << 3) +#define GLINT_LB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 3) +#define GLINT_LB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 3) +#define GLINT_LB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 3) +#define GLINT_LB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 3) + +/* LBMemoryCtl[6:5] - Localbuffer RAS Precharge */ + +#define GLINT_LB_RAS_PRECHARGE_MASK ((DWORD) 3 << 5) +#define GLINT_LB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 5) +#define GLINT_LB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 5) +#define GLINT_LB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 5) +#define GLINT_LB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 5) + +/* LBMemoryCtl[8:7] - Localbuffer CAS Low */ + +#define GLINT_LB_CAS_LOW_MASK ((DWORD) 3 << 7) +#define GLINT_LB_CAS_LOW_1_CLOCK ((DWORD) 0 << 7) +#define GLINT_LB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 7) +#define GLINT_LB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 7) +#define GLINT_LB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 7) + +/* LBMemoryCtl[9] - Localbuffer Page Mode Disable */ + +#define GLINT_LB_PAGE_MODE_MASK ((DWORD) 1 << 9) +#define GLINT_LB_PAGE_MODE_ENABLE ((DWORD) 0 << 9) +#define GLINT_LB_PAGE_MODE_DISABLE ((DWORD) 1 << 9) + +/* LBMemoryCtl[17:10] - Localbuffer Refresh Count */ + +#define GLINT_LB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 10) +#define GLINT_LB_REFRESH_COUNT_SHIFT (10) + +#define GLINT_LB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 10) + +/* LBMemoryCtl[18] - Localbuffer Dual Write Enables */ + +#define GLINT_LB_MEM_TYPE_MASK ((DWORD) 1 << 18) +#define GLINT_LB_MEM_DUAL_CAS ((DWORD) 0 << 18) +#define GLINT_LB_MEM_DUAL_WE ((DWORD) 1 << 18) + +/* LBMemoryCtl[21:20] - PCI Maximum Latency - Read Only */ + +#define GLINT_PCI_MAX_LATENCY_MASK ((DWORD) 3 << 20) +#define GLINT_PCI_MAX_LATENCY_SHIFT (20) + +/* LBMemoryCtl[23:22] - PCI Minimum Grant - Read Only */ + +#define GLINT_PCI_MIN_GRANT_MASK ((DWORD) 3 << 22) +#define GLINT_PCI_MIN_GRANT_SHIFT (22) + +/* LBMemoryCtl[26:24] - Localbuffer Visible Region Size - Read Only */ + +#define GLINT_LB_REGION_SIZE_MASK ((DWORD) 7 << 24) +#define GLINT_LB_REGION_SIZE_1_MB ((DWORD) 0 << 24) +#define GLINT_LB_REGION_SIZE_2_MB ((DWORD) 1 << 24) +#define GLINT_LB_REGION_SIZE_4_MB ((DWORD) 2 << 24) +#define GLINT_LB_REGION_SIZE_8_MB ((DWORD) 3 << 24) +#define GLINT_LB_REGION_SIZE_16_MB ((DWORD) 4 << 24) +#define GLINT_LB_REGION_SIZE_32_MB ((DWORD) 5 << 24) +#define GLINT_LB_REGION_SIZE_64_MB ((DWORD) 6 << 24) +#define GLINT_LB_REGION_SIZE_0_MB ((DWORD) 7 << 24) + +/* LBMemoryCtl[29:27] - Localbuffer Width - Read Only */ + +#define GLINT_LB_WIDTH_MASK ((DWORD) 7 << 27) +#define GLINT_LB_WIDTH_16_BITS ((DWORD) 0 << 27) +#define GLINT_LB_WIDTH_18_BITS ((DWORD) 1 << 27) +#define GLINT_LB_WIDTH_24_BITS ((DWORD) 2 << 27) +#define GLINT_LB_WIDTH_32_BITS ((DWORD) 3 << 27) +#define GLINT_LB_WIDTH_36_BITS ((DWORD) 4 << 27) +#define GLINT_LB_WIDTH_40_BITS ((DWORD) 5 << 27) +#define GLINT_LB_WIDTH_48_BITS ((DWORD) 6 << 27) +#define GLINT_LB_WIDTH_OTHER ((DWORD) 7 << 27) + +/* LBMemoryCtl[30] - Localbuffer Bypass Packing - Read Only */ + +#define GLINT_LB_BYPASS_STEP_MASK ((DWORD) 1 << 30) +#define GLINT_LB_BYPASS_STEP_64_BITS ((DWORD) 0 << 30) +#define GLINT_LB_BYPASS_STEP_32_BITS ((DWORD) 1 << 30) + +/* LBMemoryCtl[31] - Localbuffer Aperture One Enable - Read Only */ + +#define GLINT_LB_APERTURE_ONE_MASK ((DWORD) 1 << 31) +#define GLINT_LB_APERTURE_ONE_DISABLE ((DWORD) 0 << 31) +#define GLINT_LB_APERTURE_ONE_ENABLE ((DWORD) 1 << 31) + +/************************************************************************/ +/* FRAMEBUFFER REGISTERS */ +/************************************************************************/ + +#define __GLINT_FBMemoryCtl 0x1800 +#define __GLINT_FBModeSel 0x1808 +#define __GLINT_FBGCWrMask 0x1810 +#define __GLINT_FBGCColorMask 0x1818 + +/* FBMemoryCtl[1:0] - Framebuffer RAS-CAS Low */ + +#define GLINT_FB_RAS_CAS_LOW_MASK ((DWORD) 3 << 0) +#define GLINT_FB_RAS_CAS_LOW_2_CLOCKS ((DWORD) 0 << 0) +#define GLINT_FB_RAS_CAS_LOW_3_CLOCKS ((DWORD) 1 << 0) +#define GLINT_FB_RAS_CAS_LOW_4_CLOCKS ((DWORD) 2 << 0) +#define GLINT_FB_RAS_CAS_LOW_5_CLOCKS ((DWORD) 3 << 0) + +/* FBMemoryCtl[3:2] - Framebuffer RAS Precharge */ + +#define GLINT_FB_RAS_PRECHARGE_MASK ((DWORD) 3 << 2) +#define GLINT_FB_RAS_PRECHARGE_2_CLOCKS ((DWORD) 0 << 2) +#define GLINT_FB_RAS_PRECHARGE_3_CLOCKS ((DWORD) 1 << 2) +#define GLINT_FB_RAS_PRECHARGE_4_CLOCKS ((DWORD) 2 << 2) +#define GLINT_FB_RAS_PRECHARGE_5_CLOCKS ((DWORD) 3 << 2) + +/* FBMemoryCtl[5:4] - Framebuffer CAS Low */ + +#define GLINT_FB_CAS_LOW_MASK ((DWORD) 3 << 4) +#define GLINT_FB_CAS_LOW_1_CLOCK ((DWORD) 0 << 4) +#define GLINT_FB_CAS_LOW_2_CLOCKS ((DWORD) 1 << 4) +#define GLINT_FB_CAS_LOW_3_CLOCKS ((DWORD) 2 << 4) +#define GLINT_FB_CAS_LOW_4_CLOCKS ((DWORD) 3 << 4) + +/* FBMemoryCtl[13:6] - Framebuffer Refresh Count */ + +#define GLINT_FB_REFRESH_COUNT_MASK ((DWORD) 0xFF << 6) +#define GLINT_FB_REFRESH_COUNT_SHIFT (6) + +#define GLINT_FB_REFRESH_COUNT_DEFAULT ((DWORD) 0x20 << 6) + +/* FBMemoryCtl[14] - Framebuffer Page Mode Disable */ + +#define GLINT_FB_PAGE_MODE_MASK ((DWORD) 1 << 14) +#define GLINT_FB_PAGE_MODE_ENABLE ((DWORD) 0 << 14) +#define GLINT_FB_PAGE_MODE_DISABLE ((DWORD) 1 << 14) + +/* FBMemoryCtl[25:20] - Reserved - Read Only */ + +#define GLINT_FB_CTL_RESERVED_MASK ((DWORD) 0x3F << 20) +#define GLINT_FB_CTL_RESERVED_SHIFT (20) + +/* FBMemoryCtl[26] - Byte Swap Configuration Space - Read Only */ + +#define GLINT_BYTE_SWAP_CONFIG_MASK ((DWORD) 1 << 26) +#define GLINT_BYTE_SWAP_CONFIG_DISABLE ((DWORD) 0 << 26) +#define GLINT_BYTE_SWAP_CONFIG_ENABLE ((DWORD) 1 << 26) + +/* FBMemoryCtl[28] - Framebuffer Aperture One Enable - Read Only */ + +#define GLINT_FB_APERTURE_ONE_MASK ((DWORD) 1 << 28) +#define GLINT_FB_APERTURE_ONE_DISABLE ((DWORD) 0 << 28) +#define GLINT_FB_APERTURE_ONE_ENABLE ((DWORD) 1 << 28) + +/* FBMemoryCtl[31:29] - Framebuffer Visible Region Size - Read Only */ + +#define GLINT_FB_REGION_SIZE_MASK ((DWORD) 7 << 29) +#define GLINT_FB_REGION_SIZE_1_MB ((DWORD) 0 << 29) +#define GLINT_FB_REGION_SIZE_2_MB ((DWORD) 1 << 29) +#define GLINT_FB_REGION_SIZE_4_MB ((DWORD) 2 << 29) +#define GLINT_FB_REGION_SIZE_8_MB ((DWORD) 3 << 29) +#define GLINT_FB_REGION_SIZE_16_MB ((DWORD) 4 << 29) +#define GLINT_FB_REGION_SIZE_32_MB ((DWORD) 5 << 29) +#define GLINT_FB_REGION_SIZE_RESERVED ((DWORD) 6 << 29) +#define GLINT_FB_REGION_SIZE_0_MB ((DWORD) 7 << 29) + +/* FBModeSel[0] - Framebuffer Width */ + +#define GLINT_FB_WIDTH_MASK ((DWORD) 1 << 0) +#define GLINT_FB_WIDTH_32_BITS ((DWORD) 0 << 0) +#define GLINT_FB_WIDTH_64_BITS ((DWORD) 1 << 0) + +/* FBModeSel[2:1] - Framebuffer Packing */ + +#define GLINT_FB_PACKING_MASK ((DWORD) 2 << 1) +#define GLINT_FB_PACKING_32_BITS ((DWORD) 0 << 1) +#define GLINT_FB_PACKING_16_BITS ((DWORD) 1 << 1) +#define GLINT_FB_PACKING_8_BITS ((DWORD) 2 << 1) +#define GLINT_FB_PACKING_RESERVED ((DWORD) 3 << 1) + +/* FBModeSel[3] - Fast Mode Disable */ + +#define GLINT_FB_FAST_MODE_MASK ((DWORD) 1 << 3) +#define GLINT_FB_FAST_MODE_ENABLE ((DWORD) 0 << 3) +#define GLINT_FB_FAST_MODE_DISABLE ((DWORD) 1 << 3) + +/* FBModeSel[5:4] - Shared Framebuffer Mode - Read Only */ + +#define GLINT_SFB_MODE_MASK ((DWORD) 3 << 4) +#define GLINT_SFB_DISABLED ((DWORD) 0 << 4) +#define GLINT_SFB_ARBITER ((DWORD) 1 << 4) +#define GLINT_SFB_REQUESTER ((DWORD) 2 << 4) +#define GLINT_SFB_RESERVED ((DWORD) 3 << 4) + +/* FBModeSel[6] - Transfer Disable */ + +#define GLINT_TRANSFER_MODE_MASK ((DWORD) 1 << 6) +#define GLINT_TRANSFER_ENABLE ((DWORD) 0 << 6) +#define GLINT_TRANSFER_DISABLE ((DWORD) 1 << 6) + +/* FBModeSel[7] - External VTG Select */ + +#define GLINT_VTG_SELECT_MASK ((DWORD) 1 << 7) +#define GLINT_INTERNAL_VTG ((DWORD) 0 << 7) +#define GLINT_EXTERNAL_VTG ((DWORD) 1 << 7) + +/* FBModeSel[9:8] - Framebuffer Interleave */ + +#define GLINT_FB_INTERLEAVE_MASK ((DWORD) 3 << 8) +#define GLINT_FB_INTERLEAVE_1_WAY ((DWORD) 0 << 8) +#define GLINT_FB_INTERLEAVE_2_WAY ((DWORD) 1 << 8) +#define GLINT_FB_INTERLEAVE_4_WAY ((DWORD) 2 << 8) +#define GLINT_FB_INTERLEAVE_8_WAY ((DWORD) 3 << 8) + +/* FBModeSel[11:10] - Framebuffer Block Fill Size */ + +#define GLINT_FB_BLOCK_FILL_SIZE_MASK ((DWORD) 3 << 10) +#define GLINT_FB_BLOCK_FILL_UNSUPPORTED ((DWORD) 0 << 10) +#define GLINT_FB_BLOCK_FILL_4_PIXEL ((DWORD) 1 << 10) +#define GLINT_FB_BLOCK_FILL_8_PIXEL ((DWORD) 2 << 10) +#define GLINT_FB_BLOCK_FILL_RESERVED ((DWORD) 3 << 10) + +/* FBModeSel[12] - Framebuffer Dual Write Enables */ + +#define GLINT_FB_MEM_TYPE_MASK ((DWORD) 1 << 12) +#define GLINT_FB_MEM_DUAL_CAS ((DWORD) 0 << 12) +#define GLINT_FB_MEM_DUAL_WE ((DWORD) 1 << 12) + +/************************************************************************/ +/* INTERNAL VIDEO TIMING GENERATOR REGISTERS */ +/************************************************************************/ + +#define __GLINT_VTGHLimit 0x3000 +#define __GLINT_VTGHSyncStart 0x3008 +#define __GLINT_VTGHSyncEnd 0x3010 +#define __GLINT_VTGHBlankEnd 0x3018 +#define __GLINT_VTGVLimit 0x3020 +#define __GLINT_VTGVSyncStart 0x3028 +#define __GLINT_VTGVSyncEnd 0x3030 +#define __GLINT_VTGVBlankEnd 0x3038 +#define __GLINT_VTGHGateStart 0x3040 +#define __GLINT_VTGHGateEnd 0x3048 +#define __GLINT_VTGVGateStart 0x3050 +#define __GLINT_VTGVGateEnd 0x3058 +#define __GLINT_VTGPolarity 0x3060 +#define __GLINT_VTGFrameRowAddr 0x3068 +#define __GLINT_VTGVLineNumber 0x3070 +#define __GLINT_VTGSerialClk 0x3078 + +/* VTGPolarity[1:0] - HSync Ctl */ + +#define GLINT_HSYNC_POLARITY_MASK ((DWORD) 3 << 0) +#define GLINT_HSYNC_ACTIVE_HIGH ((DWORD) 0 << 0) +#define GLINT_HSYNC_FORCED_HIGH ((DWORD) 1 << 0) +#define GLINT_HSYNC_ACTIVE_LOW ((DWORD) 2 << 0) +#define GLINT_HSYNC_FORCED_LOW ((DWORD) 3 << 0) + +/* VTGPolarity[3:2] - Vsync Ctl */ + +#define GLINT_VSYNC_POLARITY_MASK ((DWORD) 3 << 2) +#define GLINT_VSYNC_ACTIVE_HIGH ((DWORD) 0 << 2) +#define GLINT_VSYNC_FORCED_HIGH ((DWORD) 1 << 2) +#define GLINT_VSYNC_ACTIVE_LOW ((DWORD) 2 << 2) +#define GLINT_VSYNC_FORCED_LOW ((DWORD) 3 << 2) + +/* VTGPolarity[5:4] - Csync Ctl */ + +#define GLINT_CSYNC_POLARITY_MASK ((DWORD) 3 << 4) +#define GLINT_CSYNC_ACTIVE_HIGH ((DWORD) 0 << 4) +#define GLINT_CSYNC_FORCED_HIGH ((DWORD) 1 << 4) +#define GLINT_CSYNC_ACTIVE_LOW ((DWORD) 2 << 4) +#define GLINT_CSYNC_FORCED_LOW ((DWORD) 3 << 4) + +/* VTGPolarity[7:6] - CBlank Ctl */ + +#define GLINT_CBLANK_POLARITY_MASK ((DWORD) 3 << 6) +#define GLINT_CBLANK_ACTIVE_HIGH ((DWORD) 0 << 6) +#define GLINT_CBLANK_FORCED_HIGH ((DWORD) 1 << 6) +#define GLINT_CBLANK_ACTIVE_LOW ((DWORD) 2 << 6) +#define GLINT_CBLANK_FORCED_LOW ((DWORD) 3 << 6) + +/* VTGSerialClk[0] - QSF Select */ + +#define GLINT_QSF_SELECT_MASK ((DWORD) 1 << 0) +#define GLINT_EXTERNAL_QSF ((DWORD) 0 << 0) +#define GLINT_INTERNAL_QSF ((DWORD) 1 << 0) + +/* VTGSerialClk[1] - Split Size */ + +#define GLINT_SPLIT_SIZE_MASK ((DWORD) 1 << 1) +#define GLINT_SPLIT_SIZE_128_WORD ((DWORD) 0 << 1) +#define GLINT_SPLIT_SIZE_256_WORD ((DWORD) 1 << 1) + +/* VTGSerialClk[2] - SCLK Ctl */ + +#define GLINT_SCLK_CTL_MASK ((DWORD) 1 << 2) +#define GLINT_SCLK_VCLK ((DWORD) 0 << 2) +#define GLINT_SCLK_VCLK_DIV_2 ((DWORD) 1 << 2) + +/* VTGSerialClk[3] - SOE Ctl */ + +#define GLINT_SOE_CTL_MASK ((DWORD) 1 << 3) +#define GLINT_SOE_0_ASSERTED ((DWORD) 0 << 3) +#define GLINT_SOE_1_ASSERTED ((DWORD) 1 << 3) + +/************************************************************************/ +/* EXTERNAL VIDEO CONTROL REGISTERS */ +/************************************************************************/ + +#define __GLINT_ExternalVideoControl 0x4000 + +/************************************************************************/ +/* GRAPHICS CORE REGISTERS AND FIFO INTERFACE */ +/************************************************************************/ + +#define __GLINT_GraphicsCoreRegisters 0x8000 + +#define __GLINT_GraphicsFIFOInterface 0x2000 + +/************************************************************************/ +/* GLINT ACCESS MACROS */ +/************************************************************************/ + +#define GLINT_ADDR(base, offset) \ +( \ +/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \ + (DWORD) ((volatile UCHAR *)(base) + (offset)) \ +) + +#define GLINT_WRITE(base, offset, data) \ +{ \ +/* DWORD_WRITE(GLINT_ADDR((base),(offset)), (data)); */ \ + WRITE_REGISTER_ULONG(GLINT_ADDR((base),(offset)), (ULONG)(data)); \ +} + +#define GLINT_READ(base, offset, data) \ +{ \ +/* DWORD_READ(GLINT_ADDR((base),(offset)), (data)); */ \ + (ULONG)(data) = READ_REGISTER_ULONG(GLINT_ADDR((base),(ULONG)(offset))); \ +} + +typedef struct +{ + /* image size */ + + long ImageWidth; + long ImageHeight; + long ImageDepth; + + /* video timing */ + + DWORD HLimit; + DWORD HSyncStart; + DWORD HSyncEnd; + DWORD HBlankEnd; + DWORD HSyncPolarity; + DWORD VLimit; + DWORD VSyncStart; + DWORD VSyncEnd; + DWORD VBlankEnd; + DWORD VSyncPolarity; + + /* Ramdac config */ + + DWORD PixelFormat; + DWORD RefDivCount; + DWORD PixelClock; + + } __VIDEO, *VIDEO; + +/************************************************************************/ + +#endif /* __GLINT_H__ */ + +/************************************************************************/ diff --git a/private/ntos/nthals/halr96b/mips/halp.h b/private/ntos/nthals/halr96b/mips/halp.h new file mode 100644 index 000000000..13a1b58e0 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/halp.h @@ -0,0 +1,365 @@ +// #pragma comment(exestr, "@(#) halp.h 1.1 95/09/28 15:33:24 nec") +/*++ BUILD Version: 0003 // Increment this if a change has global effects + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + halp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + interfaces. + +Author: + + David N. Cutler (davec) 25-Apr-1991 + + +Revision History: + + L0001 1994.9.20 kbnes!kuriyama(A) + -Modify for R94A original halfxs\mips\halp.h + -add #include"r94axxx.h " + L0002 Thu Oct 13 18:09:33 JST 1994 kbnes!kuriyama(A) + - Del HalpDisplayLED + - Del HalpLEDDisplayLock + - Del HalpLEDControlBase + - Add READ_REGISTER_DWORD + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:31:21 JST 1994 + - add data definitions for HalReportResourceUsage + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:15:11 JST 1994 + - resolve compile error + ADD002 kisimoto@oa2.kb.nec.co.jp Fri Nov 25 15:46:03 1994 + add HalpGetStatusRegister() definition + S0003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 16:51:00 JST 1995 + add _IPI_LIMIT_ support + H0004 kisimoto@oa2.kb.nec.co.jp Sun Jun 25 14:39:38 1995 + - Merge build 1057 + H0005 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 20:03:30 1995 + - Merge code for ESM from J94C + H0006 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:23:03 1995 + - Removed _J94C_ definitions. + _J94C_ definition indicates that the status of + the dump switch can acknowledge from Self-test + register. + S0007 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 20:18:18 JST 1995 + - change for x86bios support + H0008 kisimoto@oa2.kb.nec.co.jp Wed Aug 30 12:23:36 1995 + - add spinlock to support PCI Fast Back-to-back transfer. + +--*/ + +#ifndef _HALP_ +#define _HALP_ + +#if defined(NT_UP) + +#undef NT_UP + +#endif + +#include "nthal.h" +#include "hal.h" // H0004 + +#ifndef _HALI_ // H0004 +#include "..\inc\hali.h" +#endif + +#if defined(_DUO_) + +#if defined(_R94A_) + +#include "r94adma.h" +#include "r94adef.h" +#include "r94aint.h" + +#else // _R94A_ + +#include "duodma.h" +#include "duodef.h" +#include "duoint.h" + +#endif // _R94A_ + +#endif + +#if defined(_JAZZ_) + +#include "jazzdma.h" +#include "jazzdef.h" +#include "jazzint.h" + +#endif + +#include "jxhalp.h" + +#if defined(USE_BIOS_EMULATOR) // H0004 + +#include "xm86.h" +#include "x86new.h" + +#endif + + +// +// Define function prototypes. +// + +PADAPTER_OBJECT +HalpAllocateAdapter( + IN ULONG MapRegistersPerChannel, + IN PVOID AdapterBaseVa, + IN PVOID MapRegisterBase + ); + +ULONG +HalpAllocateTbEntry ( + VOID + ); + +VOID +HalpFreeTbEntry ( + VOID + ); + +VOID +HalpCacheErrorRoutine ( + VOID + ); + +BOOLEAN +HalpCalibrateStall ( + VOID + ); + +VOID +HalpClockInterrupt0 ( + VOID + ); + +VOID +HalpClockInterrupt1 ( + VOID + ); + +BOOLEAN +HalpCreateDmaStructures ( + VOID + ); + +BOOLEAN +HalpDmaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +BOOLEAN +HalpInitializeDisplay0 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +BOOLEAN +HalpInitializeDisplay1 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ); + +VOID +HalpIpiInterrupt ( + VOID + ); + +BOOLEAN +HalpMapFixedTbEntries ( + VOID + ); + +BOOLEAN +HalpMapIoSpace ( + VOID + ); + +VOID +HalpProfileInterrupt ( + VOID + ); + +#if defined(R4000) + +ULONG +HalpReadCountRegister ( + VOID + ); + +ULONG +HalpWriteCompareRegisterAndClear ( + IN ULONG Value + ); + +#endif + +VOID +HalpStallInterrupt ( + VOID + ); + +// S0007 +// change prototype HalpInitializeX86DisplayAdapter() + +BOOLEAN +HalpInitializeX86DisplayAdapter( + VOID + ); + +VOID +HalpResetX86DisplayAdapter( + VOID + ); + +#if defined(_R94A_) +VOID +READ_REGISTER_DWORD( + PLARGE_INTEGER, + PVOID + ); + +VOID +WRITE_REGISTER_DWORD( + PLARGE_INTEGER, + PVOID + ); + +VOID +HalpGetStatusRegister ( + IN PULONG Variable + ); + +BOOLEAN +HalNvramWrite( + ULONG Offset, + ULONG Count, + PVOID Buffer +); + +BOOLEAN +HalNvramRead( + ULONG Offset, + ULONG Count, + PVOID Buffer +); + +BOOLEAN +HalpNvramReadWrite( + ULONG Offset, + ULONG Count, + PVOID Buffer, + ULONG Write +); +#endif + +// +// Define external references. +// + +extern KSPIN_LOCK HalpBeepLock; +extern USHORT HalpBuiltinInterruptEnable; +extern ULONG HalpCurrentTimeIncrement; +extern KSPIN_LOCK HalpDisplayAdapterLock; +extern KAFFINITY HalpEisaBusAffinity; +extern ULONG HalpNextIntervalCount; +extern ULONG HalpNextTimeIncrement; +extern ULONG HalpNewTimeIncrement; +extern ULONG HalpProfileCountRate; +extern ULONG HalpStallScaleFactor; +extern KSPIN_LOCK HalpSystemInterruptLock; +#if defined(_IPI_LIMIT_) +extern KSPIN_LOCK HalpIpiRequestLock; +#endif //_IPI_LIMIT_ +extern KSPIN_LOCK Ecc1bitDisableLock;// H005 +extern KSPIN_LOCK Ecc1bitRoutineLock;// H005 +extern KSPIN_LOCK HalpPCIBackToBackLock; // H008 + + +// ADD001 +// +// Resource usage information +// + +#if !defined (_R94A_) +#pragma pack(1) +#endif +typedef struct { + UCHAR Flags; + KIRQL Irql; + UCHAR BusReleativeVector; +} IDTUsage; + +typedef struct _HalAddressUsage{ + struct _HalAddressUsage *Next; + CM_RESOURCE_TYPE Type; // Port or Memory + UCHAR Flags; // same as IDTUsage.Flags + struct { + ULONG Start; + USHORT Length; + } Element[]; +} ADDRESS_USAGE; +#if !defined (_R94A_) +#pragma pack() +#endif + +#define IDTOwned 0x01 // IDT is not available for others +#define InterruptLatched 0x02 // Level or Latched +#define InternalUsage 0x11 // Report usage on internal bus +#define DeviceUsage 0x21 // Report usage on device bus + +extern IDTUsage HalpIDTUsage[]; +extern ADDRESS_USAGE *HalpAddressUsageList; +// CMP001 +extern ADDRESS_USAGE HalpDefaultPcIoSpace; +extern ADDRESS_USAGE HalpEisaIoSpace; +extern ADDRESS_USAGE HalpMapRegisterMemorySpace; + +#define HalpRegisterAddressUsage(a) \ + (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a); + +// CMP001 +#define IRQ_PREFERRED 0x02 +#define IRQ_VALID 0x01 + +// CMP001 +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse +); + +// +// H0004: from halx86/i386/halp.h +// Temp definitions to thunk into supporting new bus extension format +// + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + +PBUS_HANDLER +HalpAllocateBusHandler ( + IN INTERFACE_TYPE InterfaceType, + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN INTERFACE_TYPE ParentBusDataType, + IN ULONG ParentBusNumber, + IN ULONG BusSpecificData + ); + +#define HalpHandlerForBus HaliHandlerForBus +#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p; + +#endif // _HALP_ diff --git a/private/ntos/nthals/halr96b/mips/j4cache.s b/private/ntos/nthals/halr96b/mips/j4cache.s new file mode 100644 index 000000000..0f17e43bf --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/j4cache.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\j4cache.s" diff --git a/private/ntos/nthals/halr96b/mips/j4flshbf.s b/private/ntos/nthals/halr96b/mips/j4flshbf.s new file mode 100644 index 000000000..04012b70b --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/j4flshbf.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\j4flshbf.s" diff --git a/private/ntos/nthals/halr96b/mips/j4flshio.c b/private/ntos/nthals/halr96b/mips/j4flshio.c new file mode 100644 index 000000000..2461bc392 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/j4flshio.c @@ -0,0 +1,236 @@ +// #pragma comment(exestr, "@(#) j4flshio.c 1.1 95/09/28 15:34:41 nec") +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + j4flshio.c + +Abstract: + + + This module implements the system dependent kernel function to flush + the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion, + or Duo system. + +Author: + + David N. Cutler (davec) 24-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Fri Sep 30 20:23:02 JST 1994 kbnes!kishimoto + - HalFlushIoBuffers() + Modify to return only. + R94A supports I/O coherency during I/O translation. + N.B. This modify is enabled after Beta-machine. + _R94ABBMIO_ means that machine is alpha-version. + H001 Sat Mar 18 15:19:33 1995 kbnes!kishimoto + - if operation is DMA, we have nothing to do. + + M002 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 10:51:41 JST 1995 + - add support I/O cache limit _IO_LIMIT_ +--*/ + +#include "halp.h" + +VOID +HalFlushIoBuffers ( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ) + +/*++ + +Routine Description: + + This function flushes the I/O buffer specified by the memory descriptor + list from the data cache on the current processor. + +Arguments: + + Mdl - Supplies a pointer to a memory descriptor list that describes the + I/O buffer location. + + ReadOperation - Supplies a boolean value that determines whether the I/O + operation is a read into memory. + + DmaOperation - Supplies a boolean value that determines whether the I/O + operation is a DMA operation. + +Return Value: + + None. + +--*/ + +{ + + ULONG CacheSegment; + ULONG Length; + ULONG Offset; + KIRQL OldIrql; + PULONG PageFrame; + ULONG Source; + +#if !defined(_IO_LIMIT_) && defined(_R94A_) + + // + // H001 + // R94A supports cache coherency during DMA operation, + // so we have nothing to to. + // + + if (DmaOperation == TRUE){ + return; + } + +#endif + + // + // The Jazz R4000 uses a write back data cache and, therefore, must be + // flushed on reads and writes. + // + // If the length of the I/O operation is greater than the size of the + // data cache, then sweep the entire data cache. Otherwise, flush or + // purge individual pages from the data cache as appropriate. + // + + Offset = Mdl->ByteOffset & PCR->DcacheAlignment; + Length = (Mdl->ByteCount + + PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment; + + if ((Length > PCR->FirstLevelDcacheSize) && + (Length > PCR->SecondLevelDcacheSize)) { + + // + // If the I/O operation is a DMA operation, or the I/O operation is + // not a DMA operation and the I/O operation is a page read operation, + // then sweep (index/writeback/invalidate) the entire data cache. + // + + if ((DmaOperation != FALSE) || + ((DmaOperation == FALSE) && + (ReadOperation != FALSE) && + ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) { + HalSweepDcache(); + } + + // + // If the I/O operation is a page read, then sweep (index/invalidate) + // the entire instruction cache. + // + + if ((ReadOperation != FALSE) && + ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) { + HalSweepIcache(); + } + + } else { + + // + // Flush or purge the specified pages from the data cache and + // instruction caches as appropriate. + // + // Compute the number of pages to flush and the starting MDL page + // frame address. + // + + Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment; + PageFrame = (PULONG)(Mdl + 1); + Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset; + + // + // Flush or purge the specified page segments from the data and + // instruction caches as appropriate. + // + + do { + if (Length >= (PAGE_SIZE - Offset)) { + CacheSegment = PAGE_SIZE - Offset; + + } else { + CacheSegment = Length; + } + + if (ReadOperation == FALSE) { + + // + // The I/O operation is a write and the data only needs to + // to be copied back into memory if the operation is also + // a DMA operation. + // + + if (DmaOperation != FALSE) { + HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + + } else { + + // + // If the I/O operation is a DMA operation, then purge the + // data cache. Otherwise, is the I/O operation is a page read + // operation, then flush the data cache. + // + + if (DmaOperation != FALSE) { + HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment); + + } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { + HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + + // + // If the I/O operation is a page read, then the instruction + // cache must be purged. + // + + if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { + HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + } + + PageFrame += 1; + Length -= CacheSegment; + Offset = 0; + Source += CacheSegment; + } while(Length != 0); + } + + return; +} + +ULONG +HalGetDmaAlignmentRequirement ( + VOID + ) + +/*++ + +Routine Description: + + This function returns the alignment requirements for DMA transfers on + host system. + +Arguments: + + None. + +Return Value: + + The DMA alignment requirement is returned as the fucntion value. + +--*/ + +{ + + return PCR->DcacheFillSize; +} diff --git a/private/ntos/nthals/halr96b/mips/j4prof.c b/private/ntos/nthals/halr96b/mips/j4prof.c new file mode 100644 index 000000000..dd8c2b7c9 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/j4prof.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\j4prof.c" diff --git a/private/ntos/nthals/halr96b/mips/jxbeep.c b/private/ntos/nthals/halr96b/mips/jxbeep.c new file mode 100644 index 000000000..922c80816 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxbeep.c @@ -0,0 +1,215 @@ +// #pragma comment(exestr, "@(#) jxbeep.c 1.1 95/09/28 15:35:24 nec") +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + jxbeep.c + +Abstract: + + This module implements the HAL speaker "beep" routines for a MIPS + system. + +Author: + + +Environment: + + Kernel mode + +Revision History: + + M0001 1994.9.12 kbnes!kuriyama + Modify for R94A MIPS R4400 + + - HalMakeBeep() + At R94A system, Buzzer controled by TYPHOON, not by EISA-Bridge. + Buzzer ON/OFF, Freequency Control Register was changed. + + S0002 1994.12.22 kbnes!kuriyama + cast miss ? fixed + +--*/ + +#include "halp.h" +#include "eisa.h" + +BOOLEAN +HalMakeBeep( + IN ULONG Frequency + ) + +/*++ + +Routine Description: + + This function sets the frequency of the speaker, causing it to sound a + tone. The tone will sound until the speaker is explicitly turned off, + so the driver is responsible for controlling the duration of the tone. + +Arguments: + + Frequency - Supplies the frequency of the desired tone. A frequency of + 0 means the speaker should be shut off. + +Return Value: + + TRUE - Operation was successful (frequency within range or zero). + FALSE - Operation was unsuccessful (frequency was out of range). + Current tone (if any) is unchanged. + +--*/ + +{ + + KIRQL OldIrql; + +/* start M0001 */ +#if defined(_R94A_) + BUZZER_CONTROL BuzzerControl; +#else // _R94A_ + NMI_STATUS NmiStatus; +#endif // _R94A_ +/* end M0001 */ + + PEISA_CONTROL controlBase = HalpEisaControlBase; + TIMER_CONTROL timerControl; + ULONG newCount; + BOOLEAN Result; + + // + // Raise IRQL to dispatch level and acquire the beep spin lock. + // + + KeAcquireSpinLock(&HalpBeepLock, &OldIrql); + + // + // Stop the speaker. + // + +/* start M0001 */ +#if defined(_R94A_) + + *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char); +//S0002 + BuzzerControl.SpeakerGate = 0; + BuzzerControl.SpeakerData = 0; + WRITE_REGISTER_UCHAR(&DMA_CONTROL->BuzzerControl.Char,*((PUCHAR) &BuzzerControl)); +// S0002 +#else // _R94A_ + + *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus); + NmiStatus.SpeakerGate = 0; + NmiStatus.SpeakerData = 0; + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus)); + +#endif // _R94A_ +/* end M0001 */ + + // + // If the specified frequency is zero, then the speaker is to be stopped. + // + + if (Frequency == 0) { + Result = TRUE; + + } else { + + // + // If the new count has a magnitude less than 65,536 (0x10000), then + // set the speaker time to the correct mode. Otherwise, return a value + // of FALSE sinc ethe frequency is out of range. + // + + newCount = TIMER_CLOCK_IN / Frequency; + if (newCount >= 0x10000) { + Result = FALSE; + + } else { + +/* start M0001 */ +#if defined(_R94A_) + // + // R94A Support only even value for newCount + // + + newCount &= 0xfffe; + + if (newCount == 0) { + newCount = 2; + } + +#else // _R94A_ + + // + // Set the speaker timer to the correct mode. + // + + timerControl.BcdMode = 0; + timerControl.Mode = TM_SQUARE_WAVE; + timerControl.SelectByte = SB_LSB_THEN_MSB; + timerControl.SelectCounter = SELECT_COUNTER_2; + WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl)); + +#endif // _R94A_ +/* end M0001 */ + + // + // Set the speaker timer to the correct mode. + // + +/* start M0001 */ +#if defined(_R94A_) + + WRITE_REGISTER_USHORT(&DMA_CONTROL->BuzzerCount.Short,(USHORT) newCount); +// S0002 + +#else // _R94A_ + + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff)); + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8)); + +#endif // _R94A_ +/* end M0001 */ + + // + // Start the speaker. + // + +/* start M0001 */ +#if defined(_R94A_) + + *((PUCHAR)&BuzzerControl) = READ_REGISTER_UCHAR( + &DMA_CONTROL->BuzzerControl.Char //S0002 + ); + BuzzerControl.SpeakerGate = 1; + BuzzerControl.SpeakerData = 1; + WRITE_REGISTER_UCHAR( + &DMA_CONTROL->BuzzerControl.Char,//S0002 + *((PUCHAR) &BuzzerControl) + ); + Result = TRUE; + +#else // _R94A_ + + NmiStatus.SpeakerGate = 1; + NmiStatus.SpeakerData = 1; + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + Result = TRUE; + +#endif // _R94A_ +/* end M0001 */ + + } + } + + // + // Release the beep spin lock and lower IRQL to its previous value. + // + + KeReleaseSpinLock(&HalpBeepLock, OldIrql); + return Result; +} + diff --git a/private/ntos/nthals/halr96b/mips/jxdisp.c b/private/ntos/nthals/halr96b/mips/jxdisp.c new file mode 100644 index 000000000..f30afc401 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxdisp.c @@ -0,0 +1,3605 @@ +/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.2 95/10/17 01:18:22" ) */ +/*++ + +Copyright (c) 1995 NEC Corporation +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + jxdisp.c + +Abstract: + + This module implements the HAL display initialization and output routines + for a R4400 R94A system. + +History: + + +--*/ + +/* + * New Code for 3.51 + * + * M001 kuriyama@oa2.kb.nec.co.jp Fri Jul 14 11:46:06 JST 1995 + * -change textmode 80x50 + * + * M002 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:36:23 JST 1995 + * -change for fw interface + * + * M003 kuriyama@oa2.kb.nec.co.jp Fri Jul 21 14:14:54 JST 1995 + * -add call HalpResetDisplayParameters + * for bug fix DPI board panic message + * + * M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 2 14:28:28 JST 1995 + * -add ESM critical error logging + * + * S005 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 23:42:59 JST 1995 + * -change for scroll bug fix + * + * S006 nishi@oa2.kb.nec.co.jp Mon Sep 4 18:42:00 JST 1995 + * -change for GLINT new revision board + * R01=00,R02=02 + * M007 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995 + * - Add Software Power Off, when system panic is occured + * + * M008 nishi@oa2.kb.nec.co.jp Mon Sep 18 18:42:00 JST 1995 + * - Change Logic for resume fixed TLB for DMA + * + * M009 kuriyama@oa2.kbnes.nec.co.jp Mon Sep 18 19:58:22 JST 1995 + * - bug fix for tga 800x600 72Hz + * + * M010 v-akitk@microsoft.com + * - Change for Software Power Supply(R96B) + * + */ + + +#include "halp.h" +#include "jazzvdeo.h" +#include "jzvxl484.h" +#include +#include "cirrus.h" +#include "modeset.h" +#include "mode542x.h" +#include +#include +#include + +#include "string.h" +#include "pci.h" +/* START M007 */ +#define HEADER_FILE +#include "kxmips.h" +/* START M007 */ +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalpInitializeDisplay0) +#pragma alloc_text(INIT, HalpInitializeDisplay1) + +#endif + +// +// for x86bios emulate +// +PCHAR K351UseBios=NULL; +VOID HalpCopyROMs(VOID); + +PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; // M003 + +typedef +VOID +(*PHALP_CONTROLLER_SETUP) ( + VOID + ); + +typedef +VOID +(*PHALP_DISPLAY_CHARACTER) ( + UCHAR + ); +typedef +VOID +(*PHALP_SCROLL_SCREEN) ( + UCHAR + ); + +#define TAB_SIZE 4 +#define TEXT_ATTR 0x1F + +// +// Define forward referenced procedure prototypes. +// +VOID +HalpDisplayINT10Setup ( +VOID); + +VOID HalpOutputCharacterINT10 ( + IN UCHAR Character ); + +VOID HalpScrollINT10 ( + IN UCHAR line + ); + +VOID HalpDisplayCharacterVGA ( + IN UCHAR Character ); + +BOOLEAN +HalpInitializeX86DisplayAdapter( + VOID + ); + + +PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL; + +// +// Define forward referenced procedure prototypes. +// + +VOID +HalpDisplayCharacterOld ( + IN UCHAR Character + ); + +VOID +HalpOutputCharacterOld( + IN PUCHAR Glyph + ); + +VOID +HalpDisplayCirrusSetup ( + VOID + ); + +BOOLEAN +HalpCirrusInterpretCmdStream ( + PUSHORT pusCmdStream + ); + +VOID +HalpDisplayTgaSetup ( + VOID + ); + +/* +VOID +RGB525_WRITE( + ULONG dac, + ULONG offset, + UCHAR data); + +VOID +RGB525_SET_REG( + ULONG dac, + ULONG index, + UCHAR data); +*/ + +VOID +HalpDisplayGlintSetup( + VOID + ); + +VOID +Write_Dbg_Uchar( +PUCHAR, +UCHAR +); + +// +// Must use 32Bit transfer. RtlMoveMemory() uses 64Bit transfer. +// + +VOID +HalpMoveMemory32 ( + PUCHAR Destination, + PUCHAR Source, + ULONG Length +); +/* Start M007 */ +VOID +HalpMrcModeChange( + UCHAR Mode +); +/*End M007 */ + +// +// Define virtual address of the video memory and control registers. +// + +#define VIDEO_MEMORY_BASE 0x40000000 + +// +// Define memory access constants for VXL +// + +#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000) +#define CIRRUS_OFFSET ((PUSHORT)0x3b0) + +#define TGA_REGISTER_BASE ((ULONG)0x403ff000) +#define R94A_PCI_ADDR_REG ((PULONG)(0x80000518 | 0xffffc000)) +#define R94A_PCI_DATA_REG ((PULONG)(0x80000520 | 0xffffc000)) + +#define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000) // M021 +#define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000) +#define RGB525_REGISTER_BASE ((ULONG)0x403fd000) + +// +// Define controller setup routine type. +// + +typedef +VOID +(*PHALP_CONTROLLER_SETUP) ( + VOID + ); + +// +// Define OEM font variables. +// + +ULONG HalpBytesPerRow; +ULONG HalpCharacterHeight; +ULONG HalpCharacterWidth; +ULONG HalpColumn; +ULONG HalpDisplayText; +ULONG HalpDisplayWidth; +POEM_FONT_FILE_HEADER HalpFontHeader; +ULONG HalpRow; +ULONG HalpScrollLength; +ULONG HalpScrollLine; + +ULONG HalpGlintRevisionId; // S006 + +// +// Define display variables. +// + +BOOLEAN HalpDisplayOwnedByHal; +ENTRYLO HalpDisplayPte; +ULONG HalpDisplayControlBase = 0; +ULONG HalpDisplayMemoryBase = 0; // M021 +ULONG HalpDisplayResetRegisterBase = 0; +ULONG HalpDisplayVxlClockRegisterBase = 0; +ULONG HalpDisplayVxlBt484RegisterBase = 0; +ULONG HalpDisplayVxlJaguarRegisterBase = 0; +PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL; +MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData; +BOOLEAN HalpDisplayTypeUnknown = FALSE; +ULONG HalpG364Type = 0; + +LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0}; + +LARGE_INTEGER HalpTgaPhigicalVideo = {0,0}; +LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0}; + +LARGE_INTEGER HalpGlintPhygicalVideo = {0,0}; +LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0}; +ULONG HalpDisplayPCIDevice = FALSE; +ULONG HalpDisplayType16BPP = FALSE; + +PVOID HalpMrcControlBase = NULL; // M007 +BOOLEAN HalpMrcControlMapped = FALSE; // M007 + +typedef struct _R94A_PCI_CONFIGURATION_ADDRESS_REG{ + ULONG Reserved2: 2; + ULONG RegisterNumber: 6; + ULONG FunctionNumber: 3; + ULONG DeviceNumber: 5; + ULONG BusNumber: 8; + ULONG Reserved1: 7; + ULONG ConfigEnable: 1; +} R94A_PCI_CONFIGURATION_ADDRESS_REG, *PR94A_PCI_CONFIGURATION_ADDRESS_REG; + +VOID +HalpReadPCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ); + +BOOLEAN +HalpCheckPCIDevice ( + IN PCI_SLOT_NUMBER Slot + ); + +BOOLEAN +HalpInitializeDisplay0 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This routine maps the video memory and control registers into the user + part of the idle process address space, initializes the video control + registers, and clears the video screen. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + PCONFIGURATION_COMPONENT_DATA Child; + PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; + POEM_FONT_FILE_HEADER FontHeader; + ULONG Index; + ULONG MatchKey; + PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; + PLIST_ENTRY NextEntry; + PENTRYLO PageFrame; + ENTRYLO Pte; + ULONG StartingPfn; + PCI_SLOT_NUMBER Slot; + ULONG ReadValue; + PCHAR Options; + + // + // Set the address of the font file header and compute display variables. + // + // N.B. The font information suppled by the OS Loader is used during phase + // 0 initialization. During phase 1 initialization, a pool buffer is + // allocated and the font information is copied from the OS Loader + // heap into pool. + // + + FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile; + HalpFontHeader = FontHeader; + HalpBytesPerRow = (FontHeader->PixelWidth + 7) / 8; + HalpCharacterHeight = FontHeader->PixelHeight; + HalpCharacterWidth = FontHeader->PixelWidth; + +#if defined(_X86_DBG_) + DbgPrint("\n DISP 0\n"); //DBGDBG +#endif // _X86_DBG_ + + // + // Find the configuration entry for the first display controller. + // + + MatchKey = 0; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + DisplayController, + &MatchKey); + if (ConfigurationEntry == NULL) { + MatchKey = 1; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + DisplayController, + &MatchKey); + if (ConfigurationEntry == NULL) { + return FALSE; + } + } + + + // + // Determine which video controller is present in the system. + // Copy the display controller and monitor parameters in case they are + // needed later to reinitialize the display to output a message. + // + + if (LoaderBlock->LoadOptions != NULL) { + Options = LoaderBlock->LoadOptions; + _strupr(Options); + K351UseBios = strstr(Options, "USEBIOS"); + } + if(K351UseBios!=NULL){ + DbgPrint("\nUSEBIOS---\n"); + HalpDisplayControllerSetup = HalpDisplayINT10Setup; + HalpDisplayCharacter = HalpDisplayCharacterVGA; + HalpDisplayControlBase = 0x90000000; + + }else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "necvdfrb")) { + + HalpDisplayControllerSetup = HalpDisplayCirrusSetup; + HalpDisplayCharacter = HalpDisplayCharacterOld; + HalpDisplayControlBase = 0x90000000; + + } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) { + // + // for DEC21030 PCI + // + + HalpDisplayControllerSetup = HalpDisplayTgaSetup; + HalpDisplayCharacter = HalpDisplayCharacterOld; + HalpDisplayPCIDevice = TRUE; + + Slot.u.bits.FunctionNumber = 0; + + for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (ReadValue == 0x00041011){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); + + if ((ReadValue & 0x00000002) == 0x2){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + HalpDisplayControlBase = + (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + + } else { + return FALSE; + + } + } + } + + } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) { + + // + // for GLINT 300SX PCI + // + + HalpDisplayControllerSetup = HalpDisplayGlintSetup; + HalpDisplayCharacter = HalpDisplayCharacterOld; + HalpDisplayPCIDevice = TRUE; + HalpDisplayType16BPP = TRUE; + + // + // FunctionNumber always zero + // + + Slot.u.bits.FunctionNumber = 0; + + for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (ReadValue == 0x00013d3d){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); + + // + // GLINT 300SX has no I/O space regions + // + + if (ReadValue & 0x2){ + + // + // Control Registers + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + HalpDisplayControlBase = (ReadValue & 0xfffffff0); + + // + // Framebuffer + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + HalpDisplayMemoryBase = (ReadValue & 0xfffffff0); + + // + // Revision ID + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08); // S006 + HalpGlintRevisionId = (ReadValue & 0x000000ff); + + } else { + return FALSE; + + } + } + } + } else { + // M002 +++ + HalpDisplayControllerSetup = HalpDisplayINT10Setup; + HalpDisplayCharacter = HalpDisplayCharacterVGA; + HalpDisplayControlBase = 0x90000000; + HalpDisplayTypeUnknown = TRUE; + // M002 --- + } + + Child = ConfigurationEntry->Child; + + RtlMoveMemory((PVOID)&HalpMonitorConfigurationData, + Child->ConfigurationData, + Child->ComponentEntry.ConfigurationDataLength); + + // + // Compute character output display parameters. + // + + HalpDisplayText = + HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight; + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpScrollLine = + 1024 * HalpCharacterHeight; + } else if (HalpDisplayType16BPP) { + + HalpScrollLine = + HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT); + + } else { + HalpScrollLine = + HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight; + } + + HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpDisplayWidth = + 1024 / HalpCharacterWidth; + + }else{ + + HalpDisplayWidth = + HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth; + } + + // + // Scan the memory allocation descriptors and allocate a free page + // to map the video memory and control registers, and initialize the + // PDE entry. + // + + NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) { + MemoryDescriptor = CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if ((MemoryDescriptor->MemoryType == LoaderFree) && + (MemoryDescriptor->PageCount > 1)) { + StartingPfn = MemoryDescriptor->BasePage; + MemoryDescriptor->BasePage += 1; + MemoryDescriptor->PageCount -= 1; + break; + } + + NextEntry = NextEntry->Flink; + } + + ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead); + + Pte.X1 = 0; + Pte.PFN = StartingPfn; + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + + Pte.N = 1; + +#endif + +#if defined(R4000) + + Pte.C = UNCACHED_POLICY; + +#endif + + // + // Save the page table page PTE for use in displaying information and + // map the appropriate PTE in the current page directory page to address + // the display controller page table page. + // + + HalpDisplayPte = Pte; + *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte; + + // + // Initialize the page table page. + // + + PageFrame = (PENTRYLO)(PTE_BASE | + (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) { + + HalpCirrusPhigicalVideo.HighPart = 1; + HalpCirrusPhigicalVideo.LowPart = 0; + + Pte.PFN = (HalpCirrusPhigicalVideo.HighPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + }else if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { + HalpCirrusPhigicalVideo.HighPart = 1; + HalpCirrusPhigicalVideo.LowPart = MEM_VGA; + Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + } else if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { + HalpTgaPhigicalVideo.HighPart = 1; + HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET; + Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 + HalpGlintPhygicalVideo.HighPart = 1; + HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase; + Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT); + } + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + + Pte.N = 1; + +#endif + +#if defined(R4000) + + Pte.C = UNCACHED_POLICY; + +#endif + + // + // Page table entries of the video memory. + // + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { + HalpTgaPhigicalVideoCont.HighPart = 1; + HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase; + Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *PageFrame = Pte; + + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { + + HalpGlintPhygicalVideoCont.HighPart = 1; + HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase; + + // + // IBM RGB525 + // + + Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *(PageFrame - 2) = Pte; + + // + // GLINT 300SX Internal Video Registers + // + + Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *(PageFrame - 1) = Pte; + + // + // GLINT 300SX Control Status Registers + // + + Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *PageFrame = Pte; + + } else if (HalpDisplayControllerSetup == HalpDisplayINT10Setup){ + +#if defined(_X86_DBG_) + DbgPrint("Map x86 and cirrus control register\n"); +#endif // _X86_DBG_ + + Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT; + + for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) { + *PageFrame-- = Pte; +#if defined(_X86_DBG_) + DbgPrint("Map index %x pfn %x\n",Index,Pte.PFN); +#endif // _X86_DBG_ + Pte.PFN -= 1; + } + + } else { + + // + // If we have a 'NEC-cirrus GD5428' + // use the page before last to map the reset register. + // + + // + // Page table for the video registers. + // + + Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + *PageFrame = Pte; + } + + // + // M004 + // ESM critical error logging setup. + // + + HalpInitDisplayStringIntoNvram(); + + // + // Initialize the display controller. + // + +#if defined(_X86_DBG_) + DbgPrint("\n x86adp init GOOO\n"); //DBGDBG +#endif // _X86_DBG + + if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){ + if (HalpInitializeX86DisplayAdapter()) { +#if defined(_X86_DBG_) + DbgPrint("\n x86adp init OK\n"); //DBGDBG +#endif // _X86_DBG +// HalpDisplayControllerSetup(); // initialize twice bugbug + + }else{ + + return FALSE; + } + } + + HalpDisplayControllerSetup(); + + return TRUE; +} + +BOOLEAN +HalpInitializeDisplay1 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This routine allocates pool for the OEM font file and copies the font + information from the OS Loader heap into the allocated pool. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + PVOID FontHeader; + + // + // Allocate a pool block and copy the OEM font information from the + // OS Loader heap into the pool block. + // + + FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize); + if (FontHeader == NULL) { + return FALSE; + } + + RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize); + HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader; + return TRUE; +} + +VOID +HalAcquireDisplayOwnership ( + IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters + ) + +/*++ + +Routine Description: + + This routine switches ownership of the display away from the HAL to + the system display driver. It is called when the system has reached + a point during bootstrap where it is self supporting and can output + its own messages. Once ownership has passed to the system display + driver any attempts to output messages using HalDisplayString must + result in ownership of the display reverting to the HAL and the + display hardware reinitialized for use by the HAL. + +Arguments: + + ResetDisplayParameters - if non-NULL the address of a function + the hal can call to reset the video card. The function returns + TRUE if the display was reset. + +Return Value: + + None. + +--*/ + +{ + + // + // Set HAL ownership of the display to false. + // + + HalpResetDisplayParameters=ResetDisplayParameters;// M003 + HalpDisplayOwnedByHal = FALSE; + + // + // M010 + // Set for Software Power supply control + // + +#if defined (_MRCPOWER_) + HalpMrcModeChange((UCHAR)0x1); // M007 +#endif // _MRCPOWER_ + + // + // M006 + // ESM critical logging success set success startup. + // + + HalpSuccessOsStartUp(); + + return; +} + +VOID +HalpDisplayCirrusSetup( + VOID + ) +/*++ + +Routine Description: + + This routine initializes the Cirrus VGA display controlleer. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + PULONG Buffer; + LONG Limit; + LONG Index; + ULONG dac_address, dac_reg; + + ULONG verticalFrequency; + ULONG horizontalTotal; + ULONG verticalTotal; + + // + // Calculate vertical frequency. + // + + horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime + +HalpMonitorConfigurationData.HorizontalBackPorch + +HalpMonitorConfigurationData.HorizontalFrontPorch + +HalpMonitorConfigurationData.HorizontalSync ); + + verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution + +HalpMonitorConfigurationData.VerticalBackPorch + +HalpMonitorConfigurationData.VerticalFrontPorch + +HalpMonitorConfigurationData.VerticalSync ); + + verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); + + switch (HalpMonitorConfigurationData.HorizontalResolution) { + case 640: + if( verticalFrequency < 66 ) { + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + HalpCirrusInterpretCmdStream(CL542x_640x480_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 800: + if( verticalFrequency < 58 ) { + HalpCirrusInterpretCmdStream(CL542x_800x600_256_56); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 66 ) { + HalpCirrusInterpretCmdStream(CL542x_800x600_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + HalpCirrusInterpretCmdStream(CL542x_800x600_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 1024: + + if( verticalFrequency < 47 ) { + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if ( verticalFrequency < 65) { + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + default: + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + return; + } + + // + // Initialize color pallete. + // + + dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT; + dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT; + + Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0); + + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + + Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2)); + + // + // Set the video memory to address color one. + // + Buffer = (PULONG)VIDEO_MEMORY_BASE; + Limit = (1024 * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (Index = 0; Index < Limit; Index += 1) { + *Buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; +} + +BOOLEAN +HalpCirrusInterpretCmdStream( + PUSHORT pusCmdStream + ) + +/*++ + +Routine Description: + + Interprets the appropriate command array to set up VGA registers for the + requested mode. Typically used to set the VGA into a particular mode by + programming all of the registers + +Arguments: + + + pusCmdStream - array of commands to be interpreted. + +Return Value: + + The status of the operation (can only fail on a bad command); TRUE for + success, FALSE for failure. + +Revision History: +--*/ + + + +{ + ULONG ulCmd; + ULONG ulPort; + UCHAR jValue; + USHORT usValue; + ULONG culCount; + ULONG ulIndex; + ULONG ulBase; + if (pusCmdStream == NULL) { + + return TRUE; + } + + ulBase = (ULONG)CIRRUS_BASE+0x3b0; + + // + // Now set the adapter to the desired mode. + // + + while ((ulCmd = *pusCmdStream++) != EOD) { + + // + // Determine major command type + // + + switch (ulCmd & 0xF0) { + + // + // Basic input/output command + // + + case INOUT: + + // + // Determine type of inout instruction + // + + if (!(ulCmd & IO)) { + + // + // Out instruction. Single or multiple outs? + // + + if (!(ulCmd & MULTI)) { + + // + // Single out. Byte or word out? + // + + if (!(ulCmd & BW)) { + + // + // Single byte out + // + + ulPort = *pusCmdStream++; + jValue = (UCHAR) *pusCmdStream++; + + + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), + jValue); + + } else { + + // + // Single word out + // + + ulPort = *pusCmdStream++; + usValue = *pusCmdStream++; + + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff)); + + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8)); + + + } + + } else { + + // + // Output a string of values + // Byte or word outs? + // + + if (!(ulCmd & BW)) { + + // + // String byte outs. Do in a loop; can't use + // VideoPortWritePortBufferUchar because the data + // is in USHORT form + // + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + + while (culCount--) { + jValue = (UCHAR) *pusCmdStream++; + + Write_Dbg_Uchar((PUCHAR)ulPort, + jValue); + + } + + } else { + + // + // String word outs + // + + ulPort = *pusCmdStream++; + culCount = *pusCmdStream++; + // + // Buffering out is not use on the Miniport Driver for R96 machine. + // + + + while(culCount--) + { + usValue = *pusCmdStream++; + + Write_Dbg_Uchar((PUCHAR) + (ulBase + ulPort), (UCHAR) (usValue & 0x00ff)); + Write_Dbg_Uchar((PUCHAR) + (ulBase + ulPort+1), (UCHAR) (usValue >> 8)); + + } + + } + } + + } else { + + // In instruction + // + // Currently, string in instructions aren't supported; all + // in instructions are handled as single-byte ins + // + // Byte or word in? + // + + if (!(ulCmd & BW)) { + // + // Single byte in + // + + ulPort = *pusCmdStream++; + jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort); + + } else { + + // + // Single word in + // + + ulPort = *pusCmdStream++; + usValue = READ_REGISTER_USHORT((PUSHORT) + (ulBase+ulPort)); + } + + } + + break; + + // + // Higher-level input/output commands + // + + case METAOUT: + + // + // Determine type of metaout command, based on minor + // command field + // + switch (ulCmd & 0x0F) { + + // + // Indexed outs + // + + case INDXOUT: + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + ulIndex = *pusCmdStream++; + + while (culCount--) { + + usValue = (USHORT) (ulIndex + + (((ULONG)(*pusCmdStream++)) << 8)); + + Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff)); + + Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8)); + + ulIndex++; + + } + + break; + + // + // Masked out (read, AND, XOR, write) + // + + case MASKOUT: + + ulPort = *pusCmdStream++; + jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort); + jValue &= *pusCmdStream++; + jValue ^= *pusCmdStream++; + + Write_Dbg_Uchar((PUCHAR)ulBase + ulPort, + jValue); + + break; + + // + // Attribute Controller out + // + + case ATCOUT: + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + ulIndex = *pusCmdStream++; + + while (culCount--) { + + // Write Attribute Controller index + + Write_Dbg_Uchar((PUCHAR)ulPort, + (UCHAR)ulIndex); + + // Write Attribute Controller data + jValue = (UCHAR) *pusCmdStream++; + + Write_Dbg_Uchar((PUCHAR)ulPort, jValue); + + ulIndex++; + + } + + break; + + // + // None of the above; error + // + default: + + return FALSE; + + } + + + break; + + // + // NOP + // + + case NCMD: + + break; + + // + // Unknown command; error + // + + default: + + return FALSE; + + } + + } + + return TRUE; + +} // end HalpCirrusInterpretCmdStream() + + +VOID +HalpDisplayTgaSetup( + VOID + ) +/*++ + + Routine Description: + + This routine initializes the Tga(DEC21030) Graphics accelerator. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + + PUCHAR PLLbits; + ULONG i, j; + ULONG PLLdata; + ULONG ColorData; + PULONG Buffer; + LONG Limit; + LONG Index; + ULONG VerticalFrequency; + ULONG horizontalTotal; + ULONG verticalTotal; + +// M019+++ +// +// support for nec dec-ga(tga) board. +// parameter change. +// +#if 0 + const UCHAR PLLbits640x480_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xb0, 0x20, 0xc8 }; + const UCHAR PLLbits640x480_60[7] = { 0x80, 0x08, 0x80, 0x24, 0x88, 0x80, 0x78 }; + const UCHAR PLLbits800x600_72[7] = { 0x80, 0x00, 0x80, 0x24, 0x88, 0x80, 0x78 }; + const UCHAR PLLbits800x600_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x70, 0xa0, 0x84 }; + const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; +#else + const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 }; + const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 }; + const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S007 + const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 }; + const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; +#endif // _NECDEC_ +// M019 --- + + const UCHAR Vga_Ini_ColorTable[48] = +// { VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, + { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // M010 + VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B, + VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G, + VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B, + VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B, + VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B, + VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B, + VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B, +// VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, + VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // M010 + VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B, + VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B, + VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B, + VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B, + VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B, + VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B, + VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B + }; + + // + // Calculate vertical frequency. + // + + horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime + +HalpMonitorConfigurationData.HorizontalBackPorch + +HalpMonitorConfigurationData.HorizontalFrontPorch + +HalpMonitorConfigurationData.HorizontalSync ); + + verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution + +HalpMonitorConfigurationData.VerticalBackPorch + +HalpMonitorConfigurationData.VerticalFrontPorch + +HalpMonitorConfigurationData.VerticalSync ); + + VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); + + // + // Write the PLL + // + + // Select PLL Data + if( HalpMonitorConfigurationData.HorizontalResolution == 640 + && HalpMonitorConfigurationData.VerticalResolution == 480 ){ + if( VerticalFrequency > 66 ){ + PLLbits = (PVOID)PLLbits640x480_72; // S012 + } else { + PLLbits = (PVOID)PLLbits640x480_60; // S012 + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 ){ + if( VerticalFrequency > 66 ){ + PLLbits = (PVOID)PLLbits800x600_72; // S012 + } else { + PLLbits = (PVOID)PLLbits800x600_60; // S012 + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 ){ + PLLbits = (PVOID)PLLbits1024x768_60; // S012 + } else { + PLLbits = (PVOID)PLLbits640x480_60; // S012 + } + + // Set PLL Data + for( i = 0; i <= 6; i++ ){ + for( j = 0; j <= 7; j++ ){ + PLLdata = (PLLbits[i] >> (7-j)) & 1; + if( i == 6 && j == 7 ) + PLLdata |= 2; // Set ~HOLD bit on last write + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata); + } + } + + // Verify 21030 is idle ( check busy bit on Command Status Register ) + while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ + } + + // Set to Deep Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 ); + + // Verify 21030 is idle ( check busy bit on Command Status Register ) + while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ + } + + // Set to Video Base Address Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 ); + + // Set to Plane Mask Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff ); + + // Set to Pixel Mask Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff ); + + // Set to Raster Operation + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 ); + + // Set to Mode Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d ); + + // Set to Block Color Register 0 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 ); + + // Set to Block Color Register 1 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 ); + + // + // Init. video timing registers for each resolution + // + + if( HalpMonitorConfigurationData.HorizontalResolution == 640 + && HalpMonitorConfigurationData.VerticalResolution == 480 ){ + if( VerticalFrequency > 66 ){ + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x03c294a0 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 ); + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 ){ + if( VerticalFrequency > 66 ){ + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x01a7a4c8 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x02681cc8 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 ); + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 ){ + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x04889300 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x00e64ca0 ); // M023 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 ); + } + + // Set to Raster Operation Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 ); + + // Set to Mode Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 ); + + // M019 +++ + + // + // wait for 10 msec for nec dec-ga support + // + + KeStallExecutionProcessor(10000L); + + // M019 --- + + // Set to Palette and DAC Setup & Data Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 ); + + // + // set pass thru on off & on again to verify operation + // + + // EEPROM Write Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 ); + + // + // Fill palette + // + + // Set to Palette and DAC Setup & Data Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 ); + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 ); + + for( i = 0; i < 48; i++ ){ + ColorData = Vga_Ini_ColorTable[i]; + ColorData |= 0x200; + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData ); + } + + for( i = 48; i < 768; i++ ){ + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 ); + } + + // Set to Video Valid Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 ); + + // + // Set Video Memory to address color one. + // + + Buffer = (PULONG)VIDEO_MEMORY_BASE; + Limit = (HalpMonitorConfigurationData.HorizontalResolution * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (Index = 0; Index < Limit; Index += 1) { + *Buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; + +} + +VOID +HalDisplayString ( + PUCHAR String + ) + +/*++ + +Routine Description: + + This routine displays a character string on the display screen. + + +Arguments: + + String - Supplies a pointer to the characters that are to be displayed. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + ENTRYLO SavedPte; + /* Start D001 */ + ULONG NowDisplayControlBase; + ULONG NowDisplayMemoryBase; // M021 + PENTRYLO PageFrame; + ENTRYLO Pte; + LONG Index; + /* End D001 */ + PCI_SLOT_NUMBER Slot; // M014 + ULONG ReadValue; // M014 + + // + // Raise IRQL to the highest level, acquire the display adapter spin lock, + // flush the TB, and map the display frame buffer into the address space + // of the current process. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + +#if defined(_DUO_) + + KiAcquireSpinLock(&HalpDisplayAdapterLock); + +#endif + + SavedPte = *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))); + + KeFlushCurrentTb(); + *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte; + + if (HalpDisplayPCIDevice == TRUE){ + + // + // the display type is PCI + // check physical address and reinitialize PTE + // we assume that the device has no function + // + + Slot.u.bits.FunctionNumber = 0; + + for (Slot.u.bits.DeviceNumber = 3; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){ + + // + // DEC21030 + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0)+ TGA_REG_SPC_OFFSET; + NowDisplayMemoryBase = 0; + + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){ + + // + // GLINT 300SX + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0); + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + NowDisplayMemoryBase = (ReadValue & 0xfffffff0); + + } + } + + // + // check to see if address has been changed + // + + if (HalpDisplayControlBase != NowDisplayControlBase || + HalpDisplayMemoryBase != NowDisplayMemoryBase){ + + // Called by OS, so reinitialize PTE + HalpDisplayControlBase = NowDisplayControlBase; + HalpDisplayMemoryBase = NowDisplayMemoryBase; + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + Pte.N = 1; +#endif +#if defined(R4000) + Pte.C = UNCACHED_POLICY; +#endif + + // + // Initialize the page table page. + // + + PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){ + HalpTgaPhigicalVideoCont.HighPart = 1; + HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET; + Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); + + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 + + HalpGlintPhygicalVideo.HighPart = 1; + HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase; + Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT); + } + + // + // Page table entries of the video memory. + // + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup){ + HalpTgaPhigicalVideoCont.HighPart = 1; + HalpTgaPhigicalVideoCont.LowPart = HalpDisplayControlBase; + Pte.PFN = (HalpTgaPhigicalVideoCont.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *PageFrame = Pte; + + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { // M021 + HalpGlintPhygicalVideoCont.HighPart = 1; + HalpGlintPhygicalVideoCont.LowPart = HalpDisplayControlBase; + + // + // IBM RGB525 + // + + Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x4000) >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *(PageFrame - 2) = Pte; + + // + // GLINT 300SX Internal Video Registers + // + + Pte.PFN = ((HalpGlintPhygicalVideoCont.LowPart + 0x3000) >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *(PageFrame - 1) = Pte; + + // + // GLINT 300SX Control Status Registers + // + + Pte.PFN = (HalpGlintPhygicalVideoCont.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideoCont.HighPart << (32 - PAGE_SHIFT); + *PageFrame = Pte; + } + } + } + + // + // If ownership of the display has been switched to the system display + // driver, then reinitialize the display controller and revert ownership + // to the HAL. + // + + if (HalpDisplayOwnedByHal == FALSE) { +// M003 +++ + if (HalpResetDisplayParameters && + HalpDisplayControllerSetup == HalpDisplayINT10Setup) { + // + // Video work-around. The video driver has a reset function, + // call it before resetting the system in case the bios doesn't + // know how to reset the displays video mode. + // + + if (HalpResetDisplayParameters(80, 50)) { + } +// M003--- + } + + // + // M010 + // for Software controlled power suply. + // + +#if defined(_MRCPOWER_) + HalpMrcModeChange((UCHAR)0); // M007 +#endif // _MRCPOWER_ + + HalpDisplayControllerSetup(); +// HalpResetX86DisplayAdapter(); + + // + // M004 + // re-initialize critical message + // + + HalpInitDisplayStringIntoNvram(); + + } + + // + // M004 + // ESM critical error logging start (set colomn,row) + // + + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + // + // Display characters until a null byte is encountered. + // + + while (*String != 0) { + HalpDisplayCharacter(*String++); + } + + // M004 + // ESM critical error logging(strings) + // + + HalpStringBufferCopyToNvram(); + + // + // Restore the previous mapping for the current process, flush the TB, + // release the display adapter spin lock, and lower IRQL to its previous + // level. + // + + KeFlushCurrentTb(); + *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte; + +#if defined(_DUO_) + + KiReleaseSpinLock(&HalpDisplayAdapterLock); + +#endif + + KeLowerIrql(OldIrql); + return; +} + +VOID +HalpDisplayCharacterOld ( + IN UCHAR Character + ) + +/*++ + +Routine Description: + + This routine displays a character at the current x and y positions in + the frame buffer. If a newline is encounter, then the frame buffer is + scrolled. If characters extend below the end of line, then they are not + displayed. + +Arguments: + + Character - Supplies a character to be displayed. + +Return Value: + + None. + +--*/ + +{ + + PUCHAR Destination; + PUSHORT DestinationShort; // M021 + ULONG Index; + + // + // If the character is a newline, then scroll the screen up, blank the + // bottom line, and reset the x position. + // + + if (Character == '\n') { + HalpColumn = 0; + if (HalpRow < (HalpDisplayText - 1)) { + HalpRow += 1; + + } else { + HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE, + (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), + HalpScrollLength); + +// /* START M002 */ +// RtlMoveMemory((PUCHAR)VIDEO_MEMORY_BASE, // S013 +// (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), +// HalpScrollLength); +// /* END M002 */ + + if (HalpDisplayType16BPP) { + DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength); + + } else { + Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength; + } + + if (HalpDisplayType16BPP) { + for (Index = 0; Index < HalpScrollLine/2; Index += 1) { + *DestinationShort++ = (USHORT)0x000f; + } + + } else { + for (Index = 0; Index < HalpScrollLine; Index += 1) { + *Destination++ = 1; + } + } + + } + + // + // M006 + // ESM critical logging re-print(column, row) + // + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + } else if (Character == '\r') { + HalpColumn = 0; + + // + // M006 + // ESM critical logging re-print(column,row) + // + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + } else { + + // + // M006 + // ESM critical logging put character. + // + + HalStringIntoBuffer( Character ); + + if ((Character < HalpFontHeader->FirstCharacter) || + (Character > HalpFontHeader->LastCharacter)) { + Character = HalpFontHeader->DefaultCharacter; + } + + Character -= HalpFontHeader->FirstCharacter; + HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset); + } + + return; +} + +//351 +VOID +HalpDisplayCharacterVGA ( + IN UCHAR Character + ) + +/*++ +Routine Description: + + This routine displays a character at the current x and y positions in + the frame buffer. If a newline is encounter, then the frame buffer is + scrolled. If characters extend below the end of line, then they are not + displayed. + +Arguments: + + Character - Supplies a character to be displayed. + +Return Value: + + None. + +--*/ +{ + + // + // If the character is a newline, then scroll the screen up, blank the + // bottom line, and reset the x position. + // + + if (Character == '\n') { + HalpColumn = 0; + if (HalpRow < (HalpDisplayText - 1)) { + HalpRow += 1; + } else { // need to scroll up the screen + HalpScrollINT10(1); + } + + // + // M006 + // ESM critical logging re-print(column, row) + // + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + } + + //========================================================================= + // + // IBMBJB added tab processing + // + + else if( Character == '\t' ) // tab? + { + HalpColumn += TAB_SIZE; + HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE; + + if( HalpColumn >= 80 ) // tab beyond end of screen? + { + HalpColumn = 0; // next tab stop is 1st column of next line + + if( HalpRow >= (HalpDisplayText - 1) ) + HalpScrollINT10( 1 ); // scroll the screen up + else + ++HalpRow; + } + } + + //========================================================================= + + else if (Character == '\r') { + + // + // M006 + // ESM critical logging re-print(column,row) + // + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + HalpColumn = 0; + + } else if (Character == 0x7f) { /* DEL character */ + if (HalpColumn != 0) { + HalpColumn -= 1; + HalpOutputCharacterINT10(0); + HalpColumn -= 1; + } else /* do nothing */ + ; + } else if (Character >= 0x20) { + // + // M006 + // ESM critical logging put character. + // + + HalStringIntoBuffer( Character ); + + // Auto wrap for 80 columns per line + if (HalpColumn >= 80) { + HalpColumn = 0; + if (HalpRow < (HalpDisplayText - 1)) { + HalpRow += 1; + } else { // need to scroll up the screen + HalpScrollINT10(1); + } + } + HalpOutputCharacterINT10(Character); + } else /* skip the nonprintable character */ + ; + + return; + +} /* end of HalpDisplayCharacterVGA() */ + +VOID +HalQueryDisplayParameters ( + OUT PULONG WidthInCharacters, + OUT PULONG HeightInLines, + OUT PULONG CursorColumn, + OUT PULONG CursorRow + ) + +/*++ + +Routine Description: + + This routine return information about the display area and current + cursor position. + +Arguments: + + WidthInCharacter - Supplies a pointer to a varible that receives + the width of the display area in characters. + + HeightInLines - Supplies a pointer to a variable that receives the + height of the display area in lines. + + CursorColumn - Supplies a pointer to a variable that receives the + current display column position. + + CursorRow - Supplies a pointer to a variable that receives the + current display row position. + +Return Value: + + None. + +--*/ + +{ + + // + // Set the display parameter values and return. + // + + *WidthInCharacters = HalpDisplayWidth; + *HeightInLines = HalpDisplayText; + *CursorColumn = HalpColumn; + *CursorRow = HalpRow; + return; +} + +VOID +HalSetDisplayParameters ( + IN ULONG CursorColumn, + IN ULONG CursorRow + ) + +/*++ + +Routine Description: + + This routine set the current cursor position on the display area. + +Arguments: + + CursorColumn - Supplies the new display column position. + + CursorRow - Supplies a the new display row position. + +Return Value: + + None. + +--*/ + +{ + + // + // Set the display parameter values and return. + // + + if (CursorColumn > HalpDisplayWidth) { + CursorColumn = HalpDisplayWidth; + } + + if (CursorRow > HalpDisplayText) { + CursorRow = HalpDisplayText; + } + + HalpColumn = CursorColumn; + HalpRow = CursorRow; + return; +} + +VOID +HalpOutputCharacterOld( + IN PUCHAR Glyph + ) + +/*++ + +Routine Description: + + This routine insert a set of pixels into the display at the current x + cursor position. If the current x cursor position is at the end of the + line, then a newline is displayed before the specified character. + +Arguments: + + Character - Supplies a character to be displayed. + +Return Value: + + None. + +--*/ + +{ + + PUCHAR Destination; + PUSHORT DestinationShort; // M021 + ULONG FontValue; + ULONG I; + ULONG J; + + // + // If the current x cursor position is at the end of the line, then + // output a line feed before displaying the character. + // + + if (HalpColumn == HalpDisplayWidth) { + HalpDisplayCharacter('\n'); + } + + // + // Output the specified character and update the x cursor position. + // + + if (HalpDisplayType16BPP) { + DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT))); + + } else { + Destination = (PUCHAR)(VIDEO_MEMORY_BASE + + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth)); + } + + for (I = 0; I < HalpCharacterHeight; I += 1) { + FontValue = 0; + for (J = 0; J < HalpBytesPerRow; J += 1) { + FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8)); + } + + Glyph += 1; + for (J = 0; J < HalpCharacterWidth ; J += 1) { + + if (HalpDisplayType16BPP) { + if (FontValue >> 31) + *DestinationShort++ = (USHORT)0xffff; + else + *DestinationShort++ = (USHORT)0x000f; + + }else{ + *Destination++ = (UCHAR) (FontValue >> 31) ^ 1; /* M008 */ + } + + FontValue <<= 1; + } + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + Destination += + (1024 - HalpCharacterWidth); + } + else if (HalpDisplayType16BPP){ + DestinationShort += + (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); + } + else { + Destination += + (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); + } + + } + HalpColumn += 1; + return; +} + +VOID +Write_Dbg_Uchar( + PUCHAR Ioadress, + UCHAR Moji + ) +{ +#if defined (R96DBG) + DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji); +#endif + WRITE_PORT_UCHAR(Ioadress,Moji); +} + +VOID +HalpMoveMemory32 ( + PUCHAR Destination, + PUCHAR Source, + ULONG Length + ) + +/*++ + Routine Description: + + This function moves blocks of memory. + + Arguments: + + Destination - Supplies a pointer to the destination address of + the move operation. + + Source - Supplies a pointer to the source address of the move + operation. + + Length - Supplies the length, in bytes, of the memory to be moved. + + Return Value: + + None. + +--*/ + +{ + UCHAR Remainder; + PUCHAR Dstend; + PUCHAR Srcend; + + if ( (Source == Destination) || (Length == 0) ) { + return; + } + + if ((Source < Destination)&((Source + Length) > Destination)) { + if((Destination - Source) > 4){ + Remainder = (UCHAR) Length &0x03; + Length = Length / 4; + Dstend = Destination + Length - 4 ; + Srcend = Source + Length -4; + + for (; Length > 0; Length--) { + *(PULONG)(Dstend) = *(PULONG)(Srcend); + Dstend -= 4; + Srcend -= 4; + } + for (; Remainder > 0; Remainder--) { + *Dstend = *Srcend; + Dstend--; + Srcend--; + } + return; + } + for (; Length > 0; Length--) { + *Dstend = *Srcend; + Dstend--; + Srcend--; + } + return; + } + + else { + if( (Source - Destination) > 4 ){ + Remainder = (UCHAR) Length &0x03; + Length = Length / 4; + for (; Length > 0; Length--) { + *(PULONG)(Destination) = *(PULONG)(Source); + Destination += 4; + Source += 4; + } + for (; Remainder > 0; Remainder--) { + *Destination = *Source; + Destination++; + Source++; + } + return; + } + + for (; Length > 0; Length--) { + *Destination = *Source; + Destination++; + Source++; + } + } +} + +VOID +HalpOutputCharacterINT10 ( + IN UCHAR Character + ) +{ + ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; + + Eax = 2 << 8; // AH = 2 + Ebx = 0; // BH = page number + Edx = (HalpRow << 8) + HalpColumn; + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + Eax = (0x0A << 8) + Character; // AH = 0xA AL = character + Ebx = 0; + Ecx = 1; + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + HalpColumn += 1; +} + +VOID +HalpScrollINT10 ( + IN UCHAR LinesToScroll + ) +{ + ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; + + Eax = 6 << 8; // AH = 6 (scroll up) + Eax |= LinesToScroll; // AL = lines to scroll + Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s) + Ecx = 0; // CH,CL = upper left + Edx = ((HalpDisplayText - 1) << 8) + + (HalpDisplayWidth - 1); // DH,DL = lower right // M001,S005 + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); +} + +VOID +HalpDisplayINT10Setup ( + VOID + ) +{ + ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayWidth = 80; + HalpDisplayText = 50; // M001 + HalpScrollLine = 160; + HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); + + HalpDisplayOwnedByHal = TRUE; + + HalpResetX86DisplayAdapter(); // for compaq q-vision reset + +// M001 +++ + // + // Load 8x8 font 80x50 on VGA + // + Eax = 0x1112; // AH = 11 AL=12 + Ebx = 0; + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); +// M001 --- + + // + // Set cursor to (0,0) + // + Eax = 0x02 << 8; // AH = 2 + Ebx = 0; // BH = page Number + Edx = 0; // DH = row DL = column + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + // + // Make screen white on blue by scrolling entire screen + // + Eax = 0x06 << 8; // AH = 6 AL = 0 + Ebx = TEXT_ATTR << 8; // BH = attribute + Ecx = 0; // (x,y) upper left + Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right + Edx += HalpScrollLine/2; + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + +} + +// start M014 +VOID +HalpReadPCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function returns PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data is returned. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xffffffff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} + + + +BOOLEAN +HalpCheckPCIDevice ( + IN PCI_SLOT_NUMBER Slot + ) + +/*++ + Routine Description: + + This function checks if spcified PCI slot is valid. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + + Return Value: + + TRUE - specified slot is valid + FALSE - specified slot is invalid + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + BOOLEAN ReturnValue; + ULONG OrigData; + ULONG IdValue; + KIRQL OldIrql; + + // + // Disable PCI-MasterAbort interrupt during configration read. + // + + OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable); + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f); + + // + // read VendorID and DeviceID of the specified slot + // + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + IdValue = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + if ((USHORT)(IdValue & 0xffff) == 0xffff){ + + // + // waiting until ReceivedMasterAbort bit is set + // + + while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000)) + ; + + // + // clear the ReceivedMasterAbort bit + // + + WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000) + + // + // M018 + // Clear memory address error registers. + // + + { + LARGE_INTEGER registerLarge; + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + } + + ReturnValue = FALSE; + + } else { + + ReturnValue = TRUE; + + } + + // + // Restore the PCIInterruptEnable register. + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); + + return ReturnValue; + +} +// end M014 + +#if defined(_R94A_) +VOID +HalpDisplayGlintSetup( + VOID + ) +/*++ + +Routine Description: + + This routine initializes the GLINT 300SX Graphics accelerator. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + ULONG VerticalFrequency; + ULONG horizontalTotal; + ULONG verticalTotal; + + __VIDEO __Video; + VIDEO Video = &__Video; + long ClockDivider; + + // for initialize ramdac + ULONG Dac = RGB525_REGISTER_BASE; + UCHAR ByteVal; + + // for initialize timing + ULONG Glint = GLINT_VIDEO_REGISTER_BASE - 0x3000; + + // for initialize control + ULONG SerialClk; + ULONG Temp; + ULONG Data; + ULONG Mask; + + // for initialize RampLut + ULONG Index; + + // for clear the screen + PULONG DestinationUlong; + ULONG Length; + + /* check revision id R01 or R02. assume 40MHz(R01) or 50MHz(R02) reference clock for now */ + + if ( HalpGlintRevisionId == 0){ + Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz; + } else { + Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz; // S006 + } + +// +// Calculate vertical frequency. +// + +#if defined(_GLINT60HZ_) + + VerticalFrequency = 60; + +#else + + horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime + +HalpMonitorConfigurationData.HorizontalBackPorch + +HalpMonitorConfigurationData.HorizontalFrontPorch + +HalpMonitorConfigurationData.HorizontalSync ); + + verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution + +HalpMonitorConfigurationData.VerticalBackPorch + +HalpMonitorConfigurationData.VerticalFrontPorch + +HalpMonitorConfigurationData.VerticalSync ); + + VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal); + +#endif // _GLINT60HZ_ + + // + // Initialize video data + // + + /* get timing values for named resolution */ + + if ( HalpMonitorConfigurationData.HorizontalResolution == 1280 + && HalpMonitorConfigurationData.VerticalResolution == 1024 + && VerticalFrequency == 75) + { + Video->ImageWidth = 1280; + Video->ImageHeight = 1024; + Video->HLimit = 8 * 211; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 20; + Video->HBlankEnd = 8 * 51; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 1066; + Video->VSyncStart = 2; + Video->VSyncEnd = 5; + Video->VBlankEnd = 42; + Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + /* 134 MHz */ + Video->PixelClock = RGB525_DF(3) | RGB525_VCO_DIV_COUNT(2); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 + && VerticalFrequency == 75) + { + Video->ImageWidth = 1024; + Video->ImageHeight = 768; + Video->HLimit = 8 * 164; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 14; + Video->HBlankEnd = 8 * 36; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; + Video->VLimit = 800; + Video->VSyncStart = 2; + Video->VSyncEnd = 5; + Video->VBlankEnd = 32; + Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; + /* 79 MHz */ + Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(14); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 + && VerticalFrequency == 60) + { + Video->ImageWidth = 1024; + Video->ImageHeight = 768; + Video->HLimit = 8 * 168; + Video->HSyncStart = 8 * 3; + Video->HSyncEnd = 8 * 20; + Video->HBlankEnd = 8 * 40; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 806; + Video->VSyncStart = 4; + Video->VSyncEnd = 10; + Video->VBlankEnd = 38; + Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + /* 65 MHz */ + Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 + && VerticalFrequency == 75) + { + Video->ImageWidth = 800; + Video->ImageHeight = 600; + Video->HLimit = 8 * 132; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 12; + Video->HBlankEnd = 8 * 32; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; + Video->VLimit = 625; + Video->VSyncStart = 2; + Video->VSyncEnd = 5; + Video->VBlankEnd = 25; + Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH; + /* 49.5 MHz */ + Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(34); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 + && VerticalFrequency == 60) + { + Video->ImageWidth = 800; + Video->ImageHeight = 600; + Video->HLimit = 8 * 132; + Video->HSyncStart = 8 * 5; + Video->HSyncEnd = 8 * 21; + Video->HBlankEnd = 8 * 32; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_HIGH; + Video->VLimit = 628; + Video->VSyncStart = 2; + Video->VSyncEnd = 6; + Video->VBlankEnd = 28; + Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_HIGH; + /* 40 MHz */ + Video->PixelClock = RGB525_DF(1) | RGB525_VCO_DIV_COUNT(15); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 // add 4/5/1995 + && HalpMonitorConfigurationData.VerticalResolution == 480 + && VerticalFrequency == 60) + { + Video->ImageWidth = 640; + Video->ImageHeight = 480; + Video->HLimit = 8 * 100; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 14; + Video->HBlankEnd = 8 * 20; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 525; + Video->VSyncStart = 12; + Video->VSyncEnd = 13; + Video->VBlankEnd = 45; + Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW; + /* 31.5 MHz */ + Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(36); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 640 + && HalpMonitorConfigurationData.VerticalResolution == 480 + && VerticalFrequency == 75) + { + Video->ImageWidth = 640; + Video->ImageHeight = 480; + Video->HLimit = 8 * 105; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 10; + Video->HBlankEnd = 8 * 25; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 500; + Video->VSyncStart = 2; + Video->VSyncEnd = 5; + Video->VBlankEnd = 20; + Video->VSyncPolarity = GLINT_VSYNC_ACTIVE_LOW; + /* 31.5 MHz */ + Video->PixelClock = RGB525_DF(0) | RGB525_VCO_DIV_COUNT(61); + } + else if ( HalpMonitorConfigurationData.HorizontalResolution == 1280 + && HalpMonitorConfigurationData.VerticalResolution == 1024 + && VerticalFrequency == 57) + { + Video->ImageWidth = 1280; + Video->ImageHeight = 1024; + Video->HLimit = 8 * 211; + Video->HSyncStart = 8 * 2; + Video->HSyncEnd = 8 * 20; + Video->HBlankEnd = 8 * 51; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 1066; + Video->VSyncStart = 2; + Video->VSyncEnd = 5; + Video->VBlankEnd = 42; + Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + /* 103 MHz */ + Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(38); + } + else { + // + // force to set the resolution. 1024x768(60MHz) + // + + Video->ImageWidth = 1024; + Video->ImageHeight = 768; + Video->HLimit = 8 * 168; + Video->HSyncStart = 8 * 3; + Video->HSyncEnd = 8 * 20; + Video->HBlankEnd = 8 * 40; + Video->HSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + Video->VLimit = 806; + Video->VSyncStart = 4; + Video->VSyncEnd = 10; + Video->VBlankEnd = 38; + Video->VSyncPolarity = GLINT_HSYNC_ACTIVE_LOW; + /* 65 MHz */ + Video->PixelClock = RGB525_DF(2) | RGB525_VCO_DIV_COUNT(0); +#if DBG + DbgBreakPoint(); +#endif + } + + /* record image depth */ + + Video->ImageDepth = 16; + + /* determine video clock divider and pixel format */ + + ClockDivider = 4; + Video->PixelFormat = RGB525_PIXEL_FORMAT_16_BPP; + + /* adjust horizontal timings */ + + Video->HLimit /= ClockDivider; + Video->HSyncStart /= ClockDivider; + Video->HSyncEnd /= ClockDivider; + Video->HBlankEnd /= ClockDivider; + + // + // Initialize ramdac data + // + + RGB525_WRITE(Dac, __RGB525_PixelMask, 0xff); + + /* set MiscControlOne register */ + ByteVal = RGB525_MISR_CNTL_OFF + | RGB525_VMSK_CNTL_OFF + | RGB525_PADR_RFMT_READ_ADDR + | RGB525_SENS_DSAB_DISABLE + | RGB525_VRAM_SIZE_64; + RGB525_SET_REG(Dac, __RGB525_MiscControlOne, ByteVal); + + /* set MiscControlTwo register */ + ByteVal = RGB525_PCLK_SEL_PLL + | RGB525_INTL_MODE_DISABLE + | RGB525_BLANK_CNTL_NORMAL + | RGB525_COL_RES_8_BIT + | RGB525_PORT_SEL_VRAM; + RGB525_SET_REG(Dac, __RGB525_MiscControlTwo, ByteVal); + + /* set MiscControlThree register */ + ByteVal = RGB525_SWAP_RB_DISABLE + | RGB525_SWAP_WORD_31_00_FIRST + | RGB525_SWAP_NIB_07_04_FIRST; + RGB525_SET_REG(Dac, __RGB525_MiscControlThree, ByteVal); + + /* set MiscClockControl register */ + ByteVal = RGB525_DDOTCLK_DISABLE + | RGB525_SCLK_ENABLE + | RGB525_PLL_ENABLE; + RGB525_SET_REG(Dac, __RGB525_MiscClockControl, ByteVal); + + /* set SyncControl register */ + ByteVal = RGB525_DLY_CNTL_ADD + | RGB525_VSYN_INVT_DISABLE + | RGB525_HSYN_INVT_DISABLE + | RGB525_VSYN_CNTL_NORMAL + | RGB525_HSYN_CNTL_NORMAL; + RGB525_SET_REG(Dac, __RGB525_SyncControl, ByteVal); + + /* set HSyncControl register */ + RGB525_SET_REG(Dac, __RGB525_HSyncControl, RGB525_HSYN_POS(0)); + + /* set PowerManagement register */ + ByteVal = RGB525_SCLK_PWR_NORMAL + | RGB525_DDOT_PWR_DISABLE + | RGB525_SYNC_PWR_NORMAL + | RGB525_ICLK_PWR_NORMAL + | RGB525_DAC_PWR_NORMAL; + RGB525_SET_REG(Dac, __RGB525_PowerManagement, ByteVal); + + /* set DACOperation register */ + ByteVal = RGB525_SOG_DISABLE + | RGB525_BRB_NORMAL + | RGB525_DSR_FAST + | RGB525_DPE_ENABLE; /* disable? */ + RGB525_SET_REG(Dac, __RGB525_DACOperation, ByteVal); + + /* set PaletteControl register */ + ByteVal = RGB525_6BIT_LINEAR_ENABLE + | RGB525_PALETTE_PARTITION(0); + RGB525_SET_REG(Dac, __RGB525_PaletteControl, ByteVal); + + /* set PixelFormat register */ + RGB525_SET_REG(Dac, __RGB525_PixelFormat, Video->PixelFormat); + + /* set 8BitPixelControl register */ + RGB525_SET_REG(Dac, __RGB525_8BitPixelControl, + RGB525_B8_DCOL_INDIRECT); + + /* set 16BitPixelControl register */ + ByteVal = RGB525_B16_DCOL_INDIRECT + | RGB525_B16_565 + | RGB525_B16_ZIB + | RGB525_B16_SPARSE; + + RGB525_SET_REG(Dac, __RGB525_16BitPixelControl, ByteVal); + + /* set 32BitPixelControl register */ + RGB525_SET_REG(Dac, __RGB525_32BitPixelControl, + RGB525_B32_DCOL_INDIRECT); + + /* set PLLControlOne register */ + ByteVal = RGB525_REF_SRC_REFCLK + | RGB525_PLL_INT_FS_DIRECT; + RGB525_SET_REG(Dac, __RGB525_PLLControlOne, ByteVal); + + /* set PLLControlTwo register */ + RGB525_SET_REG(Dac, __RGB525_PLLControlTwo, RGB525_PLL_INT_FS(0)); + + /* set PLLRefDivCount register */ + RGB525_SET_REG(Dac, __RGB525_PLLRefDivCount, Video->RefDivCount); + + /* set F0 register */ + RGB525_SET_REG(Dac, __RGB525_F0, Video->PixelClock); + + /* set CursorControl register */ + RGB525_SET_REG(Dac, __RGB525_CursorControl, RGB525_CURSOR_MODE_OFF); + + // + // Initialize timing + // + + /* horizontal video timing values */ + + GLINT_WRITE(Glint, __GLINT_VTGHLimit, Video->HLimit); + GLINT_WRITE(Glint, __GLINT_VTGHSyncStart, Video->HSyncStart); + GLINT_WRITE(Glint, __GLINT_VTGHSyncEnd, Video->HSyncEnd); + GLINT_WRITE(Glint, __GLINT_VTGHBlankEnd, Video->HBlankEnd); + + /* vertical video timing values */ + + GLINT_WRITE(Glint, __GLINT_VTGVLimit, Video->VLimit); + GLINT_WRITE(Glint, __GLINT_VTGVSyncStart, Video->VSyncStart); + GLINT_WRITE(Glint, __GLINT_VTGVSyncEnd, Video->VSyncEnd); + GLINT_WRITE(Glint, __GLINT_VTGVBlankEnd, Video->VBlankEnd); + + /* horizontal clock gate values */ + + GLINT_WRITE(Glint, __GLINT_VTGHGateStart, Video->HBlankEnd - 2); + GLINT_WRITE(Glint, __GLINT_VTGHGateEnd, Video->HLimit - 2); + + /* vertical clock gate values */ + + GLINT_WRITE(Glint, __GLINT_VTGVGateStart, Video->VBlankEnd - 1) + GLINT_WRITE(Glint, __GLINT_VTGVGateEnd, Video->VBlankEnd); + + // + // Initialize control + // + + /* serial clock control */ + + SerialClk = GLINT_EXTERNAL_QSF + | GLINT_SPLIT_SIZE_128_WORD + | GLINT_SCLK_VCLK_DIV_2; + + GLINT_WRITE(Glint, __GLINT_VTGSerialClk, SerialClk); + + /* set sync polarities and unblank screen */ + + // UpdatePolarityRegister(Glint, + // GLINT_CBLANK_ACTIVE_LOW + // | Video->HSyncPolarity + // | Video->VSyncPolarity, + // GLINT_CBLANK_POLARITY_MASK + // | GLINT_HSYNC_POLARITY_MASK + // | GLINT_VSYNC_POLARITY_MASK); + + Data = GLINT_CBLANK_ACTIVE_LOW + | Video->HSyncPolarity + | Video->VSyncPolarity; + Mask = GLINT_CBLANK_POLARITY_MASK + | GLINT_HSYNC_POLARITY_MASK + | GLINT_VSYNC_POLARITY_MASK; + + /* read video polarity control register */ + + GLINT_READ(Glint, __GLINT_VTGPolarity, Temp); + + /* replace existing polarity field */ + + Temp = (Temp & ~Mask) | (Data & Mask); + + /* write result back to polarity register */ + + GLINT_WRITE(Glint, __GLINT_VTGPolarity, Temp); + + /* set FrameRowAddr */ + + GLINT_WRITE(Glint, __GLINT_VTGFrameRowAddr, 0); + + // + // Initialize RampLut + // + + /* initialise palette address */ + + RGB525_WRITE(Dac, __RGB525_PalAddrWrite, 0); + + /* ramp colour components using auto-increment */ + + for (Index = 0; Index <= 0xff; Index++) + { + RGB525_WRITE(Dac, __RGB525_PaletteData, Index); + RGB525_WRITE(Dac, __RGB525_PaletteData, Index); + RGB525_WRITE(Dac, __RGB525_PaletteData, Index); + } + + // + // Clear the screen. + // + + DestinationUlong = (PULONG)VIDEO_MEMORY_BASE; + + Length = (HalpMonitorConfigurationData.VerticalResolution * + HalpMonitorConfigurationData.HorizontalResolution -1) * sizeof(USHORT); + + for (Index = 0; Index < (Length / sizeof(ULONG)); Index++) + *(DestinationUlong++) = (ULONG)0x000f000f; + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; + +} +#endif // _R94A_ + +// +// M010 +// for software controlled power supply. +// +#if defined(_MRCPOWER_) +/* Start M007 */ +VOID +HalpMrcModeChange( + UCHAR Mode +) +/*++ + +Routine Description: + + This routine is change Mode bit on MRC Controller. + +Arguments: + + Mode - Parameter for setting Mode bit on MRC + +Return Value: + + None + +--*/ +{ + + PHYSICAL_ADDRESS physicalAddress; + UCHAR ModeNow; + KIRQL OldIrql; + ENTRYLO Pte[2]; + + // + // MRC Controller Mapping, when first call + // + + if (HalpMrcControlMapped == FALSE) { + physicalAddress.HighPart = 0; + physicalAddress.LowPart = MRC_TEMP_PHYSICAL_BASE; + HalpMrcControlBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + if (HalpMrcControlBase != NULL) { + HalpMrcControlMapped = TRUE; + } + } + + if (HalpMrcControlMapped == TRUE){ + + ModeNow = READ_REGISTER_UCHAR( + &((PMRC_REGISTERS)HalpMrcControlBase)->Mode + ); + + // + // Set MRC Mode bit + // + WRITE_REGISTER_UCHAR( + &((PMRC_REGISTERS)HalpMrcControlBase)->Mode, + ((ModeNow & 0x02) | (Mode << 7)), + ); + + } else { + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT; + + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + // + // set second page to global and not valid. + // + + Pte[0].C = UNCACHED_POLICY; + Pte[1].G = 1; + Pte[1].V = 0; + + // + // Map MRC using virtual address of DMA controller. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); + + ModeNow = READ_REGISTER_UCHAR( + &MRC_CONTROL->Mode // B028 + ); + + // + // Set MRC Mode bit + // + WRITE_REGISTER_UCHAR( + &MRC_CONTROL->Mode, + ((ModeNow & 0x02) | (Mode << 7)), + ); + + + // Start M008 + // + // Resume fixed TLB for DMA + // + + Pte[0].PFN = DMA_PHYSICAL_BASE >> PAGE_SHIFT; + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + Pte[0].C = UNCACHED_POLICY; + + + Pte[1].PFN = INTERRUPT_PHYSICAL_BASE >> PAGE_SHIFT; + Pte[1].G = 1; + Pte[1].V = 1; + Pte[1].D = 1; + + Pte[1].C = UNCACHED_POLICY; + + // End M008 + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); + + KeLowerIrql(OldIrql); + } +} +/* End M007 */ +#endif // _MRCPOWER_ + +VOID +HalpWritePCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function writes PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data to write. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xffffffff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + +// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); + WRITE_REGISTER_ULONG(R94A_PCI_DATA_REG, *Buffer); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} +VOID +HalpReadPCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUSHORT Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function returns PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data is returned. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xffff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG))); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} + +VOID +HalpWritePCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUSHORT Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function returns PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data is returned. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xffff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + +// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); + WRITE_REGISTER_USHORT((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} + +VOID +HalpReadPCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function returns PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data is returned. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG))); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} + +VOID +HalpWritePCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ) + +/*++ + Routine Description: + + This function returns PCI configuration data. + + Arguments: + + Slot - Supplies a PCI slot number and function number. + Buffer - Supplies a pointer to a configuration data is returned. + Offset - Offset in the PCI configuration header. + + Return Value: + + None. + +--*/ + +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + // + // check to see if specified slot is valid + // + + if (!HalpCheckPCIDevice(Slot)) { + + // + // Invalid SlotID return no data + // + + *Buffer = 0xff; + return ; + + } + + *((PULONG) &ConfigAddressValue) = 0x0; + + ConfigAddressValue.ConfigEnable = 1; + ConfigAddressValue.DeviceNumber = Slot.u.bits.DeviceNumber; + ConfigAddressValue.FunctionNumber = Slot.u.bits.FunctionNumber; + ConfigAddressValue.RegisterNumber = Offset >> 2; + + // + // Synchronize with PCI configuration + // + +// KeRaiseIrql(PROFILE_LEVEL, &OldIrql); // M017 +// KiAcquireSpinLock(&HalpPCIConfigLock); + + WRITE_REGISTER_ULONG(R94A_PCI_ADDR_REG, *((PULONG) &ConfigAddressValue)); + +// *Buffer = READ_REGISTER_ULONG(R94A_PCI_DATA_REG); + WRITE_REGISTER_UCHAR((PUCHAR)R94A_PCI_DATA_REG + (Offset % sizeof(ULONG)),*Buffer); + + // + // Release spinlock + // + +// KiReleaseSpinLock(&HalpPCIConfigLock); +// KeLowerIrql(OldIrql); + + return; +} diff --git a/private/ntos/nthals/halr96b/mips/jxdmadsp.s b/private/ntos/nthals/halr96b/mips/jxdmadsp.s new file mode 100644 index 000000000..370edd47f --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxdmadsp.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\jxdmadsp.s" diff --git a/private/ntos/nthals/halr96b/mips/jxebsup.c b/private/ntos/nthals/halr96b/mips/jxebsup.c new file mode 100644 index 000000000..5fa4f8677 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxebsup.c @@ -0,0 +1,1398 @@ +// #pragma comment(exestr, "@(#) jxebsup.c 1.1 95/09/28 15:36:45 nec") +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + jxebsup.c + +Abstract: + + The module provides the EISA bus support for JAZZ systems. + +Author: + + Jeff Havens (jhavens) 19-Jun-1991 + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto + - HalpCreateEisa(PCI)Structures() + function name changed. + interrupt dispatcher is changed for PCI/EISA. + comment out EISA NMI disable code. + - HalpEisaDispatch() + add the PCI interrupt handler. + add the avoidance the IR7 and IR15 spurious interrupt. + H001 Tue Oct 11 18:52:39 JST 1994 kbnes!kishimoto + - modify original compile error + H002 Mon Oct 17 13:54:43 JST 1994 kbnes!kishimoto + - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX() + - modify original compile error + S003 Thu Dec 22 11:39:57 JST 1994 kbnes!A.Kuriyama + -add beta machine limit + S004 Mon Jan 23 13:57:08 JST 1995 kbnes!A.Kuriyama + -add raise irql for dummyread for EISA/PCI acknouledge + H003 Tue Jan 24 19:04:04 1995 kbnes!kishimoto + -Add Enable the PCI interrupts to the CPU + M005 Wed Jan 25 21:02:51 JST 1995 kbnes!A.Kuriyama + -add 64byte align between dummy read and EISA/PCI Ack. + H006 Tue Feb 7 21:04:30 JST 1995 kbnes!kisimoto + -bug fix when spurious interrupt occurs + S007 kuriyama@oa2.kb.nec.co.jp Thu Apr 06 00:18:14 JST 1995 + - Disable EISA NMI + S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 03:58:30 JST 1995 + - add panicflag for esm + S009 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:18:10 JST 1995 + - Merge build 1057 + H010 kisimoto@oa2.kb.nec.co.jp Fri Aug 11 17:40:26 1995 + - Removed M005, etc. + +--*/ + +#include "halp.h" +#include "eisa.h" +#include "bugcodes.h" + + +// +// Define the context structure for use by the interrupt routine. +// + +typedef +BOOLEAN +(*PSECONDARY_DISPATCH)( + PKINTERRUPT Interrupt + ); + +// +// The following is the interrupt object used for DMA controller interrupts. +// DMA controller interrupts occur when a memory parity error occurs or a +// programming error occurs to the DMA controller. +// + +KINTERRUPT HalpEisaNmiInterrupt; + +UCHAR EisaNMIMsg[] = "NMI: Eisa IOCHKERR board x\n"; + +// +// The following function is called when an EISA NMI occurs. +// + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// Define save area for EISA adapter objects. +// + +PADAPTER_OBJECT HalpEisaAdapter[8]; + +// +// Define save area for EISA interrupt mask resiters and level\edge control +// registers. +// + +UCHAR HalpEisaInterrupt1Mask; +UCHAR HalpEisaInterrupt2Mask; +UCHAR HalpEisaInterrupt1Level; +UCHAR HalpEisaInterrupt2Level; + +// +// Define EISA bus interrupt affinity. +// + +KAFFINITY HalpEisaBusAffinity; + +PADAPTER_OBJECT +HalpAllocateEisaAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor + ) +/*++ + +Routine Description: + + This function allocates an EISA adapter object according to the + specification supplied in the device description. The necessary device + descriptor information is saved. If there is + no existing adapter object for this channel then a new one is allocated. + The saved information in the adapter object is used to set the various DMA + modes when the channel is allocated or a map transfer is done. + +Arguments: + + DeviceDescription - Supplies the description of the device which want to + use the DMA adapter. + +Return Value: + + Returns a pointer to the newly created adapter object or NULL if one + cannot be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + PVOID adapterBaseVa; + ULONG channelNumber; + ULONG controllerNumber; + DMA_EXTENDED_MODE extendedMode; + UCHAR adapterMode; + BOOLEAN useChannel; + BOOLEAN eisaSystem; + + // + // Determine if the the channel number is important. Master cards on + // Eisa do not use a channel number. + // + + if (DeviceDescriptor->InterfaceType == Eisa && + DeviceDescriptor->Master) { + + useChannel = FALSE; + } else { + + useChannel = TRUE; + } + + // + // Channel 4 cannot be used since it is used for chaining. Return null if + // it is requested. + // + + if ((DeviceDescriptor->DmaChannel == 4 || + DeviceDescriptor->DmaChannel > 7) && useChannel) { + + return(NULL); + } + + // + // Set the channel number number. + // + + channelNumber = DeviceDescriptor->DmaChannel & 0x03; + + // + // Set the adapter base address to the Base address register and controller + // number. + // + + if (!(DeviceDescriptor->DmaChannel & 0x04)) { + + controllerNumber = 1; + adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; + + } else { + + controllerNumber = 2; + adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort; + + } + + // + // Determine if a new adapter object is necessary. If so then allocate it. + // + + if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) { + + adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel]; + + } else { + + // + // Allocate an adapter object. + // + + adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter( + 0, + adapterBaseVa, + NULL + ); + + if (adapterObject == NULL) { + + return(NULL); + + } + + if (useChannel) { + + HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject; + + } + + } + + + // + // If the channel is not used then indicate the this is an Eisa bus + // master by setting the page port and mode to cascade even though + // it is not used. + // + + if (!useChannel) { + adapterObject->PagePort = (PVOID) (~0x0); + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + return(adapterObject); + } + + // + // Setup the pointers to all the random registers. + // + + adapterObject->ChannelNumber = (UCHAR)channelNumber; + + if (controllerNumber == 1) { + + switch ((UCHAR)channelNumber) { + + case 0: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0; + break; + + case 1: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1; + break; + + case 2: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2; + break; + + case 3: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 1; + + // + // Save the extended mode register address. + // + + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort; + + } else { + + switch ((UCHAR)channelNumber) { // H001 + case 1: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5; + break; + + case 2: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6; + break; + + case 3: + adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7; + break; + } + + // + // Set the adapter number. + // + + adapterObject->AdapterNumber = 2; + + // + // Save the extended mode register address. + // + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort; + + } + + // + // Initialzie the extended mode port. + // + + *((PUCHAR) &extendedMode) = 0; + + extendedMode.ChannelNumber = (UCHAR)channelNumber; + + switch (DeviceDescriptor->DmaSpeed) { + case Compatible: + extendedMode.TimingMode = COMPATIBLITY_TIMING; + break; + + case TypeA: + extendedMode.TimingMode = TYPE_A_TIMING; + break; + + case TypeB: + extendedMode.TimingMode = TYPE_B_TIMING; + break; + + case TypeC: + extendedMode.TimingMode = BURST_TIMING; + break; + + default: + ObDereferenceObject( adapterObject ); + return(NULL); + + } + + switch (DeviceDescriptor->DmaWidth) { + case Width8Bits: + extendedMode.TransferSize = BY_BYTE_8_BITS; + break; + + case Width16Bits: + extendedMode.TransferSize = BY_BYTE_16_BITS; + break; + + case Width32Bits: + extendedMode.TransferSize = BY_BYTE_32_BITS; + break; + + default: + ObDereferenceObject( adapterObject ); + return(NULL); + + } + + WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode)); + + // + // Initialize the adapter mode register value to the correct parameters, + // and save them in the adapter object. + // + + adapterMode = 0; + ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber; + + if (DeviceDescriptor->Master) { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + + // + // Set the mode, and enable the request. + // + + if (adapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = adapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber) + ); + + } + + } else if (DeviceDescriptor->DemandMode) { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE; + + } else { + + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE; + + } + + if (DeviceDescriptor->AutoInitialize) { + + ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1; + + } + + adapterObject->AdapterMode = adapterMode; + + return(adapterObject); +} + +BOOLEAN +HalpCreateEisaStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for EISA operations + and connects the intermediate interrupt dispatcher. It also initializes the + EISA interrupt controller. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + ULONG DataLong; + KIRQL oldIrql; + +#if !defined(_DUO_) && !defined(_R94A_) // H000 + + // + // Initialize the EISA NMI interrupt. + // + + KeInitializeInterrupt( &HalpEisaNmiInterrupt, + HalHandleNMI, + NULL, + NULL, + EISA_NMI_LEVEL, + EISA_NMI_LEVEL, + EISA_NMI_LEVEL, + LevelSensitive, + FALSE, + 0, + FALSE + ); + + // + // Don't fail if the interrupt cannot be connected. + // + + KeConnectInterrupt( &HalpEisaNmiInterrupt ); + + // + // Clear the Eisa NMI disable bit. This bit is the high order of the + // NMI enable register. + // + +// DataByte = 0; + // + // TEMPTEMP Disable the NMI because this is causing machines in the build + // lab to fail. + // + DataByte = 0x80; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + DataByte + ); + +#else + + // + // Clear the Eisa NMI disable bit. This bit is the high order of the + // NMI enable register. + // + +// DataByte = 0; + // + // TEMPTEMP Disable the NMI because this is causing machines in the build + // lab to fail. + // + DataByte = 0x80; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + DataByte + ); + +#endif + + // + // Directly connect the EISA interrupt dispatcher to the level for + // EISA bus interrupt. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization. + // + + PCR->InterruptRoutine[EISA_DEVICE_LEVEL] = + (PKINTERRUPT_ROUTINE)HalpEisaDispatch; + + // + // start H003 + // Enable the following PCI interrupts to the CPU. + // Target abort, Master abort + // SRetry overflow, ERR, PERR + // + + DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long); + DataLong |= ENABLE_PERR_INTERRUPTS; + DataLong |= ENABLE_SERR_INTERRUPTS; + DataLong |= ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS; + DataLong |= ENABLE_MASTER_ABORT_INTERRUPTS; + DataLong |= ENABLE_TARGET_ABORT_INTERRUPTS; + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long, + DataLong); + + // + // Raise the IRQL while the EISA interrupt controller is initalized. + // + + KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql); + + // + // Initialize the EISA interrupt controller. There are two cascaded + // interrupt controllers, each of which must initialized with 4 initialize + // control words. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1; + ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + DataByte + ); + + // + // The second intitialization control word sets the iterrupt vector to + // 0-15. + // + + DataByte = 0; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = 0x08; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The thrid initialization control word set the controls for slave mode. + // The master ICW3 uses bit position and the slave ICW3 uses a numberic. + // + + DataByte = 1 << SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + DataByte = SLAVE_IRQL_LEVEL; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + // + // The fourth initialization control word is used to specify normal + // end-of-interrupt mode and not special-fully-nested mode. + // + + DataByte = 0; + ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + DataByte + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + DataByte + ); + + + // + // Disable all of the interrupts except the slave. + // + + HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + HalpEisaInterrupt2Mask = 0xFF; + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + // + // Initialize the edge/level register masks to 0 which is the default + // edge sensitive value. + // + + HalpEisaInterrupt1Level = 0; + HalpEisaInterrupt2Level = 0; + + // + // Set EISA bus interrupt affinity. + // + + HalpEisaBusAffinity = PCR->SetMember; + + // + // Restore IRQL level. + // + + KeLowerIrql(oldIrql); + + // + // Initialize the DMA mode registers to a default value. + // Disable all of the DMA channels except channel 4 which is that + // cascade of channels 0-3. + // + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort.AllMask, + 0x0F + ); + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask, + 0x0E + ); + +#if defined(_DUO_) + + // + // Enable the EISA interrupts to the CPU. + // + + DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long); + DataLong |= ENABLE_EISA_INTERRUPTS; + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long, + DataLong); + +#endif + + return(TRUE); +} + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) + +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt being generated + via the vector that is directly connected to EISA device interrupt. + + N.B. This interrupt is directly connected and therefore, no argument + values are defined. + +Arguments: + + None. + +Return Value: + + Returns the value returned from the second level routine. + +--*/ + +{ + + PULONG dispatchCode; + USHORT interruptVector; + PKINTERRUPT interruptObject; + BOOLEAN returnValue; + +#if defined(_DUO_) + + PUSHORT Acknowledge = (PUSHORT)&DMA_CONTROL->EisaInterruptAcknowledge.Long; + + // + // Read the interrupt vector. + // + + interruptVector = READ_REGISTER_USHORT(Acknowledge); + +#else + + PUCHAR Acknowledge = (PUCHAR)&DMA_CONTROL->InterruptAcknowledge.Long; + + // + // Read the interrupt vector. + // + + interruptVector = READ_REGISTER_UCHAR(Acknowledge); + +#endif + + // + // If the vector is nonzero, then it is either an EISA interrupt + // of an NMI interrupt. Otherwise, the interrupt is no longer + // present. + // + + if (interruptVector != 0) { + + // + // If the interrupt vector is 0x8000 then the interrupt is an NMI. + // Otherwise, dispatch the interrupt to the appropriate interrupt + // handler. + // + + if (interruptVector != 0x8000) { + + // + // H000 + // If the interrupt vector is 0x4000 then this is an PCI interrupt. + // Call the PCI interrupt handler. + // + + if (interruptVector != 0x4000) { + + // + // Mask the upper bits off since the vector is only a byte and + // dispatch to the secondary interrupt service routine. + // + + interruptVector &= 0xff; + + // + // H000 + // check to see if this is a spurious interrupt + // + + if (interruptVector == 7 || interruptVector == 15){ + PVOID IsrPortAddressVa; + UCHAR IsrValue; + + #define OCW3_READ_ISR 0x0b + #define OCW3_READ_IRR 0x0a + + IsrPortAddressVa = (interruptVector == 7) ? + &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0): + &(((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0); // H006 + + // + // Change mode OCW3 register, bacause we want to read ISR + // read ISR on 8259. + // + + WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_ISR); + IsrValue = READ_REGISTER_UCHAR( IsrPortAddressVa ); + + // + // resume mode OCW3 register to IRR + // + + WRITE_REGISTER_UCHAR(IsrPortAddressVa, OCW3_READ_IRR); + + // + // check to see if ISR is zero, then we do not call driver. + // + + if ( !IsrValue ){ + + goto NotCallDriver; + + } + } + + dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject); + +NotCallDriver: + + // + // Dismiss the interrupt in the EISA interrupt controllers. + // + // If this is a cascaded interrupt then the interrupt must be + // dismissed in both controllers. + // + + if (interruptVector & 0x08) { + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT); + } + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0, + NONSPECIFIC_END_OF_INTERRUPT); + + + } else { + returnValue = HalpPCIDispatch(NULL, NULL); + } + + } else { + returnValue = HalHandleNMI(NULL, NULL); + } + + } else { + returnValue = FALSE; + } + + return returnValue; +} + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the EISA bus specified EISA bus interrupt. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the EISA interrupt vector. + // + + Vector -= EISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector; + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + } + +} + +VOID +HalpEisaMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This function programs the EISA DMA controller for a transfer. + +Arguments: + + Adapter - Supplies the DMA adapter object to be programed. + + Offset - Supplies the logical address to use for the transfer. + + Length - Supplies the length of the transfer in bytes. + + WriteToDevice - Indicates the direction of the transfer. + +Return Value: + + None. + +--*/ + +{ + PUCHAR BytePtr; + UCHAR adapterMode; + + BytePtr = (PUCHAR) &Offset; + + ASSERT(Offset >= 0x100000); + + adapterMode = AdapterObject->AdapterMode; + + // + // Check to see if this request is for a master I/O card. + // + + if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) { + + // + // Set the mode, Disable the request and return. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } + + return; + } + + + // + // Determine the mode based on the transfer direction. + // + + ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ? + WRITE_TRANSFER : READ_TRANSFER; + + // + // Determine the controller number based on the Adapter base va. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + BytePtr[2] + ); + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[0] + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseAddress, + BytePtr[1] + ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + + (ULONG)AdapterObject->PagePort, + BytePtr[2] + ); + + // + // Write the high page register with zero value. This enable a special mode + // which allows ties the page register and base count into a single 24 bit + // address register. + // + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) + + (ULONG)AdapterObject->PagePort, + 0 + ); + + + // + // Notify DMA chip of the length to transfer. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) & 0xff) + ); + + WRITE_REGISTER_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount, + (UCHAR) ((Length - 1) >> 8) + ); + + + // + // Set the DMA chip to read or write mode; and unmask it. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + } + +} + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This function enables the EISA bus specified EISA bus interrupt and sets + the level/edge register to the requested value. + +Arguments: + + Vector - Supplies the vector of the ESIA interrupt that is enabled. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + None. + +--*/ + +{ + + // + // Calculate the EISA interrupt vector. + // + + Vector -= EISA_VECTORS; + + // + // Determine if this vector is for interrupt controller 1 or 2. + // + + if (Vector & 0x08) { + + // + // The interrupt is in controller 2. + // + + Vector &= 0x7; + + HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1, + HalpEisaInterrupt2Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel, + HalpEisaInterrupt2Level + ); + + } else { + + // + // The interrupt is in controller 1. + // + + Vector &= 0x7; + + HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector); + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1, + HalpEisaInterrupt1Mask + ); + + // + // Set the level/edge control register. + // + + if (InterruptMode == LevelSensitive) { + + HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector); + + } else { + + HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector); + + } + + WRITE_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel, + HalpEisaInterrupt1Level + ); + } + +} + +BOOLEAN +HalHandleNMI( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This function is called when an EISA NMI occurs. It print the appropriate + status information and bugchecks. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object + + ServiceContext - Bug number to call bugcheck with. + +Return Value: + + Returns TRUE. + +--*/ +{ + UCHAR StatusByte; + UCHAR EisaPort; + ULONG port; + + HalpChangePanicFlag(16, 0x01, 0x10); // S008 + + StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus); + + if (StatusByte & 0x80) { + HalDisplayString ("NMI: Parity Check / Parity Error\n"); + } + + if (StatusByte & 0x40) { + HalDisplayString ("NMI: Channel Check / IOCHK\n"); + } + + // + // This is an Eisa machine, check for extnded nmi information... + // + + StatusByte = READ_PORT_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl); + + if (StatusByte & 0x80) { + HalDisplayString ("NMI: Fail-safe timer\n"); + } + + if (StatusByte & 0x40) { + HalDisplayString ("NMI: Bus Timeout\n"); + } + + if (StatusByte & 0x20) { + HalDisplayString ("NMI: Software NMI generated\n"); + } + + // + // Look for any Eisa expansion board. See if it asserted NMI. + // + + for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) { + port = (EisaPort << 12) + 0xC80; + port += (ULONG) HalpEisaControlBase; + WRITE_PORT_UCHAR ((PUCHAR) port, 0xff); + StatusByte = READ_PORT_UCHAR ((PUCHAR) port); + + if ((StatusByte & 0x80) == 0) { + // + // Found valid Eisa board, Check to see if it's + // if IOCHKERR is asserted. + // + + StatusByte = READ_PORT_UCHAR ((PUCHAR) port+4); + if (StatusByte & 0x2) { + EisaNMIMsg[25] = (EisaPort > 9 ? 'A'-10 : '0') + EisaPort; + HalDisplayString (EisaNMIMsg); + } + } + } + + KeBugCheck(NMI_HARDWARE_FAILURE); + return(TRUE); +} diff --git a/private/ntos/nthals/halr96b/mips/jxenvirv.c b/private/ntos/nthals/halr96b/mips/jxenvirv.c new file mode 100644 index 000000000..c78505bcf --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxenvirv.c @@ -0,0 +1,800 @@ +// #pragma comment(exestr, "@(#) jxenvirv.c 1.1 95/09/28 15:37:20 nec") +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + jxenvirv.c + +Abstract: + + This module implements the HAL get and set environment variable routines + for a MIPS system. + +Author: + + +Environment: + + Kernel mode + +Revision History: + + M001 95.4.25 Y.Nakatani + - Add Interface of NVRAM for ESM + M002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:46:25 JST 1995 + - Change Nvram virtual address + M003 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 19:25:54 JST 1995 + - Removed _J94C_ definitions. + _J94C_ definition indicates that the status of + the dump switch can acknowledge from Self-test + register. + +--*/ + +#include "halp.h" +#include "arccodes.h" +#include "jazznvr.h" +#include "string.h" + +// +// Define local upcase macro. +// + +#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c)) + +// M002 +++ +KIRQL +HalpEsmMapNvram ( + VOID + ) + +/*++ + +Routine Description: + + This function is called to map the ESM NVRAM into a wired TB entry. + +Arguments: + + None. + +Return Value: + + The previous IRQL is returned as the function value. + +--*/ + +{ + + KIRQL OldIrql; + ENTRYLO NvramPte[2]; + + // + // Construct a pair of PTE's to map NVRAM. + // + + NvramPte[0].X1 = 0; + NvramPte[0].PFN = 0x80013000 >> PAGE_SHIFT; + NvramPte[0].G = 0; + NvramPte[0].V = 1; + NvramPte[0].D = 1; + NvramPte[0].C = UNCACHED_POLICY; + NvramPte[1] = NvramPte[0]; + NvramPte[1].PFN += 1; + + // + // Raise IRQL to the highest level, allocate a TB entry, map NVRAM + // using the alocated entry, and return the previous IRQL. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0], + (PVOID)NVRAM_VIRTUAL_BASE, + HalpAllocateTbEntry()); + + return OldIrql; +} +// M002 --- + +KIRQL +HalpMapNvram ( + VOID + ) + +/*++ + +Routine Description: + + This function is called to map the NVRAM into a wired TB entry. + +Arguments: + + None. + +Return Value: + + The previous IRQL is returned as the function value. + +--*/ + +{ + + KIRQL OldIrql; + ENTRYLO NvramPte[2]; + + // + // Construct a pair of PTE's to map NVRAM. + // + + NvramPte[0].X1 = 0; + NvramPte[0].PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT; + NvramPte[0].G = 0; + NvramPte[0].V = 1; + NvramPte[0].D = 1; + NvramPte[0].C = UNCACHED_POLICY; + NvramPte[1] = NvramPte[0]; + NvramPte[1].PFN += 1; + + // + // Raise IRQL to the highest level, allocate a TB entry, map NVRAM + // using the alocated entry, and return the previous IRQL. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KeFillFixedEntryTb((PHARDWARE_PTE)&NvramPte[0], + (PVOID)NVRAM_VIRTUAL_BASE, + HalpAllocateTbEntry()); + + return OldIrql; +} + +VOID +HalpUnmapNvram ( + IN KIRQL OldIrql + ) + +/*++ + +Routine Description: + + This function is called to unmap the NVRAM from a wired entry in + the TB. + +Arguments: + + OldIrql - Supplies the previous IRQL value. + +Return Value: + + None. + +--*/ + +{ + + // + // Free the wired TB entry that was allocated to map NVRAM and lower + // IRQL to its previous level. + // + + HalpFreeTbEntry(); + KeLowerIrql(OldIrql); + return; +} + +ARC_STATUS +HalpEnvironmentCheckChecksum ( + VOID + ) + +/*++ + +Routine Description: + + This routine checks the NVRAM environment area checksum. + + N.B. The NVRAM must be mapped before this routine is called. + +Arguments: + + None. + +Return Value: + + ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned. + +--*/ + +{ + + ULONG Checksum1; + ULONG Checksum2; + PUCHAR Environment; + ULONG Index; + PNV_CONFIGURATION NvConfiguration; + + // + // Compute the NVRAM environment area checksum. + // + + NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE; + Environment = &NvConfiguration->Environment[0]; + Checksum1 = 0; + for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) { + Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]); + } + + // + // Merge the checksum bytes from the NVRAM and compare to computed value. + // + + Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) | + (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 | + (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 | + (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24; + + // + // If the checksum mismatches, then return an I/O error. Otherwise, + // return a success status. + // + + if (Checksum1 != Checksum2) { + return EIO; + + } else { + return ESUCCESS; + } +} + +VOID +HalpEnvironmentSetChecksum ( + VOID + ) + +/*++ + +Routine Description: + + This routine sets the NVRAM environment area checksum. + + N.B. The NVRAM must be mapped before this routine is called. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + ULONG Checksum; + PUCHAR Environment; + ULONG Index; + PNV_CONFIGURATION NvConfiguration; + + // + // Compute the NVRAM environment area checksum. + // + + NvConfiguration = (PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE; + Environment = &NvConfiguration->Environment[0]; + Checksum = 0; + for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) { + Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]); + } + + // + // Write the NVRAM environment area checksum. + // + + WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0], + (UCHAR)(Checksum & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1], + (UCHAR)((Checksum >> 8) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2], + (UCHAR)((Checksum >> 16) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3], + (UCHAR)(Checksum >> 24)); + + return; +} + +ARC_STATUS +HalpFindEnvironmentVariable ( + IN PCHAR Variable, + OUT PULONG VariableIndex, + OUT PULONG ValueIndex + ) + +/*++ + +Routine Description: + + This routine performs a case insensitive search of the NVRAM environment + area for the specified variable name. + + N.B. The NVRAM must be mapped before this routine is called. + + +Arguments: + + Variable - Supplies a pointer to a zero terminated string containing an + environment variable name. + +Return Value: + + ESUCCESS is returned if the specified variable name is located. Otherwise, + ENOENT is returned. + +--*/ + +{ + + PUCHAR Environment; + ULONG Index; + PUCHAR Name; + + // + // If the variable name is null, then return no entry found. + // + + if (*Variable == 0) { + return ENOENT; + } + + // + // Search the environment section of the NVRAM for a variable name match. + // + + Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0]; + Index = 0; + do { + + // + // Set name to the beginning of the variable name and record the + // current index value. + // + + Name = Variable; + *VariableIndex = Index; + + // + // Search until the end of the current environment variable, the + // end of the specified variable name, or the end of the NVRAM is + // reached. + // + + while ((Index < LENGTH_OF_ENVIRONMENT) && + (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) { + if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) { + break; + } + + Name += 1; + Index += 1; + } + + // + // Check for a match which is signified by the end of the variable + // name and the equal separator in the current environment variable. + // + + if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) { + *ValueIndex = Index + 1; + return ESUCCESS; + } + + // + // Advance to the start of the next variable. + // + + while ((Index < LENGTH_OF_ENVIRONMENT) && + (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) { + Index += 1; + } + + Index += 1; + } while (Index < LENGTH_OF_ENVIRONMENT); + + return ENOENT; +} + +ARC_STATUS +HalGetEnvironmentVariable ( + IN PCHAR Variable, + IN USHORT Length, + OUT PCHAR Buffer + ) + +/*++ + +Routine Description: + + This function locates an environment variable and returns its value. + +Arguments: + + Variable - Supplies a pointer to a zero terminated environment variable + name. + + Length - Supplies the length of the value buffer in bytes. + + Buffer - Supplies a pointer to a buffer that receives the variable value. + +Return Value: + + ESUCCESS is returned if the enviroment variable is located. Otherwise, + ENOENT is returned. + +--*/ + +{ + + PUCHAR Environment; + ULONG Index; + KIRQL OldIrql; + ARC_STATUS Status; + ULONG ValueIndex; + ULONG VariableIndex; + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(); + + // + // If the checksum does not match or the specified variable cannot + // be located, then set the status to no entry found. Otherwise, copy + // the respective variable value to the specified output buffer. + // + + Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0]; + if ((HalpEnvironmentCheckChecksum() != ESUCCESS) || + (HalpFindEnvironmentVariable(Variable, + &VariableIndex, + &ValueIndex) != ESUCCESS)) { + + Status = ENOENT; + + } else { + + // + // Copy the specified value to the output buffer. + // + + for (Index = 0; Index < Length; Index += 1) { + *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]); + if (*Buffer == 0) { + break; + } + + Buffer += 1; + ValueIndex += 1; + } + + // + // If the length terminated the loop, then return not enough memory. + // Otherwise, return success. + // + + if (Index == Length) { + Status = ENOMEM; + + } else { + Status = ESUCCESS; + } + } + + // + // Unmap the NVRAM from the address space of the current process and + // return the function status. + // + + HalpUnmapNvram(OldIrql); + return Status; +} + +ARC_STATUS +HalSetEnvironmentVariable ( + IN PCHAR Variable, + IN PCHAR Value + ) + +/*++ + +Routine Description: + + This function creates an environment variable with the specified value. + +Arguments: + + Variable - Supplies a pointer to an environment variable name. + + Value - Supplies a pointer to the environment variable value. + +Return Value: + + ESUCCESS is returned if the environment variable is created. Otherwise, + ENOMEM is returned. + +--*/ + +{ + + UCHAR Character; + PUCHAR Environment; + KIRQL OldIrql; + ARC_STATUS Status; + ULONG TopIndex; + ULONG VariableIndex; + ULONG VariableLength; + ULONG ValueEnd; + ULONG ValueIndex; + ULONG ValueLength; + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(); + Environment = &((PNV_CONFIGURATION)NVRAM_VIRTUAL_BASE)->Environment[0]; + + // + // If the checksum does not match, then set status to an I/O error. + // + + if (HalpEnvironmentCheckChecksum() != ESUCCESS) { + Status = EIO; + goto Unmap; + } + + // + // Determine the top of the environment area by scanning backwards until + // the a non-null character is found or the beginning of the environment + // area is reached. + // + + for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) { + if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') { + break; + } + } + + // + // If the environment area contains any data, then adjust the top index + // to the first free byte. + // + + if (TopIndex != 0) { + TopIndex += 2; + } + + // + // Compute the length of the variable name and the variable value. + // + + VariableLength = strlen(Variable) + 1; + ValueLength = strlen(Value) + 1; + + // + // Check to determine if the specified variable is currently defined. + // + + if (HalpFindEnvironmentVariable(Variable, + &VariableIndex, + &ValueIndex) == ESUCCESS) { + + // + // The specified variable is currently defined. Determine the end + // of the variable value by scanning forward to the zero termination + // byte. + // + + ValueEnd = ValueIndex; + while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') { + ValueEnd += 1; + } + + ValueEnd += 1; + + // + // If there is enough free space for the new variable value, then + // remove the current variable name and value from the environment + // area, insert the new variable value at the end of the environment + // if it is not null, and set the status to success. Otherwise, set + // the status to no space available. + // + + if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) { + while (ValueEnd != TopIndex) { + Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]); + WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character); + ValueEnd += 1; + VariableIndex += 1; + } + + ValueIndex = VariableIndex; + while (ValueIndex != TopIndex) { + WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0'); + ValueIndex += 1; + } + + // + // If the new variable value is not null, then copy the variable + // name and the variable value into the enviroment area. + // + + if (*Value != '\0') { + + // + // copy the variable name to the environment area. + // + + do { + WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable)); + VariableIndex += 1; + Variable += 1; + } while (*Variable != '\0'); + + // + // Insert separator character and copy variable value to the + // environment area. + // + + WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '='); + VariableIndex += 1; + do { + WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value); + VariableIndex += 1; + Value += 1; + } while (*Value != '\0'); + } + + Status = ESUCCESS; + + } else { + Status = ENOSPC; + } + + } else { + + // + // The specified variable does not currently have a value. If the + // specified variable is null or has no value, then set the status + // to success. Otherwise, if the free area is not large enough to + // hold the new variable name and its value, then set the status to + // no space available. Otherwise, insert the variable name and value + // at the end of the environment area and set the status to success. + // + + if ((*Variable == '\0') || (*Value == '\0')) { + Status = ESUCCESS; + + } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) < + (VariableLength + ValueLength)) { + Status = ENOSPC; + + } else { + + // + // copy the variable name to the environment area. + // + + do { + WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable)); + TopIndex += 1; + Variable += 1; + } while (*Variable != '\0'); + + // + // Insert separator character and copy variable value to the + // environment area. + // + + WRITE_REGISTER_UCHAR(&Environment[TopIndex], '='); + TopIndex += 1; + do { + WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value); + TopIndex += 1; + Value += 1; + } while (*Value != '\0'); + + Status = ESUCCESS; + } + } + + // + // Compute the new checksum and write to the environment area. + // + + HalpEnvironmentSetChecksum(); + + // + // Unmap the NVRAM from the address space of the current process. + // + +Unmap: + HalpUnmapNvram(OldIrql); + return Status; +} + +BOOLEAN +HalNvramWrite( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Write Byte Count + PVOID Buffer // Pointer Of Buffer Write to NVRAM +){ + // Write into NVRAM + return HalpNvramReadWrite(Offset,Count,Buffer,1); +} + +BOOLEAN +HalNvramRead( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Read Byte Count + PVOID Buffer // Pointer Of Buffer Read From NVRAM +){ + // Read From NVRAM + return HalpNvramReadWrite(Offset,Count,Buffer,0); +} + +BOOLEAN +HalpNvramReadWrite( + ULONG Offset, // Read/Write offset of ESM NVRAM + ULONG Count, // Read/Write Byte Count + PVOID Buffer, // read/Write Pointer + ULONG Write // Operation +){ + + KIRQL OldIrql; + ULONG i; + // + // Check is addr . So decrement 1 + // + if( + Offset >=0 && + Count >=0 && + Offset <= 0x1fff && // M002 +++ + Offset+Count-1 <= 0x1fff // M002 --- + + ){ + + if(Write){ + OldIrql = HalpEsmMapNvram(); // M002 +// if (HalpEsmDebug == 1) // test +// DbgBreakPoint(); // test + for(i=0;i 0) DbgPrint( x,y ) +/* M0006 */ + +/* start M0004 */ +ULONG HalDebug = 0; +#if defined(_BBM_DMA_) +// +// define copybuffer allocate routine. +// + +VOID +HalpAllocateCopyBuffer( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + + +// +// Allocate Variable for DMA CopyBuffer +// + ULONG CopyBufferPhysicalBase; + ULONG CopyBufferVirtualAddress; + +#endif // _BBM_DMA_ + +#if defined(_BETA_LIMIT_) +PVOID +HalViewMemory ( + IN PVOID Destination, + IN ULONG Length + ); +#endif // _BETA_LIMIT_ +/* end M0004 */ + +// +// The DMA controller has a larger number of map registers which may be used +// by any adapter channel. In order to pool all of the map registers a master +// adapter object is used. This object is allocated and saved internal to this +// file. It contains a bit map for allocation of the registers and a queue +// for requests which are waiting for more map registers. This object is +// allocated during the first request to allocate an adapter. +// + +PADAPTER_OBJECT MasterAdapterObject; + +// +// The following is the interrupt object used for DMA controller interrupts. +// DMA controller interrupts occur when a memory parity error occurs or a +// programming error occurs to the DMA controller. +// + +KINTERRUPT HalpDmaChannelInterrupt; + +/* start M0001 */ +#if defined(_R94A_) +// +// The following is the interrupt object used for Typhoon Error interrupts. +// Typhoon errorr interrupts occur when internal busmaster device error occurs. +// + +KINTERRUPT HalpTyphoonErrorInterrupt; + +#endif // _R94A_ +/* end M0001 */ + +UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. "; + +// +// Pointer to phyiscal memory for map registers. +// + +ULONG HalpMapRegisterPhysicalBase; + +// +// The following function is called when a DMA channel interrupt occurs. +// + +BOOLEAN +HalpDmaChannel( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +// +// The following is an array of adapter object structures for the internal DMA +// channels. +// + +PADAPTER_OBJECT HalpInternalAdapters[8]; + +IO_ALLOCATION_ACTION +HalpAllocationRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context + ); + +ULONG +HalpReadEisaData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +/* start M0001 */ +#if defined(_R94A_) +BOOLEAN +HalpCreateTyphoonErrorStructures ( + VOID + ); + +BOOLEAN +HalpTyphoonError( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); +#endif // _R94A_ +/* end M0001 */ + + +NTSTATUS +HalAllocateAdapterChannel( + IN PADAPTER_OBJECT AdapterObject, + IN PWAIT_CONTEXT_BLOCK Wcb, + IN ULONG NumberOfMapRegisters, + IN PDRIVER_CONTROL ExecutionRoutine + ) +/*++ + +Routine Description: + + This routine allocates the adapter channel specified by the adapter object. + This is accomplished by placing the device object of the driver that wants + to allocate the adapter on the adapter's queue. If the queue is already + "busy", then the adapter has already been allocated, so the device object + is simply placed onto the queue and waits until the adapter becomes free. + + Once the adapter becomes free (or if it already is), then the driver's + execution routine is invoked. + + Also, a number of map registers may be allocated to the driver by specifying + a non-zero value for NumberOfMapRegisters. Then the map register must be + allocated from the master adapter. Once there are a sufficient number of + map registers available, then the execution routine is called and the + base address of the allocated map registers in the adapter is also passed + to the driver's execution routine. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + + Wcb - Supplies a wait context block for saving the allocation parameters. + The DeviceObject, CurrentIrp and DeviceContext should be initalized. + + NumberOfMapRegisters - The number of map registers that are to be allocated + from the channel, if any. + + ExecutionRoutine - The address of the driver's execution routine that is + invoked once the adapter channel (and possibly map registers) have been + allocated. + +Return Value: + + Returns STATUS_SUCESS unless too many map registers are requested. + +Notes: + + Note that this routine MUST be invoked at DISPATCH_LEVEL or above. + +--*/ + +{ + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + LONG MapRegisterNumber; + KIRQL Irql; + ULONG Hint; +// M0018 +++ +#if defined(_DMA_EXPAND_) + ULONG Limit; +#endif //_DMA_EXPAND_ +// M0018 --- + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + if (AdapterObject->MasterAdapter != NULL) { + MasterAdapter = AdapterObject->MasterAdapter; + } else { + MasterAdapter = AdapterObject; + } + + // + // Initialize the device object's wait context block in case this device + // must wait before being able to allocate the adapter. + // + + Wcb->DeviceRoutine = ExecutionRoutine; + Wcb->NumberOfMapRegisters = NumberOfMapRegisters; + + // + // Allocate the adapter object for this particular device. If the + // adapter cannot be allocated because it has already been allocated + // to another device, then return to the caller now; otherwise, + // continue. + // + + if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue, + &Wcb->WaitQueueEntry )) { + + // + // The adapter was not busy so it has been allocated. Now check + // to see whether this driver wishes to allocate any map registers. + // If so, then queue the device object to the master adapter queue + // to wait for them to become available. If the driver wants map + // registers, ensure that this adapter has enough total map registers + // to satisfy the request. + // + + AdapterObject->CurrentWcb = Wcb; + AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters; + + if (NumberOfMapRegisters != 0) { + if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + // + // Lock the map register bit map and the adapter queue in the + // master adapter object. The channel structure offset is used as + // a hint for the register search. + // + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + MapRegisterNumber = -1; + + if (IsListEmpty( &MasterAdapter->AdapterQueue)) { + +// M0018 +++ +#if defined(_DMA_EXPAND_) + if (AdapterObject->Dma32BitAddresses) { + Hint = EISA_MIN_ADR / PAGE_SIZE; + Limit = EISA_MAX_ADR / PAGE_SIZE; + } else { + Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters; + } +#else // _DMA_EXPAND_ +// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Hint = (0x100000 / PAGE_SIZE); // M0024 +#endif // _DMA_EXPAND_ +// M0018 --- + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + Hint + ); + + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber < Hint) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber >= Limit ) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } +#endif // _DMA_EXPAND_ +// M0018 --- + } + + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Queue this request + // on the master adapter where is will wait until some registers + // are deallocated. + // + + InsertTailList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + Busy = 1; + + } else { + AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + } + + // + // If there were either enough map registers available or no map + // registers needed to be allocated, invoke the driver's execution + // routine now. + // + + if (!Busy) { + + Action = ExecutionRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext + ); + + // + // If the driver wishes to keep the map registers then set the number + // allocated to zero and set the action to deallocate object. + // + + if (Action == DeallocateObjectKeepRegisters) { + AdapterObject->NumberOfMapRegisters = 0; + Action = DeallocateObject; + } + + // + // If the driver would like to have the adapter deallocated, + // then deallocate any map registers allocated and then release + // the adapter object. + // + + if (Action == DeallocateObject) { + IoFreeAdapterChannel( AdapterObject ); + } + } + } + + return(STATUS_SUCCESS); + +} + +PVOID +HalAllocateCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + OUT PPHYSICAL_ADDRESS LogicalAddress, + IN BOOLEAN CacheEnabled + ) +/*++ + +Routine Description: + + This function allocates the memory for a common buffer and maps so that it + can be accessed by a master device and the CPU. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer to be allocated. + + LogicalAddress - Returns the logical address of the common buffer. + + CacheEnable - Indicates whether the memeory is cached or not. + +Return Value: + + Returns the virtual address of the common buffer. If the buffer cannot be + allocated then NULL is returned. + +--*/ + +{ + PVOID virtualAddress; + PVOID mapRegisterBase; + ULONG numberOfMapRegisters; + ULONG mappedLength; + WAIT_CONTEXT_BLOCK wcb; + KEVENT allocationEvent; + NTSTATUS status; + PMDL mdl; + KIRQL irql; + + numberOfMapRegisters = BYTES_TO_PAGES(Length); + + // + // Allocate the actual buffer. + // + + if (CacheEnabled != FALSE) { + virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length); + + } else { + virtualAddress = MmAllocateNonCachedMemory(Length); + } + + + if (virtualAddress == NULL) { + return(virtualAddress); + + } + + // + // Initialize an event. + // + + KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE); + + // + // Initialize the wait context block. Use the device object to indicate + // where the map register base should be stored. + // + + wcb.DeviceObject = &mapRegisterBase; + wcb.CurrentIrp = NULL; + wcb.DeviceContext = &allocationEvent; + + // + // Allocate the adapter and the map registers. + // + + KeRaiseIrql(DISPATCH_LEVEL, &irql); + + status = HalAllocateAdapterChannel( + AdapterObject, + &wcb, + numberOfMapRegisters, + HalpAllocationRoutine + ); + + KeLowerIrql(irql); + + if (!NT_SUCCESS(status)) { + + // + // Cleanup and return NULL. + // + + if (CacheEnabled != FALSE) { + ExFreePool(virtualAddress); + + } else { + MmFreeNonCachedMemory(virtualAddress, Length); + } + + return(NULL); + + } + + // + // Wait for the map registers to be allocated. + // + + status = KeWaitForSingleObject( + &allocationEvent, + Executive, + KernelMode, + FALSE, + NULL + ); + + if (!NT_SUCCESS(status)) { + + // + // Cleanup and return NULL. + // + + if (CacheEnabled != FALSE) { + ExFreePool(virtualAddress); + + } else { + MmFreeNonCachedMemory(virtualAddress, Length); + } + + return(NULL); + + } + + // + // Create an mdl to use with call to I/O map transfer. + // + + mdl = IoAllocateMdl( + virtualAddress, + Length, + FALSE, + FALSE, + NULL + ); + + MmBuildMdlForNonPagedPool(mdl); + + // + // Map the transfer so that the controller can access the memory. + // + + mappedLength = Length; + *LogicalAddress = IoMapTransfer( + NULL, + mdl, + mapRegisterBase, + virtualAddress, + &mappedLength, + TRUE + ); + + IoFreeMdl(mdl); + + if (mappedLength < Length) { + + // + // Cleanup and indicate that the allocation failed. + // + + HalFreeCommonBuffer( + AdapterObject, + Length, + *LogicalAddress, + virtualAddress, + CacheEnabled + ); + + return(NULL); + } + + // + // The allocation completed successfully. + // + + return(virtualAddress); + +} + +PVOID +HalAllocateCrashDumpRegisters( + IN PADAPTER_OBJECT AdapterObject, + IN PULONG NumberOfMapRegisters + ) +/*++ + +Routine Description: + + This routine is called during the crash dump disk driver's initialization + to allocate a number map registers permanently. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + NumberOfMapRegisters - Number of map registers requested and update to show + number actually allocated. + +Return Value: + + Returns STATUS_SUCESS if map registers allocated. + +--*/ + +{ + PADAPTER_OBJECT MasterAdapter; + ULONG MapRegisterNumber; + ULONG Hint; +// M0018 +++ +#if defined(_DMA_EXPAND_) + ULONG Limit; +#endif // _DMA_EXPAND_ +// M0018 --- + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + if (AdapterObject->MasterAdapter) { + MasterAdapter = AdapterObject->MasterAdapter; + } else { + MasterAdapter = AdapterObject; + } + + // + // Ensure that this adapter has enough total map registers to satisfy + // the request. + // + + if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + return NULL; + } + + // + // Attempt to allocate the required number of map registers w/o + // affecting those registers that were allocated when the system + // crashed. Note that once again the map registers to be allocated + // must be above the 1MB range if this is an EISA bus device. + // + + MapRegisterNumber = (ULONG)-1; + +// M0018 +++ +#if defined(_DMA_EXPAND_) + if (AdapterObject->Dma32BitAddresses) { + Hint = EISA_MIN_ADR / PAGE_SIZE; + Limit = EISA_MAX_ADR / PAGE_SIZE; + } else { + Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Limit = ISA_MAX_ADR / PAGE_SIZE - *NumberOfMapRegisters; + } +#else // _DMA_EXPAND +// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Hint = (0x100000 / PAGE_SIZE); // M0024 +#endif // _DMA_EXPAND_ +// M0018 --- + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + *NumberOfMapRegisters, + Hint + ); + + // + // Ensure that any allocated map registers are valid for this adapter. + // + + if ((ULONG) MapRegisterNumber < Hint) { + + // + // Make it appear as if there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + *NumberOfMapRegisters + ); + + MapRegisterNumber = (ULONG) -1; + } + +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber >= Limit ) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + *NumberOfMapRegisters + ); + + MapRegisterNumber = (ULONG) -1; + } +#endif // _DMA_EXPAND_ +// M0018 --- + + if (MapRegisterNumber == (ULONG)-1) { + + // + // Not enough free map registers were found, so they were busy + // being used by the system when it crashed. Force the appropriate + // number to be "allocated" at the base by simply overjamming the + // bits and return the base map register as the start. + // + + RtlSetBits( + MasterAdapter->MapRegisters, + Hint, + *NumberOfMapRegisters + ); + MapRegisterNumber = Hint; + + } + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // + + AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); + + return AdapterObject->MapRegisterBase; +} + +BOOLEAN +HalFlushCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PHYSICAL_ADDRESS LogicalAddress, + IN PVOID VirtualAddress + ) +/*++ + +Routine Description: + + This function is called to flush any hardware adapter buffers when the + driver needs to read data written by an I/O master device to a common + buffer. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer. This should be the same + value used for the allocation of the buffer. + + LogicalAddress - Supplies the logical address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + VirtualAddress - Supplies the virtual address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + +Return Value: + + Returns TRUE if no errors were detected; otherwise, FALSE is return. + +--*/ + +{ +#if 0 // M0008 +/* M0006 +++ */ +#if defined(_BETA_LIMIT_) +{ + ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, i; + KIRQL OldIrql; + + // D001 +// DbgPrint("DmaFlush start\n"); + KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama + for (i = 0; i < 8; i++ ) { + PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i]; + LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i]; + Ptag = READ_REGISTER_ULONG(PtagReg); + Ltag = READ_REGISTER_ULONG(LtagReg); + if (Ptag & 0x1) { + if (Ltag & 0x1) { + if ((LogicalAddress.LowPart & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (LogicalAddress.LowPart + Length))) { + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + if (HalDebug) + DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n", + PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead); + } + } + } + } + KeLowerIrql(OldIrql); +// DbgPrint("DmaFlush end\n"); +} +#endif // _BETA_LIMIT_ +/* M0006 --- */ +#endif // 0 // M0008 + return(TRUE); + +} + +VOID +HalFreeCommonBuffer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Length, + IN PHYSICAL_ADDRESS LogicalAddress, + IN PVOID VirtualAddress, + IN BOOLEAN CacheEnabled + ) +/*++ + +Routine Description: + + This function frees a common buffer and all of the resouces it uses. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object used by this + device. + + Length - Supplies the length of the common buffer. This should be the same + value used for the allocation of the buffer. + + LogicalAddress - Supplies the logical address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + VirtualAddress - Supplies the virtual address of the common buffer. This + must be the same value return by HalAllocateCommonBuffer. + + CacheEnable - Indicates whether the memeory is cached or not. + +Return Value: + + None + +--*/ + +{ + PTRANSLATION_ENTRY mapRegisterBase; + ULONG numberOfMapRegisters; + ULONG mapRegisterNumber; + + // + // Calculate the number of map registers, the map register number and + // the map register base. + // + + numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); + mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT; + + mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase + + mapRegisterNumber; + + // + // Free the map registers. + // + + IoFreeMapRegisters( + AdapterObject, + (PVOID) mapRegisterBase, + numberOfMapRegisters + ); + + // + // Free the memory for the common buffer. + // + + if (CacheEnabled != FALSE) { + ExFreePool(VirtualAddress); + + } else { + MmFreeNonCachedMemory(VirtualAddress, Length); + } + + return; + +} + +PADAPTER_OBJECT +HalGetAdapter( + IN PDEVICE_DESCRIPTION DeviceDescription, + IN OUT PULONG NumberOfMapRegisters + ) + +/*++ + +Routine Description: + + This function returns the appropriate adapter object for the device defined + in the device description structure. Three bus types are supported for the + system: Internal, Isa, and Eisa. + +Arguments: + + DeviceDescription - Supplies a description of the deivce. + + NumberOfMapRegisters - Returns the maximum number of map registers which + may be allocated by the device driver. + +Return Value: + + A pointer to the requested adapter object or NULL if an adapter could not + be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + +// M0020 +++ +#if DBG +#if defined (_DMA_EXPAND_) + DbgPrint("\nHalGetAdapter(): DeviceDescription->32BitAddresses = %d\n",DeviceDescription->Dma32BitAddresses); +#endif // _DMA_EXPAND_ +#endif // DBG +// M0020 --- + + // + // Make sure this is the correct version. + // + + if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) { + + return(NULL); + + } + + // + // Return number of map registers requested based on the maximum + // transfer length. + // + + *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1; + + if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) { + *NumberOfMapRegisters = DMA_REQUEST_LIMIT; + } + + if (DeviceDescription->InterfaceType == Internal) { + + + // + // Return the adapter pointer for internal adapters. + // + // If this is a master controler such as the SONIC then return the + // last channel. + // + + if (DeviceDescription->Master) { + +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // Create an adapter. + // + + adapterObject = HalpAllocateAdapter( + 0, + (PVOID) &(DMA_CONTROL)->Channel[7], + NULL + ); + + adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; + +// M0020 +++ +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); +#endif DBG + + if (adapterObject->Dma32BitAddresses) { + if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L; + } + + } else { + if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L; + } + } +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); + DbgPrint("internal master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses); +#endif // DBG +// M0020 --- + + return(adapterObject); + +#else // _DMA_EXPAND + + // + // Create an adapter if necessary. + // + + if (HalpInternalAdapters[7] == NULL) { + + HalpInternalAdapters[7] = HalpAllocateAdapter( + 0, + (PVOID) &(DMA_CONTROL)->Channel[7], + NULL + ); + + } + + return(HalpInternalAdapters[7]); +#endif // _DMA_EXPAND_ +// M0018 --- + + } + + // + // Make sure the DMA channel range is valid. Only use channels 0-6. + // + +/* start M0001 */ +#if defined(_R94A_) + + if (DeviceDescription->DmaChannel > 3) { // duo and r94a have only 0-3 channel + + return(NULL); + } + +#else // _R94A_ + + if (DeviceDescription->DmaChannel > 6) { + + return(NULL); + } + +#endif // _R94A_ +/* end M0001 */ + + // + // If necessary allocate an adapter; otherwise, + // just return the adapter for the requested channel. + // + + if (HalpInternalAdapters[DeviceDescription->DmaChannel] == NULL) { + + HalpInternalAdapters[DeviceDescription->DmaChannel] = + HalpAllocateAdapter( + 0, + (PVOID) &(DMA_CONTROL)->Channel[DeviceDescription->DmaChannel], + NULL + ); + + } + +// M0012 +++ +#if defined(_R94A_) +// M0020 +++ +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); +#endif DBG +// M0020 --- + + // + // Internal slave dma limit 1MB. (TYPHOON tip limit) + // + + if (*NumberOfMapRegisters > ( 0x100000 >> PAGE_SHIFT )) { + + *NumberOfMapRegisters = ( 0x100000 >> PAGE_SHIFT ); + } + +#endif // _R94A_ +// M0012 --- + + if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) { + + *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4; + } + +// M0018 +++ +#if defined(_DMA_EXPAND_) +// M0020 +++ + if (HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses) { // S0021 + if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L; + } + } else { + if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L; + } + } + + HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses + = DeviceDescription->Dma32BitAddresses; +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); + DbgPrint("internal slave HalpInternalAdapters[%d]->Dma32BitAddresses = %d\n", + DeviceDescription->DmaChannel, + HalpInternalAdapters[DeviceDescription->DmaChannel]->Dma32BitAddresses); +#endif // DBG + +// M0020 --- +#endif // _DMA_EXPAND_ +// M0018 --- + return(HalpInternalAdapters[DeviceDescription->DmaChannel]); + } + +/* start M0001 */ +#if defined(_R94A_) + // + // PCI Bus check. + // + if (DeviceDescription->InterfaceType == PCIBus) { + + adapterObject = HalpAllocatePCIAdapter( DeviceDescription ); + + if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) { + + *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4; + } +// M0018 +++ +#if defined(_DMA_EXPAND_) +// M0020 +++ + if (adapterObject->Dma32BitAddresses) { + if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L; + } + } else { + if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L; + } + } + + adapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses; +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); + DbgPrint("PCI master adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses); +#endif // DBG +// M0020 --- +#endif // _DMA_EXPAND_ +// M0018 --- + + return(adapterObject); // B0016 + + } +#endif // _R94A_ +/* end M0001 */ + + // + // If the request is for a unsupported bus then return NULL. + // + + if (DeviceDescription->InterfaceType != Isa && + DeviceDescription->InterfaceType != Eisa) { + + // + // This bus type is unsupported return NULL. + // + + return(NULL); + } +// M0020 +++ +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); +#endif DBG +// M0020 --- + + // + // Create an adapter object. + // + + adapterObject = HalpAllocateEisaAdapter( DeviceDescription ); + + if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 4) { + + *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 4; + } + +// M0018 +++ +#if defined(_DMA_EXPAND_) +// M0020 +++ + if (adapterObject->Dma32BitAddresses) { + if (*NumberOfMapRegisters > (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = (EISA_MAX_ADR - EISA_MIN_ADR) + / PAGE_SIZE / 8L; + } + } else { + if (*NumberOfMapRegisters > ISA_MAX_ADR / PAGE_SIZE / 8L) { + *NumberOfMapRegisters = ISA_MAX_ADR / PAGE_SIZE / 8L; + } + } + +#if DBG + DbgPrint("*NumberOfMapRegisters = %d\n",*NumberOfMapRegisters); + DbgPrint("eisa/isa adapterObject->Dma32BitAddresses = %d\n",adapterObject->Dma32BitAddresses); +#endif // DBG +// M0020 --- + +#endif // _DMA_EXPAND_ +// M0018 --- + + return(adapterObject); +} + +#if 0 // CHG0001 + +BOOLEAN +HalTranslateBusAddress( + IN INTERFACE_TYPE InterfaceType, + IN ULONG BusNumber, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function returns the system physical address for a specified I/O bus + address. The return value is suitable for use in a subsequent call to + MmMapIoSpace. + +Arguments: + + InterfaceType - Supplies the type of bus which the address is for. + + BusNumber - Supplies the bus number for the device. + + BusAddress - Supplies the bus relative address. + + AddressSpace - Supplies the address space number for the device: 0 for + memory and 1 for I/O space. Returns the address space on this system. + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + TranslatedAddress->HighPart = 0; + + // + // If this is for the internal bus then just return the passed parameter. + // + + if (InterfaceType == Internal) { + + // + // Return the passed parameters. + // + + TranslatedAddress->LowPart = BusAddress.LowPart; + return(TRUE); + } + +/* start M0001 */ +#if defined(_R94A_) + + if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != PCIBus) { + +#else // _R94A_ + + if (InterfaceType != Isa && InterfaceType != Eisa) { + +#endif // _R94A_ +/* end M0001 */ + + // + // Not on this system return nothing. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + // + // There is only one I/O bus which is an EISA, so the bus number is unused. + // + // Determine the address based on whether the bus address is in I/O space + // or bus memory space. + // + + if (*AddressSpace) { + + // + // The address is in I/O space. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE; + if (TranslatedAddress->LowPart < BusAddress.LowPart) { + + // + // A carry occurred. + // + + TranslatedAddress->HighPart = 1; + } + return(TRUE); + + } else { + + // + // The address is in memory space. + // + + *AddressSpace = 0; + +#if !defined(_DUO_) + + if (DMA_CONTROL->RevisionLevel.Long < 2) { + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE; + } else { + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; + TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; + + } +#else + + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; + TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; + +#endif + + if (TranslatedAddress->LowPart < BusAddress.LowPart) { + + // + // A carry occurred. + // + + TranslatedAddress->HighPart = 1; + } + return(TRUE); + + } +} +#endif + + +PADAPTER_OBJECT +HalpAllocateAdapter( + IN ULONG MapRegistersPerChannel, + IN PVOID AdapterBaseVa, + IN PVOID MapRegisterBase + ) + +/*++ + +Routine Description: + + This routine allocates and initializes an adapter object to represent an + adapter or a DMA controller on the system. + +Arguments: + + MapRegistersPerChannel - Unused. + + AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa + is NULL then the MasterAdapterObject is allocated. + + MapRegisterBase - Unused. + +Return Value: + + The function value is a pointer to the allocate adapter object. + +--*/ + +{ + + PADAPTER_OBJECT AdapterObject; + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG Size; + ULONG BitmapSize; + HANDLE Handle; + NTSTATUS Status; + ULONG Mode; + + // + // Initalize the master adapter if necessary. + // + + if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) { + + MasterAdapterObject = HalpAllocateAdapter( 0, + NULL, + NULL + ); + + // + // If we could not allocate the master adapter then give up. + // + + if (MasterAdapterObject == NULL) { + return(NULL); + } + } + + // + // Begin by initializing the object attributes structure to be used when + // creating the adapter object. + // + + InitializeObjectAttributes( &ObjectAttributes, + NULL, + OBJ_PERMANENT, + (HANDLE) NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + // + // Determine the size of the adapter object. If this is the master object + // then allocate space for the register bit map; otherwise, just allocate + // an adapter object. + // + + if (AdapterBaseVa == NULL) { + + + BitmapSize = (((sizeof( RTL_BITMAP ) + + ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3)) + + 3) & ~3); + + Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; + + } else { + + Size = sizeof( ADAPTER_OBJECT ); + + } + + // + // Now create the adapter object. + // + + Status = ObCreateObject( KernelMode, + *((POBJECT_TYPE *)IoAdapterObjectType), + &ObjectAttributes, + KernelMode, + (PVOID) NULL, + Size, + 0, + 0, + (PVOID *)&AdapterObject ); + + // + // Reference the object. + // + + if (NT_SUCCESS(Status)) { + + Status = ObReferenceObjectByPointer( + AdapterObject, + FILE_READ_DATA | FILE_WRITE_DATA, + *((POBJECT_TYPE *)IoAdapterObjectType), + KernelMode + ); + + } + + // + // If the adapter object was successfully created, then attempt to insert + // it into the the object table. + // + + if (NT_SUCCESS( Status )) { + + Status = ObInsertObject( AdapterObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + (PVOID *) NULL, + &Handle ); + + if (NT_SUCCESS( Status )) { + + ZwClose( Handle ); + + // + // Initialize the adapter object itself. + // + + AdapterObject->Type = IO_TYPE_ADAPTER; + AdapterObject->Size = (USHORT) Size; + AdapterObject->MapRegistersPerChannel = + DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY); + AdapterObject->AdapterBaseVa = AdapterBaseVa; + AdapterObject->MasterAdapter = MasterAdapterObject; + AdapterObject->PagePort = NULL; + + // + // Initialize the channel wait queue for this + // adapter. + // + + KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue ); + + // + // If this is the MasterAdatper then initialize the register bit map, + // AdapterQueue and the spin lock. + // + + if ( AdapterBaseVa == NULL ) { + ULONG MapRegisterSize; + + KeInitializeSpinLock( &AdapterObject->SpinLock ); + + InitializeListHead( &AdapterObject->AdapterQueue ); + + AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1); + RtlInitializeBitMap( AdapterObject->MapRegisters, + (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )), + DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY) + ); + RtlClearAllBits( AdapterObject->MapRegisters ); + +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // set bit for unusable area + // + +// M0020 +++ +#if DBG + DbgPrint("translatiron start %x\n",HalpMapRegisterPhysicalBase); + DbgPrint("translatiron size %x\n",MapRegisterSize); +#endif // DBG + + RtlFindClearBitsAndSet( + AdapterObject->MapRegisters, + ((EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE), + (ISA_MAX_ADR / PAGE_SIZE) + ); + DbgPrint("unused start %x\n",ISA_MAX_ADR / PAGE_SIZE); + DbgPrint("unused length %x\n",(EISA_MIN_ADR - ISA_MAX_ADR) / PAGE_SIZE); +// M0020 --- +#endif // _DMA_EXPAND_ +// M0018 --- + + // + // The memory for the map registers was allocated by + // HalpAllocateMapRegisters during phase 0 initialization. + // + + MapRegisterSize = DMA_TRANSLATION_LIMIT; + MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize); + + // + // Convert the physical address to a non-cached virtual address. + // + + AdapterObject->MapRegisterBase = (PVOID) + (HalpMapRegisterPhysicalBase | KSEG1_BASE); + + WRITE_REGISTER_ULONG( + &DMA_CONTROL->TranslationBase.Long, + HalpMapRegisterPhysicalBase + ); + + WRITE_REGISTER_ULONG( + &DMA_CONTROL->TranslationLimit.Long, + MapRegisterSize + ); + + // + // Initialize the DMA mode registers for the Floppy, SCSI and Sound. + // The initialization values come fomr the System Specification. + // + +#if defined(_JAZZ_) + + Mode = 0; + ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS; + ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS; + ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0; + ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 0; + ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1; + WRITE_REGISTER_ULONG( + &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long, + (ULONG) Mode + ); + + ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_120NS; + ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_8BITS; + ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0; + ((PDMA_CHANNEL_MODE) &Mode)->FastDmaCycle = 1; + WRITE_REGISTER_ULONG( + &DMA_CONTROL->Channel[FLOPPY_CHANNEL].Mode.Long, + (ULONG) Mode + ); + + ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS; + ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS; + ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0; + ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1; + WRITE_REGISTER_ULONG( + &DMA_CONTROL->Channel[SOUND_CHANNEL_A].Mode.Long, + (ULONG) Mode + ); + + ((PDMA_CHANNEL_MODE) &Mode)->AccessTime = ACCESS_80NS; + ((PDMA_CHANNEL_MODE) &Mode)->TransferWidth = WIDTH_16BITS; + ((PDMA_CHANNEL_MODE) &Mode)->InterruptEnable = 0; + ((PDMA_CHANNEL_MODE) &Mode)->BurstMode = 1; + WRITE_REGISTER_ULONG( + &DMA_CONTROL->Channel[SOUND_CHANNEL_B].Mode.Long, + (ULONG) Mode + ); + +#endif + + } + + } else { + + // + // An error was incurred for some reason. Set the return value + // to NULL. + // + + AdapterObject = (PADAPTER_OBJECT) NULL; + } + } else { + AdapterObject = (PADAPTER_OBJECT) NULL; + } + return AdapterObject; + + return (PADAPTER_OBJECT) NULL; +} + +VOID +IoFreeMapRegisters( + PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters + ) +/*++ + +Routine Description: + + This routine deallocates the map registers for the adapter. If there are + any queued adapter waiting for an attempt is made to allocate the next + entry. + +Arguments: + + AdapterObject - The adapter object to where the map register should be + returned. + + MapRegisterBase - The map register base of the registers to be deallocated. + + NumberOfMapRegisters - The number of registers to be deallocated. + +Return Value: + + None + +--+*/ + +{ + PADAPTER_OBJECT MasterAdapter; + LONG MapRegisterNumber; + PLIST_ENTRY Packet; + IO_ALLOCATION_ACTION Action; + PWAIT_CONTEXT_BLOCK Wcb; + KIRQL Irql; + ULONG Hint; +// M0018 +++ +#if defined(_DMA_EXPAND_) + ULONG Limit; +#endif // _DMA_EXPAND_ +// M0018 --- + + + // + // Begin by getting the address of the master adapter. + // + + if (AdapterObject->MasterAdapter != NULL) { + MasterAdapter = AdapterObject->MasterAdapter; + } else { + MasterAdapter = AdapterObject; + } + + MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase - + (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase; + + // + // Acquire the master adapter spinlock which locks the adapter queue and the + // bit map for the map registers. + // + + KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql); + + // + // Return the registers to the bit map. + // + + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + // + // Process any requests waiting for map registers in the adapter queue. + // Requests are processed until a request cannot be satisfied or until + // there are no more requests in the queue. + // + + while(TRUE) { + + if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){ + break; + } + + Packet = RemoveHeadList( &MasterAdapter->AdapterQueue ); + AdapterObject = CONTAINING_RECORD( Packet, + ADAPTER_OBJECT, + AdapterQueue + ); + Wcb = AdapterObject->CurrentWcb; + + // + // Attempt to allocate map registers for this request. Use the previous + // register base as a hint. + // + +// M0018 +++ +#if defined(_DMA_EXPAND_) + if (AdapterObject->Dma32BitAddresses) { + Hint = EISA_MIN_ADR / PAGE_SIZE; + Limit = EISA_MAX_ADR / PAGE_SIZE; + } else { + Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Limit = ISA_MAX_ADR / PAGE_SIZE - NumberOfMapRegisters; + } +#else // _DMA_EXPAND_ +// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Hint = (0x100000 / PAGE_SIZE); // M0024 +#endif // _DMA_EXPAND_ +// M0018 --- + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + Hint + ); + + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber < Hint) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } + +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber >= Limit ) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } +#endif // _DMA_EXPAND_ +// M0018 --- + + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Put this request back on + // the adapter queue where is came from. + // + + InsertHeadList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + + break; + + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Invoke the driver's execution routine now. + // + + Action = Wcb->DeviceRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext + ); + + // + // If the driver wishes to keep the map registers then set the number + // allocated to zero and set the action to deallocate object. + // + + if (Action == DeallocateObjectKeepRegisters) { + AdapterObject->NumberOfMapRegisters = 0; + Action = DeallocateObject; + } + + // + // If the driver would like to have the adapter deallocated, + // then deallocate any map registers allocated and then release + // the adapter object. + // + + if (Action == DeallocateObject) { + + // + // The map registers registers are deallocated here rather than in + // IoFreeAdapterChannel. This limits the number of times + // this routine can be called recursively possibly overflowing + // the stack. The worst case occurs if there is a pending + // request for the adapter that uses map registers and whos + // excution routine decallocates the adapter. In that case if there + // are no requests in the master adapter queue, then IoFreeMapRegisters + // will get called again. + // + + if (AdapterObject->NumberOfMapRegisters != 0) { + + // + // Deallocate the map registers and clear the count so that + // IoFreeAdapterChannel will not deallocate them again. + // + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + AdapterObject->NumberOfMapRegisters + ); + + AdapterObject->NumberOfMapRegisters = 0; + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + } + + IoFreeAdapterChannel( AdapterObject ); + } + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); +} + +VOID +IoFreeAdapterChannel( + IN PADAPTER_OBJECT AdapterObject + ) + +/*++ + +Routine Description: + + This routine is invoked to deallocate the specified adapter object. + Any map registers that were allocated are also automatically deallocated. + No checks are made to ensure that the adapter is really allocated to + a device object. However, if it is not, then kernel will bugcheck. + + If another device is waiting in the queue to allocate the adapter object + it will be pulled from the queue and its execution routine will be + invoked. + +Arguments: + + AdapterObject - Pointer to the adapter object to be deallocated. + +Return Value: + + None. + +--*/ + +{ + PKDEVICE_QUEUE_ENTRY Packet; + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + PWAIT_CONTEXT_BLOCK Wcb; + KIRQL Irql; + LONG MapRegisterNumber; + ULONG Hint; +// M0018 +++ +#if defined(_DMA_EXPAND_) + ULONG Limit; +#endif // _DMA_EXPAND_ +// M0018 --- + + // + // Begin by getting the address of the master adapter. + // + + if (AdapterObject->MasterAdapter != NULL) { + MasterAdapter = AdapterObject->MasterAdapter; + } else { + MasterAdapter = AdapterObject; + } + + // + // Pull requests of the adapter's device wait queue as long as the + // adapter is free and there are sufficient map registers available. + // + + while( TRUE ){ + + // + // Begin by checking to see whether there are any map registers that + // need to be deallocated. If so, then deallocate them now. + // + + if (AdapterObject->NumberOfMapRegisters != 0) { + IoFreeMapRegisters( AdapterObject, + AdapterObject->MapRegisterBase, + AdapterObject->NumberOfMapRegisters + ); + } + + // + // Simply remove the next entry from the adapter's device wait queue. + // If one was successfully removed, allocate any map registers that it + // requires and invoke its execution routine. + // + + Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue ); + if (Packet == NULL) { + + // + // There are no more requests break out of the loop. + // + + break; + } + + Wcb = CONTAINING_RECORD( Packet, + WAIT_CONTEXT_BLOCK, + WaitQueueEntry ); + + AdapterObject->CurrentWcb = Wcb; + AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters; + + // + // Check to see whether this driver wishes to allocate any map + // registers. If so, then queue the device object to the master + // adapter queue to wait for them to become available. If the driver + // wants map registers, ensure that this adapter has enough total + // map registers to satisfy the request. + // + + if (Wcb->NumberOfMapRegisters != 0) { + if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { + KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS ); + } + + // + // Lock the map register bit map and the adapter queue in the + // master adapter object. The channel structure offset is used as + // a hint for the register search. + // + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + MapRegisterNumber = -1; + + if (IsListEmpty( &MasterAdapter->AdapterQueue)) { + +// M0018 +++ +#if defined(_DMA_EXPAND_) + if (AdapterObject->Dma32BitAddresses) { + Hint = EISA_MIN_ADR / PAGE_SIZE; + Limit = EISA_MAX_ADR / PAGE_SIZE; + } else { + Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Limit = ISA_MAX_ADR / PAGE_SIZE - Wcb->NumberOfMapRegisters; + } +#else // _DMA_EXPAND_ +// Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; + Hint = (0x100000 / PAGE_SIZE); // M0024 +#endif // _DMA_EXPAND_ +// M0018 --- + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + Wcb->NumberOfMapRegisters, + Hint + ); + + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber < Hint) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + Wcb->NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } +// M0018 +++ +#if defined(_DMA_EXPAND_) + // + // Make sure this map register is valid for this adapter. + // + + if ((ULONG) MapRegisterNumber >= Limit ) { + + // + // Make it look like there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + Wcb->NumberOfMapRegisters + ); + + MapRegisterNumber = -1; + } +#endif // _DMA_EXPAND_ +// M0018 --- + + } + + if (MapRegisterNumber == -1) { + + // + // There were not enough free map registers. Queue this request + // on the master adapter where is will wait until some registers + // are deallocated. + // + + InsertTailList( &MasterAdapter->AdapterQueue, + &AdapterObject->AdapterQueue + ); + Busy = 1; + + } else { + AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + } + + // + // If there were either enough map registers available or no map + // registers needed to be allocated, invoke the driver's execution + // routine now. + // + + if (!Busy) { + AdapterObject->CurrentWcb = Wcb; + Action = Wcb->DeviceRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext + ); + + // + // If the execution routine would like to have the adapter + // deallocated, then release the adapter object. + // + + if (Action == KeepObject) { + + // + // This request wants to keep the channel a while so break + // out of the loop. + // + + break; + } + + // + // If the driver wants to keep the map registers then set the + // number allocated to 0. This keeps the deallocation routine + // from deallocating them. + // + + if (Action == DeallocateObjectKeepRegisters) { + AdapterObject->NumberOfMapRegisters = 0; + } + } else { + + // + // This request did not get the requested number of map registers so + // out of the loop. + // + + break; + } + } +} + +BOOLEAN +HalpCreateDmaStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for DMA operations + and connects the intermediate interrupt dispatcher. It also connects + an interrupt handler to the DMA channel interrupt. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + // + // Initialize the DMA interrupt dispatcher for I/O interrupts. + // + + KeInitializeInterrupt( &HalpDmaChannelInterrupt, + HalpDmaChannel, + (PVOID) NULL, + (PKSPIN_LOCK) NULL, + DMA_LEVEL, + DMA_LEVEL, + DMA_LEVEL, + LevelSensitive, + FALSE, + 0, + FALSE + ); + + // + // Don't fail if the interrupt cannot be connected. + // + + KeConnectInterrupt( &HalpDmaChannelInterrupt ); + + // + // Directly connect the local device interrupt dispatcher to the local + // device interrupt vector. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization). + // + + PCR->InterruptRoutine[DEVICE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpDmaDispatch; + +/* start M0001 */ +#if defined(_R94A_) + +/* M0010 +++ */ + + // + // Enable DmaChannel Interrupt + // +{ + ULONG Dword,Channel; + + Dword = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long); + + Dword |= 1; // S0011 + + WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long, Dword); // S011 + +#if 0 // S0017 + // + // Enable Interrupt when done every channel + // + + for (Channel = 0; Channel < 4; Channel++) { + Dword = READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode); + Dword |= 0x20; + WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Mode, Dword); + } +#endif // 0 // S0017 +} + + +/* M0010 --- */ + + // + // Initialize Typhoon error interrupts. + // + + HalpCreateTyphoonErrorStructures(); + +#endif // _R94A_ +/* end M0001 */ + + return TRUE; +} + +PHYSICAL_ADDRESS +IoMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN OUT PULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine is invoked to set up the map registers in the DMA controller + to allow a transfer to or from a device. + +Arguments: + + AdapterObject - Pointer to the adapter object representing the DMA + controller channel that has been allocated. + + Mdl - Pointer to the MDL that describes the pages of memory that are + being read or written. + + MapRegisterBase - The address of the base map register that has been + allocated to the device driver for use in mapping the transfer. + + CurrentVa - Current virtual address in the buffer described by the MDL + that the transfer is being done to or from. + + Length - Supplies the length of the transfer. This determines the + number of map registers that need to be written to map the transfer. + Returns the length of the transfer which was actually mapped. + + WriteToDevice - Boolean value that indicates whether this is a write + to the device from memory (TRUE), or vice versa. + +Return Value: + + Returns the logical address to be used by bus masters. + +--*/ + +{ + PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase; + PULONG PageFrameNumber; + ULONG NumberOfPages; + ULONG Offset; + ULONG i; + KIRQL OldIrql; // kuriyama + + // + // Begin by determining where in the buffer this portion of the operation + // is taking place. + // + +/* start M0004 */ +#if defined(_BBM_DMA_) +// +// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice +// + ULONG bufferAddress; + ULONG bufferLogical; +#endif // _BBM_DMA_ +/* end M0004 */ + +#if 0 //M0008 +/* M0005 +++ */ +#if defined(_BETA_LIMIT_) +{ + ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress; + KIRQL OldIrql; + + if (!WriteToDevice) { + logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT; + KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama + for (i = 0; i < 8; i++ ) { + PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i]; + LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i]; + Ptag = READ_REGISTER_ULONG(PtagReg); + Ltag = READ_REGISTER_ULONG(LtagReg); + if (Ptag & 0x1) { + if (Ltag & 0x1) { + if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + *Length))) { + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + if (HalDebug) + DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n", + PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead); + } + } + } + } + KeLowerIrql(OldIrql); + } +} +#endif // _BETA_LIMIT_ +/* M0005 --- */ +#endif // 0 // M0008 + +#if defined(_BBM_DMA_) +{ + ULONG PtagReg, Ptag, DummyRead; + // D001 + if (*Length > (PAGE_SIZE * DMA_TRANSLATION_LIMIT / 8 / 8 )) { // kuriyama + DbgPrint("IoMapTransfer: *Length > %d pages\n", (DMA_TRANSLATION_LIMIT / 8 / 8)); + } + KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama + for (i = 0; i < 8; i++ ) { + PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i]; + Ptag = READ_REGISTER_ULONG(PtagReg); + if (Ptag & 0x1) { + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + if (HalDebug) + DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n", + PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead); + } + } +} +#endif // _BBM_DMA_ +#if 0 // kuriyama // D001 Delete checking ByteMask +// temp kuriyama start + for (i=0; i < 8; i++) { + if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i])){ + DbgPrint("IoMapTransfer : LowByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheLowByteMask[i])); + KeBugCheck(NMI_HARDWARE_FAILURE); + } + if (READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i])){ + DbgPrint("IoMapTransfer : HighByteMask[%d] is 0x%x\n",i,(ULONG)READ_REGISTER_ULONG(&DMA_CONTROL->IoCacheHighByteMask[i])); + KeBugCheck(NMI_HARDWARE_FAILURE); + } + } +// temp kuriyaam end +#endif // if 0 // kuriyama + + Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa ); + + + PageFrameNumber = (PULONG) (Mdl + 1); + NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT; + PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT); + +/* start M0004 */ +#if defined(_BBM_DMA_) +// +// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice +// + if (!WriteToDevice) { +// HalSweepDcache(); +// HalSweepIcache(); + HalDump("IoMapTransfer: AdapterObject = %x\n",(ULONG)AdapterObject); + for (i = 0; i < NumberOfPages; i++) { + bufferLogical = (((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT) + (i << PAGE_SHIFT); + HalDump("IoMapTransfer: bufferLogical = %x\n",bufferLogical); + bufferAddress = CopyBufferPhysicalBase + bufferLogical; + HalDump("IoMapTransfer: bufferAddress = %x\n",bufferAddress); + (DmaMapRegister++)->PageFrame = bufferAddress; + } + } else { + for (i = 0; i < NumberOfPages; i++) { + (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT; + } + } +#else // _BBM_DMA_ + for (i = 0; i < NumberOfPages; i++) { + (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT; + } +#endif // _BBM_DMA_ +/* end M0004 */ + +/* start M0004 */ +#if defined(_BBM_DMA_) +// +// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice +// + if (!WriteToDevice) { + Offset = 0; + ; + } +#endif // _BBM_DMA_ +/* end M0004 */ + + // + // Set the offset to point to the map register plus the offset. + // + + Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT; +/* start M0004 */ + if (!WriteToDevice) { + HalDump("IoMapTransfer: Offset %x\n",Offset); /* M0004 */ + HalDump("IoMapTransfer: Length %x\n",*Length); /* M0004 */ + HalDump("IoMapTransfer: CurrentVa %x\n",CurrentVa); /* M0004 */ + } +/* end M0004 */ + + // + // Invalidate the translation entry. + // + + WRITE_REGISTER_ULONG(&DMA_CONTROL->TranslationInvalidate.Long, 1); + +#if defined(_BBM_DMA_) + KeLowerIrql(OldIrql); // kuriyama +#endif //_BBM_DMA_ + if ( AdapterObject == NULL) { + return(RtlConvertUlongToLargeInteger(Offset)); + } + + if (AdapterObject->PagePort == NULL) { + +// M0013 +++ +#if defined(_R94A_) + // + // if Master Device, nothing set to DMAC. + // + + if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) { + return(RtlConvertUlongToLargeInteger(Offset)); + } +#endif // _R94A_ +// M0013 --- + // + // Set the local DMA Registers. + // + + WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Address.Long, Offset); + WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long, *Length); + + i = 0; + ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 1; + ((PDMA_CHANNEL_ENABLE) &i)->TransferDirection = + WriteToDevice ? DMA_WRITE_OP : DMA_READ_OP; + WRITE_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, i); + + + } else { + + // + // Start the EISA DMA controller. + // + + HalpEisaMapTransfer( + AdapterObject, + Offset, + *Length, + WriteToDevice + ); + + } + return(RtlConvertUlongToLargeInteger(Offset)); +} + +BOOLEAN +IoFlushAdapterBuffers( + IN PADAPTER_OBJECT AdapterObject, + IN PMDL Mdl, + IN PVOID MapRegisterBase, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine flushes the DMA adapter object buffers and clears the + enable flag which aborts the dma. + +Arguments: + + AdapterObject - Pointer to the adapter object representing the DMA + controller channel. + + Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down + buffer to/from which the I/O occured. + + MapRegisterBase - A pointer to the base of the map registers in the adapter + or DMA controller. + + CurrentVa - The current virtual address in the buffer described the the Mdl + where the I/O operation occurred. + + Length - Supplies the length of the transfer. + + WriteToDevice - Supplies a BOOLEAN value that indicates the direction of + the data transfer was to the device. + +Return Value: + + TRUE - If the transfer was successful. + + FALSE - If there was an error in the transfer. + +--*/ + +{ + + ULONG i; + UCHAR DataByte; + +/* start M0004 */ +#if defined(_BBM_DMA_) +// +// Note. BBM Must use 4kbyte aligned CopyBuffer when ReadFromDevice +// + +#if 0 + PCCHAR bufferAddress; +#endif + + PCCHAR mapAddress; + ULONG logicalAddress; + ULONG Offset; + PULONG PageFrameNumber; + ULONG NumberOfPages; + + if (!WriteToDevice) { + + HalDump("IoFlushAdapterBuffers: AdapterObject = %x\n",(ULONG)AdapterObject); + +#if 0 + bufferAddress = MmGetSystemAddressForMdl(Mdl); + bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl); + HalDump("IoFlushAdapterBuffers: bufferAddress = %x\n",bufferAddress); + HalDump("IoFlushAdapterBuffers: Length = %x\n",Length); +#endif + + logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT; + HalDump("IoFlushAdapterBuffers: logicalAddress = %x\n",logicalAddress); + + Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa ); + HalDump("IoFlushAdapterBuffers: Offset = %x\n",Offset); + + mapAddress = (PCCHAR)(CopyBufferVirtualAddress + logicalAddress); + + HalDump("IoFlushAdapterBuffers: mapAddress = %x\n",mapAddress); + HalDump("IoFlushAdapterBuffers: CurrentVa = %x\n",CurrentVa); + +// DbgBreakPoint(); +// RtlMoveMemory(CurrentVa, mapAddress, Length); +// DbgBreakPoint(); + + PageFrameNumber = (PULONG) (Mdl + 1); + NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT; + + HalDump("IoFlushAdapterBuffers: NumberOfPages = %x\n",NumberOfPages); + + PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT); + + HalDump("IoFlushAdapterBuffers: PageFrameNumber = %x\n",PageFrameNumber); + + if (NumberOfPages == 1) { + +#if 0 + HalDump( + "IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress); + HalDump("IoFlushAdapterBuffers: Length = %x\n",Length); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )+ Offset), + (PVOID)mapAddress, Length + ); + + } else if ( NumberOfPages == 2) { + +#if 0 + HalDump( + "IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress); + HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset), + (PVOID)mapAddress, (ULONG)(PAGE_SIZE - Offset) + ); + +#if 0 + HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + PAGE_SIZE + Offset); + HalDump("IoFlushAdapterBuffers: Length = %x\n" , BYTE_OFFSET(Length + Offset - 1) + 1); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + ((PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE )), +// (PVOID)(mapAddress + PAGE_SIZE + Offset), + (PVOID)(mapAddress + PAGE_SIZE - Offset), // H001 + (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1) + ); + + } else { + +#if 0 + HalDump( + "IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress); + HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE - Offset); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + (PVOID)((((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ) + Offset), + (PVOID)mapAddress, + (ULONG)(PAGE_SIZE - Offset) + ); + + for (i = 1; i < (NumberOfPages - 1); i++) { +#if 0 + HalDump("IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) +Offset); + HalDump("IoFlushAdapterBuffers: Length = %x\n",PAGE_SIZE); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE), +// (PVOID)((mapAddress + (i * PAGE_SIZE)) + Offset), + (PVOID)(mapAddress + (i * PAGE_SIZE) - Offset), // H001 + PAGE_SIZE + ); + + } + +#if 0 + HalDump( + "IoFlushAdapterBuffers: USERBUFFER = %x\n", + (((ULONG)*PageFrameNumber << PAGE_SHIFT) | KSEG1_BASE) + Offset + ); + HalDump("IoFlushAdapterBuffers: COPYBUFFER = %x\n",mapAddress + (i * PAGE_SIZE) + Offset); + HalDump("IoFlushAdapterBuffers: Length = %x\n",BYTE_OFFSET(Length + Offset - 1) + 1); +#endif + +// HalSweepIcache(); +// HalSweepDcache(); + + RtlMoveMemory( + (PVOID)(((ULONG) *PageFrameNumber++ << PAGE_SHIFT) | KSEG1_BASE ), +// (PVOID)(mapAddress + (i * PAGE_SIZE) + Offset), + (PVOID)(mapAddress + (NumberOfPages - 1) * PAGE_SIZE - Offset), // H001 + (ULONG)(BYTE_OFFSET(Length + Offset - 1) + 1) + ); + + } + } +#endif // _BBM_DMA_ +/* end M0004 */ +/* M0006 +++ */ +#if defined(_BETA_LIMIT_) +#if 0 // M0008 +{ + ULONG PtagReg, Ptag, LtagReg, Ltag, DummyRead, logicalAddress; + KIRQL OldIrql; + + if (!WriteToDevice) { // M0005 + logicalAddress = (ULONG)((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT; + // D001 +// DbgPrint("DmaFlush start\n"); + KeRaiseIrql(DEVICE_LEVEL, &OldIrql); // kuriyama + for (i = 0; i < 8; i++ ) { + PtagReg = (ULONG)&DMA_CONTROL->IoCachePhysicalTag[i]; + LtagReg = (ULONG)&DMA_CONTROL->IoCacheLogicalTag[i]; + Ptag = READ_REGISTER_ULONG(PtagReg); + Ltag = READ_REGISTER_ULONG(LtagReg); + if (Ptag & 0x1) { + if (Ltag & 0x1) { + if ((logicalAddress & 0xffffffc0) <= (Ltag & 0xffffffc0) && ((Ltag & 0xffffffc0) < (logicalAddress + Length))) { + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + DummyRead = READ_REGISTER_ULONG((KSEG1_BASE|(Ptag&0xFFFFFFC0))); + if (HalDebug) + DbgPrint("Found Valid Entry:0x%x Tag:0x%x. Read 0x%x=0x%x\n", + PtagReg, Ptag, (KSEG1_BASE|(Ptag&0xFFFFFFC0)), DummyRead); + } + } + } + } + KeLowerIrql(OldIrql); +// DbgPrint("DmaFlush end\n"); + } // M0005 + +} +#endif // 0 //M0008 +/* M0005,M0014 +++ */ +{ + ULONG Offset, NumberOfPages; + PULONG PageFrameNumber; + KIRQL OldIrql; + + if (Length != 0) { //S0015 + if (!WriteToDevice) { + KeRaiseIrql(HIGH_LEVEL, &OldIrql); // kuriyama + Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa ); + + PageFrameNumber = (PULONG) (Mdl + 1); + NumberOfPages = (Offset + Length + PAGE_SIZE - 1) >> PAGE_SHIFT; + PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT); + + if (NumberOfPages == 1) { + HalViewMemory((PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++ + << PAGE_SHIFT) + Offset))), + Length); + } else { + HalViewMemory( (PVOID)((KSEG1_BASE |(((ULONG) *PageFrameNumber++ + << PAGE_SHIFT) + Offset))), + (PAGE_SIZE - Offset)); + for (i = 1; i < NumberOfPages -1; i++) { + HalViewMemory( (PVOID)((KSEG1_BASE |((ULONG) *PageFrameNumber++ + << PAGE_SHIFT))), PAGE_SIZE); + } + HalViewMemory( (PVOID)((KSEG1_BASE + |((ULONG) *PageFrameNumber++ << PAGE_SHIFT))), + BYTE_OFFSET(Offset + Length -1) +1); + } + KeLowerIrql(OldIrql); + } + } +} + +/* M0005,M0014 --- */ + +#endif // _BETA_LIMIT_ +/* M0006 --- */ + + if (AdapterObject == NULL) { + + // + // This is a master adadapter so there is nothing to do. + // + + return(TRUE); + } + + if (AdapterObject->PagePort) { + + // + // If this is a master channel, then just return since the DMA + // request does not need to be disabled. + // + + DataByte = AdapterObject->AdapterMode; + + if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) { + + return(TRUE); + + } + + // + // Clear the EISA DMA adapter. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) + ); + + } + + } else { + +// M0013 +++ +#if defined(_R94A_) + // + // if Master Device, nothing set to DMAC. + // + + if ( AdapterObject->AdapterBaseVa == &(DMA_CONTROL)->Channel[7]) { + return(TRUE); + } +#endif // _R94A_ +// M0013 --- + // + // Clear on board DMA + // + + i = READ_REGISTER_ULONG( + &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long + ); + + ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0; + WRITE_REGISTER_ULONG( + &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, + i + ); + + i = READ_REGISTER_USHORT( + &((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable + ); + } + + return(TRUE); +} + +IO_ALLOCATION_ACTION +HalpAllocationRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context + ) + +/*++ + +Routine Description: + + This function is called by HalAllocateAdapterChannel when sufficent resources + are available to the driver. This routine saves the MapRegisterBase, + and set the event pointed to by the context parameter. + +Arguments: + + DeviceObject - Supplies a pointer where the map register base should be + stored. + + Irp - Unused. + + MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer. + + Context - Supplies a pointer to an event which is set to indicate the + AdapterObject has been allocated. + +Return Value: + + DeallocateObjectKeepRegisters - Indicates the adapter should be freed + and mapregisters should remain allocated after return. + +--*/ + +{ + + UNREFERENCED_PARAMETER(Irp); + + *((PVOID *) DeviceObject) = MapRegisterBase; + + (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE ); + + return(DeallocateObjectKeepRegisters); +} + +#if 0 // CHG0001 + +ULONG +HalGetBusDataByOffset( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Offset - Offset in the BusData buffer + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + + ULONG DataLength = 0; + + switch (BusDataType) { + case EisaConfiguration: + DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length); + break; + +/* start M0001 */ +#if 0 +#if defined(_R94A_) + + case PCIConfiguration: + DataLength = HalpReadPCIData(BusNumber, SlotNumber, Buffer, Offset, Length); + break; + +#endif // _R94A_ +#endif // 0 +/* end M0001 */ + + } + + return(DataLength); + +} +ULONG +HalGetBusData( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ) +/*++ + +Routine Description: + + Subset of HalGetBusDataByOffset, just pass the request along. + +--*/ +{ + return HalGetBusDataByOffset ( + BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length + ); +} + +ULONG +HalSetBusDataByOffset( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function sets the bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Offset - Offset in the BusData buffer + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + + ULONG DataLength = 0; + +/* start M0001 */ +#if 0 +#if defined(_R94A_) + + switch (BusDataType) { + + case PCIConfiguration: + DataLength = HalpWritePCIData(BusNumber, SlotNumber, Buffer, Offset, Length); + break; + } + +#endif // _R94A_ +#endif // 0 +/* end M0001 */ + + return(DataLength); +} + +ULONG +HalSetBusData( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ) +/*++ + +Routine Description: + + Subset of HalGetBusDataByOffset, just pass the request along. + +--*/ +{ + return HalSetBusDataByOffset( + BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length + ); +} + +NTSTATUS +HalAssignSlotResources ( + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN INTERFACE_TYPE BusType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine it's required resources. + Calls IoAssignResources to allocate them. + Sets the targeted device with it's assigned resoruces + and returns the assignments to the caller. + +Arguments: + + RegistryPath - Passed to IoAssignResources. + A device specific registry path in the current-control-set, used + to check for pre-assigned settings and to track various resource + assignment information for this device. + + DriverClassName Used to report the assigned resources for the driver/device + DriverObject - Used to report the assigned resources for the driver/device + DeviceObject - Used to report the assigned resources for the driver/device + (ie, IoReportResoruceUsage) + BusType + BusNumber + SlotNumber - Together BusType,BusNumber,SlotNumber uniquely + indentify the device to be queried & set. + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + // + // This HAL doesn't support any buses which support + // HalAssignSlotResources + // + + return STATUS_NOT_SUPPORTED; + +} + +NTSTATUS +HalAdjustResourceList ( + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + +Routine Description: + + Takes the pResourceList and limits any requested resource to + it's corrisponding bus requirements. + +Arguments: + + pResourceList - The resource list to adjust. + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + // + // BUGBUG: This function should verify that the resoruces fit + // the bus requirements - for now we will assume that the bus + // can support anything the device may ask for. + // + + return STATUS_SUCCESS; +} + +ULONG +HalpReadEisaData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Eisa bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + OBJECT_ATTRIBUTES ObjectAttributes; + OBJECT_ATTRIBUTES BusObjectAttributes; + PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter"; + PWSTR ConfigData = L"Configuration Data"; + ANSI_STRING TmpString; + UCHAR BusString[] = "00"; + UNICODE_STRING RootName, BusName; + UNICODE_STRING ConfigDataName; + NTSTATUS NtStatus; + PKEY_VALUE_FULL_INFORMATION ValueInformation; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource; + PCM_EISA_SLOT_INFORMATION SlotInformation; + ULONG PartialCount; + ULONG TotalDataSize, SlotDataSize; + HANDLE EisaHandle, BusHandle; + ULONG BytesWritten, BytesNeeded; + PUCHAR KeyValueBuffer; + ULONG i; + ULONG DataLength = 0; + PUCHAR DataBuffer = Buffer; + BOOLEAN Found = FALSE; + + + RtlInitUnicodeString( + &RootName, + EisaPath + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &RootName, + OBJ_CASE_INSENSITIVE, + (HANDLE)NULL, + NULL + ); + + // + // Open the EISA root + // + + NtStatus = ZwOpenKey( + &EisaHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + KdPrint(("HAL: Open Status = %x\n",NtStatus)); + return(0); + } + + // + // Init bus number path + // + + if (BusNumber > 99) { + return (0); + } + + if (BusNumber > 9) { + BusString[0] += (UCHAR) (BusNumber/10); + BusString[1] += (UCHAR) (BusNumber % 10); + } else { + BusString[0] += (UCHAR) BusNumber; + BusString[1] = '\0'; + } + + RtlInitAnsiString( + &TmpString, + BusString + ); + + RtlAnsiStringToUnicodeString( + &BusName, + &TmpString, + TRUE + ); + + + InitializeObjectAttributes( + &BusObjectAttributes, + &BusName, + OBJ_CASE_INSENSITIVE, + (HANDLE)EisaHandle, + NULL + ); + + // + // Open the EISA root + Bus Number + // + + NtStatus = ZwOpenKey( + &BusHandle, + KEY_READ, + &BusObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus)); + return(0); + } + + // + // opening the configuration data. This first call tells us how + // much memory we need to allocate + // + + RtlInitUnicodeString( + &ConfigDataName, + ConfigData + ); + + // + // This should fail. We need to make this call so we can + // get the actual size of the buffer to allocate. + // + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + 0, + &BytesNeeded + ); + + KeyValueBuffer = ExAllocatePool( + NonPagedPool, + BytesNeeded + ); + + if (KeyValueBuffer == NULL) { + KdPrint(("HAL: Cannot allocate Key Value Buffer\n")); + ZwClose(BusHandle); + return(0); + } + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer; + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + BytesNeeded, + &BytesWritten + ); + + + ZwClose(BusHandle); + + if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) { + KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus)); + ExFreePool(KeyValueBuffer); + return(0); + } + + + // + // We get back a Full Resource Descriptor List + // + + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation + + ValueInformation->DataOffset); + + PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) + &(Descriptor->PartialResourceList.PartialDescriptors); + PartialCount = Descriptor->PartialResourceList.Count; + + for (i = 0; i < PartialCount; i++) { + + // + // Do each partial Resource + // + + switch (PartialResource->Type) { + case CmResourceTypeNull: + case CmResourceTypePort: + case CmResourceTypeInterrupt: + case CmResourceTypeMemory: + case CmResourceTypeDma: + + // + // We dont care about these. + // + + PartialResource++; + + break; + + case CmResourceTypeDeviceSpecific: + + // + // Bingo! + // + + TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)PartialResource + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + + while (((LONG)TotalDataSize) > 0) { + + if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION); + + } else { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) + + SlotInformation->NumberFunctions * + sizeof(CM_EISA_FUNCTION_INFORMATION); + } + + if (SlotDataSize > TotalDataSize) { + + // + // Something is wrong again + // + + ExFreePool(KeyValueBuffer); + return(0); + + } + + if (SlotNumber != 0) { + + SlotNumber--; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)SlotInformation + SlotDataSize); + + TotalDataSize -= SlotDataSize; + + continue; + + } + + // + // This is our slot + // + + Found = TRUE; + break; + + } + + // + // End loop + // + + i = PartialCount; + + break; + + default: + KdPrint(("Bad Data in registry!\n")); + ExFreePool(KeyValueBuffer); + return(0); + } + } + + if (Found) { + + i = Length + Offset; + if (i > SlotDataSize) { + i = SlotDataSize; + } + + DataLength = i - Offset; + RtlMoveMemory ((PVOID)Buffer, (PVOID)((PUCHAR)SlotInformation + Offset), (ULONG)DataLength); + + } + + ExFreePool(KeyValueBuffer); + return DataLength; +} +#endif + +ULONG +HalReadDmaCounter( + IN PADAPTER_OBJECT AdapterObject + ) +/*++ + +Routine Description: + + This function reads the DMA counter and returns the number of bytes left + to be transfered. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object to be read. + +Return Value: + + Returns the number of bytes still be be transfered. + +--*/ + +{ + ULONG i; + ULONG saveEnable; + ULONG count; + ULONG high; + + if (AdapterObject->PagePort) { + + // + // Determine the controller number based on the Adapter number. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } + + // + // The DMA counter has a bias of one and can only be 16 bit long. + // + + count = (count + 1) & 0xFFFF; + + } else { + + // + // Disable the DMA + // + + i = READ_REGISTER_ULONG( + &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long + ); + + saveEnable = i; + + ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0; + WRITE_REGISTER_ULONG( + &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, + i + ); + + // + // Read the transfer count. + // + + count = 0xfffff & READ_REGISTER_ULONG(&((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->ByteCount.Long); // beta typhoon errata// M0009 + + // + // Reset the Enable register. + // + + WRITE_REGISTER_ULONG( + &((PDMA_CHANNEL) AdapterObject->AdapterBaseVa)->Enable.Long, + saveEnable + ); + + } + + return(count); +} + + +BOOLEAN +HalpDmaChannel( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This routine is called when a DMA channel interrupt occurs. + These should never occur. Bugcheck is called if an error does occur. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object + + ServiceContext - Bug number to call bugcheck with. + +Return Value: + + Returns TRUE. + +--*/ +{ + + ULONG DataWord; + ULONG Channel; + DMA_CHANNEL_ENABLE ChannelWord; + ULONG ErrorFlag = 0; /* M0003 */ + +#if defined(_JAZZ_) + + // + // Read the DMA channel interrupt source register. + // + + DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->InterruptSource.Long); + + for (Channel = 0; Channel < 8; Channel++) { + + // + // Determine which channel is interrupting. + // + + if (!(DataWord & ( 1 << Channel))) { + continue; + } + + DmaChannelMsg[18] = (CHAR) Channel + '0'; + + HalDisplayString(DmaChannelMsg); + + *((PULONG) &ChannelWord) = + READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long); + + if (ChannelWord.TerminalCount) { + HalDisplayString("Terminal count was reached.\n"); + } + + if (ChannelWord.MemoryError) { + HalDisplayString("A memory error was detected.\n"); + } + + if (ChannelWord.TranslationError) { + HalDisplayString("A translation error occured.\n"); + } + + } + + KeBugCheck(NMI_HARDWARE_FAILURE); + +#endif + +/* start M0001 */ +#if defined(_R94A_) + + HalpChangePanicFlag(16, 0x01, 0x10); // S0023 + + // + // Read the DMA channel interrupt source register. + // + + DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->ChannelInterruptAcknowledge.Long); + + for (Channel = 0; Channel < 4; Channel++) { + + // + // Determine which channel is interrupting. + // + + if (!(DataWord & ( 1 << Channel))) { + continue; + } + + DmaChannelMsg[18] = (CHAR) Channel + '0'; + + + *((PULONG) &ChannelWord) = + READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long); + +/* start M0002 */ + if (ChannelWord.TerminalCount) { + if ((0xfffff & READ_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].ByteCount.Long)) != 0) { // beta typhoon errta // M0009 + HalDisplayString(DmaChannelMsg); + HalDisplayString("Terminal count was reached."); // S0011 + ErrorFlag++; + } + } + + if (ChannelWord.MemoryError) { + HalDisplayString(DmaChannelMsg); + HalDisplayString("A memory error was detected."); // S0011 + ErrorFlag++; + } + + if (ChannelWord.ParityError) { + HalDisplayString(DmaChannelMsg); + HalDisplayString("A Parity error occured."); // S0011 + ErrorFlag++; + } + + if (ChannelWord.MasterAbort) { + HalDisplayString(DmaChannelMsg); + HalDisplayString("A PCIBus Master Abort error occured."); // S0011 + ErrorFlag++; + } + + // Clear Dma Channel Interrupt + WRITE_REGISTER_ULONG(&DMA_CONTROL->Channel[Channel].Enable.Long, 0x00000100); // M0009 +/* end M0002 */ + } + + if (ErrorFlag != 0) { + KeBugCheck(NMI_HARDWARE_FAILURE); + } +#endif // _R94A_ +/* end M0001 */ + + return(TRUE); +} + +VOID +HalpAllocateMapRegisters( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + This routine allocates memory for map registers directly from the loader + block information. This memory must be non-cached and contiguous. + +Arguments: + + LoaderBlock - Pointer to the loader block which contains the memory descriptors. + +Return Value: + + None. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG MaxPageAddress; + ULONG PhysicalAddress; + ULONG MapRegisterSize; + + MapRegisterSize = DMA_TRANSLATION_LIMIT; + MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize); + + // + // The address must be in KSEG 0. + // + + MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ; + + // + // Scan the memory allocation descriptors and allocate map buffers + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + // + // Search for a block of memory which is contains a memory chuck + // that is greater than size pages, and has a physical address less + // than MAXIMUM_PHYSICAL_ADDRESS. + // + + if ((Descriptor->MemoryType == LoaderFree || + Descriptor->MemoryType == MemoryFirmwareTemporary) && + (Descriptor->BasePage) && + (Descriptor->PageCount >= MapRegisterSize) && + (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) { + + PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT; + break; + } + + NextMd = NextMd->Flink; + } + + // + // Use the extra descriptor to define the memory at the end of the + // original block. + // + + ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead); + + if (NextMd == &LoaderBlock->MemoryDescriptorListHead) + return; + + // + // Adjust the memory descriptors. + // + + Descriptor->BasePage += MapRegisterSize; + Descriptor->PageCount -= MapRegisterSize; + + if (Descriptor->PageCount == 0) { + + // + // The whole block was allocated, + // Remove the entry from the list completely. + // + + RemoveEntryList(&Descriptor->ListEntry); + + } + + // + // Save the map register base. + // + + HalpMapRegisterPhysicalBase = PhysicalAddress; + +#if defined(_BBM_DMA_) +/* start kuriyama TLB fill 0xff */ // D001 + RtlFillMemory( (HalpMapRegisterPhysicalBase | KSEG1_BASE), 0x2000, 0xff); +/* end kuriyama TLB fill 0xff */ +#endif // _BBM_DMA_ + +/* start M0004 */ +#if defined(_BBM_DMA_) + HalpAllocateCopyBuffer(LoaderBlock); +#endif // _BBM_DMA_ +/* end M0004 */ +} + +/* start M0001 */ +#if defined(_R94A_) +BOOLEAN +HalpCreateTyphoonErrorStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for Typhoon Error + interrupt dispatcher. It also connects an interrupt handler to the + Typhoon Error interrupt. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + // + // Initialize the Typhoon Error interrupt dispatcher for I/O interrupts. + // + + KeInitializeInterrupt( &HalpTyphoonErrorInterrupt, + HalpTyphoonError, + (PVOID) NULL, + (PKSPIN_LOCK) NULL, + TYPHOON_ERROR_INTERRUPT_VECTOR, + DEVICE_LEVEL, + DEVICE_LEVEL, + LevelSensitive, + FALSE, + 0, + FALSE + ); + + // + // Don't fail if the interrupt cannot be connected. + // + + return KeConnectInterrupt( &HalpTyphoonErrorInterrupt ); + +} +#endif // _R94A_ +/* end M0001 */ + +/* start M0001 */ +#if defined(_R94A_) +BOOLEAN +HalpTyphoonError( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This routine is called when a Typhoon Error interrupt occurs. + This error is cretical. Bugcheck is called if an error does occur. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object + + ServiceContext - Bug number to call bugcheck with. + +Return Value: + + Returns TRUE. + + Note. This function never return. This function call always KeBugCheck(). + +--*/ +{ + + ULONG DataWord; + + HalpChangePanicFlag(16, 0x01, 0x10); // S0023 + + // + // Read the Typhoon Error Status register. + // + + DataWord = READ_REGISTER_ULONG(&DMA_CONTROL->TyphoonErrorStatus); + + HalDisplayString("\nHAL: Internal master error occurred.\n"); // S0022 + + if ( DataWord & 2) { + + HalDisplayString("ethernet bus master error\n"); + + } + + if ( DataWord & 4) { + + HalDisplayString("SCSI port 1 bus master error\n"); + + } + + KeBugCheck(NMI_HARDWARE_FAILURE); + + + return(TRUE); +} +#endif // _R94A_ +/* end M0001 */ + +#if defined(_BBM_DMA_) +VOID +HalpAllocateCopyBuffer( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + This routine allocates memory for copybuffer directly from the loader + block information. This memory must be non-cached and contiguous. + +Arguments: + + LoaderBlock - Pointer to the loader block which contains the memory descriptors. + +Return Value: + + None. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG MaxPageAddress; + ULONG PhysicalAddress; + ULONG MapRegisterSize; + + MapRegisterSize = 0x400000; + MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize); + + // + // The address must be in KSEG 0. + // + + MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ; + + // + // Scan the memory allocation descriptors and allocate map buffers + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + Descriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + // + // Search for a block of memory which is contains a memory chuck + // that is greater than size pages, and has a physical address less + // than MAXIMUM_PHYSICAL_ADDRESS. + // + + if ((Descriptor->MemoryType == LoaderFree || + Descriptor->MemoryType == MemoryFirmwareTemporary) && + (Descriptor->BasePage) && + (Descriptor->PageCount >= MapRegisterSize) && + (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) { + + PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT; + break; + } + + NextMd = NextMd->Flink; + } + + // + // Use the extra descriptor to define the memory at the end of the + // original block. + // + + ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead); + + if (NextMd == &LoaderBlock->MemoryDescriptorListHead) + return; + + // + // Adjust the memory descriptors. + // + + Descriptor->BasePage += MapRegisterSize; + Descriptor->PageCount -= MapRegisterSize; + + if (Descriptor->PageCount == 0) { + + // + // The whole block was allocated, + // Remove the entry from the list completely. + // + + RemoveEntryList(&Descriptor->ListEntry); + + } + + // + // Save the map register base. + // + + CopyBufferPhysicalBase = PhysicalAddress; + HalDump("Common Buffer Physical = %x\n",CopyBufferPhysicalBase); + CopyBufferVirtualAddress = PhysicalAddress | KSEG1_BASE; + HalDump("Common Buffer Virtual = %x\n",CopyBufferVirtualAddress); +} +#endif // _BBM_DMA_ +/* end M0004 */ diff --git a/private/ntos/nthals/halr96b/mips/jxmapio.c b/private/ntos/nthals/halr96b/mips/jxmapio.c new file mode 100644 index 000000000..879f96410 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxmapio.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\jxmapio.c" diff --git a/private/ntos/nthals/halr96b/mips/jxmaptb.c b/private/ntos/nthals/halr96b/mips/jxmaptb.c new file mode 100644 index 000000000..9262bc775 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxmaptb.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\jxmaptb.c" diff --git a/private/ntos/nthals/halr96b/mips/jxport.c b/private/ntos/nthals/halr96b/mips/jxport.c new file mode 100644 index 000000000..26e310528 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxport.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\jxport.c" diff --git a/private/ntos/nthals/halr96b/mips/jxreturn.c b/private/ntos/nthals/halr96b/mips/jxreturn.c new file mode 100644 index 000000000..d77d5642b --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxreturn.c @@ -0,0 +1,258 @@ +// #pragma comment(exestr, "@(#) jxreturn.c 1.1 95/09/28 15:40:17 nec") +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxreturn.c + +Abstract: + + This module implements the HAL return to firmware function. + +Author: + + David N. Cutler (davec) 21-Aug-1991 + +Revision History: + + H000 Tue Apr 25 16:02:05 1995 kbnes!kisimoto + -add Powerdown if argument value indicates + HalPowerDownRoutine + S001 kuriyama@oa2.kb.nec.co.jp Sun May 21 18:32:55 JST 1995 + -compile error clear + S002 kuriyama@oa2.kb.nec.co.jp Sun May 21 20:19:48 JST 1995 + - powoff bug? fixed + H003 Sat Aug 12 19:33:45 1995 kbnes!kisimoto + - Removed _J94C_ definitions. + _J94C_ definition indicates that the status of the + dump switch can acknowledge from Self-test register. + + M004 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:28:35 JST 1995 + - add for x86bios emurator support +--*/ +#include "halp.h" +#define HEADER_FILE +#include "kxmips.h" + +// +// Define keyboard registers structure. +// + +typedef struct _KBD_REGISTERS { + union { + UCHAR Output; + UCHAR Input; + } Data; + + union { + UCHAR Status; + UCHAR Command; + } Control; +} KBD_REGISTERS; + +#define KBD_IBF_MASK 2 // input buffer full mask + +#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status)) +#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte) +#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte) +#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output)) + +VOID +HalReturnToFirmware( + IN FIRMWARE_REENTRY Routine + ) + +/*++ + +Routine Description: + + This function returns control to the specified firmware routine. + In most cases it generates a soft reset by asserting the reset line + trough the keyboard controller. + The Keyboard controller is mapped using the same virtual address + and the same fixed entry as the DMA. + +Arguments: + + Routine - Supplies a value indicating which firmware routine to invoke. + +Return Value: + + Does not return. + +--*/ + +{ + + KIRQL OldIrql; + ENTRYLO Pte[2]; + ULONG Index; // A001 + volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE; + ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; //S004 + + // + // Disable Interrupts. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Case on the type of return. + // + + switch (Routine) { + case HalHaltRoutine: + + // + // Hang looping. + // + + for (;;) { + } + + case HalPowerDownRoutine: + +#if defined (_MRCPOWER_) + + // + // S004 + // Reset ISA Display Adapter to 80x25 color text mode. + // + + Eax = 0x12; // AH = 0 AL = 0x12 + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + // + // H000,S001 + // Powerdown the machine + // + + // + // Map the MRC + // + + Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT; + + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + #if defined(R3000) + + Pte[0].N = 1; + + #endif + + #if defined(R4000) + + // + // set second page to global and not valid. + // + + Pte[0].C = UNCACHED_POLICY; + Pte[1].G = 1; + Pte[1].V = 0; + + #endif + + // + // Map MRC using virtual address of DMA controller. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); + + // + // Send Powerdown Command to the MRC. + // + + + for (;;) { // S002 + WRITE_REGISTER_UCHAR( + &MRC_CONTROL->SoftwarePowerOff, + 0x1 + ); + } + + for (;;) { + } +#endif //_MRCPOWER_ + + case HalRestartRoutine: + case HalRebootRoutine: + case HalInteractiveModeRoutine: + + // + // S004 + // Reset ISA Display Adapter to 80x25 color text mode. + // + + Eax = 0x12; // AH = 0 AL = 0x12 + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + // + // Map the keyboard controller + // + + Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT; + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + #if defined(R3000) + + Pte[0].N = 1; + + #endif + + #if defined(R4000) + + // + // set second page to global and not valid. + // + + Pte[0].C = UNCACHED_POLICY; + Pte[1].G = 1; + Pte[1].V = 0; + + #endif + + // + // Map keyboard controller using virtual address of DMA controller. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); + + // + // Send WriteOutputBuffer Command to the controller. + // + + while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { + } + + KbdStoreCommand(0xD1); + + // + // Write a zero to the output buffer. Causes reset line to be asserted. + // + + while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { + } + + KbdStoreData(0); + for (;;) { + } + + default: + KdPrint(("HalReturnToFirmware invalid argument\n")); + KeLowerIrql(OldIrql); + DbgBreakPoint(); + } +} + + diff --git a/private/ntos/nthals/halr96b/mips/jxsysint.c b/private/ntos/nthals/halr96b/mips/jxsysint.c new file mode 100644 index 000000000..ebe54f024 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxsysint.c @@ -0,0 +1,355 @@ +// #pragma comment(exestr, "@(#) jxsysint.c 1.1 95/09/28 15:40:45 nec") +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + jxsysint.c + +Abstract: + + This module implements the HAL enable/disable system interrupt, and + request interprocessor interrupt routines for a MIPS R3000 or R4000 + Jazz system. + +Author: + + David N. Cutler (davec) 6-May-1991 + +Environment: + + Kernel mode + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto + - HalDisableSystemInterrupt() + change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL. + add the PCI interrupt vector. + Interrupt Enable register is zero origin on beta-version of + STORM chipset. + if ASIC3 register is zero, then chipset is beta-version. + - HalEnableSystemInterrupt() + change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL. + add the PCI interrupt vector. + Interrupt Enable register is zero origin on beta-version of + STORM chipset. + if ASIC3 register is zero, then chipset is beta-version. + - HalGetInterruptVector() + add PCIBus interface. + change Irql from EISA_DEVICE_LEVEL to EISA_PCI_DEVICE_LEVEL. + If InterfaceType is Internal and ASIC3 register is zero, + then return the vector which was plus the offset of DEVICE_VECTORS. + H001 Mon Oct 17 14:21:21 JST 1994 kbnes!kishimoto + - Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX() + - XXX_EISA_PCI_XXX rename to XXX_EISA_XXX + - MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT + - HalGetInterruptVector() + returns PCI-vector plus offset PCI_VECTORS. + - modify original compile error + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:46:35 JST 1994 + - reslve compile error + H002 Mon Oct 31 17:45:56 1994 kbnes!kishimoto + - HalGetInterruptVector() + Internal SCSI interrupt vector set to 5 (for BBM only) + M003 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:06:37 JST 1995 + - add _IPI_LIMIT_ support + S004 kuriyama@oa2.kb.nec.co.jp Sat Apr 01 11:10:52 JST 1995 + - compile error clear + H005 Fri Aug 11 16:53:13 1995 kbnes!kishimoto + - delete M003, and HalGetInterruptVector(move to bushnd.c) + +--*/ + +#include "halp.h" + +VOID +HalDisableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine disables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is disabled. + + Irql - Supplies the IRQL of the interrupting source. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + // + // If the vector number is within the range of builtin devices, then + // disable the builtin device interrupt. + // + + if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) { + HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1)); + +#if defined(_R94A_) + + if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){ + + // + // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt + // Enable register is zero origin. + // + // N.B. This obstruction is limiteded to beta-version of STORM chipset. + // + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill, + HalpBuiltinInterruptEnable); + } else { + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, + HalpBuiltinInterruptEnable); + } + +#else + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, + HalpBuiltinInterruptEnable); + +#endif + + } + + // + // If the vector number is within the range of the EISA interrupts, then + // disable the EISA interrrupt. + // + + if (Vector >= EISA_VECTORS && + Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR && + Irql == EISA_DEVICE_LEVEL) { + HalpDisableEisaInterrupt(Vector); + } + +#if defined(_R94A_) + + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + if (Vector >= PCI_VECTORS && + Vector <= PCI_VECTORS + R94A_PCI_SLOT && + Irql == EISA_DEVICE_LEVEL) { + HalpDisablePCIInterrupt(Vector); + } + +#endif + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return; +} + +BOOLEAN +HalEnableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + // + // If the vector number is within the range of builtin devices, then + // enable the builtin device interrupt. + // + + if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) { + HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1)); + +#if defined(_R94A_) + + if ( READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ASIC3Revision.Long) == 0 ){ + + // + // The bit assign of TYPHOON(in STORM chipset)'s I/O Device Interrupt + // Enable register is zero origin. + // + // N.B. This obstruction is limiteded to beta-version of STORM chipset. + // + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Fill, + HalpBuiltinInterruptEnable); + + } else { + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, + HalpBuiltinInterruptEnable); + + } +#else + + WRITE_REGISTER_USHORT(&((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE)->Enable, + HalpBuiltinInterruptEnable); + +#endif + + } + + // + // If the vector number is within the range of the EISA interrupts, then + // enable the EISA interrrupt and set the Level/Edge register. + // + + if (Vector >= EISA_VECTORS && + Vector < EISA_VECTORS + MAXIMUM_EISA_VECTOR && + Irql == EISA_DEVICE_LEVEL) { + HalpEnableEisaInterrupt( Vector, InterruptMode); + } + +#if defined(_R94A_) + + // + // If the vector number is within the range of the PCI interrupts, then + // enable the PCI interrrupt. + // + + if (Vector >= PCI_VECTORS && + Vector <= PCI_VECTORS + R94A_PCI_SLOT && + Irql == EISA_DEVICE_LEVEL) { + HalpEnablePCIInterrupt(Vector); + } + +#endif + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return TRUE; +} + +VOID +HalRequestIpi ( + IN ULONG Mask + ) + +/*++ + +Routine Description: + + This routine requests an interprocessor interrupt on a set of processors. + + N.B. This routine must ensure that the interrupt is posted at the target + processor(s) before returning. + +Arguments: + + Mask - Supplies the set of processors that are sent an interprocessor + interrupt. + +Return Value: + + None. + +--*/ + +{ + +#if defined(_DUO_) // S004 + +// M003 +++ +#if defined(_IPI_LIMIT_) + ULONG OldIpiReq; + KIRQL OldIrql; + + // + // Request an interprocessor interrupt on each of the specified target + // processors. + // + KeRaiseIrql(HIGH_LEVEL,&OldIrql); + + KiAcquireSpinLock(&HalpIpiRequestLock); + + OldIpiReq = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long); + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long, + OldIpiReq | Mask); + + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long); + + KiReleaseSpinLock(&HalpIpiRequestLock); + + KeLowerIrql(OldIrql); + + +#else // _IPI_LIMIT_ + // + // Request an interprocessor interrupt on each of the specified target + // processors. + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->IpInterruptRequest.Long, + Mask); + +#endif //_IPI_LIMIT_ +// M003 --- + +#endif + + return; +} diff --git a/private/ntos/nthals/halr96b/mips/jxtime.c b/private/ntos/nthals/halr96b/mips/jxtime.c new file mode 100644 index 000000000..5d9c29705 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxtime.c @@ -0,0 +1,377 @@ +// #pragma comment(exestr, "@(#) jxtime.c 1.1 95/09/28 15:41:57 nec") +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxtime.c + +Abstract: + + This module implements the HAL set/query realtime clock routines for + a MIPS R3000 or R4000 Jazz system. + +Author: + + David N. Cutler (davec) 5-May-1991 + +Environment: + + Kernel mode + +Revision History: + + M0001 1994.9.9 kbnes!A.Kuriyama + + Modify for R94A + + HalpReadClockRegister() - R94A use RTC Index register except EISA NmiEnable + register. + HalpWriteClockRegister() - R94A use RTC Index register except EISA NmiEnable + register. + + M0002 1994.10.8 kbnes!kuriyama(A) + + HalpReadClockRegister() + -add specify Read Data register + HalpWritelockRegister() + -add specify Write Data register + + M0003 1994.10.14 kbnes!kuriyama(A) + + define error clear + + M0004 1994.12.19 kbnes!kuriyama(A) + + define miss fix +--*/ + +#include "halp.h" +#include "jazzrtc.h" +#include "eisa.h" + + +// +// Define forward referenced procedure prototypes. +// + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ); + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ); + +BOOLEAN +HalQueryRealTimeClock ( + OUT PTIME_FIELDS TimeFields + ) + +/*++ + +Routine Description: + + This routine queries the realtime clock. + + N.B. This routine is required to provide any synchronization necessary + to query the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that receives + the realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are read from the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + KIRQL OldIrql; + + // + // If the realtime clock battery is still functioning, then read + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Wait until the realtime clock is not being updated. + // + + do { + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA); + } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1); + + // + // Read the realtime clock values. + // + + TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR); + TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH); + TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH); + TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1; + TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR); + TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE); + TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND); + TimeFields->Milliseconds = 0; + KeLowerIrql(OldIrql); + return TRUE; + + } else { + KeLowerIrql(OldIrql); + return FALSE; + } +} + +BOOLEAN +HalSetRealTimeClock ( + IN PTIME_FIELDS TimeFields + ) + +/*++ + +Routine Description: + + This routine sets the realtime clock. + + N.B. This routine is required to provide any synchronization necessary + to set the realtime clock information. + +Arguments: + + TimeFields - Supplies a pointer to a time structure that specifies the + realtime clock information. + +Return Value: + + If the power to the realtime clock has not failed, then the time + values are written to the realtime clock and a value of TRUE is + returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + UCHAR DataByte; + KIRQL OldIrql; + + // + // If the realtime clock battery is still functioning, then write + // the realtime clock values, and return a function value of TRUE. + // Otherwise, return a function value of FALSE. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD); + if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) { + + // + // Set the realtime clock control to set the time. + // + + DataByte = 0; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->DataMode = 1; + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1; + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + + // + // Write the realtime clock values. + // + + HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980)); + HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month); + HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day); + HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1)); + HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour); + HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute); + HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second); + + // + // Set the realtime clock control to update the time. + // + + ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0; + HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte); + KeLowerIrql(OldIrql); + return TRUE; + + } else { + KeLowerIrql(OldIrql); + return FALSE; + } +} + +UCHAR +HalpReadClockRegister ( + UCHAR Register + ) + +/*++ + +Routine Description: + + This routine reads the specified realtime clock register. + +Arguments: + + Register - Supplies the number of the register whose value is read. + +Return Value: + + The value of the register is returned as the function value. + +--*/ + +{ + +/* start M0001 */ +#if defined(_R94A_) /* M0003 */ + // Insert the realtime clock register number, and write the value back + // to RTC Index register. This selects the realtime clock register + // that is read. + // + + WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index, + Register); + + +#else // _R94A_ + + // + // Insert the realtime clock register number, and write the value back + // to the EISA NMI enable register. This selects the realtime clock register + // that is read. Note this is a write only register and the EISA NMI + // is always enabled. + // + + // + // TEMPTEMP Disable NMI's for now because this is causing machines in the + // build lab to get NMI's during boot. + // + + Register |= 0x80; + + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + Register); + +#endif // _R94A_ +/* end M0001 */ + + // + // Read the realtime clock register value. + // + +/* start M0002 */ +#if defined(_R94A_) // M0004 + + return READ_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data); + + +#else // _R94A_ + + return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase); + +#endif // _R94A_ +/* end M0002 */ + +} + +VOID +HalpWriteClockRegister ( + UCHAR Register, + UCHAR Value + ) + +/*++ + +Routine Description: + + This routine writes the specified value to the specified realtime + clock register. + +Arguments: + + Register - Supplies the number of the register whose value is written. + + Value - Supplies the value that is written to the specified register. + +Return Value: + + The value of the register is returned as the function value. + +--*/ + +{ + +/* start M0001 */ +#if defined(_R94A_) + // + // Insert the realtime clock register number, and write the value back + // to RTC Index register. This selects the realtime clock + // register that is written. + // + + WRITE_REGISTER_UCHAR(&((PRTC_REGISTERS) HalpRealTimeClockBase)->Index, + Register); + +#else // _R94A_ + + // + // Insert the realtime clock register number, and write the value back + // to the EISA NMI enable register. This selects the realtime clock + // register that is written. Note this is a write only register and + // the EISA NMI is always enabled. + // + + Register |= 0x80; + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + Register); + +#endif // _R94A_ +/* end M0001 */ + + // + // Write the realtime clock register value. + // + +/* start M0002 */ +#if defined(_R94A_) // M0004 + + WRITE_REGISTER_UCHAR( &((PRTC_REGISTERS) HalpRealTimeClockBase)->Data, Value); + +#else // _R94A_ + + WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value); + +#endif // _R94A_ +/* end M0002 */ + + return; +} + + + + + + + + + diff --git a/private/ntos/nthals/halr96b/mips/jxusage.c b/private/ntos/nthals/halr96b/mips/jxusage.c new file mode 100644 index 000000000..12a54de49 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/jxusage.c @@ -0,0 +1,510 @@ +// #pragma comment(exestr, "@(#) jxusage.c 1.1 95/09/28 15:42:20 nec") +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ixusage.c + +Abstract: + +Author: + + Ken Reneris (kenr) + +Environment: + + Kernel mode only. + +Revision History: + + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994 + - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS + CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994 + - delete HalpEnableInterruptHandler, HalpRegisterVector + - change IDT vector LOOP, R94A report up to DEVICE_VECTORS + - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994 + - resolve compile error + CMP002 ataka@oa2.kb.nec.co.jp Tue Oct 18 22:33:14 JST 1994 + - add following + // HalpRegisterAddressUsage (&HalpDefaultPcIoSpace); + // HalpRegisterAddressUsage (&HalpEisaIoSpace); + // HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace); + +--*/ + +#include "halp.h" + + +// +// Array to remember hal's IDT usage +// + +#if !defined(_R94A_) // CMP001 +extern ADDRESS_USAGE *HalpAddressUsageList; +extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif // _R94A + +KAFFINITY HalpActiveProcessors; + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ); + +// CMP001 +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpGetResourceSortValue) +#pragma alloc_text(INIT,HalpReportResourceUsage) +#endif + + + +#if !defined (_R94A_) // CHG001 +VOID +HalpEnableInterruptHandler ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql, + IN VOID (*HalInterruptServiceRoutine)(VOID), + IN KINTERRUPT_MODE InterruptMode + ) +/*++ + +Routine Description: + + This function connects & registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql); + + + // + // Connect the IDT and enable the vector now + // + + KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine); + HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode); +} + + + +VOID +HalpRegisterVector ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql + ) +/*++ + +Routine Description: + + This registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ +#if DBG + // There are only 0ff IDT entries... + ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR && + BusInterruptVector <= MAXIMUM_IDTVECTOR); +#endif + + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + + HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags; + HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql; + HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector; +} +#endif // _R94A_ + + +VOID +HalpGetResourceSortValue ( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, + OUT PULONG sortscale, + OUT PLARGE_INTEGER sortvalue + ) +/*++ + +Routine Description: + + Used by HalpReportResourceUsage in order to properly sort + partial_resource_descriptors. + +Arguments: + + pRCurLoc - resource descriptor + +Return Value: + + sortscale - scaling of resource descriptor for sorting + sortvalue - value to sort on + + +--*/ +{ + switch (pRCurLoc->Type) { + case CmResourceTypeInterrupt: + *sortscale = 0; + *sortvalue = RtlConvertUlongToLargeInteger( + pRCurLoc->u.Interrupt.Level ); + break; + + case CmResourceTypePort: + *sortscale = 1; + *sortvalue = pRCurLoc->u.Port.Start; + break; + + case CmResourceTypeMemory: + *sortscale = 2; + *sortvalue = pRCurLoc->u.Memory.Start; + break; + + default: + *sortscale = 4; + *sortvalue = RtlConvertUlongToLargeInteger (0); + break; + } +} + + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse + ) +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ +{ + PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList; + PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc; + PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc; + CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc; + ULONG i, j, k, ListSize, Count; + ULONG curscale, sortscale; + UCHAR pass, reporton; + INTERFACE_TYPE interfacetype; + ULONG CurrentIDT, CurrentElement; + ADDRESS_USAGE *CurrentAddress; + LARGE_INTEGER curvalue, sortvalue; + + +#if defined(_R94A_) +// HalpRegisterAddressUsage (&HalpDefaultPcIoSpace); +// HalpRegisterAddressUsage (&HalpEisaIoSpace); +// HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace); +#endif // _R94A_ + + + + // + // Allocate some space to build the resource structure + // + + RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); + TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2); + + // This functions assumes unset fields are zero + RtlZeroMemory (RawResourceList, PAGE_SIZE*2); + RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2); + + // + // Initialize the lists + // + + RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1; + + pRFullDesc = RawResourceList->List; + pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List; + pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List; + + // + // Make sure all vectors 00-2f are reserved + // 00-1E reserved by Intel + // 1F reserved by Intel for APIC (apc priority level) + // 20-2e reserved by Microsoft + // 2f reserved by Microsoft for APIC (dpc priority level) + // + +#if defined(_R94A_) // CHG001 + for(i=0; i < DEVICE_VECTORS; i++) { // ADD001 + HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched; + HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; + } +#else + for(i=0; i < PRIMARY_VECTOR_BASE; i++) { + if (!(HalpIDTUsage[i].Flags & IDTOwned)) { + HalpIDTUsage[i].Flags = InternalUsage; + HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; + } + } +#endif + + for(pass=0; pass < 2; pass++) { + if (pass == 0) { + // + // First pass - build resource lists for resources reported + // reported against device usage. + // + + reporton = DeviceUsage & ~IDTOwned; + interfacetype = DeviceInterfaceToUse; + } else { + + // + // Second pass = build reousce lists for resources reported + // as internal usage. + // + + reporton = InternalUsage & ~IDTOwned; + interfacetype = Internal; + } + + CurrentIDT = 0; + CurrentElement = 0; + CurrentAddress = HalpAddressUsageList; + + for (; ;) { + if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001 + // + // Check to see if CurrentIDT needs to be reported + // + + if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) { + // Don't report on this one + CurrentIDT++; + continue; + } + + // + // Report CurrentIDT resource + // + + RPartialDesc.Type = CmResourceTypeInterrupt; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + RPartialDesc.Flags = + HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ? + CM_RESOURCE_INTERRUPT_LATCHED : + CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; + + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + TPartialDesc.u.Interrupt.Vector = CurrentIDT; + TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql; + + CurrentIDT++; + + } else { + // + // Check to see if CurrentAddress needs to be reported + // + + if (!CurrentAddress) { + break; // No addresses left + } + + if (!(CurrentAddress->Flags & reporton)) { + // Don't report on this list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + if (!CurrentAddress->Element[CurrentElement].Length) { + // End of current list, go to next list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + // + // Report CurrentAddress + // + + RPartialDesc.Type = (UCHAR) CurrentAddress->Type; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + if (RPartialDesc.Type == CmResourceTypePort) { + i = 1; // address space port + RPartialDesc.Flags = CM_RESOURCE_PORT_IO; + } else { + i = 0; // address space memory + RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; + } + + // Notice: assuming u.Memory and u.Port have the same layout + RPartialDesc.u.Memory.Start.HighPart = 0; + RPartialDesc.u.Memory.Start.LowPart = + CurrentAddress->Element[CurrentElement].Start; + + RPartialDesc.u.Memory.Length = + CurrentAddress->Element[CurrentElement].Length; + + // translated address = Raw address + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + HalTranslateBusAddress ( + interfacetype, // device bus or internal + 0, // bus number + RPartialDesc.u.Memory.Start, // source address + &i, // address space + &TPartialDesc.u.Memory.Start ); // translated address + + if (RPartialDesc.Type == CmResourceTypePort && i == 0) { + TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; + } + + CurrentElement++; + } + + // + // Include the current resource in the HALs list + // + + if (pRFullDesc->InterfaceType != interfacetype) { + // + // Interface type changed, add another full section + // + + RawResourceList->Count++; + TranslatedResourceList->Count++; + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + + pRFullDesc->InterfaceType = interfacetype; + pTFullDesc->InterfaceType = interfacetype; + + pRPartList = &pRFullDesc->PartialResourceList; + pTPartList = &pTFullDesc->PartialResourceList; + + // + // Bump current location pointers up + // + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + } + + + pRPartList->Count++; + pTPartList->Count++; + RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc); + RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc); + + pRCurLoc++; + pTCurLoc++; + } + } + + ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) ); + + // + // The HAL's resource usage structures have been built + // Sort the partial lists based on the Raw resource values + // + + pRFullDesc = RawResourceList->List; + pTFullDesc = TranslatedResourceList->List; + + for (i=0; i < RawResourceList->Count; i++) { + + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + Count = pRFullDesc->PartialResourceList.Count; + + for (j=0; j < Count; j++) { + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + + pRSortLoc = pRCurLoc; + pTSortLoc = pTCurLoc; + + for (k=j; k < Count; k++) { + HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); + + if (sortscale < curscale || + (sortscale == curscale && + RtlLargeIntegerLessThan (sortvalue, curvalue)) ) { + + // + // Swap the elements.. + // + + RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); + RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); + RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); + + // swap translated descriptor as well + RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); + RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); + RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); + + // get new curscale & curvalue + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + } + + pRSortLoc++; + pTSortLoc++; + } + + pRCurLoc++; + pTCurLoc++; + } + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + } + + + // + // Inform the IO system of our resources.. + // + + IoReportHalResourceUsage ( + HalName, + RawResourceList, + TranslatedResourceList, + ListSize + ); + + ExFreePool (RawResourceList); + ExFreePool (TranslatedResourceList); +} diff --git a/private/ntos/nthals/halr96b/mips/mipsdat.c b/private/ntos/nthals/halr96b/mips/mipsdat.c new file mode 100644 index 000000000..bfe2b9273 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/mipsdat.c @@ -0,0 +1,145 @@ +// #pragma comment(exestr, "@(#) mipsdat.c 1.1 95/09/28 15:42:43 nec") +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ixdat.c + +Abstract: + + Declares various data which is initialize data, or pagable data. + +Author: + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +/*++ + +Revision History: + + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994 + - add HalpMapRegisterMemorySpace + BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994 + - change HalpMapRegisterMemorySpace Size + CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994 + - change HalpIDTUsage size to MAXIMUM_VECTOR + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994 + - resolve compile error + A002 ataka@oa2.kb.nec.co.jp 1995/6/17 + - merge 1050 + +--*/ + + + + +#include "halp.h" + +#ifdef ALLOC_DATA_PRAGMA +#pragma data_seg("INIT") +#endif + +// +// The following data is only valid during system initialiation +// and the memory will be re-claimed by the system afterwards +// + +ADDRESS_USAGE HalpDefaultPcIoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA + EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA + EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA + + EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC + EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC + + EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word + EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe + + EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B) + EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A + + EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable + EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports + 0,0 + } +}; + +ADDRESS_USAGE HalpEisaIoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA + + EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI + EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted + + EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers + + EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable + 0, 0 + } +}; + +#define R94A_MAPREGISTER_BASE 100 // CMP001 + +// BUG001 +ADDRESS_USAGE HalpMapRegisterMemorySpace = { + NULL, CmResourceTypeMemory, InternalUsage, + { + R94A_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001 + 0, 0 + } +}; + + +// +// From usage.c +// + +ADDRESS_USAGE *HalpAddressUsageList; + +// +// Misc hal stuff in the registry +// + +WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer"; + + +// +// From ixpcibus.c +// + +WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter"; +WCHAR rgzConfigurationData[] = L"Configuration Data"; +WCHAR rgzIdentifier[] = L"Identifier"; +WCHAR rgzPCIIndetifier[] = L"PCI"; +WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002 + + +#ifdef ALLOC_DATA_PRAGMA +#pragma data_seg() +#endif + +// +// IDT vector usage info +// +// CNG001 +#if defined(MIPS) +IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[] +#else // CMP001 +IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif + diff --git a/private/ntos/nthals/halr96b/mips/mode542x.h b/private/ntos/nthals/halr96b/mips/mode542x.h new file mode 100644 index 000000000..3550a0714 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/mode542x.h @@ -0,0 +1,1302 @@ +// #pragma comment(exestr, "@(#) mode542x.h 1.1 95/09/28 15:43:49 nec") +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + Mode542x.h + +Abstract: + + This module contains all the global data used by the Cirrus Logic + CL-542x driver. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +// +// The next set of tables are for the CL542x +// Note: all resolutions supported +// + +// +// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x. +// + +USHORT CL542x_640x480[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode + + EOD +}; + +// +// 800x600 16-color (60Hz refresh) mode set command string for CL 542x. +// + +USHORT CL542x_800x600[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode + + EOD +}; + +// +// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x. +// + +USHORT CL542x_1024x768[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + + OWM, + GRAPH_ADDRESS_PORT, + 3, +#if ONE_64K_BANK + 0x0009, 0x000a, 0x000b, +#endif +#if TWO_32K_BANKS + 0x0009, 0x000a, 0x010b, +#endif + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + EOD +}; + +//----------------------------- +// standard VGA text modes here +// 80x25 at 640x350 +// +//----------------------------- + +// +// 80x25 text mode set command string for CL 542x. +// (720x400 pixel resolution; 9x16 character cell.) +// + +USHORT CL542x_80x25Text[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0009, 0x000a, 0x000b, // no banking in text mode + + EOD +}; + +// +// 80x25 text mode set command string for CL 542x. +// (640x350 pixel resolution; 8x14 character cell.) +// + +USHORT CL542x_80x25_14_Text[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + 0x0009, 0x000a, 0x000b, // no banking in text mode + + EOD +}; + +// +// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x. +// + +USHORT CL542x_1280x1024[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, +#if ONE_64K_BANK + 0x0009, 0x000a, 0x000b, +#endif +#if TWO_32K_BANKS + 0x0009, 0x000a, 0x010b, +#endif + + EOD +}; + +// +// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x. +// + +USHORT CL542x_640x480_64k[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 4, + 0x0506, // Some BIOS's set Chain Odd maps bit +#if ONE_64K_BANK + 0x0009, 0x000a, 0x000b, +#endif +#if TWO_32K_BANKS + 0x0009, 0x000a, 0x010b, +#endif + + EOD +}; + +#ifdef _X86_ + +// +// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x. +// + +USHORT CL542x_640x480_256[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, +#if ONE_64K_BANK + 0x0009, 0x000a, 0x000b, +#endif +#if TWO_32K_BANKS + 0x0009, 0x000a, 0x010b, +#endif + + EOD +}; + +// +// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x. +// + +USHORT CL542x_800x600_256[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, + GRAPH_ADDRESS_PORT, + 3, +#if ONE_64K_BANK + 0x0009, 0x000a, 0x000b, +#endif +#if TWO_32K_BANKS + 0x0009, 0x000a, 0x010b, +#endif + + EOD +}; + +#else + +// +// NOTE(DBCS) : Update 94/09/12 - NEC Corporation +// +// - Add mode set command string for NEC MIPS machine. +// +// - 640x480 256 color 72Hz +// - 800x600 256 color 56 / 60Hz +// - 1024x768 256 color 70 / 45Hz +// + +#if defined(DBCS) && defined(_MIPS_) + +// +// For MIPS NEC machine only +// + +// +// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for +// CL 542x. +// + +USHORT CL542x_640x480_256_60[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// the Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B,0x5B0C,0x450D,0x7E0E, + 0x2B1B,0x2F1C,0x301D,0x331E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xE3, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F, + 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83, + 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, + 0xFF, 0x00, 0x00, 0x22, + +#else + + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, + 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c, + 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3, + 0xff, 0x00, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for +// CL 542x. +// + +USHORT CL542x_640x480_256_72[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// the Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B,0x5B0C,0x450D,0x420E, + 0x2B1B,0x2F1C,0x301D,0x1F1E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xEF, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h) +// +// - Set Mode Type is VESA compatible. (Old Miss match) +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99, + 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, + 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, + 0xFF, 0x00, 0x00, 0x22, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + + +// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match +// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode. +// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B, +// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3, +// 0xFF, 0x00, 0x00, 0x22, + +#else + + 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, + 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c, + 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3, + 0xff, 0x00, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for +// CL 542x. +// + +USHORT CL542x_800x600_256_56[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B,0x5B0C,0x450D,0x7E0E, + 0x2B1B,0x2F1C,0x301D,0x331E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xEF, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12, + 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3, + 0xFF, 0x00, 0x00, 0x22, + +#else + + 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C, + 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3, + 0xff, 0x00, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for +// CL 542x. +// + +USHORT CL542x_800x600_256_60[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B,0x5B0C,0x450D,0x510E, + 0x2B1B,0x2F1C,0x301D,0x3A1E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0xEF, + +#else + + 0x2F, + +#endif // defined(DBCS) && defined(_MIPS_) + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, + 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3, + 0xFF, 0x00, 0x00, 0x22, + +#else + + 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C, + 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3, + 0xff, 0x00, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for +// CL 542x. +// + +USHORT CL542x_800x600_256_72[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x4A0B,0x5B0C,0x450D,0x650E, + +#else + + 0x4A0B,0x5B0C,0x450D,0x640E, + +#endif // defined(DBCS) && defined(_MIPS_) + + 0x2B1B,0x2F1C,0x301D,0x3A1E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0xEF, + +#else + + 0x2F, + +#endif // defined(DBCS) && defined(_MIPS_) + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C, + 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3, + 0xFF, 0x00, 0x00, 0x22, + +#else + + 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C, + 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80, + 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3, + 0xff, 0x00, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for +// CL 542x. +// + +USHORT CL542x_1024x768_256_60[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x4A0B, 0x5B0C, 0x450D, 0x760E, + 0x2B1B, 0x2F1C, 0x301D, 0x341E, + +#else + + 0x4A0B, 0x5B0C, 0x450D, 0x3B0E, + 0x2B1B, 0x2F1C, 0x301D, 0x1A1E, + +#endif // defined(DBCS) && defined(_MIPS_) + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xEF, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, + 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, + 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3, + 0xFF, 0x4A, 0x00, 0x22, + +#else + + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, + 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, + 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3, + 0xff, 0x4A, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for +// CL 542x. +// + +USHORT CL542x_1024x768_256_70[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B, 0x5B0C, 0x450D, 0x6E0E, + 0x2B1B, 0x2F1C, 0x301D, 0x2A1E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + 0xEF, + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96, + 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, + 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3, + 0xFF, 0x4A, 0x00, 0x22, + +#else + + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, + 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x88, + 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3, + 0xff, 0x4A, 0x00, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +// +// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for +// CL 542x. (Interlaced) +// + +USHORT CL542x_1024x768_256_87[] = { + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 2, // count + 0x1206, // enable extensions + 0x0012, + + OWM, // begin setmode + SEQ_ADDRESS_PORT, + 15, // count + 0x100, // start sync reset + 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed Liner addressing. +// + + (LA_MASK << 12 | 0x0107), + 0x0008, + 0x4A0B, 0x5B0C, 0x450D, 0x550E, + 0x2B1B, 0x2F1C, 0x301D, 0x361E, + + OB, // point sequencer index to ff + SEQ_ADDRESS_PORT, + 0x0F, + + METAOUT+MASKOUT, // masked out. + SEQ_DATA_PORT, + 0xDF,0x20, // and mask, xor mask + + OB, // misc. register + MISC_OUTPUT_REG_WRITE_PORT, + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0xEF, + +#else + + 0x2F, + +#endif // defined(DBCS) && defined(_MIPS_) + + OW, // text/graphics bit + GRAPH_ADDRESS_PORT, + 0x506, + + OW, // end sync reset + SEQ_ADDRESS_PORT, + 0x300, + + OW, // unprotect crtc 0-7 + CRTC_ADDRESS_PORT_COLOR, + 0x2011, + + METAOUT+INDXOUT, // program crtc registers + CRTC_ADDRESS_PORT_COLOR, + 28,0, // count, startindex + +// +// NOTE(DBCS) : Update 94/10/26 - NEC Corporation +// +// - Set Mode Type is VESA compatible. +// + +#if defined(DBCS) && defined(_MIPS_) + + 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99, + 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83, + 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3, + 0xff, 0x4A, 0x01, 0x22, + +#else + + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, + 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x81, 0x84, + 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3, + 0xff, 0x4A, 0x01, 0x22, + +#endif // defined(DBCS) && defined(_MIPS_) + + METAOUT+INDXOUT, // program gdc registers + GRAPH_ADDRESS_PORT, + 9,0, // count, startindex + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x05, 0x0F, 0xFF, + + IB, // prepare atc for writing + INPUT_STATUS_1_COLOR, + + METAOUT+ATCOUT, // program atc registers + ATT_ADDRESS_PORT, + 21,0, // count, startindex + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, + 0x0F, 0x00, 0x00, + + OB, // turn video on. + ATT_ADDRESS_PORT, + 0x20, + + OB, + DAC_PIXEL_MASK_PORT, + 0xFF, + + OWM, + GRAPH_ADDRESS_PORT, + 3, + +// +// The Miniport Driver for R96 machine is Liner addressing mode. +// This set command was changed it for Liner addressing. +// + + 0x0009, 0x000a, 0x000b, + + EOD +}; + +#endif // defined(DBCS) && defined(_MIPS_) + +#endif diff --git a/private/ntos/nthals/halr96b/mips/modeset.h b/private/ntos/nthals/halr96b/mips/modeset.h new file mode 100644 index 000000000..63122b13b --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/modeset.h @@ -0,0 +1,85 @@ +// #pragma comment(exestr, "@(#) modeset.h 1.1 95/09/28 15:45:03 nec") +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + Modeset.h + +Abstract: + + This module contains all the global data used by the Cirrus Logic + CL-6410 and CL-6420 driver. + +Environment: + + Kernel mode + +Notes: + + This module based on Cirrus Minport Driver. And modify for R96 MIPS + R4400 HAL Cirrus display initialize. + +Revision History: + +--*/ + +/* + * M001 1993.19.28 A. Kuriyama @ oa2 + * + * - Modify for R96 MIPS R4400 HAL + * + * Delete : Mode structure. + * + * Revision History in Cirrus Miniport Driver as follows: + * + * L001 1993.10.15 Kuroki + * + * - Modify for R96 MIPS R4400 + * + * Delete : Micro channel Bus Initialize. + * VDM & Text, Fullscreen mode support. + * Banking routine. + * CL64xx Chip support. + * 16-color mode. + * + * Add : Liner Addressing. + * + * + * + */ + +#include "cmdcnst.h" + +//--------------------------------------------------------------------------- +// +// The actual register values for the supported modes are in chipset-specific +// include files: +// +// mode64xx.h has values for CL6410 and CL6420 +// mode542x.h has values for CL5422, CL5424, and CL5426 +// + + +USHORT HalpCirrus_MODESET_1K_WIDE[] = { + OW, // stretch scans to 1k + CRTC_ADDRESS_PORT_COLOR, + 0x8013, + + EOD +}; + + + + + + + + + + + + + + diff --git a/private/ntos/nthals/halr96b/mips/pcibrd.c b/private/ntos/nthals/halr96b/mips/pcibrd.c new file mode 100644 index 000000000..2124dda34 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/pcibrd.c @@ -0,0 +1,1020 @@ +// #pragma comment(exestr, "@(#) pcibrd.c 1.1 95/09/28 15:45:30 nec") +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpcibrd.c + +Abstract: + + Get PCI-PCI bridge information + +Author: + + Ken Reneris (kenr) 14-June-1994 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "stdio.h" + +// debugging only... +// #define INIT_PCI_BRIDGE 1 + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzReservedResources[]; + + +#if DBG +#define DBGMSG(a) DbgPrint(a) +#else +#define DBGMSG(a) +#endif + + + +#define IsPciBridge(a) \ + (a->VendorID != PCI_INVALID_VENDORID && \ + PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \ + a->SubClass == 4 && a->BaseClass == 6) + + +typedef struct { + ULONG BusNo; + PBUS_HANDLER BusHandler; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + ULONG IO, Memory, PFMemory; + UCHAR Buffer[PCI_COMMON_HDR_LENGTH]; +} CONFIGBRIDGE, *PCONFIGBRIDGE; + +// +// Internal prototypes +// + + +#ifdef INIT_PCI_BRIDGE +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ); +#endif + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG Base, + IN ULONG Limit + ); + + +ULONG +HalpGetBridgedPCIInterrupt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetBridgedPCIISAInt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +NTSTATUS +HalpGetBridgedPCIIrqTable ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PUCHAR IrqTable + ); + + + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpGetPciBridgeConfig) +#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk) +#pragma alloc_text(INIT,HalpFixupPciSupportedRanges) + +#ifdef INIT_PCI_BRIDGE +#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt) +//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable) +#pragma alloc_text(INIT,HalpGetPciBridgeNeeds) +#endif +#endif + + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN PUCHAR MaxPciBus + ) +/*++ + +Routine Description: + + Scan the devices on all known pci buses trying to locate any + pci to pci bridges. Record the hierarchy for the buses, and + which buses have what addressing limits. + +Arguments: + + HwType - Configuration type. + MaxPciBus - # of PCI buses reported by the bios + +--*/ +{ + PBUS_HANDLER ChildBus; + PPCIPBUSDATA ChildBusData; + ULONG d, f, i, j, BusNo; + UCHAR Rescan; + BOOLEAN FoundDisabledBridge; + CONFIGBRIDGE CB; + + Rescan = 0; + FoundDisabledBridge = FALSE; + + // + // Find each bus on a bridge and initialize it's base and limit information + // + + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + // next device + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge, next function + continue; + } + + if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is not enabled - skip it for now + FoundDisabledBridge = TRUE; + continue; + } + + if ((ULONG) CB.PciData->u.type1.PrimaryBus != + CB.BusHandler->BusNumber) { + + DBGMSG ("HAL GetPciData: bad primarybus!!!\n"); + // what to do? + } + + // + // Found a PCI-PCI bridge. Determine it's parent child + // releationships + // + + ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus); + if (!ChildBus) { + DBGMSG ("HAL GetPciData: found configured pci bridge\n"); + + // up the number of buses + if (CB.PciData->u.type1.SecondaryBus > Rescan) { + Rescan = CB.PciData->u.type1.SecondaryBus; + } + continue; + } + + ChildBusData = (PPCIPBUSDATA) ChildBus->BusData; + if (ChildBusData->BridgeConfigRead) { + // this child buses releationships already processed + continue; + } + + // + // Remember the limits which are programmed into this bridge + // + + ChildBusData->BridgeConfigRead = TRUE; + HalpSetBusHandlerParent (ChildBus, CB.BusHandler); + ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber; + ChildBusData->CommonData.ParentSlot = CB.SlotNumber; + + ChildBus->BusAddresses->IO.Base = + PciBridgeIO2Base( + CB.PciData->u.type1.IOBase, + CB.PciData->u.type1.IOBaseUpper16 + ); + + ChildBus->BusAddresses->IO.Limit = + PciBridgeIO2Limit( + CB.PciData->u.type1.IOLimit, + CB.PciData->u.type1.IOLimitUpper16 + ); + + // + // Special VGA address remapping occuring on this bridge? + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + HalpSetPciBridgedVgaCronk ( + ChildBus->BusNumber, + (ULONG) ChildBus->BusAddresses->IO.Base, + (ULONG) ChildBus->BusAddresses->IO.Limit + ); + } + + // + // If supported I/O ranges on this bus are limitied to + // 256bytes on every 1K aligned boundry within the + // range, then redo supported IO BusAddresses to match + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + // assume Base is 1K aligned + i = (ULONG) ChildBus->BusAddresses->IO.Base; + j = (ULONG) ChildBus->BusAddresses->IO.Limit; + + // convert head entry + ChildBus->BusAddresses->IO.Limit = i + 256; + i += 1024; + + // add remaining ranges + while (i < j) { + HalpAddRange ( + &ChildBus->BusAddresses->IO, + 1, // address space + 0, // system base + i, // bus address + i + 256 // bus limit + ); + + // next range + i += 1024; + } + } + + ChildBus->BusAddresses->Memory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase); + + ChildBus->BusAddresses->Memory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit); + + // On x86 it's ok to clip Prefetch to 32 bits + + if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) { + ChildBus->BusAddresses->PrefetchMemory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase); + + + ChildBus->BusAddresses->PrefetchMemory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit); + + if (CB.PciData->u.type1.PrefetchLimitUpper32) { + ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff; + } + } + + // should call HalpAssignPCISlotResources to assign + // baseaddresses, etc... + } + } + } + + if (Rescan) { + *MaxPciBus = Rescan; + return TRUE; + } + + if (!FoundDisabledBridge) { + return FALSE; + } + + DBGMSG ("HAL GetPciData: found disabled pci bridge\n"); + +#ifdef INIT_PCI_BRIDGE + // + // We've calculated all the parent's buses known bases & limits. + // While doing this a pci-pci bus was found that the bios didn't + // configure. This is not expected, and we'll make some guesses + // at a configuration here and enable it. + // + // (this code is primarily for testing the above code since + // currently no system bioses actually configure the child buses) + // + + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge + continue; + } + + if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is enabled + continue; + } + + // + // We have a disabled bus - assign it a number, then + // determine all the requirements of all devices + // on the other side of this bridge + // + + CB.BusNo = BusNo; + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + } + } + } + // preform Rescan + return TRUE; + +#else + + return FALSE; + +#endif + +} + +VOID +HalpFixupPciSupportedRanges ( + IN ULONG MaxBuses + ) +/*++ + +Routine Description: + + PCI-PCI bridged buses only see addresses which their parent + bueses support. So adjust any PCI SUPPORT_RANGES to be + a complete subset of all of it's parent buses. + + PCI-PCI briges use postive address decode to forward addresses. + So, remove any addresses from any PCI bus which are bridged to + a child PCI bus. + +--*/ +{ + ULONG i; + PBUS_HANDLER Bus, ParentBus; + PSUPPORTED_RANGES HRanges; + + // + // Pass 1 - shrink all PCI supported ranges to be a subset of + // all of it's parent buses + // + + for (i = 0; i < MaxBuses; i++) { + + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + HRanges = Bus->BusAddresses; + Bus->BusAddresses = HalpMergeRanges ( + ParentBus->BusAddresses, + HRanges + ); + + HalpFreeRangeList (HRanges); + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Pass 2 - remove all child PCI bus ranges from parent PCI buses + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + if (ParentBus->InterfaceType == PCIBus) { + HalpRemoveRanges ( + ParentBus->BusAddresses, + Bus->BusAddresses + ); + } + + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Cleanup + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + HalpConsolidateRanges (Bus->BusAddresses); + } +} + + + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG BaseAddress, + IN ULONG LimitAddress + ) +/*++ + +Routine Description: . + + The 'vga compatible addresses' bit is set in the bridge control regiter. + This causes the bridge to pass any I/O address in the range of: 10bit + decode 3b0-3bb & 3c0-3df, as TEN bit addresses. + + As far as I can tell this "feature" is an attempt to solve some problem + which the folks solving it did not fully understand, so instead of doing + it right we have this fine mess. + + The solution is to take the least of all evils which is to remove any + I/O port ranges which are getting remapped from any IoAssignResource + request. (ie, IoAssignResources will never contimplate giving any + I/O port out in the suspected ranges). + + note: memory allocation error here is fatal so don't bother with the + return codes. + +Arguments: + + Base - Base of IO address range in question + Limit - Limit of IO address range in question + +--*/ +{ + UNICODE_STRING unicodeString; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE handle; + ULONG Length; + PCM_RESOURCE_LIST ResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + ULONG AddressMSBs; + WCHAR ValueName[80]; + NTSTATUS status; + + // + // Open reserved resource settings + // + + RtlInitUnicodeString (&unicodeString, rgzReservedResources); + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) { + return; + } + + // + // Build resource list of reseved ranges + // + + Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 * + sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) + + sizeof (CM_RESOURCE_LIST); + + ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length); + memset (ResourceList, 0, Length); + + ResourceList->Count = 1; + ResourceList->List[0].InterfaceType = PCIBus; + ResourceList->List[0].BusNumber = BusNumber; + Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; + + while (BaseAddress < LimitAddress) { + AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr + + // + // Add xx3b0 through xx3bb + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0; + Descriptor->u.Port.Length = 0xb; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Add xx3c0 through xx3df + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0; + Descriptor->u.Port.Length = 0x1f; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Next range + // + + BaseAddress += 1024; + } + + // + // Add the reserved ranges to avoid during IoAssignResource + // + + swprintf (ValueName, L"HAL_PCI_%d", BusNumber); + RtlInitUnicodeString (&unicodeString, ValueName); + + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_RESOURCE_LIST, + ResourceList, + (ULONG) Descriptor - (ULONG) ResourceList + ); + + + ExFreePool (ResourceList); + ZwClose (handle); +} + + + +#ifdef INIT_PCI_BRIDGE + +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ) +{ + ACCESS_MASK DesiredAccess; + UNICODE_STRING unicodeString; + PUCHAR buffer; + HANDLE handle; + OBJECT_ATTRIBUTES objectAttributes; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCONFIGURATION_COMPONENT Component; + CONFIGBRIDGE CB; + ULONG mnum, d, f, i; + NTSTATUS status; + + buffer = ExAllocatePool (PagedPool, 1024); + + // init + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + Current->IO = Current->Memory = Current->PFMemory = 0; + + // + // Assign this bridge an ID, and turn on configuration space + // + + Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo; + Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus; + Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF; + Current->PciData->u.type1.SecondaryStatus = 0xffff; + Current->PciData->Status = 0xffff; + Current->PciData->Command = 0; + + Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + KeStallExecutionProcessor (100); + + Current->PciData->u.type1.BridgeControl = 0; + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + KeStallExecutionProcessor (100); + + // + // Allocate new handler for bus + // + + CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + CB.BusNo = *MaxPciBus; + *MaxPciBus += 1; + + // + // Add another PCI bus in the registry + // + + mnum = 0; + for (; ;) { + // + // Find next available MultiFunctionAdapter key + // + + DesiredAccess = KEY_READ | KEY_WRITE; + swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum); + RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer); + + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes); + if (!NT_SUCCESS(status)) { + break; + } + + // already exists, next + ZwClose (handle); + mnum += 1; + } + + ZwCreateKey (&handle, + DesiredAccess, + &objectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &d + ); + + // + // Add needed registry values for this MultifucntionAdapter entry + // + + RtlInitUnicodeString (&unicodeString, rgzIdentifier); + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_SZ, + L"PCI", + sizeof (L"PCI") + ); + + RtlInitUnicodeString (&unicodeString, rgzConfigurationData); + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer; + Descriptor->InterfaceType = PCIBus; + Descriptor->BusNumber = CB.BusNo; + Descriptor->PartialResourceList.Version = 0; + Descriptor->PartialResourceList.Revision = 0; + Descriptor->PartialResourceList.Count = 0; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_FULL_RESOURCE_DESCRIPTOR, + Descriptor, + sizeof (*Descriptor) + ); + + + RtlInitUnicodeString (&unicodeString, L"Component Information"); + Component = (PCONFIGURATION_COMPONENT) buffer; + RtlZeroMemory (Component, sizeof (*Component)); + Component->AffinityMask = 0xffffffff; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_BINARY, + Component, + FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength) + ); + + ZwClose (handle); + + + // + // Since the BIOS didn't configure this bridge we'll assume that + // the PCI interrupts are bridged. (for BIOS configured buses we + // assume that the BIOS put the ISA bus IRQ in the InterruptLine value) + // + + CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line; + CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin; + //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable; + + if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) { + + // + // The parent bus'es interrupt pin to vector mappings is not + // a static function, and is determined by the boot firmware. + // + + //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt; + + // read each device on parent bus + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + Current->BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (CB.PciData->u.type0.InterruptPin && + (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE || + PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) { + + // get bios supplied int mapping + i = CB.PciData->u.type0.InterruptPin + d % 4; + CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine; + } + } + } + + } else { + _asm int 3; + } + + // + // Look at each device on the bus and determine it's resource needs + // + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (IsPciBridge (CB.PciData)) { + // oh look - another bridge ... + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + continue; + } + + if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) { + continue; + } + + // found a device - figure out the resources it needs + } + } + + // + // Found all sub-buses set SubordinateBus accordingly + // + + Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + // + // Set the bridges IO, Memory, and Prefetch Memory windows + // + + // For now just pick some numbers & set everyone the same + // IO 0x6000 - 0xFFFF + // MEM 0x40000000 - 0x4FFFFFFF + // PFMEM 0x50000000 - 0x5FFFFFFF + + Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4; + Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4; + Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4; + Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4; + Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4; + Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4; + + Current->PciData->u.type1.PrefetchBaseUpper32 = 0; + Current->PciData->u.type1.PrefetchLimitUpper32 = 0; + Current->PciData->u.type1.IOBaseUpper16 = 0; + Current->PciData->u.type1.IOLimitUpper16 = 0; + Current->PciData->u.type1.BridgeControl = + PCI_ENABLE_BRIDGE_ISA; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + HalpReadPCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + // enable memory & io decodes + + Current->PciData->Command = + PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + &Current->PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (Current->PciData->Command) + ); + + ExFreePool (buffer); +} + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + + This function maps the device's InterruptPin to an InterruptLine + value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Convert slot Pin into Bus INTA-D. + // + + i = (PciData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + i = (PciNewData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + +#endif diff --git a/private/ntos/nthals/halr96b/mips/pcibus.c b/private/ntos/nthals/halr96b/mips/pcibus.c new file mode 100644 index 000000000..a77edf46e --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/pcibus.c @@ -0,0 +1,3585 @@ +// #pragma comment(exestr, "@(#) pcibus.c 1.1 95/09/28 15:45:56 nec") +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpcidat.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + Ken Reneris (kenr) 14-June-1994 + +Environment: + + Kernel mode + +Revision History: + +Modification History: + + H001 Fri Jun 30 02:54:08 1995 kbnes!kisimoto + - Merge build 1057 ixpcibus.c + H002 Tue Jul 4 20:43:12 1995 kbnes!kisimoto + - disable preferred setting for back-to-back + support. If enable, IoAssign... allocates + current enabled address space. + H003 Wed Jul 5 14:27:46 1995 kbnes!kisimoto + - initialize with FALSE + H004 Tue Sep 5 20:06:16 1995 kbnes!kisimoto + - PCI Fast Back-to-back transfer support + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +#if defined(_R94A_) // H001 +#include "r94adef.h" +#include "string.h" +#endif // _R94A_ + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + + +typedef ULONG (*FncConfigIO) ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +typedef VOID (*FncSync) ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +typedef VOID (*FncReleaseSync) ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +typedef struct _PCI_CONFIG_HANDLER { + FncSync Synchronize; + FncReleaseSync ReleaseSynchronzation; + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER; + + + +// +// Prototypes +// + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +#if 0 +VOID +HalpInitializePciBus ( + VOID + ); +#endif + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +//------------------------------------------------- + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + + +// +// Globals +// + +// KSPIN_LOCK HalpPCIConfigLock; // H001 + +PCI_CONFIG_HANDLER PCIConfigHandler; + +PCI_CONFIG_HANDLER PCIConfigHandlerType1 = { + HalpPCISynchronizeType1, + HalpPCIReleaseSynchronzationType1, + { + HalpPCIReadUlongType1, // 0 + HalpPCIReadUcharType1, // 1 + HalpPCIReadUshortType1 // 2 + }, + { + HalpPCIWriteUlongType1, // 0 + HalpPCIWriteUcharType1, // 1 + HalpPCIWriteUshortType1 // 2 + } +}; + +PCI_CONFIG_HANDLER PCIConfigHandlerType2 = { + HalpPCISynchronizeType2, + HalpPCIReleaseSynchronzationType2, + { + HalpPCIReadUlongType2, // 0 + HalpPCIReadUcharType2, // 1 + HalpPCIReadUshortType2 // 2 + }, + { + HalpPCIWriteUlongType2, // 0 + HalpPCIWriteUcharType2, // 1 + HalpPCIWriteUshortType2 // 2 + } +}; + +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +BOOLEAN HalpDoingCrashDump = FALSE; // H003 +ULONG HalpFoundUncapablePCIDevice = 0; // H004 +ULONG HalpPCINumberOfMappedGA = 0; +ULONG HalpPCIBackToBackReg0Start = 0; +ULONG HalpPCIBackToBackReg1Start = 0; +ULONG HalpPCIBackToBackReg0Open = 1; +ULONG HalpPCIBackToBackReg1Open = 1; +ULONG HalpNumberOfPCIGA = 0; +ULONG HalpPCIMemoryLimit = 0xffffffff; + +#define INIT_VALUE_OF_BACK_TO_BACK_ADDR 0x00000000 +#define INIT_VALUE_OF_BACK_TO_BACK_MASK 0xffffffff + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ); + +#if defined(_R94A_) // H001 +ULONG +HalpGetPCIInterruptVector( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); +ULONG +HalpGetNumberOfPCIGA( + IN ULONG NumberBuses + ); +VOID +HalpSetBackToBackSpace( + IN PPCI_COMMON_CONFIG PciConfigRequired, + IN PPCI_COMMON_CONFIG PciConfigMapped, + IN PBUS_HANDLER BusHandler + ); +VOID +HalpSetBackToBackRegister( + IN ULONG BaseAddress, + IN ULONG Length, + IN ULONG Register + ); +#endif // _R94A_ + +#if DBG +#define DBGMSG(a) DbgPrint(a) +ULONG R94aDoTestPci = 0; +ULONG R94aDoTestPciNec = 0; +ULONG R94aDoOtherTest = 0; +VOID +HalpTestPciNec ( + ULONG + ); +VOID +HalpTestPciPrintResult( + IN PULONG Buffer, + IN ULONG Length + ); +VOID +HalpOtherTestNec ( + ULONG + ); +VOID +HalpTestPci ( + ULONG + ); +#else +#define DBGMSG(a) +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitializePciBus) +#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler) +#pragma alloc_text(INIT,HalpIsValidPCIDevice) +#pragma alloc_text(PAGE,HalpAssignPCISlotResources) +#endif + + + +VOID +HalpInitializePciBus ( + VOID + ) +{ + PPCI_REGISTRY_INFO PCIRegInfo; + UNICODE_STRING unicodeString, ConfigName, IdentName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE hMFunc, hBus; + NTSTATUS status; + UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99]; + PWSTR p; + WCHAR wstr[8]; + ULONG i, d, junk, HwType, BusNo, f; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PKEY_VALUE_FULL_INFORMATION ValueInfo; + PCM_FULL_RESOURCE_DESCRIPTOR Desc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc; + + PCI_REGISTRY_INFO tPCIRegInfo; // H001 + +#if 0 // H001 + // + // Search the hardware description looking for any reported + // PCI bus. The first ARC entry for a PCI bus will contain + // the PCI_REGISTRY_INFO. + + RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, // handle + NULL); + + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + return ; + } + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + + for (i=0; TRUE; i++) { + RtlIntegerToUnicodeString (i, 10, &unicodeString); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + hMFunc, + NULL); + + status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + // + // Out of Multifunction adapter entries... + // + + ZwClose (hMFunc); + return ; + } + + // + // Check the Indentifier to see if this is a PCI entry + // + + status = ZwQueryValueKey ( + hBus, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + if (!NT_SUCCESS (status)) { + ZwClose (hBus); + continue; + } + + p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset); + if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) { + ZwClose (hBus); + continue; + } + + // + // The first PCI entry has the PCI_REGISTRY_INFO structure + // attached to it. + // + + status = ZwQueryValueKey ( + hBus, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + ZwClose (hBus); + if (!NT_SUCCESS(status)) { + continue ; + } + + Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) + ValueInfo + ValueInfo->DataOffset); + PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR) + Desc->PartialResourceList.PartialDescriptors); + + if (PDesc->Type == CmResourceTypeDeviceSpecific) { + // got it.. + PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + break; + } + } + + // + // Initialize spinlock for synchronizing access to PCI space + // + +// KeInitializeSpinLock (&HalpPCIConfigLock); // H001 + PciData = (PPCI_COMMON_CONFIG) iBuffer; + +#endif // 0 + +#if defined(_R94A_) // H001 + + PCIRegInfo = &tPCIRegInfo; + PCIRegInfo->NoBuses = 1; + PCIRegInfo->HardwareMechanism=0x1; // HURRICANE PCI Config Type + +#if DBG + DbgPrint("PCI System Get Data:\n"); + DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision ); + DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision ); + DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses ); + DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism ); +#endif // DBG + +#endif // _R94A_ + + // + // PCIRegInfo describes the system's PCI support as indicated by the BIOS. + // + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + + // + // Some AMI bioses claim machines are Type2 configuration when they + // are really type1. If this is a Type2 with at least one bus, + // try to verify it's not really a type1 bus + // + + if (PCIRegInfo->NoBuses && HwType == 2) { + + // + // Check each slot for a valid device. Which every style configuration + // space shows a valid device first will be used + // + + SlotNumber.u.bits.Reserved = 0; + SlotNumber.u.bits.FunctionNumber = 0; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + // + // First try what the BIOS claims - type 2. Allocate type2 + // test handle for PCI bus 0. + // + + HwType = 2; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + // + // Valid device not found on Type2 access for this slot. + // Reallocate the bus handler are Type1 and take a look. + // + + HwType = 1; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + HwType = 2; + } + + // + // Reset handler for PCI bus 0 to whatever style config space + // was finally decided. + // + + HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE); + } + + + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + +#if 0 // H001 + do { +#endif + for (i=0; i < PCIRegInfo->NoBuses; i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // + +#if 0 // H001 + } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ; + + // + // Fixup SUPPORTED_RANGES + // + + HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses); + + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) { + BusHandler = HalpHandlerForBus (PCIBus, BusNo); + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Check for chips with known work-arounds to apply + // + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x04A3 && + PciData->RevisionID < 0x11) { + + // + // 82430 PCMC controller + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + + buffer[0] &= ~0x08; // turn off bit 3 register 0x53 + + if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn + buffer[1] &= ~0x01; // bit 0 register 0x54 + } + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + } + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x0484 && + PciData->RevisionID <= 3) { + + // + // 82378 ISA bridge & SIO + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + + buffer[0] &= ~0x1; // turn off bit 0 register 0x41 + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + } + + } // next function + } // next device + } // next bus +#endif + + // + // H005 + // Compute the number of PCI-GA device and + // initialize Fast Back-to-back register. + // + + HalpNumberOfPCIGA = HalpGetNumberOfPCIGA(PCIRegInfo->NoBuses); + +#if DBG + HalpTestPci (0); +#if defined(_R94A_) + DbgPrint("HalpInitializePciBus: Call HalpTestPci(%x)\n",R94aDoTestPci); + HalpTestPci (R94aDoTestPci); + DbgPrint("HalpInitializePciBus: Call HalpTestPciNec(%x)\n",R94aDoTestPciNec); + HalpTestPciNec (R94aDoTestPciNec); + DbgPrint("HalpInitializePciBus: Call HalpOtherTest(%x)\n",R94aDoOtherTest); + HalpOtherTestNec (R94aDoOtherTest); +#endif +#endif +} + + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ) +{ + PBUS_HANDLER Bus; + PPCIPBUSDATA BusData; + + Bus = HalpAllocateBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // bus # + Internal, // child of this bus + 0, // and number + sizeof (PCIPBUSDATA) // sizeof bus specific buffer + ); + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; +#if defined(_R94A_) + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector; +#else + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus; +#endif + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + Bus->BusAddresses->Dma.Limit = 0; + + BusData = (PPCIPBUSDATA) Bus->BusData; + + // + // Fill in common PCI data + // + + BusData->CommonData.Tag = PCI_DATA_TAG; + BusData->CommonData.Version = PCI_DATA_VERSION; + BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig; + BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig; + BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine; + BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin; + + // + // Set defaults + // + + BusData->MaxDevice = PCI_MAX_DEVICES; + BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq; + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof (PCIConfigHandler)); + +#if defined(_R94A_) // H001 + BusData->Config.Type1.Address = (PULONG)R94A_PCI_TYPE1_ADDR_PORT; + BusData->Config.Type1.Data = R94A_PCI_TYPE1_DATA_PORT; +#else + BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT; + BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; +#endif // _R94A_ + break; + + case 2: + // + // Initialize access port information for Type2 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); + + BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; + BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; + BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; + + // + // Early PCI machines didn't decode the last bit of + // the device id. Shrink type 2 support max device. + // + BusData->MaxDevice = 0x10; + + break; + + default: + // unsupport type + DBGMSG ("HAL: Unkown PCI type\n"); + } + + if (!TestAllocation) { +#ifdef SUBCLASSPCI + HalpSubclassPCISupport (Bus, HwType); +#endif + } + + return Bus; +} + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +/*++ + +Routine Description: + + Reads the device configuration data for the given slot and + returns TRUE if the configuration data appears to be valid for + a PCI device; otherwise returns FALSE. + +Arguments: + + BusHandler - Bus to check + Slot - Slot to check + +--*/ + +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG i, j; + + + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // Read device common header + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Valid device header? + // + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + return FALSE; + } + + // + // Check fields for reasonable values + // + + if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) || + (PciData->u.type0.InterruptLine & 0x70)) { + return FALSE; + } + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + j = PciData->u.type0.BaseAddresses[i]; + + if (j & PCI_ADDRESS_IO_SPACE) { + if ((j > 0x2 && j < 0xffff) || j > 0xffffff) { // H001 + // IO port < 64KB | IO port > 16MB + return FALSE; + } + } else { + if (j > 0xf && j < 0x3ffffff) { // H001 + // Mem address < 64MB + return FALSE; + } + } + + if (Is64BitBaseAddress(j)) { + i += 1; + } + } + + // + // Guess it's a valid device.. + // + + return TRUE; +} + + + + + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + BusNumber - Indicates which bus. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + + If this PCI slot has never been set, then the configuration information + returned is zeroed. + + +--*/ +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len; + ULONG i, bit; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue + // in the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested at least some data within the + // common header. Read the whole header, effect the + // fields we need to and then copy the user's requested + // bytes from the header + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Read this PCI devices slot data + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + +#if 0 + DbgPrint ("--------------->>> Now Print the Slot Information\n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + BusHandler->BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, PciData->VendorID, PciData->DeviceID, + PciData->RevisionID); + + + if (PciData->u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin); + } + + if (PciData->u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine); + } + + if (PciData->u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress); + } + + DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData->ProgIf, PciData->SubClass, PciData->BaseClass); + + { ULONG k, j; + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData->u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]); + k = 1; + } + } + DbgPrint("\n"); + } +#endif // DBG + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + + } else { + + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData); + } + + // + // Has this PCI device been configured? + // + +#if DBG + + // + // On DBG build, if this PCI device has not yet been configured, + // then don't report any current configuration the device may have. + // + + bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) { + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + PciData->u.type0.BaseAddresses[i] = 0; + } + + PciData->u.type0.ROMBaseAddress = 0; + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + } +#endif + + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len, cnt; + + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + // no device, or header type unkown + return 0; + } + + + // + // Set this device as configured + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; +#if DBG + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&BusData->DeviceConfigured, cnt, 1); +#endif + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + + // in case interrupt line or pin was editted + BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n"); + DbgBreakPoint (); + } +#endif + // + // Set new PCI configuration + // + +#if DBG // H001 + DbgPrint("SetPciData: PciData2->u.type0.InterruptLine:%x\n",PciData2->u.type0.InterruptLine); +#endif + HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + USHORT IdValue; // H001 + ULONG OrigData; // H001 + + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + RtlFillMemory (Buffer, Length, (UCHAR) -1); + + return ; + } + +#if defined(_R94A_) // H001 + + // + // resolve PCI master abort during we are looking for PCI device + // check to see if spcified slot is valid. + // + + // + // Disable PCI-MasterAbort interrupt during configration read. + // + + OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable); + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f); + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2, + PCIConfigHandler.ConfigRead); + + if (IdValue == 0xffff){ + + // + // This PCI slot has no card + // wait until ReceivedMasterAbort bit is set + // + + while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000)) + ; + + // + // clear the ReceivedMasterAbort bit + // + + WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000); + + // + // Clear memory address error registers. + // + + { + LARGE_INTEGER registerLarge; + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + } + + // + // Restore the PCIInterruptEnable register, and return no data + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); + RtlFillMemory (Buffer, Length, (UCHAR) -1); + + return ; + } + + // + // Restore the PCIInterruptEnable register. + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); + +#endif // _R94A_ + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigRead); +} + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + USHORT IdValue; // H001 + ULONG OrigData; // H001 + + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID do nothing + // + return ; + } + +#if defined(_R94A_) // H001 + + // + // resolve PCI master abort during we are looking for PCI device + // check to see if spcified slot is valid. + // + + // + // Disable PCI-MasterAbort interrupt during configration read. + // + + OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable); + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f); + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2, + PCIConfigHandler.ConfigRead); + + if (IdValue == 0xffff){ + + // + // This PCI slot has no card + // wait until ReceivedMasterAbort bit is set + // + + while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000)) + ; + + // + // clear the ReceivedMasterAbort bit + // + + WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000); + + // + // Clear memory address error registers. + // + + { + LARGE_INTEGER registerLarge; + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + } + + // + // Restore the PCIInterruptEnable register, and return no data + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); + RtlFillMemory (Buffer, Length, (UCHAR) -1); + + return ; + } + + // + // Restore the PCIInterruptEnable register. + // + + WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData); + +#endif // _R94A_ + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigWrite); +} + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +{ + PCI_SLOT_NUMBER Slot2; + PPCIPBUSDATA BusData; + UCHAR HeaderType; + ULONG i; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + +#if defined(_R94A_) // H001 + if (Slot.u.bits.DeviceNumber < 3 || + Slot.u.bits.DeviceNumber > 20) { + return FALSE; + } +#else + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { + return FALSE; + } +#endif // _R94A_ + + if (Slot.u.bits.FunctionNumber == 0) { + return TRUE; + } + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return FALSE; + } + + return TRUE; +} + + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + UCHAR State[20]; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.DeviceNumber < 3) { // H001 +#if DBG + DbgPrint("HalpPCIConfig: Ignore Slot %x\n",Slot.u.bits.DeviceNumber); +#endif + return; + } + + PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State); + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (BusData, State, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql); +} + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = 0; + PciCfg1->u.bits.BusNumber = BusHandler->BusNumber; + PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; + PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; + PciCfg1->u.bits.Enable = TRUE; + + // + // Synchronize with PCI type1 config space + // + + if (!HalpDoingCrashDump) { + KeRaiseIrql (PROFILE_LEVEL, Irql); // H001 + KiAcquireSpinLock (&HalpPCIConfigLock); + } else { + *Irql = HIGH_LEVEL; + } +} + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + PCI_TYPE1_CFG_BITS PciCfg1; + PPCIPBUSDATA BusData; + + // + // Disable PCI configuration space + // + + PciCfg1.u.AsULONG = 0; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG); + + // + // Release spinlock + // + + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); // H001 + } +} + + +ULONG +HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i)); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i)); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data); + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer)); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer)); + return sizeof (ULONG); +} + + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr + ) +{ + PCI_TYPE2_CSE_BITS PciCfg2Cse; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Initialize Cfg2Addr + // + + PciCfg2Addr->u.AsUSHORT = 0; + PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber; + PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base; + + // + // Synchronize with type2 config space - type2 config space + // remaps 4K of IO space, so we can not allow other I/Os to occur + // while using type2 config space. + // + + HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql); + + PciCfg2Cse.u.AsUCHAR = 0; + PciCfg2Cse.u.bits.Enable = TRUE; + PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber; + PciCfg2Cse.u.bits.Key = 0xff; + + // + // Select bus & enable type 2 configuration space + // + + WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber); + WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); +} + + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + PCI_TYPE2_CSE_BITS PciCfg2Cse; + PPCIPBUSDATA BusData; + + // + // disable PCI configuration space + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + PciCfg2Cse.u.AsUCHAR = 0; + WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); + WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0); + + // + // Restore interrupts, release spinlock + // + + HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql); +} + + +ULONG +HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT); + return sizeof(ULONG); +} + + +ULONG +HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer)); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer)); + return sizeof(ULONG); +} + + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine it's required resources. + Calls IoAssignResources to allocate them. + Sets the targeted device with it's assigned resoruces + and returns the assignments to the caller. + +Arguments: + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + NTSTATUS status; + PUCHAR WorkingPool; + PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2; + PCI_COMMON_CONFIG PciData3; // H005 + PCI_SLOT_NUMBER PciSlot; + PPCIPBUSDATA BusData; + PIO_RESOURCE_REQUIREMENTS_LIST CompleteList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor; + ULONG BusNumber; + ULONG i, j, m, length, memtype; + ULONG NoBaseAddress, RomIndex, Option; + PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1]; + PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1]; + BOOLEAN Match, EnableRomBase; + + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + BusNumber = BusHandler->BusNumber; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Allocate some pool for working space + // + + i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) + + sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 + + PCI_COMMON_HDR_LENGTH * 3; + + WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i); + if (!WorkingPool) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero initialize pool, and get pointers into memory + // + + RtlZeroMemory (WorkingPool, i); + CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool; + PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3); + PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2); + PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1); + + // + // Read the PCI device's configuration + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + if (PciData->VendorID == PCI_INVALID_VENDORID) { + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // Make a copy of the device's current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + // + // Initialize base addresses base on configuration data type + // + + switch (PCI_CONFIG_TYPE(PciData)) { + case 0 : + NoBaseAddress = PCI_TYPE0_ADDRESSES+1; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type0.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type0.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress; + RomIndex = j; + break; + case 1: + NoBaseAddress = PCI_TYPE1_ADDRESSES+1; + for (j=0; j < PCI_TYPE1_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type1.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type1.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress; + RomIndex = j; + break; + + default: + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // If the BIOS doesn't have the device's ROM enabled, then we won't + // enable it either. Remove it from the list. + // + + EnableRomBase = TRUE; + +#if 0 // H001 + if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) { + ASSERT (RomIndex+1 == NoBaseAddress); + EnableRomBase = FALSE; + NoBaseAddress -= 1; + } +#endif + + // + // Set resources to all bits on to see what type of resources + // are required. + // + + for (j=0; j < NoBaseAddress; j++) { + *BaseAddress[j] = 0xFFFFFFFF; + } + + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // H004 + // Make a copy of the device's current settings + // + + RtlMoveMemory ((PPCI_COMMON_CONFIG)&PciData3, PciData, PCI_COMMON_HDR_LENGTH); + + // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); + + // + // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device + // + + CompleteList->InterfaceType = PCIBus; + CompleteList->BusNumber = BusNumber; + CompleteList->SlotNumber = Slot; + CompleteList->AlternativeLists = 1; + + CompleteList->List[0].Version = 1; + CompleteList->List[0].Revision = 1; + + Descriptor = CompleteList->List[0].Descriptors; + + // + // If PCI device has an interrupt resource, add it + // + + if (PciData->u.type0.InterruptPin) { + CompleteList->List[0].Count++; + + Descriptor->Option = 0; + Descriptor->Type = CmResourceTypeInterrupt; + Descriptor->ShareDisposition = CmResourceShareShared; + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + + // Fill in any vector here - we'll pick it back up in + // HalAdjustResourceList and adjust it to it's allowed settings + Descriptor->u.Interrupt.MinimumVector = 0; + Descriptor->u.Interrupt.MaximumVector = 0xff; + Descriptor++; + } + + // + // Add a memory/port resoruce for each PCI resource + // + + // Clear ROM reserved bits + + *BaseAddress[RomIndex] &= ~0x7FF; + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + i = *BaseAddress[j]; + + // scan for first set bit, that's the length & alignment + length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4); + while (!(i & length) && length) { + length <<= 1; + } + + // scan for last set bit, that's the maxaddress + 1 + for (m = length; i & m; m <<= 1) ; + m--; + + // check for hosed PCI configuration requirements + if (length & ~m) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); + + DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i); +#endif + // the device is in error - punt. don't allow this + // resource any option - it either gets set to whatever + // bits it was able to return, or it doesn't get set. + + if (i & PCI_ADDRESS_IO_SPACE) { + m = i & ~0x3; + Descriptor->u.Port.MinimumAddress.LowPart = m; + } else { + m = i & ~0xf; + Descriptor->u.Memory.MinimumAddress.LowPart = m; + } + + m += length; // max address is min address + length + } + + // + // Add requested resource + // + + Descriptor->Option = 0; + if (i & PCI_ADDRESS_IO_SPACE) { + memtype = 0; + +#if 0 // H002 + if (!Is64BitBaseAddress(i) && + PciOrigData->Command & PCI_ENABLE_IO_SPACE) { + + // + // The IO range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } +#endif + // + // Add this IO range + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MaximumAddress.LowPart = m; + +#if DBG // H001 + DbgPrint("HalpAssign: Port %x len %x align %x\n", length, length, m); +#endif // DBG + + } else { + + memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK; + + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + if (j == RomIndex) { + // this is a ROM address + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + } + + if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) { + Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; + } + +#if 0 // H002 + if (!Is64BitBaseAddress(i) && + (j == RomIndex || + PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) { + + // + // The memory range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Flags = Descriptor[-1].Flags; + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } +#endif + // + // Add this memory range + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + + Descriptor->u.Memory.Length = length; + Descriptor->u.Memory.Alignment = length; + Descriptor->u.Memory.MaximumAddress.LowPart = m; + + if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) { + // limit to 20 bit address + Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF; + } + +#if DBG // H001 + DbgPrint("HalpAssign: Memory %x len %x align %x\n", length, length, m); +#endif // DBG + + } + + CompleteList->List[0].Count++; + Descriptor++; + + + if (Is64BitBaseAddress(i)) { + // skip upper half of 64 bit address since this processor + // only supports 32 bits of address space + j++; + } + } + } + + CompleteList->ListSize = (ULONG) + ((PUCHAR) Descriptor - (PUCHAR) CompleteList); + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses. This is done in + // case HalAdjustResourceList wants to read the current settings + // in the device. + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + // + // Have the IO system allocate resource assignments + // + +#if DBG // H001 + DbgPrint("Call IoAssignResources\n"); +#endif // DBG + + status = IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + CompleteList, + pAllocatedResources + ); + + if (!NT_SUCCESS(status)) { + goto CleanUp; + } + + // + // Slurp the assigments back into the PciData structure and + // perform them + // + + CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors; + + // + // If PCI device has an interrupt resource then that was + // passed in as the first requested resource + // + + if (PciData->u.type0.InterruptPin) { + PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector; + BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData); + CmDescriptor++; + } + + // + // Pull out resources in the order they were passed to IoAssignResources + // + + for (j=0; j < NoBaseAddress; j++) { + i = *BaseAddress[j]; + if (i) { + if (i & PCI_ADDRESS_IO_SPACE) { + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart; +#if DBG // H001 + DbgPrint("HalpAssign assigned: Port %x\n", *BaseAddress[j]); +#endif // DBG + } else { + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; +#if DBG // H001 + DbgPrint("HalpAssign assigned: Memory %x\n", *BaseAddress[j]); +#endif // DBG + } + CmDescriptor++; + } + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + + // + // Turn off decodes, then set new addresses + // + +#if DBG // H001 + DbgPrint("Set Assigned Resources\n"); +#endif // DBG + + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Read configuration back and verify address settings took + // + +#if DBG // H001 + DbgPrint("Read Common header to see write results\n"); +#endif // DBG + + HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH); + + Match = TRUE; + if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + Match = FALSE; + } + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) { + i = (ULONG) ~0x3; + } else { + i = (ULONG) ~0xF; + } + + if ((*BaseAddress[j] & i) != + *((PULONG) ((PUCHAR) BaseAddress[j] - + (PUCHAR) PciData + + (PUCHAR) PciData2)) & i) { + + Match = FALSE; + } + + if (Is64BitBaseAddress(*BaseAddress[j])) { + // skip upper 32 bits + j++; + } + } + } + + if (!Match) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); +#endif + status = STATUS_DEVICE_PROTOCOL_ERROR; + goto CleanUp; + } + + // + // H004 + // set memory space as back-to-back available + // + + HalpSetBackToBackSpace(&PciData3, PciData2, BusHandler); + + // + // Settings took - turn on the appropiate decodes + // + + if (EnableRomBase && *BaseAddress[RomIndex]) { + // a rom address was allocated and should be enabled + *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig ( + BusHandler, + PciSlot, + BaseAddress[RomIndex], + (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData), + sizeof (ULONG) + ); + } + + // + // Enable IO, Memory, and BUS_MASTER decodes + // (use HalSetBusData since valid settings now set) + // + + PciData->Command |= PCI_ENABLE_IO_SPACE | + PCI_ENABLE_MEMORY_SPACE | + PCI_ENABLE_BUS_MASTER; + + HalSetBusDataByOffset ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + &PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (PciData->Command) + ); + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + if (*pAllocatedResources) { + IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + NULL, + NULL + ); + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + ExFreePool (WorkingPool); + return status; +} + +#if DBG +VOID +HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Note: This is reading the DeviceSpecific area of + // the device's configuration - normally this should + // only be done on device for which the caller understands. + // I'm doing it here only for debugging. + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + +#if 0 + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); +#endif + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.Command, PciData.Status, PciData.ProgIf, + PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + +#if 0 + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } +#endif + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + +#if 0 + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); +#endif + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} + +#if defined (_R94A_) // H001 +VOID +HalpTestPciNec (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag && bus < 1; bus++) { /* R94A_ Support Only 1 */ + + for (i = 0; i < PCI_MAX_DEVICES; i++) { /* R94A_ Support Only 2 slots(include bridge) */ + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < 8; f++) { + SlotNumber.u.bits.FunctionNumber = f; + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, j); + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + HalpTestPciPrintResult((PULONG)&PciData, 1); + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData)); + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + PciData.u.type0.InterruptLine = 5; // For trial + DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific) + ); + HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH); + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData)); + + DbgPrint ("--------------->>> Now Print the Slot Information\n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.ProgIf, PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("We got the bridge\n"); + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + + // + // now print original data + // + DbgPrint ("--------------->>> Now Print the Original Slot Information\n"); + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData)); + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} + + +VOID +HalpTestPciPrintResult( + IN PULONG Buffer, + IN ULONG Length +) +{ + ULONG i, Lines, pchar; + + DbgPrint("----- I/O Data. (%d)byts.\n", Length); + + for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) { + DbgPrint("%08x: ", Lines * 16); + for (i = 0; i < 4; pchar += 4, i++) { + if (pchar >= Length) + break; + DbgPrint("%08x ", *Buffer++); + } + DbgPrint("\n"); + } +} + +VOID +HalpOtherTestNec ( + IN ULONG doOtherTest +) +{ + if (!doOtherTest) + return; + + + DbgPrint("\n\n===== Additional Testing...\n"); + { + CM_EISA_SLOT_INFORMATION EisaSlotInfo; + PCM_EISA_SLOT_INFORMATION EisaBuffer; + PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo; + ULONG slot, funcs, Length; + + #define MAX_EISA_SLOT 4 + + DbgPrint("----- Read Eisa Configration:\n"); + for (slot = 0; slot < MAX_EISA_SLOT; slot++) { + Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo)); + if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) { + + // + // The data is messed up since this should never occur + // + + break; + } + Length = sizeof(CM_EISA_SLOT_INFORMATION) + + (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions); + EisaBuffer = ExAllocatePool(NonPagedPool, Length); + HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length); + // Print all Eisa Data + + EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION) + ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION)); + + DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot); + DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n", + EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags, + EisaBuffer->MajorRevision, EisaBuffer->MinorRevision); + DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n", + EisaBuffer->Checksum, + EisaBuffer->NumberFunctions, + EisaBuffer->FunctionInformation, + EisaBuffer->CompressedId); + for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) { + DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n", + EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1, + EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision, + EisaFunctionInfo->MajorRevision); + + // EisaFunctionInfo->Selections[26]; + // EisaFunctionInfo->FunctionFlags; + // EisaFunctionInfo->TypeString[80]; + // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9]; + // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7]; + // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4]; + // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20]; + // UCHAR EisaFunctionInfo->InitializationData[60]; + EisaFunctionInfo++; + } + + } + } + DbgBreakPoint (); + { + #define MEMORY_SPACE 0 + #define IO_SPACE 1 + PHYSICAL_ADDRESS cardAddress; + ULONG addressSpace = IO_SPACE; + PHYSICAL_ADDRESS PhysAddr; + + PhysAddr.LowPart = 0; + PhysAddr.HighPart = 0; + + + + DbgPrint("----- Translate Internal Bus Address(I/O): "); + HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Eisa Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Isa Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate PCI Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Internal Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Eisa Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Isa Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate PCI Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + } + DbgBreakPoint (); + + { + KAFFINITY affinity; + KIRQL Irql; + ULONG Vec; + + DbgPrint("----- GetInterruptVector internal\n"); + Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector Eisa\n"); + Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector Isa\n"); + Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector PCI\n"); + Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + } + DbgBreakPoint (); +} + +#endif // _R94A_ +#endif // DBG + +VOID +HalpSetBackToBackSpace( + IN PPCI_COMMON_CONFIG PciConfigRequired, + IN PPCI_COMMON_CONFIG PciConfigMapped, + IN PBUS_HANDLER BusHandler + ) +/*++ + +Routine Description: + + This function sets memory space of PCI device to Fast Back-to-back register. + +Arguments: + + PciConfigRequired - Supplies the description of the memory space which + device required. + PciConfigMapped - Supplies the description of the memory space which + should be mapped to back-to-back space. + BusHandler - Supplies the pointer to Bushandler. + +Return Value: + + None. + +--*/ + +{ + ULONG NoBaseAddress; + ULONG BaseAddress, LowerAddress; + ULONG CurrentAddress; + ULONG FoundMemoryAddress; + ULONG i, j, Length; + +#if DBG + DbgPrint(" check PCI-device!\n"); + DbgPrint(" - VendorID ................ %04x\n", PciConfigMapped->VendorID); + DbgPrint(" - DeviceID ................ %04x\n", PciConfigMapped->DeviceID); + DbgPrint(" - back-to-back capable? ... %s\n", (PciConfigMapped->Status & 0x80) ? "o" : "x"); + if (PciConfigMapped->BaseClass == 0x03 + || (PciConfigMapped->BaseClass == 0x00 && PciConfigMapped->SubClass == 0x01)){ + DbgPrint(" - Is this GA device? ...... o\n"); + } else { + DbgPrint(" - Is this GA device? ...... x\n"); + } +#endif + + KiAcquireSpinLock(&HalpPCIBackToBackLock); + + // + // calulate memory region of this device. + // + + switch (PCI_CONFIG_TYPE(PciConfigMapped)) { + case 0 : + NoBaseAddress = PCI_TYPE0_ADDRESSES; + break; + case 1: + NoBaseAddress = PCI_TYPE1_ADDRESSES; + break; + default: + // never come here. + // (already except by HalpAssignPCISlotResources) + return; + } + + Length = 0; + BaseAddress = 0xffffffff; + LowerAddress = 0xffffffff; + FoundMemoryAddress = 0; + + // + // get base and limit address + // + + for (i = 0; i < NoBaseAddress; i++) { + CurrentAddress = PciConfigMapped->u.type0.BaseAddresses[i]; + if (!(CurrentAddress & PCI_ADDRESS_IO_SPACE) + && ((CurrentAddress & PCI_ADDRESS_MEMORY_TYPE_MASK) != 0x2)) { + + // + // this is memory space and not need to map below 1M + // + + CurrentAddress = CurrentAddress & 0xfffffff0; + if (CurrentAddress) { + FoundMemoryAddress = 1; + if (LowerAddress > CurrentAddress) + LowerAddress = CurrentAddress; + // scan for first set bit, that's the length & alignment + j = 1 << 4; + while (!(PciConfigRequired->u.type0.BaseAddresses[i] & j) && j) + j <<= 1; +#if DBG + DbgPrint(" - [%d]MemoryAddress ........ 0x%08x\n", i, CurrentAddress); + DbgPrint(" - [%d]Length ............... 0x%08x\n", i, j); +#endif + if (Length < j){ + BaseAddress = CurrentAddress; + Length = j; + } + } + } + } + +#if DBG + DbgPrint(" - LowerAddress ............ 0x%08x\n", LowerAddress); + DbgPrint(" - BaseAddress ............. 0x%08x\n", BaseAddress); + DbgPrint(" - Length .................. 0x%08x\n", Length); +#endif + + // + // If this device has memory space, then change memory limit + // value used be allocation for PCI memory space to + // 'LowerAddress - 1' of this device, otherwise release spinlock + // and return. + // + + if (FoundMemoryAddress) { + HalpPCIMemoryLimit = LowerAddress - 1; + } else { + goto NotSetBackToBack; + } + + // + // We do not support the PCI devices which connected under + // PCI-PCI bridge. + // + + if (BusHandler->BusNumber == 0) { + + if (PciConfigMapped->Status & 0x80) { + + // + // This device is back-to-back capable. + // We can map the memory space of this device as + // back-to-back available. + // Set flag to indicate setting started. + // + + if (!HalpPCIBackToBackReg0Start) { + HalpPCIBackToBackReg0Start = 1; + + } else if (HalpPCIBackToBackReg0Start && !HalpPCIBackToBackReg0Open) { + HalpPCIBackToBackReg1Start = 1; + + } + + // + // BUGBUG: Some pci drivers assign its memory space by itself. + // This means that we can not control the memory address of + // such device by MemoryLimit value. So, we can not enable the + // following codes now. + // N.B. following code does not finished. + // + +// if (!HalpFoundUncapablePCIDevice) { +// +// // +// // Uncapable device not mapped yet, so we can expand +// // back-to-back space. +// // We expand back-to-back space until uncapable device +// // is found. +// // +// +// if (back-to-back reg0 == initialize value){ +// HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); +// } else { +// back-to-back reg0 =+ add this memory range; +// MemoryLimit = the BaseAddress of this device; +// } +// +// if (PciConfigMapped->BaseClass == 0x03 +// || (PciConfigMapped->BaseClass == 0x00 +// && PciConfigMapped->SubClass == 0x01)) { +// HalpPCINumberOfMappedGA++; +// } +// +// } else { + + if (HalpNumberOfPCIGA > 1) { + + // + // There are some PCI-GA cards. + // If this is PCI-GA, then set to back-to-back, + // else we do not map. + // + + if (PciConfigMapped->BaseClass == 0x03 + || (PciConfigMapped->BaseClass == 0x00 + && PciConfigMapped->SubClass == 0x01)) { + + switch (HalpPCINumberOfMappedGA) { + + case 0: + + // + // We need set PCI-GA to both back-to-back space. + // The control reach here, it indicates PCI-GA + // not mapped to back-to-back space yet. + // + + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); + HalpPCIBackToBackReg0Open = 0; + break; + + case 1: + + // + // Control is transfered to this routine when one PCI-GA + // is already mapped. This means that reg0 had already used. + // We use reg1. + // + + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1); + HalpPCIBackToBackReg1Open = 0; + + } + + HalpPCINumberOfMappedGA++; + } + + } else { + + // + // There is only one-card as PCI-GA. + // We need set PCI-GA to back-to-back. + // If this is GA and reg0 is opened, then use reg0. + // If this is GA and reg0 is closeed, then use reg1. + // + + if (PciConfigMapped->BaseClass == 0x03 + || (PciConfigMapped->BaseClass == 0x00 + && PciConfigMapped->SubClass == 0x01)) { + + if (HalpPCIBackToBackReg0Open) { + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); + HalpPCIBackToBackReg0Open = 0; + + } else { + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1); + HalpPCIBackToBackReg1Open = 0; + + } + + HalpPCINumberOfMappedGA++; + + } else { + + // + // We can set only if reg0 or reg1 is not used. + // + + if (HalpPCIBackToBackReg0Open) { + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); + HalpPCIBackToBackReg0Open = 0; + + } else if (HalpPCIBackToBackReg1Open){ + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1); + HalpPCIBackToBackReg1Open = 0; + + } + } + } +// } + + } else { + + // + // This is back-to-back uncapable. + // + + HalpFoundUncapablePCIDevice = 1; + + // + // if device is back-to-back uncapable¡¤map only GA. + // + + if (PciConfigMapped->BaseClass == 0x03 + || (PciConfigMapped->BaseClass == 0x00 + && PciConfigMapped->SubClass == 0x01)) { + + // + // In case of two or more cards are connected, the + // process is depend on the number of PCI-GA which + // already mapped. + // But we do not need to map 3rd PCI-GA or more. + // + + if (HalpNumberOfPCIGA > 1) { + + switch (HalpPCINumberOfMappedGA) { + + case 0: + + // + // Re-nitialize all values to void already settings, + // and use reg0 + // + + HalpPCIBackToBackReg0Start = 1; + HalpPCIBackToBackReg1Start = 0; + HalpPCIBackToBackReg0Open = 1; + HalpPCIBackToBackReg1Open = 1; + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); + break; + + case 1: + + // + // Control is transfered to this routine when one PCI-GA + // is already mapped. This means that reg0 had already used. + // We use reg1. + // + // N.B. We do not know reg0 is opened or closed, so close + // reg0 here. + // (ex) 1st mapped ... capable = 1, not GA + // 2nd mapped ... capable = 0, GA + // + + HalpPCIBackToBackReg0Open = 0; + HalpPCIBackToBackReg1Start = 1; + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1); + + } + + } else { + + // + // There is only one-card as PCI-GA. + // If back-to-back reg0 not being useed, use reg0, + // else close the space of reg0 and use reg1. + // (Also when reg0 is closed, use reg1) + // + + if (!HalpPCIBackToBackReg0Start) { + HalpPCIBackToBackReg0Start = 1; + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0); + + } else { + HalpPCIBackToBackReg0Open = 0; + HalpPCIBackToBackReg1Start = 1; + HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1); + + } + } + } + + // + // if being to set to back-to-back register, we have to close. + // + + if (HalpPCIBackToBackReg0Start && HalpPCIBackToBackReg0Open) { + HalpPCIBackToBackReg0Open = 0; + + } else if (HalpPCIBackToBackReg1Start && HalpPCIBackToBackReg1Open) { + HalpPCIBackToBackReg1Open = 0; + + } + + } + + } + +NotSetBackToBack: + KiReleaseSpinLock(&HalpPCIBackToBackLock); + +} + +VOID +HalpSetBackToBackRegister( + IN ULONG BaseAddress, + IN ULONG Length, + IN ULONG Register + ) +/*++ + +Routine Description: + + This function sets memory space of PCI device to Fast Back-to-back register. + +Arguments: + + BaseAddress - Supplies the address which to be mapped with back-to-back. + Length - Supplies the length which to be mapped with back-to-back. + Register - Supplies the back-to-back register number. + +Return Value: + + None. + +--*/ + +{ + ULONG Mask; + + // + // make mask value + // + + Mask = ~(Length - 1); + + // + // set to back-to-back register + // + +#if DBG + DbgPrint(" set back-to-back register.\n"); + DbgPrint(" - Register ................ %d\n", Register); + DbgPrint(" - Address ................. 0x%08x\n", BaseAddress); + DbgPrint(" - Mask .................... 0x%08x\n", Mask); +#endif + + WRITE_REGISTER_ULONG( + &DMA_CONTROL->PCIFastBackToBack[Register].Address, + BaseAddress + ); + + WRITE_REGISTER_ULONG( + &DMA_CONTROL->PCIFastBackToBack[Register].Mask, + Mask + ); + +} + +ULONG +HalpGetNumberOfPCIGA( + IN ULONG NumberBuses + ) +/*++ + +Routine Description: + + This function determines the number of PCI-GAs. + And initialize Fast Back-to-back register. + +Arguments: + + NumberBuses - Supplies the number of the PCI-buses. + +Return Value: + + number of PCI-GA. + +--*/ + +{ + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG Bus; + ULONG Slot; + ULONG Function; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + ULONG Count; + ULONG Register; + USHORT commandValue; + + Count = 0; + PciData = (PPCI_COMMON_CONFIG)&iBuffer; + + // + // BUGBUG: Fast Back-to-back transaction can be used + // only bus number zero on this version. + // PCI devices connected on bus number 1 or more will + // be available with back-to-back on future. + // + + NumberBuses = 1; + + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + for (Bus = 0; Bus < NumberBuses; Bus++) { + BusHandler = HalpHandlerForBus (PCIBus, Bus); + + for (Slot = 0; Slot < PCI_MAX_DEVICES; Slot++) { + SlotNumber.u.bits.DeviceNumber = Slot; + + for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) { + SlotNumber.u.bits.FunctionNumber = Function; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Check for chips with known work-arounds to apply + // + + if (PciData->BaseClass == 0x03 + || (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01)){ + + // + // This is Graphics Adapter. Inclement count. + // + + Count++; + } + + } // next PCI function + + } // next PCI slot + + } // next PCI bus + +#if DBG + DbgPrint(" number of PCI-GA.\n"); + DbgPrint(" - number of PCI-GA ........ %d\n", Count); +#endif + + // + // Initialize Fast Back-to-back register. + // + + for (Register = 0; Register < 2; Register++) { + WRITE_REGISTER_ULONG( + &DMA_CONTROL->PCIFastBackToBack[Register].Address, + INIT_VALUE_OF_BACK_TO_BACK_ADDR + ); + + WRITE_REGISTER_ULONG( + &DMA_CONTROL->PCIFastBackToBack[Register].Mask, + INIT_VALUE_OF_BACK_TO_BACK_MASK + ); + } + + commandValue = READ_REGISTER_USHORT(&DMA_CONTROL->PCICommand); + WRITE_REGISTER_USHORT(&DMA_CONTROL->PCICommand, (commandValue & ~0x0200)); + + return Count; + +} diff --git a/private/ntos/nthals/halr96b/mips/pciint.c b/private/ntos/nthals/halr96b/mips/pciint.c new file mode 100644 index 000000000..06571660d --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/pciint.c @@ -0,0 +1,376 @@ +// #pragma comment(exestr, "@(#) pciint.c 1.1 95/09/28 15:46:29 nec") +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpciint.c + +Abstract: + + All PCI bus interrupt mapping is in this module, so that a real + system which doesn't have all the limitations which PC PCI + systems have can replaced this code easly. + (bus memory & i/o address mappings can also be fix here) + +Author: + + Ken Reneris + +Environment: + + Kernel mode + +Revision History: + +Modification History: + + H001 Fri Jun 30 02:58:57 1995 kbnes!kisimoto + - Merge build 1057 + H002 Tue Sep 5 20:21:24 1995 kbnes!kisimoto + - PCI Fast Back-to-back transfer support + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +ULONG PciIsaIrq; +ULONG HalpEisaELCR; +BOOLEAN HalpDoingCrashDump; +extern ULONG HalpPCIMemoryLimit; // H002 + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus) +#pragma alloc_text(PAGE,HalpAdjustPCIResourceList) +#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq) +#endif + +#if defined(_R94A_) // H001 +ULONG R94A_PCIPinToLineTable[][4] = { + { 0xF, 0xF, 0xF, 0xF }, // Slot 0(Hurricane)No InterruptPin + { 0xF, 0xF, 0xF, 0xF }, // Slot 1(Typhoon) No InterruptPin assign + { 0xF, 0xF, 0xF, 0xF }, // Slot 2(PCEB) No InterruptPin assign + { 0x3, 0x3, 0x3, 0x3 }, // Slot 3 : INT A B C D + { 0x2, 0x2, 0x2, 0x2 }, // Slot 4 : INT A B C D + { 0x1, 0x1, 0x1, 0x1 } // Slot 5 : INT A B C D +}; +#endif // _R94A_ + +ULONG +HalpGetPCIIntOnISABus ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) +{ + if (BusInterruptLevel < 1) { + // bogus bus level + return 0; + } + + + // + // Current PCI buses just map their IRQs ontop of the ISA space, + // so foreward this to the isa handler for the isa vector + // (the isa vector was saved away at either HalSetBusData or + // IoAssignReosurces time - if someone is trying to connect a + // PCI interrupt without performing one of those operations first, + // they are broken). + // + + return HalGetInterruptVector ( +#ifndef MCA + Isa, 0, +#else + MicroChannel, 0, +#endif + BusInterruptLevel ^ IRQXOR, + 0, + Irql, + Affinity + ); +} + + +VOID +HalpPCIPin2ISALine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + + This function maps the device's InterruptPin to an InterruptLine + value. + + On the current PC implementations, the bios has already filled in + InterruptLine as it's ISA value and there's no portable way to + change it. + + On a DBG build we adjust InterruptLine just to ensure driver's + don't connect to it without translating it on the PCI bus. + +--*/ +{ + if (!PciData->u.type0.InterruptPin) { + return ; + } + +#if defined(_R94A_) // H001 + + PciData->u.type0.InterruptLine = + (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciData->u.type0.InterruptPin]; + +#else + + // + // Set vector as a level vector. (note: this code assumes the + // irq is static and does not move). + // + + if (PciData->u.type0.InterruptLine >= 1 && + PciData->u.type0.InterruptLine <= 15) { + + // + // If this bit was on the in the PIC ELCR register, + // then mark it in PciIsaIrq. (for use in hal.dll, + // such that we can assume the interrupt controller + // has been properly marked as a level interrupt for + // this IRQ. Other hals probabily don't care.) + // + + PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine); + } + + // + // On a PC there's no Slot/Pin/Line mapping which needs to + // be done. + // + + PciData->u.type0.InterruptLine ^= IRQXOR; + +#endif // _R94A_ + +} + + + +VOID +HalpPCIISALine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + On the current PC implementations, this information is + fixed by the BIOS. Just make sure the value isn't being + editted since PCI doesn't tell us how to dynically + connect the interrupt. + +--*/ +{ + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + +#if defined(_R94A_) // H001 + + PciNewData->u.type0.InterruptLine = + (UCHAR)R94A_PCIPinToLineTable[SlotNumber.u.bits.DeviceNumber][PciOldData->u.type0.InterruptPin]; + +#else + + PciNewData->u.type0.InterruptLine ^= IRQXOR; + +#endif // _R94A_ + +#if DBG + if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine || + PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) { + DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n"); + // DbgBreakPoint (); + } +#endif +} + +#if !defined(SUBCLASSPCI) + +VOID +HalpPCIAcquireType2Lock ( + PKSPIN_LOCK SpinLock, + PKIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { +#if defined(_R94A_) // H001 + KeRaiseIrql(PROFILE_LEVEL, Irql); +#else + *Irql = KfRaiseIrql (HIGH_LEVEL); +#endif + KiAcquireSpinLock (SpinLock); + } else { + *Irql = HIGH_LEVEL; + } +} + + +VOID +HalpPCIReleaseType2Lock ( + PKSPIN_LOCK SpinLock, + KIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (SpinLock); +#if defined(_R94A_) // H001 + KeLowerIrql (Irql); +#else + KfLowerIrql (Irql); +#endif // _R94A_ + } +} + +#endif + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + Rewrite the callers requested resource list to fit within + the supported ranges of this bus +--*/ +{ + NTSTATUS Status; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER PciSlot; + PSUPPORTED_RANGE Interrupt; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber); + + // + // Determine PCI device's interrupt restrictions + // + + Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt); + + if (!NT_SUCCESS(Status)) { + return Status; + } + + // + // H002 + // change Memory.Limit value to BaseAddress which last mapped. + // + +#if DBG + DbgPrint(" change Memory.Limit!\n"); + DbgPrint(" - Before limit ............ 0x%08x\n", + ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart); +#endif + + ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart = HalpPCIMemoryLimit; + +#if DBG + DbgPrint(" - After limit ............. 0x%08x\n", + ((PLARGE_INTEGER)(&BusHandler->BusAddresses->Memory.Limit))->LowPart); +#endif + + // + // Adjust resources + // + + Status = HaliAdjustResourceListRange ( + BusHandler->BusAddresses, + Interrupt, + pResourceList + ); + + ExFreePool (Interrupt); + return Status; +} + + +NTSTATUS +HalpGetISAFixedPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ) +{ + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciData; + +#if defined(_R94A_) // H001 + PPCIPBUSDATA BusData; +#endif + + PciData = (PPCI_COMMON_CONFIG) buffer; + HalGetBusData ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + return STATUS_UNSUCCESSFUL; + } + + *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE)); + if (!*Interrupt) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE)); + (*Interrupt)->Base = 1; // base = 1, limit = 0 + +#if defined(_R94A_) // H001 + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); + +#else + + if (!PciData->u.type0.InterruptPin) { + return STATUS_SUCCESS; + } + + if (PciData->u.type0.InterruptLine == IRQXOR) { +#if DBG + DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n"); +#endif + // + // We need to let the caller continue, since the caller may + // not care that the interrupt vector is connected or not + // + + return STATUS_SUCCESS; + } + +#endif // _R94A_ + + (*Interrupt)->Base = PciData->u.type0.InterruptLine; + (*Interrupt)->Limit = PciData->u.type0.InterruptLine; + return STATUS_SUCCESS; +} diff --git a/private/ntos/nthals/halr96b/mips/pcip.h b/private/ntos/nthals/halr96b/mips/pcip.h new file mode 100644 index 000000000..8e6a361a8 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/pcip.h @@ -0,0 +1,200 @@ +// #pragma comment(exestr, "@(#) pcip.h 1.1 95/09/28 15:46:56 nec") +/*++ + + Modification History + + H001 Fri Jun 30 02:51:55 1995 kbnes!kisimoto + - add definition + +--*/ + +// +// Hal specific PCI bus structures +// + +typedef NTSTATUS +(*PciIrqRange) ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ); + +typedef struct tagPCIPBUSDATA { + + // + // Defined PCI data + // + + PCIBUSDATA CommonData; + + // + // Implementation specific data + // + + union { + struct { + PULONG Address; + ULONG Data; + } Type1; + struct { + PUCHAR CSE; + PUCHAR Forward; + ULONG Base; + } Type2; + } Config; + + ULONG MaxDevice; + PciIrqRange GetIrqRange; + + BOOLEAN BridgeConfigRead; + UCHAR ParentBus; + UCHAR reserved[2]; + UCHAR SwizzleIn[4]; + + RTL_BITMAP DeviceConfigured; + ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32]; +} PCIPBUSDATA, *PPCIPBUSDATA; + +#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev); + +#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION) + +#define Is64BitBaseAddress(a) \ + (((a & PCI_ADDRESS_IO_SPACE) == 0) && \ + ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)) + +#if defined(_R94A_) // H001 +#define R94A_PCI_TYPE1_ADDR_PORT 0xFFFFc518 +#define R94A_PCI_TYPE1_DATA_PORT 0xFFFFc520 +#endif // _R94A_ + +#if DBG +#define IRQXOR 0x2B +#else +#define IRQXOR 0 +#endif + + +// +// Prototypes for functions in ixpcibus.c +// + +VOID +HalpInitializePciBus ( + VOID + ); + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ); + + +// +// Prototypes for functions in ixpciint.c +// + +ULONG +HalpGetPCIIntOnISABus ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpPCIAcquireType2Lock ( + PKSPIN_LOCK SpinLock, + PKIRQL Irql + ); + +VOID +HalpPCIReleaseType2Lock ( + PKSPIN_LOCK SpinLock, + KIRQL Irql + ); + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +VOID +HalpPCIPin2ISALine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + +VOID +HalpPCIISALine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +NTSTATUS +HalpGetISAFixedPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ); + +// +// Prototypes for functions in ixpcibrd.c +// + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN PUCHAR MaxPciBus + ); + +VOID +HalpFixupPciSupportedRanges ( + IN ULONG MaxBuses + ); + +// +// +// + +#ifdef SUBCLASSPCI + +VOID +HalpSubclassPCISupport ( + IN PBUS_HANDLER BusHandler, + IN ULONG HwType + ); + +#endif diff --git a/private/ntos/nthals/halr96b/mips/pcisup.c b/private/ntos/nthals/halr96b/mips/pcisup.c new file mode 100644 index 000000000..d46cc00e4 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/pcisup.c @@ -0,0 +1,632 @@ +// #pragma comment(exestr, "@(#) r94apcisup.c 1.1 95/09/28 18:37:11 nec") +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + r94apisup.c + +Abstract: + + The module provides the PCI bus support for R94A systems. + +Author: + + +Revision History: + + L0001 1994.9.20 kbnes!kuriyama(A) + -New module for R94A R4400 system + -add HalpAllocaltePCIAdapter() + + H0001 Tue Sep 20 22:58:03 JST 1994 kbnes!kishimoto + -add HalpEnablePCIInterrupt() + -add HalpDisablePCIInterrupt() + -add HalpPCIDispatch() + -add HalpPCIFatalError() + + H0002 Tue Oct 4 12:47:58 JST 1994 kbnes!kishimoto + -modify HalpPCIFatalError() + display the appropriate PCI errors + + L0002 1994.10.13 kbnes!kuriyama(A) + -add HalpAllocaltePCIAdapter() + -add AdapterBaseVa set routine + + H0003 Fri Oct 14 14:54:40 JST 1994 kbnes!kishimoto + -chg use READ_REGISTER_DWORD to read 64-bit I/O register + + H0003 Mon Oct 17 14:36:57 JST 1994 kbnes!kishimoto + -chg Hal(p)EisaPCIXXX() rename to Hal(p)EisaXXX() + XXX_EISA_PCI_XXX rename to XXX_EISA_XXX + MAXIMUM_PCI_SLOT rename to R94A_PCI_SLOT + + H0004 Wed Oct 19 13:24:51 JST 1994 kbnes!kishimoto + -chg HalpPCIDispatch() + The PCI-error check change up the order. + + H0005 Wed Oct 19 20:17:09 JST 1994 kbnes!kishimoto + -add substitute READ_REGISTER_BUFFER_UCHAR for + READ_REGISTER_DWORD because of storm alpha- + version cannot 64-bit access. + + L0006 Wed Oct 19 22:01:27 JST 1994 kbnes!kuriyama(A) + -chg HalpAllocatePCIAdapter() + del useChannel + del channelNumber + del controllerNumber + del eisaSystem + chg AdapterBaseVa value + + H0006 Tue Nov 22 22:10:00 1994 kbnes!kishimoto + -del delete _R94ABBM32_ + The limitation of 32bit bus-access is only applied + under PCI-bus. I make a wrong application. + + H0007 Fri Jul 21 18:02:55 1995 kbnes!kishimoto + -merge source with J94C + +--*/ + +#include "halp.h" +#include "eisa.h" + +#if defined(_R94A_) + +#include + +/* start H0000 */ + +// +// Define the context structure for use by the interrupt routine. +// + +typedef BOOLEAN (*PSECONDARY_DISPATCH)( + PVOID InterruptRoutine + ); + +VOID +HalpPCIFatalError( + STORM_PCI_INTRRUPT_STATUS InterruptStatus + ); + +/* end H0000 */ + +// start L0001 +PADAPTER_OBJECT +HalpAllocatePCIAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor + ) +/*++ + +Routine Description: + + This function allocates an PCI adapter object according to the + specification supplied in the device description. The necessary device + descriptor information is saved. If there is + no existing adapter object for this channel then a new one is allocated. + The saved information in the adapter object is used to set the various DMA + modes when the channel is allocated or a map transfer is done. + +Arguments: + + DeviceDescription - Supplies the description of the device which want to + use the DMA adapter. + +Return Value: + + Returns a pointer to the newly created adapter object or NULL if one + cannot be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + PVOID adapterBaseVa; + UCHAR adapterMode; + + // + // All PCI Cards is Master card. + // + + if (DeviceDescriptor->InterfaceType == PCIBus && + DeviceDescriptor->Master) { + + } else { + + return(NULL); + } + + +/* start L0002 */ + // + // Set the adapter base address to the Base address register and controller + // number. + // + + adapterBaseVa = ~0; /* L0006 */ +/* end L0002 */ + + // + // Allocate an adapter object. + // + + adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter( + 0, + adapterBaseVa, + NULL + ); + + if (adapterObject == NULL) { + + return(NULL); + + } + + // + // If the channel is not used then indicate the this is an PCI bus + // master by setting the page port and mode to cascade even though + // it is not used. + // + + adapterObject->PagePort = (PVOID) (~0x0); + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE; + return(adapterObject); + +} +// end L0001 + +/* start H0001 */ +VOID +HalpEnablePCIInterrupt ( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function enables the PCI bus specified PCI bus interrupt. + PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6) + +Arguments: + + Vector - Supplies the vector of the interrupt that is enabled. + +Return Value: + + None. + +--*/ + +{ + + ULONG i; + + // + // enable specified PCI bus interrupt. + // + + i = READ_REGISTER_ULONG( + &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable + ); + + WRITE_REGISTER_ULONG( + &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable, + (ULONG)( i | 1 << (Vector - PCI_VECTORS)) + ); + + return; + +} + +VOID +HalpDisablePCIInterrupt ( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function Disables the PCI bus specified PCI bus interrupt. + PCI interrupts must be LevelSensitve. (PCI Spec. 2.2.6) + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + + ULONG i; + + // + // disable specified PCI bus interrupt. + // + + i = READ_REGISTER_ULONG( + &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable + ); + + WRITE_REGISTER_ULONG( + &((PDMA_REGISTERS) DMA_VIRTUAL_BASE)->PCIInterruptEnable, + (ULONG)( i & ~(1 << (Vector - PCI_VECTORS))) + ); + + return; + +} + + +BOOLEAN +HalpPCIDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) +/*++ + +Routine Description: + + This routine is entered as the result of an interrupt being generated + via the vector that is connected to an interrupt object that describes + the PCI device interrupts. Its function is to call the third + level interrupt dispatch routine and acknowledge the interrupt at the PCI + controller. + + This service routine should be connected as follows: + + KeInitializeInterrupt(&Interrupt, HalpEisaDispatch, + EISA_VIRTUAL_BASE, + (PKSPIN_LOCK)NULL, EISA_DEVICE_LEVEL, EISA_DEVICE_LEVEL, + EISA_DEVICE_LEVEL, LevelSensitive, TRUE, 0, FALSE); + KeConnectInterrupt(&Interrupt); + +Arguments: + + Interrupt - Supplies a pointer to the interrupt object. + + ServiceContext - Supplies a pointer to the EISA interrupt acknowledge + register. + +Return Value: + + Returns the value returned from the third level routine. + +--*/ + +{ + STORM_PCI_INTRRUPT_STATUS InterruptStatus; + PKINTERRUPT interruptObject; + PULONG dispatchCode; + BOOLEAN returnValue; + LONG Index; + + // + // Read the interrupt vector. + // + + *((PULONG) &InterruptStatus) = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus); + + // + // BUGBUG + // + + if (*((PULONG)&InterruptStatus) == 0) { + + // + // There is not PCI interrupt. + // + + return(FALSE); + + } + + // + // Check if there are any non-recoverable PCI errors. + // R94A has the following PCI error interrupts. + // Target abort interrupt + // Master abort interrupt + // Retry overflow interrupt + // SERR interrupt + // PERR interrupt + // + + if (InterruptStatus.Perr == 1 || + InterruptStatus.Serr == 1 || + InterruptStatus.RetryOverflow == 1 || + InterruptStatus.MasterAbort == 1 || + InterruptStatus.TargetAbort == 1) { + + // + // Display the appropriate PCI errors and bugcheck to dump the machine state. + // + + HalpPCIFatalError(InterruptStatus); + KeBugCheck(DATA_BUS_ERROR); + + // + // The following code is never executed. + // + + return(FALSE); + } + + // + // if INT[A.B.C.D] is active, then call the appropriate PCI drivers. + // + + if ((*((PULONG)&InterruptStatus) & 0xf) != 0x0) { + + // + // Dispatch to the secondary interrupt service routine. + // + // N.B. R94A PCI interrupts flow : + // + // system slot1 slot2 slot3 + // INT A <----------+ + + + // INT B <------+ + + + + // INT C <---+ | + + + + // Reserved | | + + + + // | +-----------+ | + // +----------------------+ + // + // + // PCI Interrupt Status Register Bit Definitions are: + // + // [31:09] Reserved + // [08] Target abort interrupt status + // [07] Master abort interrupt status + // [06] Retry overflow interrupt status + // [05] SERR interrupt status + // [04] PERR interrupt status + // [03] INTA interrupt status + // [02] INTB interrupt status + // [01] INTC interrupt status + // [00] INTD interrupt status + // + + for (Index = 3; Index > (3 - R94A_PCI_SLOT); Index--) { + + // + // Check if the PCI interrupt occur. + // + + if (((*((PULONG)&InterruptStatus) & 0xf) & ((ULONG)1 << Index)) != 0x0) { + + dispatchCode = (PULONG)(PCR->InterruptRoutine[PCI_VECTORS + Index]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject); + + } + + } + + } + + return(returnValue); + +} + + +VOID +HalpPCIFatalError( + STORM_PCI_INTRRUPT_STATUS InterruptStatus + ) +/*++ + +Routine Description: + + This routine is entered as the result of an PCI fatal interrupt. + This function displays appropriate PCI error information. + +Arguments: + + InterruptStatus - PCI Interrupt Status value. + +Return Value: + + None. + +--*/ + +{ + + UCHAR Buffer[100]; + UCHAR registerChar; + ULONG registerLong; + LARGE_INTEGER registerLarge; + LARGE_INTEGER InvalidAddressValue; + LARGE_INTEGER EccDiagnosticValue; + + HalpChangePanicFlag(16, 0x01, 0x10); // H0007 + + HalDisplayString("\nFatal system error occured\n\n"); + + // + // Display the following register value. + // + // register name address + // + // Remode Failed Address 0x80000010 32bit + // Memory Failed Address 0x80000018 32bit + // Processor Invalid Address 0x80000020 33bit + // ECC Diagnostic 0x800001c8 64bit + // PCI Status 0x80000606 16bit + // PCI Master Retry Timer 0x80000668 32bit + // + + // + // Display the PCI fatal error information + // + + if (InterruptStatus.Perr){ + HalDisplayString("PCI: Data parity error\n"); + } + + if (InterruptStatus.Serr){ + HalDisplayString("PCI: Address parity error\n"); + } + + if (InterruptStatus.RetryOverflow){ + HalDisplayString("PCI: Retry overflow\n"); + } + + if (InterruptStatus.MasterAbort){ + HalDisplayString("PCI: Master abort\n"); + } + + if (InterruptStatus.TargetAbort){ + HalDisplayString("PCI: Target abort\n"); + } + + // ! start + // test test test : dump the hardware registers of R94A + // + // dump R94A all hardware-registers to buffer instead of display console + // registers that is only important for analasis dump are display to console + // + // registers which display to console are: + // 0x80000000 Configuration + // 0x80000010 RemoteFailedAddress + // 0x80000018 MemoryFailedAddress + // 0x80000020 InvalidAddress + // 0x80000078 NmiSource + // 0x800000f8 InterruptEnable + // 0x80000188 Errortype + // 0x800001c8 EccDiagnostic + // 0x80000530 PCIInterruptEnable + // 0x80000538 PCIInterruptStatus + // 0x80000606 PCIStatus + // 0x800005bc TyphoonErrorStatus + // 0x80000668 PCIMasterRetryTimer + // + // 0x8000f000 I/O Device Interrupt Enable + // + + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, &InvalidAddressValue); + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, &EccDiagnosticValue); + + sprintf(Buffer, + "Configuration : %08x RemoteFailedAddress : %08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->Configuration.Long), + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long)); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "MemoryFailedAddress : %08x InvalidAddress :%01x%08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long), + (InvalidAddressValue.HighPart & 0x1), InvalidAddressValue.LowPart); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "NmiSource : %08x InterruptEnable : %08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long), + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long)); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "Errortype : %08x EccDiagnostic(High) : %08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->NmiSource.Long), + EccDiagnosticValue.HighPart); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "EccDiagnostic(Low) : %08x PCIInterruptEnable : %08x\n", + EccDiagnosticValue.LowPart, + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable.Long)); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "PCIInterruptStatus : %08x PCIStatus : %08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptStatus.Long), + READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus)); + + HalDisplayString((UCHAR *)Buffer); + + sprintf(Buffer, + "TyphoonErrorStatus : %08x PCIMasterRetryTimer : %08x\n", + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->TyphoonErrorStatus), + READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer)); + + HalDisplayString((UCHAR *)Buffer); + + HalpGetStatusRegister(®isterLong); + + sprintf(Buffer, + "I/O DevIntEnable : %08x (CPU)StatusRegister : %08x\n", + READ_REGISTER_ULONG((PINTERRUPT_REGISTERS)INTERRUPT_VIRTUAL_BASE), + registerLong); + + HalDisplayString((UCHAR *)Buffer); + + + // + // ! end + // + +// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->RemoteFailedAddress.Long); +// sprintf ((UCHAR *)Buffer, "RemodeFailedAddress = 0x%08x\n", registerLong); +// HalDisplayString((UCHAR *)Buffer); + +// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long); +// sprintf ((UCHAR *)Buffer, "MemoryFailedAddress = 0x%08x\n", registerLong); +// HalDisplayString((UCHAR *)Buffer); + + // + // memo + // + // (./ntos/inc/mips.h) + // #define READ_REGISTER_BUFFER_UCHAR(x, y, z) { + // PUCHAR registerBuffer = x; + // PUCHAR readBuffer = y; + // ULONG readCount; + // for (readCount = z; readCount--; readBuffer++, registerBuffer++) { + // *readBuffer = *(volatile UCHAR * const)(registerBuffer); + // } + // } + // + +/* start H0003 */ + +// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); +// sprintf ((UCHAR *)Buffer, "InvalidAddress =0x%01x%08x\n", registerLarge.HighPart & 0x1, registerLarge.LowPart); +// HalDisplayString((UCHAR *)Buffer); + +// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic, ®isterLarge); +// sprintf ((UCHAR *)Buffer, "EccDiagnostic(High) = 0x%08x\n", registerLarge.HighPart); +// HalDisplayString((UCHAR *)Buffer); + +// sprintf ((UCHAR *)Buffer, "EccDiagnostic(Low) = 0x%08x\n", registerLarge.LowPart); +// HalDisplayString((UCHAR *)Buffer); + +/* end H0003 */ + +// registerChar = READ_REGISTER_UCHAR(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus); +// sprintf ((UCHAR *)Buffer, "PCIStatus = 0x%08x\n", registerChar); +// HalDisplayString((UCHAR *)Buffer); + +// registerLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIMasterRetryTimer); +// sprintf ((UCHAR *)Buffer, "PCIMasterRetryTimer = 0x%08x\n", registerLong); +// HalDisplayString((UCHAR *)Buffer); + + return; + +} + +/* end H0001 */ +#endif // _R94A_ diff --git a/private/ntos/nthals/halr96b/mips/r94adbg.c b/private/ntos/nthals/halr96b/mips/r94adbg.c new file mode 100644 index 000000000..e48290c04 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94adbg.c @@ -0,0 +1,157 @@ +// #pragma comment(exestr, "@(#) r94adbg.c 1.1 95/09/28 15:47:19 nec") +/*++ + +Copyright (c) 1994 KOBE NEC Software + +Module Name: + + r94adbg.c + +Abstract: + + The module provides the debug support functions for R94A systems. + +Author: + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Thu Sep 8 10:32:42 JST 1994 kbnes!kishimoto + - add HalDisplayLED() + new function. + - add HalpOutputCharacterToLED() + new function. + + H001 Mon Oct 17 13:01:53 JST 1994 kbnes!kishimoto + - add HalR94aDebugPrint() + new function. + - chg HalpDisplayLED() + rename from HalDisplayLED() + + H002 Thu Oct 20 19:42:03 JST 1994 kbnes!kishimoto + - add R94aBbmLEDMapped used at KdPortInitialize()(jxport.c) + for debug use only + + H003 Fri Oct 21 10:18:01 JST 1994 kbnes!kishimoto + - add specify the output device. + + M004 Fri Jan 06 10:49:29 JST 1995 kbnes!kuriyama + - add HalpPrintMdl() + + H005 Sat Mar 18 16:23:05 JST 1995 kbnes!kishimoto + - always include "halp.h" + + S006 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:49:48 JST 1995 + - delete PrintMdl routine (if defined _PRINT_MDL_) + +--*/ + +#include +#include +#include "halp.h" // H005 + +#define R94A_LED 0 +#define R94A_DBG 1 +#define R94A_CON 2 + +ULONG HalpR94aDebugOutput = R94A_DBG ; // start H003 +ULONG R94aDebugLevel = 1; + +VOID +HalR94aDebugPrint( + ULONG DebugLevel, + PUCHAR LedCharactor, + PUCHAR Message, + ... + ) +/*++ + +Routine Description: + + This function is used to display debug information. + + Usage : + HalR94aDebugPrint( + (ULONG) 3, + "1234", + "Dbg : Current file is %s [%d]\n", + __FILE__, + __LINE__ + ); + +Arguments: + + DebugLevel - Debug level for output. + If DebugLevel less than R94aDebugLevel, not display. + + LedCharactor - Display charactor for LED. + + Message - Display format for console or debug-teminal. + +Return Value: + + None. + +--*/ + +{ + va_list argp; + ULONG Index; + CHAR Buffer[100]; + + if (DebugLevel >= R94aDebugLevel) { + + va_start(argp, Message); + vsprintf(Buffer, Message, argp); + + if (HalpR94aDebugOutput & (1 << R94A_DBG)) { // H003 + + DbgPrint(Buffer); + + } + + if (HalpR94aDebugOutput & (1 << R94A_CON)) { + + HalDisplayString(Buffer); + + } + + va_end(argp); + } + + return; +} +/* end H001 */ + +/* M004 +++ */ +#if defined(_PRINT_MDL_) //S006 +VOID +HalpPrintMdl(PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + PLIST_ENTRY NextMd; + PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; + + + // + // Get the lower bound of the free physical memory and the + // number of physical pages by walking the memory descriptor lists. + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + + MemoryDescriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType); + DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage); + DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount); + + NextMd = MemoryDescriptor->ListEntry.Flink; + } +} +#endif // _PRINT_MDL_ // S006 +/* M004 --- */ diff --git a/private/ntos/nthals/halr96b/mips/r94adef.h b/private/ntos/nthals/halr96b/mips/r94adef.h new file mode 100644 index 000000000..4ebbff766 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94adef.h @@ -0,0 +1,266 @@ +// #pragma comment(exestr, "@(#) r94adef.h 1.1 95/09/28 15:47:51 nec") +/*++ BUILD Version: 0005 // Increment this if a change has global effects + +Copyright (c) 1994 NEC Corporation + +Module Name: + + r94adef.h + +Abstract: + + This module is the header file that describes hardware addresses + for the R94A system. + +Author: + + Akitoshi Kuriyama 23-Aug-1994 + +Revision History: + + M001 1994.8.23 A. Kuriyama + - Modify for R94A MIPS R4400 (original duodef.h) + M002 1994.9.24 A. Kuriyama + - Modify PCI A-D Vector Value + H000 Sat Sep 24 23:11:51 JST 1994 kbnes!kishimoto + - Add the number of PCI slots + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 17:10:13 JST 1994 + - Add + #define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+64*1024) + #define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW + 64*1024*1024) + #define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001 + M003 Mon Oct 17 17:26:12 JST 1994 kbnes!kuriyama + name change MAXIMUN_PCI_SLOT -> R94A_PCI_SLOT + ADD002 ataka@oa2.kb.nec.co.jp Mon Oct 17 19:30:00 JST 1994 + - change PCI_CONTROL_PHYSICAL_BASE, PCI_MEMORY_PHYSICAL_BASE_LOW + 64*1024 -> 10000 64*1024*1024 -> 4000000 + D001 ataka@oa2.kb.nec.co.jp Sat Nov 05 16:06:26 JST 1994 + - reduce DMA_TRANSLATION_LIMIT to 4 only for BBM DMA + S0004 Thu Dec 22 11:55:04 JST 1994 kbnes!A.Kuriyama + -add beta machine limit + S0005 Thu Jan 05 17:17:09 JST 1995 kbnes!A.Kuriyama + - warning clear + S0006 Thu Jan 05 18:52:51 JST 1995 kbnes!A.Kuriyama + - dma_limit change + M0007 Tue Mar 07 14:34:55 JST 1995 kbnes!kuriyama (A) + - expand dma logical address + M0008 Fri Mar 10 15:34:25 JST 1995 kbnes!kuriyama (A) + - expand dma logical address bug fix + M0009 Tue Mar 21 02:45:16 1995 kbnes!kishimoto + - physical base of PCI memory set to 64M + M0010 Tue Mar 21 03:06:05 1995 kbnes!kishimoto + - M0009 could not allocate memory + set base to zero. + M0011 Tue Apr 25 16:34:35 1995 kbnes!kishimoto + - add MRC registers + S0012 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 01:55:08 JST 1995 + - add NVRAM_VIRTUAL_BASE + M0011 Sat Aug 12 16:51:50 1995 kbnes!kishimoto + - rearrange the comments. + +--*/ + +#ifndef _R94ADEF_ +#define _R94ADEF_ + +// +// ADD001,ADD002 +// Define physical base addresses for system mapping. +// + +#define VIDEO_MEMORY_PHYSICAL_BASE 0x40000000 // physical base of video memory +#define VIDEO_CONTROL_PHYSICAL_BASE 0x60000000 // physical base of video control +#define CURSOR_CONTROL_PHYSICAL_BASE 0x60008000 // physical base of cursor control +#define VIDEO_ID_PHYSICAL_BASE 0x60010000 // physical base of video id register +#define VIDEO_RESET_PHYSICAL_BASE 0x60020000 // physical base of reset register +#define DEVICE_PHYSICAL_BASE 0x80000000 // physical base of device space +#define NET_PHYSICAL_BASE 0x80001000 // physical base of ethernet control +#define SCSI1_PHYSICAL_BASE 0x80002000 // physical base of SCSI1 control +#define SCSI2_PHYSICAL_BASE 0x80003000 // physical base of SCSI2 control +#define RTCLOCK_PHYSICAL_BASE 0x80004000 // physical base of realtime clock +#define KEYBOARD_PHYSICAL_BASE 0x80005000 // physical base of keyboard control +#define MOUSE_PHYSICAL_BASE 0x80005000 // physical base of mouse control +#define SERIAL0_PHYSICAL_BASE 0x80006000 // physical base of serial port 0 +#define SERIAL1_PHYSICAL_BASE 0x80007000 // physical base of serial port 1 +#define PARALLEL_PHYSICAL_BASE 0x80008000 // physical base of parallel port +#define EISA_CONTROL_PHYSICAL_BASE 0x90000000 // physical base of EISA control +#define EISA_MEMORY_PHYSICAL_BASE 0x91000000 // physical base of EISA memory +#define EISA_MEMORY_VERSION2_LOW 0x00000000 // physical base of EISA memory +#define EISA_MEMORY_VERSION2_HIGH 0x00000001 // with version 2 address chip +#define PROM_PHYSICAL_BASE 0xfff00000 // physical base of boot PROM +#define EEPROM_PHYSICAL_BASE 0xfff40000 // physical base of FLASH PROM +#define PCI_CONTROL_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE) // physical base of PCI control +#define PCI_MEMORY_PHYSICAL_BASE_LOW (EISA_MEMORY_VERSION2_LOW) // physical base of PCI memory +#define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x00000001 // physical base of PCI memory + +// +// S0012 +// Define virtual/physical base addresses for system mapping. +// + +#define NVRAM_VIRTUAL_BASE 0xffff8000 // virtual base of nonvolatile RAM +#define NVRAM_PHYSICAL_BASE 0x80009000 // physical base of nonvolatile RAM + +#define SP_VIRTUAL_BASE 0xffffa000 // virtual base of serial port 0 +#define SP_PHYSICAL_BASE SERIAL0_PHYSICAL_BASE // physical base of serial port 0 + +#define DMA_VIRTUAL_BASE 0xffffc000 // virtual base of DMA control +#define DMA_PHYSICAL_BASE DEVICE_PHYSICAL_BASE // physical base of DMA control + +#define INTERRUPT_VIRTUAL_BASE 0xffffd000 // virtual base of interrupt source +#define INTERRUPT_PHYSICAL_BASE 0x8000f000 // physical base of interrupt source + +// +// Define the size of the DMA translation table. +// + +#if defined (_BBM_DMA_) // D001,S0004,S0005,S0006 + +#define DMA_TRANSLATION_LIMIT (sizeof(TRANSLATION_ENTRY) * 8 * 4) // translation table limit + +#else + +#if defined(_DMA_EXPAND_) // M0007,M0008 + +#define ISA_MAX_ADR 0x400000L // ISA MAX Logical Address +#define EISA_MIN_ADR 0x1000000L // EISA/PCI MIN Logical Address +#define EISA_MAX_ADR 0x2000000L // EISA/PCI MAX Logical Address +#define DMA_TRANSLATION_LIMIT (EISA_MAX_ADR / PAGE_SIZE * sizeof(TRANSLATION_ENTRY) ) + // translation table limit +#else // _DMA_EXPAND_ + +#define DMA_TRANSLATION_LIMIT 0x2000 // translation table limit + +#endif // _DMA_EXPAND_ + +#endif // (_BBM_DMA_) + + +// +// Define the maximum number of map registers allowed per allocation. +// + +#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY) * 8)) + +// +// Define pointer to DMA control registers. +// + +#define DMA_CONTROL ((volatile PDMA_REGISTERS)(DMA_VIRTUAL_BASE)) + +// +// Define DMA channel interrupt level. +// + +#define DMA_LEVEL 3 + +// +// Define the minimum and maximum system time increment values in 100ns units. +// + +#define MAXIMUM_INCREMENT (10 * 1000 * 10) +#define MINIMUM_INCREMENT (1 * 1000 * 10) + +// +// Define Duo clock level. +// + +#define CLOCK_LEVEL 6 // Interval clock level +#define CLOCK_INTERVAL ((MAXIMUM_INCREMENT / (10 * 1000)) - 1) // Ms minus 1 +#define CLOCK2_LEVEL CLOCK_LEVEL // + +// +// Define EISA device level. +// + +#define EISA_DEVICE_LEVEL 5 // EISA bus interrupt level + +// +// Define EISA device interrupt vectors. +// + +#define EISA_VECTORS 32 + +#define IRQL10_VECTOR (10 + EISA_VECTORS) // Eisa interrupt request level 10 +#define IRQL11_VECTOR (11 + EISA_VECTORS) // Eisa interrupt request level 11 +#define IRQL12_VECTOR (12 + EISA_VECTORS) // Eisa interrupt request level 12 +#define IRQL13_VECTOR (13 + EISA_VECTORS) // Eisa interrupt request level 13 + +#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector + +// +// Define I/O device interrupt level. +// + +#define DEVICE_LEVEL 4 // I/O device interrupt level + +// +// Define device interrupt vectors. +// + +#define DEVICE_VECTORS 16 // starting builtin device vector + +#define PARALLEL_VECTOR (1 + DEVICE_VECTORS) // Parallel device interrupt vector +//#define VIDEO_VECTOR (3 + DEVICE_VECTORS) // video device interrupt vector +#define AUDIO_VECTOR (3 + DEVICE_VECTORS) // audio device interrupt vector +#define NET_VECTOR (4 + DEVICE_VECTORS) // ethernet device interrupt vector +#define SCSI1_VECTOR (5 + DEVICE_VECTORS) // SCSI device interrupt vector +#define SCSI2_VECTOR (6 + DEVICE_VECTORS) // SCSI device interrupt vector +#define KEYBOARD_VECTOR (7 + DEVICE_VECTORS) // Keyboard device interrupt vector +#define MOUSE_VECTOR (8 + DEVICE_VECTORS) // Mouse device interrupt vector +#define SERIAL0_VECTOR (9 + DEVICE_VECTORS) // Serial device 0 interrupt vector +#define SERIAL1_VECTOR (10 + DEVICE_VECTORS) // Serial device 1 interrupt vector +#define TYPHOON_ERROR_INTERRUPT_VECTOR (15 + DEVICE_VECTORS) // TYPHOON error vector +//#define MAXIMUM_BUILTIN_VECTOR SERIAL1_VECTOR // maximum builtin vector +#define MAXIMUM_BUILTIN_VECTOR TYPHOON_ERROR_INTERRUPT_VECTOR // maximum builtin vector + +// +// M0001,M0002 +// Define PCI device interrupt vectors. +// + +#define PCI_VECTORS 80 +//#define INTERRUPT_D_VECTOR (0 + PCI_VECTORS) +//#define INTERRUPT_C_VECTOR (1 + PCI_VECTORS) +//#define INTERRUPT_B_VECTOR (2 + PCI_VECTORS) +//#define INTERRUPT_A_VECTOR (3 + PCI_VECTORS) +//#define MAXIMUM_PCI_VECTOR INTERRUPT_A_VECTOR + +// +// Define the clock speed in megahetz for the SCSI protocol chips. +// + +#define NCR_SCSI_CLOCK_SPEED 24 + +// +// PROM entry point definitions. +// +// Define base address of prom entry vector and prom entry macro. +// + +#define PROM_BASE (KSEG1_BASE | 0x1fc00000) +#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8)) + +// +// H000,M003 +// the number of lines which PCI interrupts. +// + +#define R94A_PCI_SLOT 3 + +// +// M0011 +// Define pointer to MRC control registers. +// + +#define MRC_CONTROL ((volatile PMRC_REGISTERS)(DMA_VIRTUAL_BASE)) + +// +// M0011 +// Define physical base addresses for system mapping. +// + +#define MRC_TEMP_PHYSICAL_BASE 0x80012000 // physical base of MRC and TEMP sensor + +#endif // _R94ADEF_ + diff --git a/private/ntos/nthals/halr96b/mips/r94adma.h b/private/ntos/nthals/halr96b/mips/r94adma.h new file mode 100644 index 000000000..5d8676ebb --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94adma.h @@ -0,0 +1,433 @@ +// #pragma comment(exestr, "@(#) r94adma.h 1.1 95/09/28 15:48:23 nec") +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1994 NEC Corporation + +Module Name: + + r94adma.h + +Abstract: + + This module is the header file that describes the DMA control register + structure for the R94A system. + +Author: + + David N. Cutler (davec) 13-Nov-1990 + +Revision History: + + M001 1994.8.24 A. Kuriyama + - Modify for R94A MIPS R4400 (original duodma.h) + H000 Sat Sep 24 21:36:20 JST 1994 kbnes!kishimoto + - Add PCIInterruptStatus register structure definition + M002 Mon Oct 03 19:52:16 JST 1994 kbnes!kuriyama(A) + - Add PCI(HURRICANE) register + - Change InvalidAddress register to DMA_LARGE_REGISTER + - Change RTC_REGISTER structure define. + - add Optional... registers + H001 Fri Dec 9 18:29:10 1994 kbnes!kishimoto + - Modify LEDControl definition (SHORT -> CHAR) + H002 Tue Jan 24 18:24:48 1995 kbnes!kishimoto + - Add PCI interrupt enable bits definitions. + H003 Tue Apr 25 16:38:06 1995 kbnes!kishimoto + - Add MRC registers + H004 Sat Aug 12 16:18:53 1995 kbnes!kishimoto + - rearrange comments. + +--*/ + +#ifndef _R94ADMA_ +#define _R94ADMA_ + +// +// M001 +// Define DMA register structures. +// + +typedef struct _DMA_REGISTER { + ULONG Long; + ULONG Fill; +} DMA_REGISTER, *PDMA_REGISTER; + +typedef struct _DMA_CHAR_REGISTER { + UCHAR Char; + UCHAR Fill; + USHORT Fill2; +} DMA_CHAR_REGISTER, *PDMA_CHAR_REGISTER; + +typedef struct _DMA_SHORT_REGISTER { + USHORT Short; + USHORT Fill; +} DMA_SHORT_REGISTER, *PDMA_SHORT_REGISTER; + +typedef struct _DMA_LARGE_REGISTER { + union { + LARGE_INTEGER LargeInteger; + double Double; + } u; +} DMA_LARGE_REGISTER, *PDMA_LARGE_REGISTER; + +// +// Define DMA channel register structure. +// + +typedef struct _DMA_CHANNEL { + DMA_REGISTER Mode; + DMA_REGISTER Enable; + DMA_REGISTER ByteCount; + DMA_REGISTER Address; +} DMA_CHANNEL, *PDMA_CHANNEL; + +// +// M002 +// Define PCI Address/Mask register structure +// + +typedef struct _PCI_ADDRESS_MASK { + ULONG Address; + ULONG Mask; +} PCI_ADDRESS_MASK, *PPCI_ADDRESS_MASK; + +// +// Define DMA control register structure. +// + +typedef volatile struct _DMA_REGISTERS { + DMA_REGISTER Configuration; // offset 000 + DMA_REGISTER RevisionLevel; // offset 008 + DMA_REGISTER RemoteFailedAddress; // offset 010 + DMA_REGISTER MemoryFailedAddress; // offset 018 + DMA_LARGE_REGISTER InvalidAddress; // offset 020 // M002 + DMA_REGISTER TranslationBase; // offset 028 + DMA_REGISTER TranslationLimit; // offset 030 + DMA_REGISTER TranslationInvalidate; // offset 038 + DMA_REGISTER ChannelInterruptAcknowledge; // offset 040 + DMA_REGISTER LocalInterruptAcknowledge; // offset 048 + DMA_REGISTER EisaInterruptAcknowledge; // offset 050 + DMA_REGISTER TimerInterruptAcknowledge; // offset 058 + DMA_REGISTER IpInterruptAcknowledge; // offset 060 + DMA_REGISTER Reserved1; // offset 068 + DMA_REGISTER WhoAmI; // offset 070 + DMA_REGISTER NmiSource; // offset 078 + DMA_REGISTER RemoteSpeed[15]; // offset 080 + DMA_REGISTER InterruptEnable; // offset 0f8 + DMA_CHANNEL Channel[4]; // offset 100 + DMA_REGISTER ArbitrationControl; // offset 180 + DMA_REGISTER Errortype; // offset 188 + DMA_REGISTER RefreshRate; // offset 190 + DMA_REGISTER RefreshCounter; // offset 198 + DMA_REGISTER SystemSecurity; // offset 1a0 + DMA_REGISTER InterruptInterval; // offset 1a8 + DMA_REGISTER IntervalTimer; // offset 1b0 + DMA_REGISTER IpInterruptRequest; // offset 1b8 + DMA_REGISTER InterruptDiagnostic; // offset 1c0 + DMA_LARGE_REGISTER EccDiagnostic; // offset 1c8 + DMA_REGISTER MemoryConfig[4]; // offset 1d0 + DMA_REGISTER Reserved2; + DMA_REGISTER Reserved3; + DMA_LARGE_REGISTER IoCacheBuffer[64]; // offset 200 + DMA_REGISTER IoCachePhysicalTag[8]; // offset 400 + DMA_REGISTER IoCacheLogicalTag[8]; // offset 440 + DMA_REGISTER IoCacheLowByteMask[8]; // offset 480 + DMA_REGISTER IoCacheHighByteMask[8]; // offset ??? wrong? + + // + // M001,M002,H001 + // new registers of STORM-chipset + // + + DMA_REGISTER ProcessorBootModeControl; // offset 500 + DMA_REGISTER ClockCounter; // offset 508 + DMA_REGISTER MemoryTimingControl; // offset 510 + DMA_REGISTER PCIConfigurationAddress; // offset 518 + DMA_REGISTER PCIConfigurationData; // offset 520 + DMA_REGISTER PCISpecialCycle; // offset 528 + DMA_REGISTER PCIInterruptEnable; // offset 530 + DMA_REGISTER PCIInterruptStatus; // offset 538 + DMA_REGISTER CopyTagConfiguration; // offset 540 + DMA_REGISTER CopyTagAddress; // offset 548 + DMA_REGISTER CopyTagData; // offset 550 + DMA_REGISTER ASIC2Revision; // offset 558 + DMA_REGISTER ASIC3Revision; // offset 560 + DMA_REGISTER Reserved4; // offset 568 + ULONG OptionalRemoteSpeed1; // offset 570 + ULONG OptionalRemoteSpeed2; // offset 574 + ULONG OptionalRemoteSpeed3; // offset 578 + ULONG OptionalRemoteSpeed4; // offset 57c + DMA_REGISTER LocalInterruptAcknowledge2; // offset 580 + DMA_REGISTER OptionalIoConfiguration1; // offset 588 + DMA_REGISTER OptionalIoConfiguration2; // offset 590 + DMA_REGISTER OptionalIoConfiguration3; // offset 598 + DMA_REGISTER OptionalIoConfiguration4; // offset 5a0 + DMA_SHORT_REGISTER BuzzerCount; // offset 5a8 + DMA_CHAR_REGISTER BuzzerControl; // offset 5ac + DMA_SHORT_REGISTER LEDCount; // offset 5b0 + DMA_CHAR_REGISTER LEDControl; // offset 5b4 + DMA_SHORT_REGISTER NECIoPort; // offset 5b8 + ULONG TyphoonErrorStatus; // offset 5bc + DMA_REGISTER AddressConversionRegion; // offset 5c0 + DMA_REGISTER AddressConversionMask; // offset 5c8 + DMA_REGISTER Reserved12; // offset 5d0 + DMA_REGISTER Reserved13; // offset 5d8 + DMA_REGISTER Reserved14; // offset 5e0 + DMA_REGISTER Reserved15; // offset 5e8 + DMA_REGISTER Reserved16; // offset 5f0 + DMA_REGISTER Reserved17; // offset 5f8 + USHORT PCIVenderID; // offset 600 + USHORT PCIDeviceID; // offset 602 + USHORT PCICommand; // offset 604 + USHORT PCIStatus; // offset 606 + UCHAR PCIRevisionID; // offset 608 + UCHAR PCIProgIf; // offset 609 + UCHAR PCISubClass; // offset 60a + UCHAR PCIBaseClass; // offset 60b + UCHAR PCICacheLineSize; // offset 60c + UCHAR PCILatencyTimer; // offset 60d + UCHAR PCIHeaderType; // offset 60e + UCHAR PCIBIST; // offset 60f + DMA_REGISTER Reserved18; // offset 610 + DMA_REGISTER Reserved19; // offset 618 + DMA_REGISTER Reserved20; // offset 620 + DMA_REGISTER Reserved21; // offset 628 + ULONG PCIROMBaseAddress; // offset 630 + ULONG Reserved22[2]; // offset 634 + UCHAR PCIInterruptLine; // offset 63c + UCHAR PCIInterruptPin; // offset 63d + UCHAR PCIMinimumGrant; // offset 63e + UCHAR PCIMaximumLatency; // offset 63f + PCI_ADDRESS_MASK PCIFastBackToBack[2]; // offset 640 + PCI_ADDRESS_MASK PCIBurst[2]; // offset 650 + PCI_ADDRESS_MASK PCIMemory; // offset 660 + ULONG PCIMasterRetryTimer; // offset 668 +} DMA_REGISTERS, *PDMA_REGISTERS; + +// +// Configuration Register values. +// + +#define LOAD_CLEAN_EXCLUSIVE 0x20 +#define DISABLE_EISA_MEMORY 0x10 +#define ENABLE_PROCESSOR_B 0x08 +#define MAP_PROM 0x04 + +// +// Interrupt Enable bits. +// +#define ENABLE_CHANNEL_INTERRUPTS (1 << 0) +#define ENABLE_DEVICE_INTERRUPTS (1 << 1) +#define ENABLE_EISA_INTERRUPTS (1 << 2) +#define ENABLE_TIMER_INTERRUPTS (1 << 3) +#define ENABLE_IP_INTERRUPTS (1 << 4) + +// +// Eisa Interupt Acknowledge Register values. +// + +#define EISA_NMI_VECTOR 0x8000 + +// +// DMA_NMI_SRC register bit definitions. +// + +#define NMI_SRC_MEMORY_ERROR 1 +#define NMI_SRC_R4000_ADDRESS_ERROR 2 +#define NMI_SRC_IO_CACHE_ERROR 4 +#define NMI_SRC_ADR_NMI 8 + +// +// Define DMA channel mode register structure. +// + +typedef struct _DMA_CHANNEL_MODE { + ULONG AccessTime : 3; + ULONG TransferWidth : 2; + ULONG InterruptEnable : 1; + ULONG BurstMode : 1; + ULONG Reserved1 : 25; +} DMA_CHANNEL_MODE, *PDMA_CHANNEL_MODE; + +// +// Define access time values. +// + +#define ACCESS_40NS 0x0 // 40ns access time +#define ACCESS_80NS 0x1 // 80ns access time +#define ACCESS_120NS 0x2 // 120ns access time +#define ACCESS_160NS 0x3 // 160ns access time +#define ACCESS_200NS 0x4 // 200ns access time +#define ACCESS_240NS 0x5 // 240ns access time +#define ACCESS_280NS 0x6 // 280ns access time +#define ACCESS_320NS 0x7 // 320ns access time + +// +// Define transfer width values. +// + +#define WIDTH_8BITS 0x1 // 8-bit transfer width +#define WIDTH_16BITS 0x2 // 16-bit transfer width +#define WIDTH_32BITS 0x3 // 32-bit transfer width + +// +// M001 +// Define DMA channel enable register structure. +// + +typedef struct _DMA_CHANNEL_ENABLE { + ULONG ChannelEnable : 1; + ULONG TransferDirection : 1; + ULONG Reserved1 : 6; + ULONG TerminalCount : 1; + ULONG MemoryError : 1; +// ULONG TranslationError : 1; +// ULONG Reserved2 : 21; + ULONG ParityError : 1; + ULONG MasterAbort : 1; + ULONG Reserved2 : 20; +} DMA_CHANNEL_ENABLE, *PDMA_CHANNEL_ENABLE; + +// +// M001,M002 +// define RTC structure. +// + +typedef struct _RTC_REGISTERS { + UCHAR Data; + UCHAR Index; +} RTC_REGISTERS, *PRTC_REGISTERS; + +// +// Define transfer direction values. +// + +#define DMA_READ_OP 0x0 // read from device +#define DMA_WRITE_OP 0x1 // write to device + +// +// Define translation table entry structure. +// + +typedef volatile struct _TRANSLATION_ENTRY { + ULONG PageFrame; + ULONG Fill; +} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY; + +// +// Error Type Register values +// + +#define SONIC_ADDRESS_ERROR 4 +#define SONIC_MEMORY_ERROR 0x40 +#define EISA_ADDRESS_ERROR 1 +#define EISA_MEMORY_ERROR 2 + +// +// Address Mask definitions. +// + +#define LFAR_ADDRESS_MASK 0xfffff000 +#define RFAR_ADDRESS_MASK 0x00ffffc0 +#define MFAR_ADDRESS_MASK 0x1ffffff0 + +// +// ECC Register Definitions. +// + +#define ECC_SINGLE_BIT_DP0 0x02000000 +#define ECC_SINGLE_BIT_DP1 0x20000000 +#define ECC_SINGLE_BIT ( ECC_SINGLE_BIT_DP0 | ECC_SINGLE_BIT_DP1 ) +#define ECC_DOUBLE_BIT_DP0 0x04000000 +#define ECC_DOUBLE_BIT_DP1 0x40000000 +#define ECC_DOUBLE_BIT ( ECC_DOUBLE_BIT_DP0 | ECC_DOUBLE_BIT_DP1 ) +#define ECC_MULTIPLE_BIT_DP0 0x08000000 +#define ECC_MULTIPLE_BIT_DP1 0x80000000 + +#define ECC_FORCE_DP0 0x010000 +#define ECC_FORCE_DP1 0x100000 +#define ECC_DISABLE_SINGLE_DP0 0x020000 +#define ECC_DISABLE_SINGLE_DP1 0x200000 +#define ECC_ENABLE_DP0 0x040000 +#define ECC_ENABLE_DP1 0x400000 + +// +// LED/DIAG Register Definitions. +// + +#define DIAG_NMI_SWITCH 2 + +// +// Common error bit definitions +// + +#define SINGLE_ERROR 1 +#define MULTIPLE_ERROR 2 +#define RFAR_CACHE_FLUSH 4 + +// +// M001 +// Define NMI Status/Control register structure. +// + +typedef struct _BUZZER_CONTROL { + UCHAR SpeakerGate : 1; + UCHAR SpeakerData : 1; + UCHAR Reserved1 : 3; + UCHAR SpeakerTimer : 1; + UCHAR Reserved2 : 2; +}BUZZER_CONTROL, *PBUZZER_CONTROL; + +// +// H000 +// Define PCI Interrupt Status register structure. +// + +typedef struct _STORM_PCI_INTRRUPT_STATUS{ + ULONG IntD: 1; + ULONG IntC: 1; + ULONG IntB: 1; + ULONG IntA: 1; + ULONG Perr: 1; + ULONG Serr: 1; + ULONG RetryOverflow: 1; + ULONG MasterAbort: 1; + ULONG TargetAbort: 1; + ULONG Reserved: 23; +} STORM_PCI_INTRRUPT_STATUS, *PSTORM_PCI_INTRRUPT_STATUS; + +// +// H002 +// PCI Interrupt Enable bits. +// + +#define ENABLE_TARGET_ABORT_INTERRUPTS (1 << 8) +#define ENABLE_MASTER_ABORT_INTERRUPTS (1 << 7) +#define ENABLE_RETRY_OVERFLOW_EISA_INTERRUPTS (1 << 6) +#define ENABLE_SERR_INTERRUPTS (1 << 5) +#define ENABLE_PERR_INTERRUPTS (1 << 4) + +// +// H003 +// Define MRC control register structure. +// + +typedef volatile struct _MRC_REGISTERS { + UCHAR Reserved1[256]; // offset 000 + UCHAR Interrupt; // offset 100 + UCHAR Reserved2[7]; // offset 107 + UCHAR Mode; // offset 108 + UCHAR Reserved3[39]; // offset 109 + UCHAR SoftwarePowerOff; // offset 130 + UCHAR Reserved4[15]; // offset 131 + UCHAR LEDBitControl; // offset 140 + UCHAR Reserved5[3]; // offset 141 + UCHAR SegmentLEDControl[4]; // offset 144 + UCHAR Reserved6[155]; // offset 145 + UCHAR TempEnable; // offset 1e0 + UCHAR Reserved7[31]; // offset 145 + UCHAR TempSensor; // offset 200 + UCHAR Reserved8[3583]; // offset 201 +} MRC_REGISTERS, *PMRC_REGISTERS; + + +#endif // _R94ADMA_ diff --git a/private/ntos/nthals/halr96b/mips/r94ainfo.c b/private/ntos/nthals/halr96b/mips/r94ainfo.c new file mode 100644 index 000000000..a2c59341b --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94ainfo.c @@ -0,0 +1,99 @@ +// #pragma comment(exestr, "@(#) r94ainfo.c 1.1 95/09/28 15:48:57 nec") +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation +All rights reserved. + +Module Name: + + ixinfo.c + +Abstract: + +Environment: + + Kernel mode only. + +Revision History + + A002 1995/6/17 ataka@oa2.kb.nec.co.jp + - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h + +--*/ + + +#include "halp.h" + +NTSTATUS +HalpQueryInstalledBusInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HaliQuerySystemInformation) +#pragma alloc_text(PAGE,HaliSetSystemInformation) +#endif + +NTSTATUS +HaliQuerySystemInformation( + IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + OUT PVOID Buffer, + OUT PULONG ReturnedLength + ) +{ + NTSTATUS Status; + PVOID InternalBuffer; + ULONG Length; + + PAGED_CODE(); + + Status = STATUS_SUCCESS; + *ReturnedLength = 0; + Length = 0; + + switch (InformationClass) { + case HalInstalledBusInformation: + Status = HalpQueryInstalledBusInformation ( + Buffer, + BufferSize, + ReturnedLength + ); + break; + + default: + Status = STATUS_INVALID_LEVEL; + break; + } + + // + // If non-zero Length copy data to callers buffer + // + + if (Length) { + if (BufferSize < Length) { + Length = BufferSize; + } + + *ReturnedLength = Length; + RtlCopyMemory (Buffer, InternalBuffer, Length); + } + + return Status; +} + +NTSTATUS +HaliSetSystemInformation ( + IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN PVOID Buffer + ) +{ + PAGED_CODE(); + return STATUS_INVALID_LEVEL; +} + + diff --git a/private/ntos/nthals/halr96b/mips/r94aint.h b/private/ntos/nthals/halr96b/mips/r94aint.h new file mode 100644 index 000000000..6904b9a85 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94aint.h @@ -0,0 +1,35 @@ +// #pragma comment(exestr, "@(#) r94aint.h 1.1 95/09/28 15:49:28 nec") +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + duoint.h + +Abstract: + + This module is the header file that describes hardware structure + for the interrupt source and enable registers on the DUO system. + +Author: + + Lluis Abello (lluis) 20-Apr-1993 + +Revision History: + +--*/ + +#ifndef _DUOINT_ +#define _DUOINT_ + +// +// Define Interrupt register structure. +// + +typedef struct _INTERRUPT_REGISTERS { + USHORT Fill; + USHORT Enable; +} INTERRUPT_REGISTERS, *PINTERRUPT_REGISTERS; + +#endif // _DUOINT_ diff --git a/private/ntos/nthals/halr96b/mips/r94aio.s b/private/ntos/nthals/halr96b/mips/r94aio.s new file mode 100644 index 000000000..fed2171e2 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94aio.s @@ -0,0 +1,149 @@ +// .ident "@(#) r94aio.s 1.1 95/09/28 18:36:07 nec" +//++ +// +// Copyright (c) 1994 KOBE NEC Software Corporation +// +// Module Name: +// +// r94aio.s +// +// Abstract: +// +// This module implements the system dependent kernel function to read +// and write the 64-bit register on a MIPS R4000 R94A system. +// +// Author: +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// H000 Fri Oct 7 19:57:09 JST 1994 kbnes!kisimoto +// new READ_REGISTER_DWORD +// new WRITE_REGISTER_DWORD +// +//-- + +#if defined(_R94A_) + +#include "halmips.h" + +//++ +// +// VOID +// READ_REGISTER_DWORD ( +// IN PLARGE_INTEGER RegisterAddress, +// IN PVOID Variable +// ) +// +// Routine Description: +// +// 64-bit I/O space register read function. +// +// Arguments: +// +// RegisterAddress (a0) - Supplies a pointer to the destination address of +// the move operation. +// +// Variable (a1) - Supplies a pointer to the source address of the move +// operation. +// +// Return Value: +// +// None. +// +// Destination and Source must be 8-byte aligned. +// +//-- + + LEAF_ENTRY(READ_REGISTER_DWORD) + + ldc1 f0,0(a0) // move 8-byte block + sdc1 f0,0(a1) // + + sync // synchronize read + + j ra // return + + .end READ_REGISTER_DWORD + + +//++ +// +// VOID +// WRITE_REGISTER_DWORD ( +// IN PLARGE_INTEGER RegisterAddress, +// IN PVOID Variable +// ) +// +// Routine Description: +// +// 64-bit I/O space register write function. +// +// Arguments: +// +// RegisterAddress (a0) - Supplies a pointer to the destination address of +// the move operation. +// +// Variable (a1) - Supplies a pointer to the source address of the move +// operation. +// +// Return Value: +// +// None. +// +// Destination and Source must be 8-byte aligned. +// +//-- + + LEAF_ENTRY(WRITE_REGISTER_DWORD) + + ldc1 f0,0(a1) // move 8-byte block + sdc1 f0,0(a0) // + + sync // synchronize write + + j ra // return + + .end WRITE_REGISTER_DWORD + + +//++ +// +// VOID +// HalpGetStatusRegister ( +// IN PULONG Variable +// ) +// +// Routine Description: +// +// This function returns value which is status register of R4400. +// +// Arguments: +// +// Variable (a0) - Supplies a pointer to the destination address of +// the move operation. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpGetStatusRegister) + + .set noreorder + .set noat + mfc0 t0,psr // get current processor status + nop // 1 cycle hazzard + sw t0,0(a0) // save integer registers a0 - a3 + .set at + .set reorder + + j ra // return + + .end HalpGetStatusRegister + +#endif diff --git a/private/ntos/nthals/halr96b/mips/r94anmi.s b/private/ntos/nthals/halr96b/mips/r94anmi.s new file mode 100644 index 000000000..b0f87aabb --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/r94anmi.s @@ -0,0 +1,621 @@ +/* #pragma comment(exestr, "@(#) NEC(MIPS) r94anmi.s 1.2 95/10/17 01:19:11" ) */ +// +// TITLE("R94A NMI routine") +//++ +// +// Copyright (c) 1995 NEC Corporation +// +// Module Name: +// +// r94anmi.s +// +// Abstract: +// +// This routine support for dump switch. +// +// Author: +// +// Akitoshi Kuriyama (NEC Software Kobe,Inc) +// +// Environment: +// +// Kernel mode only. +// +// R4400 based only. +// +// Revision History: +// +// kuriyama@oa2.kbnes.nec.co.jp Sun Oct 15 20:11:38 JST 1995 +// - new code for J94D (!_MRCDUMP_ _MRCPOWER_ compile option need) +// +//-- +#include "halmips.h" + + SBTTL("NMI dispatch routine") +//++ +// +// VOID +// HalpNMIDispatch ( +// VOID +// ) +// +// Routine Description: +// +// This function was called by firmware when NMI occuerd. +// +// Arguments: +// +// none. +// +// Return Value: +// +// none. +// +//-- + + LEAF_ENTRY(HalpNMIDispatch) + + .set noreorder + .set noat + +// +// Save temporary Registers for use. +// save area shoud have for every processros. +// + + li k0,0xffffc070 // get processor number. + lw k0,(k0) // + bne k0,zero,10f // + nop // fill + + la k1,HalpNMISave0 // set save address. + j 20f // + nop // fill + +10: + la k1,HalpNMISave1 // set save address. + nop // 1 cycle hazzerd + +20: + sw AT,0x0(k1) // register save. + sw v0,0x4(k1) // + sw v1,0x8(k1) // + sw a0,0xc(k1) // + sw a1,0x10(k1) // + sw a2,0x14(k1) // + sw a3,0x18(k1) // + sw t0,0x1c(k1) // + sw t1,0x20(k1) // + sw t2,0x24(k1) // + sw t3,0x28(k1) // + sw t4,0x2c(k1) // + sw t5,0x30(k1) // + sw t6,0x34(k1) // + sw t7,0x38(k1) // + sw t8,0x3c(k1) // + sw t9,0x40(k1) // + sw gp,0x44(k1) // + sw sp,0x48(k1) // + sw s8,0x4c(k1) // + sw ra,0x50(k1) // + mfc0 k0,psr // + nop // + nop // + sw k0,0x54(k1) // + nop // + mfc0 k0,cause // + nop // + nop // + sw k0,0x58(k1) // + nop // + mfc0 k0,epc // + nop // + nop // + sw k0,0x5c(k1) // + nop // + mfc0 k0,errorepc // + nop // + nop // + sw k0,0x60(k1) // + nop // + mfc0 k0,cacheerr // + nop // + nop // + sw k0,0x64(k1) // + + sdc1 f0,0x68(k1) // + +// +// Set Dump Switch Status register to tlb fixed entry +// + + li t0,4 // set index 4(hurricane register) + li t1,0x80012 << 6 // set MRC register + li t2,0x8000e << 6 // set Self-Test address + + mfc0 t3,index // save tlb registers + mfc0 t4,entryhi // + mfc0 t5,entrylo0 // + mfc0 t6,entrylo1 // + mfc0 t7,pagemask // + mtc0 t0,index // + nop + nop + nop + + tlbr // read index 4 tlb + nop + nop + nop + nop + + mfc0 t8,entrylo0 // Get entrylo0 + mfc0 t9,entrylo1 // Get entrylo1 + nop + nop + nop + or t1,t8,t1 // set MRC address + or t2,t8,t2 // set Self-test address + nop + + mtc0 t1,entrylo0 // set MRC to tlb 4 0 + mtc0 t2,entrylo1 // set Self-test to tlb 4 1 + nop // + nop // + nop // + nop // + + tlbwi // write to tlb entry + nop // + nop // + nop // + nop // + +// +// read dump status +// + +#if defined(_MRCDUMP_) + + li t1,0xffffc108 // load MRC Mode value + +#else // SELFTEST DUMP + + li t1,0xffffd000 // load Self-Test value + + li k0,0x1b // set dash + sb k0,(t1) // display led + sync + +#endif // _MRCDUMP_ + + lb k0,(t1) // load Dump switch status. + nop // + lb k0,(t1) // wait + nop // + +// +// Check dump status +// + + li t1,2 // check for dump switch + and k0,k0,t1 // + +#if defined(_MRCDUMP_) + beq k0,zero,30f // if 0 dump swith was not pressed +#else // _MRCDUMP_ + bne k0,zero,30f // if 0 dump swith was pressed +#endif // _MRCDUMP_ + nop // + +#if !defined(_MRCDUMP_) + li t1,0xffffd000 // set dump switch status address + li t2,0x1b // display LED dash + sb t2,(t1) // + sync // +#endif // not _MRCDUMP_ + +// +// enable powoff NMI +// + +#if defined(_MRCPOWER_) + li t1,0xffffc108 // + li t0,0x82 // + nop // + sb t0,(t1) // + nop // + li t0,0x80 // + nop // + sb t0,(t1) // + nop // + li t0,0x02 // + nop // + sb t0,(t1) // + nop // +#endif // _MRCPOWER_ + +// +// restore tlb 4 entry +// + + mtc0 t8,entrylo0 // restore tlb 4 0 + mtc0 t9,entrylo1 // restore tlb 4 1 + nop // + nop // + nop // + nop // + + tlbwi // write to tlb entry + nop // + nop // + nop // + nop // + +// +// restore tlb registers +// + mtc0 t3,index // + mtc0 t4,entryhi // + mtc0 t5,entrylo0 // + mtc0 t6,entrylo1 // + mtc0 t7,pagemask // + +#if !defined(_MRCDUMP_) + la k0,0xffffc5b8 // get NEC I/O port value + lb t0,(k0) // + nop // 1 cycle hazzerd + li t1,0xfd // clear dump enable bit + and t0,t0,t1 + sb t0,(k0) // set NEC I/O port value +#endif // not _MRCDUMP_ + +// +// set NMI flag 1 +// + + la t2,HalpNMIFlag // set NMI flag address + li t3,0xa0000000 // set KSEG1_BASE + or t2,t2,t3 // + li t3,1 // + sw t3,(t2) // set NMI flag 1 + +// +// set dump flag 1 +// + + la t2,HalpDumpNMIFlag // set Dump NMI flag address + li t3,0xa0000000 // set KSEG1_BASE + or t2,t2,t3 // + li t3,1 // + sw t3,(t2) // set NMI flag 1 + +// +// clear psr BEV bit +// + + mfc0 t0,psr // get psr + li t2,0xffbfffff // clear BEV bit + nop // fill + nop // fill + and t0,t0,t2 // + nop // + mtc0 t0,psr // set psr + + lw t0,0x1c(k1) // restore temporary registers + lw t1,0x20(k1) // + lw t2,0x24(k1) // + lw t3,0x28(k1) // + lw t4,0x2c(k1) // + lw t5,0x30(k1) // + lw t6,0x34(k1) // + lw t7,0x38(k1) // + lw t8,0x3c(k1) // + lw t9,0x40(k1) // + lw AT,0x0(k1) // + + eret // return to error epc + nop // errata + nop // + nop // + eret // + nop // + +30: + +// +// No Dump Switch. +// +// Check Power Switch + +#if defined(_MRCPOWER_) + li t1,0xffffc108 + nop + li t0,0x02 + nop + sb t0,(t1) + nop + +#endif // _MRCPOWER_ + + mtc0 t8,entrylo0 // restore tlb 4 + mtc0 t9,entrylo1 // restore tlb 4 + nop // + nop // + nop // + nop // + + tlbwi // write to tlb entry + nop // + nop // + nop // + nop // + + mtc0 t3,index // restore tlb registers + mtc0 t4,entryhi // + mtc0 t5,entrylo0 // + mtc0 t6,entrylo1 // + mtc0 t7,pagemask // + + +// +// set NMI flag 1 +// + la t2,HalpNMIFlag // set NMI flag address + li t3,0xa0000000 // set KSEG1_BASE + or t2,t2,t3 // + li t3,1 // + sw t3,(t2) // set NMI flag 1 + +// S003 +++ + li t1,0xffffc078 // check NMI source + lw t0,(t1) // check NMI source + nop // + beq t0,zero,40f // + nop // + li t1,0xffffc020 + nop + ldc1 f0,(t1) // clear processor invalid + nop + sdc1 f0,0x70(k1) // save processor invalid +40: +// S003 --- + + mfc0 t0,psr // get psr + li t2,0xffbfffff // clear BEV bit + nop // fill + nop // fill + and t0,t0,t2 // + nop // + mtc0 t0,psr // set psr + + lw t0,0x1c(k1) // restore temporary registers + lw t1,0x20(k1) // + lw t2,0x24(k1) // + lw t3,0x28(k1) // + lw t4,0x2c(k1) // + lw t5,0x30(k1) // + lw t6,0x34(k1) // + lw t7,0x38(k1) // + lw t8,0x3c(k1) // + lw t9,0x40(k1) // + lw AT,0x0(k1) // + ldc1 f0,0x68(k1) // + nop + + eret // return to errorepc + nop // errata + nop // + nop // + eret // + nop // + +// L001 --- + + .set at + .set reorder + + .end HalpNMIDispatch + +// Start M008 + SBTTL("Software Power Off") +//++ +// +// VOID +// HalpPowOffNMIDispatch ( +// VOID +// ) +// +// Routine Description: +// +// This function was called by firmware when NMI occuerd. +// +// Arguments: +// +// none. +// +// Return Value: +// +// none. +// +//-- + + LEAF_ENTRY(HalpPowOffNMIDispatch) + + .set noat + .set noreorder + +// +// Save temporary Registers for use. +// save area shoud have for every processros. +// + + li k0,0xffffc070 // get processor number. + lw k0,(k0) // + bne k0,zero,60f // + nop // fill + + la k1,HalpNMISave0 // set save address. + j 70f // + nop // fill + +60: + la k1,HalpNMISave1 // set save address. + nop // 1 cycle hazzerd + +70: + sw t0,0(k1) // save temporary registers + sw t1,4(k1) // + sw t2,8(k1) // + sw t3,12(k1) // + sw t4,16(k1) // + sw t5,20(k1) // + sw t6,24(k1) // + sw t7,28(k1) // + sw AT,32(k1) // + +// +// Set Power Switch Status register to tlb fixed entry +// + li t0,4 // set index 4(hurricane register) + + li t1,0x80012 << 6 // set MRC register + + mfc0 t3,index // save tlb registers + mfc0 t4,entryhi // + mfc0 t5,entrylo0 // + mfc0 t6,entrylo1 // + mfc0 t7,pagemask // + mtc0 t0,index // + nop + nop + nop + + tlbr // read index 4 tlb + nop + nop + nop + nop + + mfc0 t2,entrylo0 // set Self-test address to tlb + nop + nop + nop + or t1,t2,t1 + nop + + mtc0 t1,entrylo0 // set Self-Test to tlb 4 + nop // + nop // + nop // + nop // + + tlbwi // write to tlb entry + nop // + nop // + nop // + nop // + + li t1,0xffffc100 // load MRC Int value + + nop + lb k0,(t1) // load Interrupt status. + nop + lb k0,(t1) // wait + nop + + li t0,0x01 // set clear value + sb t0,(t1) // clear OffSw bit + + li t1,0x4 // check for OffSw switch + nop // + and k0,k0,t1 // + + beq k0,zero,80f // 0 means Power switch was not pressed + nop // + + li t1,0xffffc130 // load MRC Software PowerOff Register + + nop + + lb t0,0x1 // set PowerOff Value + +90: + sb t0,(t1) // write PowerOff bit + beq zero,zero,90b + nop + + eret + nop + nop + nop + eret + nop +80: + +// +// No Power Switch. +// + + mtc0 t2,entrylo0 // restore tlb 4 + nop // + nop // + nop // + nop // + + tlbwi // write to tlb entry + nop // + nop // + nop // + nop // + + mtc0 t3,index // restore tlb registers + mtc0 t4,entryhi // + mtc0 t5,entrylo0 // + mtc0 t6,entrylo1 // + mtc0 t7,pagemask // + + + la t2,HalpNMIFlag // set NMI flag address + li t3,0xa0000000 // set KSEG1_BASE + or t2,t2,t3 // + li t3,1 // + sw t3,(t2) // set NMI flag 1 + + lw t0,0xffffc078 // check NMI source + nop // + beq t0,zero,45f // + nop // + lw t0,0xffffc020 // clear processor invalid +45: + + mfc0 t0,psr // get psr + li t2,0xffbfffff // clear BEV bit + nop // fill + nop // fill + and t0,t0,t2 // + nop // + mtc0 t0,psr // set psr + + lw t0,0(k1) // restore temporary registers + lw t1,4(k1) // + lw t2,8(k1) // + lw t3,12(k1) // + lw t4,16(k1) // + lw t5,20(k1) // + lw t6,24(k1) // + lw t7,28(k1) // + lw AT,32(k1) // + + eret // return to errorepc + nop // errata + nop // + nop // + eret // + nop // + + .set reorder + .set at + + .end HalpPowOffNMIDispatch +// End M008 diff --git a/private/ntos/nthals/halr96b/mips/rgb525.h b/private/ntos/nthals/halr96b/mips/rgb525.h new file mode 100644 index 000000000..a4e53e09e --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/rgb525.h @@ -0,0 +1,468 @@ +// #pragma comment(exestr, "@(#) rgb525.h 1.2 95/09/28 18:38:14 nec") +/************************************************************************ + * * + * Copyright (c) 1994 3Dlabs Inc. Ltd. * + * All rights reserved * + * * + * This software and its associated documentation contains proprietary, * + * confidential and trade secret information of 3Dlabs Inc. Ltd. and * + * except as provided by written agreement with 3Dlabs Inc. Ltd. * + * * + * a) no part may be disclosed, distributed, reproduced, transmitted, * + * transcribed, stored in a retrieval system, adapted or translated * + * in any form or by any means electronic, mechanical, magnetic, * + * optical, chemical, manual or otherwise, * + * * + * and * + * * + * b) the recipient is not entitled to discover through reverse * + * engineering or reverse compiling or other such techniques or * + * processes the trade secrets contained therein or in the * + * documentation. * + * * + ************************************************************************/ + +#ifndef __RGB525_H__ +#define __RGB525_H__ + +/************************************************************************/ +/* DIRECT ACCESS REGISTERS */ +/************************************************************************/ + +/* direct registers on 64-bit boundaries */ + +#define __RGB525_PalAddrWrite 0x00 +#define __RGB525_PaletteData 0x08 +#define __RGB525_PixelMask 0x10 +#define __RGB525_PalAddrRead 0x18 +#define __RGB525_IndexLow 0x20 +#define __RGB525_IndexHigh 0x28 +#define __RGB525_IndexedData 0x30 +#define __RGB525_IndexControl 0x38 + +/************************************************************************/ +/* INDEXED REGISTERS - MISCELLANEOUS CONTROL */ +/************************************************************************/ + +#define __RGB525_MiscControlOne 0x0070 +#define __RGB525_MiscControlTwo 0x0071 +#define __RGB525_MiscControlThree 0x0072 +#define __RGB525_MiscClockControl 0x0002 +#define __RGB525_SyncControl 0x0003 +#define __RGB525_HSyncControl 0x0004 +#define __RGB525_PowerManagement 0x0005 +#define __RGB525_DACOperation 0x0006 +#define __RGB525_PaletteControl 0x0007 + +/* MiscControlOne */ + +#define RGB525_MISR_CNTL_OFF (0 << 7) +#define RGB525_MISR_CNTL_ON (1 << 7) +#define RGB525_VMSK_CNTL_OFF (0 << 6) +#define RGB525_VMSK_CNTL_ON (1 << 6) +#define RGB525_PADR_RFMT_READ_ADDR (0 << 5) +#define RGB525_PADR_RFMT_PAL_STATE (1 << 5) +#define RGB525_SENS_DSAB_ENABLE (0 << 4) +#define RGB525_SENS_DSAB_DISABLE (1 << 4) +#define RGB525_SENS_SEL_BIT3 (0 << 3) +#define RGB525_SENS_SEL_BIT7 (1 << 3) +#define RGB525_VRAM_SIZE_32 (0 << 0) +#define RGB525_VRAM_SIZE_64 (1 << 0) + +/* MiscControlTwo */ + +#define RGB525_PCLK_SEL_LCLK (0 << 6) +#define RGB525_PCLK_SEL_PLL (1 << 6) +#define RGB525_PCLK_SEL_EXT (2 << 6) +#define RGB525_INTL_MODE_DISABLE (0 << 5) +#define RGB525_INTL_MODE_ENABLE (1 << 5) +#define RGB525_BLANK_CNTL_NORMAL (0 << 4) +#define RGB525_BLANK_CNTL_BLANKED (1 << 4) +#define RGB525_COL_RES_6_BIT (0 << 2) +#define RGB525_COL_RES_8_BIT (1 << 2) +#define RGB525_PORT_SEL_VGA (0 << 0) +#define RGB525_PORT_SEL_VRAM (1 << 0) + +/* MiscControlThree */ + +#define RGB525_SWAP_RB_DISABLE (0 << 7) +#define RGB525_SWAP_RB_ENABLE (1 << 7) +#define RGB525_SWAP_WORD_31_00_FIRST (0 << 4) +#define RGB525_SWAP_WORD_63_32_FIRST (1 << 4) +#define RGB525_SWAP_NIB_07_04_FIRST (0 << 2) +#define RGB525_SWAP_NIB_03_00_FIRST (1 << 2) + +/* MiscClockControl */ + +#define RGB525_DDOTCLK_ENABLE (0 << 7) +#define RGB525_DDOTCLK_DISABLE (1 << 7) +#define RGB525_SCLK_ENABLE (0 << 6) +#define RGB525_SCLK_DISABLE (1 << 6) +#define RGB525_B24P_DDOT_DIV_PLL (0 << 5) +#define RGB525_B24P_DDOT_SCLK (1 << 5) +#define RGB525_DDOT_PLL_DIV_1 (0 << 1) +#define RGB525_DDOT_PLL_DIV_2 (1 << 1) +#define RGB525_DDOT_PLL_DIV_4 (2 << 1) +#define RGB525_DDOT_PLL_DIV_8 (3 << 1) +#define RGB525_DDOT_PLL_DIV_16 (4 << 1) +#define RGB525_PLL_DISABLE (0 << 0) +#define RGB525_PLL_ENABLE (1 << 0) + +/* SyncControl */ + +#define RGB525_DLY_CNTL_ADD (0 << 7) +#define RGB525_DLY_SYNC_NOADD (1 << 7) +#define RGB525_CSYN_INVT_DISABLE (0 << 6) +#define RGB525_CSYN_INVT_ENABLE (1 << 6) +#define RGB525_VSYN_INVT_DISABLE (0 << 5) +#define RGB525_VSYN_INVT_ENABLE (1 << 5) +#define RGB525_HSYN_INVT_DISABLE (0 << 4) +#define RGB525_HSYN_INVT_ENABLE (1 << 4) +#define RGB525_VSYN_CNTL_NORMAL (0 << 2) +#define RGB525_VSYN_CNTL_HIGH (1 << 2) +#define RGB525_VSYN_CNTL_LOW (2 << 2) +#define RGB525_VSYN_CNTL_DISABLE (3 << 2) +#define RGB525_HSYN_CNTL_NORMAL (0 << 0) +#define RGB525_HSYN_CNTL_HIGH (1 << 0) +#define RGB525_HSYN_CNTL_LOW (2 << 0) +#define RGB525_HSYN_CNTL_DISABLE (3 << 0) + +/* HSyncControl */ + +#define RGB525_HSYN_POS(n) ((n) & 0xF) + +/* PowerManagement */ + +#define RGB525_SCLK_PWR_NORMAL (0 << 4) +#define RGB525_SCLK_PWR_DISABLE (1 << 4) +#define RGB525_DDOT_PWR_NORMAL (0 << 3) +#define RGB525_DDOT_PWR_DISABLE (1 << 3) +#define RGB525_SYNC_PWR_NORMAL (0 << 2) +#define RGB525_SYNC_PWR_DISABLE (1 << 2) +#define RGB525_ICLK_PWR_NORMAL (0 << 1) +#define RGB525_ICLK_PWR_DISABLE (1 << 1) +#define RGB525_DAC_PWR_NORMAL (0 << 0) +#define RGB525_DAC_PWR_DISABLE (1 << 0) + +/* DACOperation */ + +#define RGB525_SOG_DISABLE (0 << 3) +#define RGB525_SOG_ENABLE (1 << 3) +#define RGB525_BRB_NORMAL (0 << 2) +#define RGB525_BRB_ALWAYS (1 << 2) +#define RGB525_DSR_SLOW (0 << 1) +#define RGB525_DSR_FAST (1 << 1) +#define RGB525_DPE_DISABLE (0 << 0) +#define RGB525_DPE_ENABLE (1 << 0) + +/* PaletteControl */ + +#define RGB525_6BIT_LINEAR_ENABLE (0 << 7) +#define RGB525_6BIT_LINEAR_DISABLE (1 << 7) +#define RGB525_PALETTE_PARTITION(n) ((n) & 0xF) + +/************************************************************************/ +/* INDEXED REGISTERS - PIXEL REPRESENTATION */ +/************************************************************************/ + +#define __RGB525_PixelFormat 0x000A +#define __RGB525_8BitPixelControl 0x000B +#define __RGB525_16BitPixelControl 0x000C +#define __RGB525_24BitPixelControl 0x000D +#define __RGB525_32BitPixelControl 0x000E + +/* PixelFormat */ + +#define RGB525_PIXEL_FORMAT_4_BPP (2 << 0) +#define RGB525_PIXEL_FORMAT_8_BPP (3 << 0) +#define RGB525_PIXEL_FORMAT_16_BPP (4 << 0) +#define RGB525_PIXEL_FORMAT_24_BPP (5 << 0) +#define RGB525_PIXEL_FORMAT_32_BPP (6 << 0) + +/* 8BitPixelControl */ + +#define RGB525_B8_DCOL_INDIRECT (0 << 0) +#define RGB525_B8_DCOL_DIRECT (1 << 0) + +/* 16BitPixelControl */ + +#define RGB525_B16_DCOL_INDIRECT (0 << 6) +#define RGB525_B16_DCOL_DYNAMIC (1 << 6) +#define RGB525_B16_DCOL_DIRECT (3 << 6) +#define RGB525_B16_POL_FORCES_BYPASS (0 << 5) +#define RGB525_B16_POL_FORCES_LOOKUP (1 << 5) +#define RGB525_B16_ZIB (0 << 2) +#define RGB525_B16_LINEAR (1 << 2) +#define RGB525_B16_555 (0 << 1) +#define RGB525_B16_565 (1 << 1) +#define RGB525_B16_SPARSE (0 << 0) +#define RGB525_B16_CONTIGUOUS (1 << 0) + +/* 24BitPixelControl */ + +#define RGB525_B24_DCOL_INDIRECT (0 << 0) +#define RGB525_B24_DCOL_DIRECT (1 << 0) + +/* 32BitPixelControl */ + +#define RGB525_B32_POL_FORCES_BYPASS (0 << 2) +#define RGB525_B32_POL_FORCES_LOOKUP (1 << 2) +#define RGB525_B32_DCOL_INDIRECT (0 << 0) +#define RGB525_B32_DCOL_DYNAMIC (1 << 0) +#define RGB525_B32_DCOL_DIRECT (3 << 0) + +/************************************************************************/ +/* INDEXED REGISTERS - FREQUENCY CONTROL */ +/************************************************************************/ + +#define __RGB525_PLLControlOne 0x0010 +#define __RGB525_PLLControlTwo 0x0011 +#define __RGB525_PLLRefDivCount 0x0014 + +#define __RGB525_F0 0x0020 +#define __RGB525_F1 0x0021 +#define __RGB525_F2 0x0022 +#define __RGB525_F3 0x0023 +#define __RGB525_F4 0x0024 +#define __RGB525_F5 0x0025 +#define __RGB525_F6 0x0026 +#define __RGB525_F7 0x0027 +#define __RGB525_F8 0x0028 +#define __RGB525_F9 0x0029 +#define __RGB525_F10 0x002A +#define __RGB525_F11 0x002B +#define __RGB525_F12 0x002C +#define __RGB525_F13 0x002D +#define __RGB525_F14 0x002E +#define __RGB525_F15 0x002F + +#define __RGB525_M0 0x0020 +#define __RGB525_M1 0x0022 +#define __RGB525_M2 0x0024 +#define __RGB525_M3 0x0026 +#define __RGB525_M4 0x0028 +#define __RGB525_M5 0x002A +#define __RGB525_M6 0x002C +#define __RGB525_M7 ox002E + +#define __RGB525_N0 0x0021 +#define __RGB525_N1 0x0023 +#define __RGB525_N2 0x0025 +#define __RGB525_N3 0x0027 +#define __RGB525_N4 0x0029 +#define __RGB525_N5 0x002B +#define __RGB525_N6 0x002D +#define __RGB525_N7 ox002F + +/* PLLControlOne */ + +#define RGB525_REF_SRC_REFCLK (0 << 4) +#define RGB525_REF_SRC_EXTCLK (1 << 4) +#define RGB525_PLL_EXT_FS_DIRECT (0 << 0) +#define RGB525_PLL_EXT_FS_M_N (1 << 0) +#define RGB525_PLL_INT_FS_DIRECT (2 << 0) +#define RGB525_PLL_INT_FS_M_N (3 << 0) + +/* PLLControlTwo */ + +#define RGB525_PLL_INT_FS(n) ((n) & 0xF) + +/* PLLRefDivCount */ + +#define RGB525_REF_DIV_COUNT(n) ((n) & 0x1F) + +#define RGB525_PLL_REFCLK_4_MHz (0x02) +#define RGB525_PLL_REFCLK_6_MHz (0x03) +#define RGB525_PLL_REFCLK_8_MHz (0x04) +#define RGB525_PLL_REFCLK_10_MHz (0x05) +#define RGB525_PLL_REFCLK_12_MHz (0x06) +#define RGB525_PLL_REFCLK_14_MHz (0x07) +#define RGB525_PLL_REFCLK_16_MHz (0x08) +#define RGB525_PLL_REFCLK_18_MHz (0x09) +#define RGB525_PLL_REFCLK_20_MHz (0x0A) +#define RGB525_PLL_REFCLK_22_MHz (0x0B) +#define RGB525_PLL_REFCLK_24_MHz (0x0C) +#define RGB525_PLL_REFCLK_26_MHz (0x0D) +#define RGB525_PLL_REFCLK_28_MHz (0x0E) +#define RGB525_PLL_REFCLK_30_MHz (0x0F) +#define RGB525_PLL_REFCLK_32_MHz (0x10) +#define RGB525_PLL_REFCLK_34_MHz (0x11) +#define RGB525_PLL_REFCLK_36_MHz (0x12) +#define RGB525_PLL_REFCLK_38_MHz (0x13) +#define RGB525_PLL_REFCLK_40_MHz (0x14) +#define RGB525_PLL_REFCLK_42_MHz (0x15) +#define RGB525_PLL_REFCLK_44_MHz (0x16) +#define RGB525_PLL_REFCLK_46_MHz (0x17) +#define RGB525_PLL_REFCLK_48_MHz (0x18) +#define RGB525_PLL_REFCLK_50_MHz (0x19) +#define RGB525_PLL_REFCLK_52_MHz (0x1A) +#define RGB525_PLL_REFCLK_54_MHz (0x1B) +#define RGB525_PLL_REFCLK_56_MHz (0x1C) +#define RGB525_PLL_REFCLK_58_MHz (0x1D) +#define RGB525_PLL_REFCLK_60_MHz (0x1E) +#define RGB525_PLL_REFCLK_62_MHz (0x1F) + +/* F0-F15[7:0] */ + +#define RGB525_DF(n) (((n) & 0x3) << 6) +#define RGB525_VCO_DIV_COUNT(n) ((n) & 0x3F) + +/************************************************************************/ +/* INDEXED REGISTERS - CURSOR */ +/************************************************************************/ + +#define __RGB525_CursorControl 0x0030 +#define __RGB525_CursorXLow 0x0031 +#define __RGB525_CursorXHigh 0x0032 +#define __RGB525_CursorYLow 0x0033 +#define __RGB525_CursorYHigh 0x0034 +#define __RGB525_CursorHotSpotX 0x0035 +#define __RGB525_CursorHotSpotY 0x0036 +#define __RGB525_CursorColor1Red 0x0040 +#define __RGB525_CursorColor1Green 0x0041 +#define __RGB525_CursorColor1Blue 0x0042 +#define __RGB525_CursorColor2Red 0x0043 +#define __RGB525_CursorColor2Green 0x0044 +#define __RGB525_CursorColor2Blue 0x0045 +#define __RGB525_CursorColor3Red 0x0046 +#define __RGB525_CursorColor3Green 0x0047 +#define __RGB525_CursorColor3Blue 0x0048 + +/* CursorControl */ + +#define RGB525_SMLC_PART_0 (0 << 6) +#define RGB525_SMLC_PART_1 (1 << 6) +#define RGB525_SMLC_PART_2 (2 << 6) +#define RGB525_SMLC_PART_3 (3 << 6) +#define RGB525_PIX_ORDER_RIGHT_TO_LEFT (0 << 5) +#define RGB525_PIX_ORDER_LEFT_TO_RIGHT (1 << 5) +#define RGB525_LOC_READ_LAST_WRITTEN (0 << 4) +#define RGB525_LOC_READ_ACTUAL_LOCATION (1 << 4) +#define RGB525_UPDT_CNTL_DELAYED (0 << 3) +#define RGB525_UPDT_CNTL_IMMEDIATE (1 << 3) +#define RGB525_CURSOR_SIZE_32 (0 << 2) +#define RGB525_CURSOR_SIZE_64 (1 << 2) +#define RGB525_CURSOR_MODE_OFF (0 << 0) +#define RGB525_CURSOR_MODE_3_COLOR (1 << 0) +#define RGB525_CURSOR_MODE_2_COLOR_HL (2 << 0) +#define RGB525_CURSOR_MODE_2_COLOR (3 << 0) + +/************************************************************************/ +/* INDEXED REGISTERS - BORDER COLOR */ +/************************************************************************/ + +#define __RGB525_BorderColorRed 0x0060 +#define __RGB525_BorderColorGreen 0x0061 +#define __RGB525_BorderColorBlue 0x0062 + +/************************************************************************/ +/* INDEXED REGISTERS - DIAGNOSTIC SUPPORT */ +/************************************************************************/ + +#define __RGB525_RevisionLevel 0x0000 +#define __RGB525_ProductID 0x0001 +#define __RGB525_DACSense 0x0082 +#define __RGB525_MISRRed 0x0084 +#define __RGB525_MISRGreen 0x0086 +#define __RGB525_MISRBlue 0x0088 +#define __RGB525_PLLVCODivInput 0x008E +#define __RGB525_PLLVCORefInput 0x008F +#define __RGB525_VramMaskLow 0x0090 +#define __RGB525_VramMaskHigh 0x0091 + +/* RevisionLevel */ + +#define RGB525_PRODUCT_REV_LEVEL 0xF0 + +/* ProductID */ + +#define RGB525_PRODUCT_ID_CODE 0x01 + +/************************************************************************/ +/* INDEXED REGISTERS - CURSOR ARRAY */ +/************************************************************************/ + +#define __RGB525_CursorArray 0x0100 + +/************************************************************************/ +/* DIRECT ACCESS MACROS */ +/************************************************************************/ +/* + * The pixel clock must be running to access the palette and the cursor + * array, and the timings for the microprocessor signals are specified + * in units of pixel clocks. Six clocks must be allowed for an internal + * access to complete, following a palette or cursor access. + * + * In the worst case (VGA 640x480 resolution) the pixel clock is 40 ns, + * giving a time of 280 ns for seven pixel clocks. Assuming the fastest + * host clock is 100 MHz, a delay of 28 host clocks is required. Again + * assuming that the loop below takes 3 clocks per iteration, it should + * be executed at least 10 times. + */ + +#define RGB525_DELAY \ +{ \ + volatile DWORD __rgb525_dly; \ + \ + for (__rgb525_dly = 0; __rgb525_dly < 10; __rgb525_dly++); \ +} + +/* + * All RGB525 accesses are followed by a short delay, as required by + * the AC Characteristics table in the RGB525 Databook. However, the + * text implies that non-palette or cursor-array accesses can happen + * closer together. Everything is delayed here for simplicity. + */ + +#define RGB525_ADDR(base, offset) \ +( \ +/* (DWORD) ((volatile BYTE *)(base) + (offset)) */ \ + (DWORD) ((base) + (offset)) \ +) + +#define RGB525_WRITE(dac, offset, data) \ +{ \ +/* DWORD_WRITE(RGB525_ADDR((dac),(offset)), (data)); */ \ + WRITE_REGISTER_UCHAR(RGB525_ADDR((dac),(offset)), (UCHAR)(data)); \ + RGB525_DELAY; \ +} + +#define RGB525_READ_BYTE(dac, offset, data) \ +{ \ + DWORD __rgb525_tmp; \ + \ +/* DWORD_READ(RGB525_ADDR((dac),(offset)), __rgb525_tmp); */ \ + __rgb525_tmp = READ_REGISTER_UCHAR(RGB525_ADDR((dac),(offset))); \ +/* (data) = (BYTE) (__rgb525_tmp & BYTE_MAX); */ \ + (data) = (UCHAR) (__rgb525_tmp & 0xff); \ + RGB525_DELAY; \ +} + +/************************************************************************/ +/* INDEXED ACCESS MACROS */ +/************************************************************************/ + +#define RGB525_SET_INDEX(dac, index) \ +{ \ + RGB525_WRITE((dac), __RGB525_IndexLow, (index)); \ +/* RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> BYTE_BITS); */ \ + RGB525_WRITE((dac), __RGB525_IndexHigh, (index) >> 8); \ +} + +#define RGB525_SET_REG(dac, index, data) \ +{ \ + RGB525_SET_INDEX((dac), (index)); \ + RGB525_WRITE((dac), __RGB525_IndexedData, (data)); \ +} + +#define RGB525_GET_REG(dac, index, data) \ +{ \ + RGB525_SET_INDEX((dac), (index)); \ + RGB525_READ_BYTE((dac), __RGB525_IndexedData, (data)); \ +} + +/************************************************************************/ + +#endif /* __RGB525_H__ */ + +/************************************************************************/ diff --git a/private/ntos/nthals/halr96b/mips/tga.h b/private/ntos/nthals/halr96b/mips/tga.h new file mode 100644 index 000000000..3e6257c7c --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/tga.h @@ -0,0 +1,93 @@ +// #pragma comment(exestr, "@(#) tga.h 1.1 95/09/28 18:38:49 nec") +/*++ + +Module Name: + + tga.h + +Abstract: + + This module contains the register definitions for the TGA (DEC21030) + +Author: + + T.Katoh create-data 1994/11/30 + +Revision Histort: + +--*/ + +// TGA Core Space Map offset for 8-bpp Frame Buffers + +#define TGA_REG_SPC_OFFSET 0x00100000 +#define TGA_DSP_BUF_OFFSET 0x00200000 + +// TGA register offsets, organized by functionality. + +#define PLANE_MASK 0x00000028 +#define ONE_SHOT_PIXEL_MASK 0x0000002C +#define MODE 0x00000030 +#define RASTER_OP 0x00000034 +#define DEEP 0x00000050 +#define BLK_COLOR_R0 0X00000140 +#define BLK_COLOR_R1 0X00000144 +#define H_CONT 0x00000064 +#define V_CONT 0x00000068 +#define VIDEO_BASE 0x0000006c +#define VIDEO_VALID 0x00000070 +#define RAMDAC_SETUP 0x000000C0 +#define EEPROM_WRITE 0x000001e0 +#define CLOCK 0x000001e8 +#define RAMDAC_DATA 0X000001f0 +#define COMMAND_STATUS 0x000001f8 + +// Initiate Palette Data + +#define VGA_INI_PALETTE_BLACK_R 0x00 +#define VGA_INI_PALETTE_BLACK_G 0x00 +#define VGA_INI_PALETTE_BLACK_B 0x00 +#define VGA_INI_PALETTE_RED_R 0xAA +#define VGA_INI_PALETTE_RED_G 0x00 +#define VGA_INI_PALETTE_RED_B 0x00 +#define VGA_INI_PALETTE_GREEN_R 0x00 +#define VGA_INI_PALETTE_GREEN_B 0xAA +#define VGA_INI_PALETTE_GREEN_G 0x00 +#define VGA_INI_PALETTE_YELLOW_R 0xAA +#define VGA_INI_PALETTE_YELLOW_G 0xAA +#define VGA_INI_PALETTE_YELLOW_B 0x00 +#define VGA_INI_PALETTE_BLUE_R 0x00 +#define VGA_INI_PALETTE_BLUE_G 0x00 +#define VGA_INI_PALETTE_BLUE_B 0xAA +#define VGA_INI_PALETTE_MAGENTA_R 0xAA +#define VGA_INI_PALETTE_MAGENTA_G 0x00 +#define VGA_INI_PALETTE_MAGENTA_B 0xAA +#define VGA_INI_PALETTE_CYAN_R 0x00 +#define VGA_INI_PALETTE_CYAN_G 0xAA +#define VGA_INI_PALETTE_CYAN_B 0xAA +#define VGA_INI_PALETTE_WHITE_R 0xAA +#define VGA_INI_PALETTE_WHITE_G 0xAA +#define VGA_INI_PALETTE_WHITE_B 0xAA +#define VGA_INI_PALETTE_HI_BLACK_R 0x00 +#define VGA_INI_PALETTE_HI_BLACK_G 0x00 +#define VGA_INI_PALETTE_HI_BLACK_B 0x00 +#define VGA_INI_PALETTE_HI_RED_R 0xFF +#define VGA_INI_PALETTE_HI_RED_G 0x00 +#define VGA_INI_PALETTE_HI_RED_B 0x00 +#define VGA_INI_PALETTE_HI_GREEN_R 0x00 +#define VGA_INI_PALETTE_HI_GREEN_G 0xFF +#define VGA_INI_PALETTE_HI_GREEN_B 0x00 +#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF +#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF +#define VGA_INI_PALETTE_HI_YELLOW_B 0x00 +#define VGA_INI_PALETTE_HI_BLUE_R 0x00 +#define VGA_INI_PALETTE_HI_BLUE_G 0x00 +#define VGA_INI_PALETTE_HI_BLUE_B 0xFF +#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF +#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00 +#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF +#define VGA_INI_PALETTE_HI_CYAN_R 0x00 +#define VGA_INI_PALETTE_HI_CYAN_G 0xFF +#define VGA_INI_PALETTE_HI_CYAN_B 0xFF +#define VGA_INI_PALETTE_HI_WHITE_R 0xFF +#define VGA_INI_PALETTE_HI_WHITE_G 0xFF +#define VGA_INI_PALETTE_HI_WHITE_B 0xFF diff --git a/private/ntos/nthals/halr96b/mips/x4clock.s b/private/ntos/nthals/halr96b/mips/x4clock.s new file mode 100644 index 000000000..2e3aaac3a --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/x4clock.s @@ -0,0 +1,433 @@ +// .ident "@(#) x4clock.s 1.1 95/09/28 18:39:17 nec" +// TITLE("Interval and Profile Clock Interrupts") +//++ +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// x4clock.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interval and profile clock interrupts on a MIPS R4000 system. +// +// Author: +// +// David N. Cutler (davec) 26-Apr-1991 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// M001 Fri Feb 17 17:48:03 JST 1995 kbnes!kuriyama (A) +// - Change HalpClockInterrupt0(() +// for dump switch support. +// +// S002 Tue Feb 21 21:24:13 JST 1995 kbnes!kuriyama (A) +// - use HalpNMIFlag +// +// S003 Wed Feb 22 11:18:59 JST 1995 kbnes!kuriyama (A) +// - enter kernel debugger when NMI only checked version +// +// S004 Wed Feb 22 14:25:20 JST 1995 kbnes!kuriyama (A) +// - enter kernel debugger when NMI free version +// +// S005 Sat Mar 18 20:30:05 JST 1995 kbnes!kuriyama (A) +// - nmi logic change +// +// M006 kuriyama@oa2.kb.nec.co.jp Wed Jun 28 14:16:29 JST 1995 +// - change nmi logic +// +// M007 Thu Jul 20 19:31:41 JST 1995 kbnes!kisimoto +// - Merge build 1057 +// +//-- + +#include "halmips.h" + +#if defined(_DUO_) + +#include "duodef.h" + +#endif + +#if defined(_JAZZ_) + +#include "jazzdef.h" + +#endif + +// M001 +++ +#if defined(_R94A_) + .extern HalpNMIFlag + .extern HalpNMIInterrupt + .extern HalpDumpNMIFlag //S002 +#endif //_R94A_ +// M001 --- + + SBTTL("System Clock Interrupt - Processor 0") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt and +// transfer control to the standard system routine to update the system +// time and the execution time of the current thread and process. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 +CiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +CiRa: .space 4 // saved return address +CiFrameLength: // + + NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero) + + subu sp,sp,CiFrameLength // allocate stack frame + sw ra,CiRa(sp) // save return address + + PROLOGUE_END + + .set noreorder + +// M001 +++ +#if defined(_R94A_) +// +// check if dump swich flag set. +// + + la t0,HalpNMIFlag // set NMI flag address + li t1,0xa0000000 // set KSEG1_BASE + or t0,t0,t1 + lw t1,(t0) // load NMI flag + nop + beq t1,zero,10f + nop + sw zero,(t0) + + lw t0,KdDebuggerEnabled // get address of debugger enable + nop + lbu t0,0(t0) // get debugger enable flag + nop + beq zero,t0,5f // if eq, debugger not enabled + nop + nop + beq zero,v0,40f // if eq, no breakin requested + nop + break BREAKIN_BREAKPOINT // break into the debugger + nop +5: + +// S002 +++ + la t0,HalpDumpNMIFlag // set Dump NMI flag address + li t1,0xa0000000 // set KSEG1_BASE + or t0,t0,t1 // + lw a0,(t0) // load Dump NMI flag + nop // +// S003 +++ + sw zero,(t0) // clear Dump NMI flag + nop // +// S003 --- +// S005 + lw zero,DMA_VIRTUAL_BASE + 0x58 // clear acknowledge // M006 +// S002 --- + jal HalpNMIInterrupt // jump to NMI routine + nop // +10: +#endif // _R94A_ +// M001 --- + +#if defined(_DUO_) + + lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt + +#endif + +#if defined(_JAZZ_) + + lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt + +#endif + + + .set reorder + + move a0,s8 // set address of trap frame + lw a1,HalpCurrentTimeIncrement // set current time increment + lw t0,__imp_KeUpdateSystemTime // update system time + jal t0 // + +// +// The following code is a work around for a bug in the Fusion machines +// where the clock interrupt is not dismissed by reading the acknowledge +// register. +// + +#if defined(_JAZZ_) + + .set noreorder + .set noat + mfc0 t0,cause // read the cause register + lw t1,HalpEisaControlBase // get EISA control base address + sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit + bgez t0,10f // if gez, no clock interrupt pending + li t2,0x2 // get NMI port enable bit + lb t3,0x70(t1) // save EISA NMI interrupt disable + lb t4,0x461(t1) // save EISA extended NMI status + sb zero,0x70(t1) // clear EISA NMI interrupt disable + sb t2,0x461(t1) // set EISA NMI port enable + sb zero,0x462(t1) // generate EISA NMI interrupt + sb zero,0x461(t1) // clear EISA extended NMI status + sb t2,0x461(t1) // + lb zero,0x461(t1) // synchronize clear operatin + sb t3,0x70(t1) // restore EISA NMI interupt disable + sb t4,0x461(t1) // restore EISA exteneed NMI status + lb zero,0x461(t1) // synchronize restore operation + .set at + .set reorder + +10: // + +#endif + +// +// At each clock interrupt the next time increment is moved to the current +// time increment to "pipeline" the update of the current increment at the +// correct time. If the next interval count is nonzero, then the new time +// increment is moved to the next time increment and the next interval count +// register is loaded with the specified interval count minus one (i.e., ms). +// + + lw t0,KdDebuggerEnabled // get address of debugger enable + lw t1,HalpNextIntervalCount // get next interval count + lw t2,HalpNextTimeIncrement // get the next increment value + lbu t0,0(t0) // get debugger enable flag + lw t3,HalpNewTimeIncrement // get new new time increment value + lw ra,CiRa(sp) // restore return address + or t4,t1,t0 // set interval count or debugger? + sw t2,HalpCurrentTimeIncrement // set current increment value + bne zero,t4,20f // if ne, interval change or debugger + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return + +// +// The interval count must be changed or the debugger is enabled. +// + +20: sw zero,HalpNextIntervalCount // clear next interval count + beq zero,t1,30f // if eq, not interval count change + subu t1,t1,1 // compute millisecond interval count + + .set noreorder + +#if defined(_DUO_) + + sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count + +#endif + +#if defined(_JAZZ_) + + sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count + +#endif + + .set reorder + + sw t3,HalpNextTimeIncrement // set next time increment value +30: beq zero,t0,40f // if eq, debugger not enabled + jal KdPollBreakIn // check if breakin is requested + beq zero,v0,40f // if eq, no breakin requested + li a0,DBG_STATUS_CONTROL_C // break in and send + jal DbgBreakPointWithStatus // status to debugger +40: lw ra,CiRa(sp) // restore return address + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return + + .end HalpClockInterrupt0 + + SBTTL("System Clock Interrupt - Processor N") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt +// and transfer control to the standard system routine to update the +// execution time of the current thread and process. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpClockInterrupt1) + +#if defined(_DUO_) + + lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt + move a0,s8 // set address of trap frame + lw t1,__imp_KeUpdateRunTime // update system runtime + j t1 // + +#else // M007 + + j ra // + +#endif + + .end HalpClockInterrupt1 + + SBTTL("Profile Clock Interrupt") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by the +// profile clock. Its function is to acknowledge the profile interrupt, +// compute the next compare value, update the performance counter, and +// transfer control to the standard system routine to process any active +// profiles. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpProfileInterrupt) + + .set noreorder + .set noat + mfc0 t1,count // get current count value + mfc0 t0,compare // get current comparison value + addu t1,t1,8 // factor in lost cycles + subu t1,t1,t0 // compute initial count value + mtc0 t0,compare // dismiss interrupt + mtc0 t1,count // set new count register value + .set at + .set reorder + +#if defined(NT_UP) + + la t1,HalpPerformanceCounter // get performance counter address + +#else + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + la t2,HalpPerformanceCounter // get performance counter address + lbu t1,PbNumber(t1) // get processor number + sll t1,t1,3 // compute address of performance count + addu t1,t1,t2 // + +#endif + + lw t2,LiLowPart(t1) // get low part of performance count + lw t3,LiHighPart(t1) // get high part of performance count + addu t2,t2,t0 // update low part of performance count + sw t2,LiLowPart(t1) // store low part of performance count + sltu t4,t2,t0 // generate carry into high part + addu t3,t3,t4 // update high part of performance count + sw t3,LiHighPart(t1) // store high part of performance count + move a0,s8 // set address of trap frame + lw t4,__imp_KeProfileInterrupt // process profile interrupt + j t4 // + + .end HalpProfileInterrupt + + SBTTL("Read Count Register") +//++ +// +// ULONG +// HalpReadCountRegister ( +// VOID +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register and +// returns the value. +// +// Arguments: +// +// None. +// +// Return Value: +// +// Current value of the count register. +// +//-- + + LEAF_ENTRY(HalpReadCountRegister) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + .set at + .set reorder + + j ra // return + + .end HalpReadCountRegister + + SBTTL("Write Compare Register And Clear") +//++ +// +// ULONG +// HalpWriteCompareRegisterAndClear ( +// IN ULONG Value +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register, writes +// the value of the compare register, clears the count register, and +// returns the previous value of the count register. +// +// Arguments: +// +// Value - Supplies the value written to the compare register. +// +// Return Value: +// +// Previous value of the count register. +// +//-- + + LEAF_ENTRY(HalpWriteCompareRegisterAndClear) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + mtc0 a0,compare // set compare register value + li t0,7 // set lost cycle count + mtc0 t0,count // set count register to zero + .set at + .set reorder + + j ra // return + + .end HalpWriteCompareRegisterAndClear diff --git a/private/ntos/nthals/halr96b/mips/x4tb.s b/private/ntos/nthals/halr96b/mips/x4tb.s new file mode 100644 index 000000000..be37d6677 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/x4tb.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\x4tb.s" diff --git a/private/ntos/nthals/halr96b/mips/x86bios.c b/private/ntos/nthals/halr96b/mips/x86bios.c new file mode 100644 index 000000000..68a599e80 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/x86bios.c @@ -0,0 +1,1261 @@ +// #pragma comment(exestr, "@(#) x86bios.c 1.1 95/09/28 18:40:12 nec") +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + x86bios.c + +Abstract: + + + This module implements the platform specific interface between a device + driver and the execution of x86 ROM bios code for the device. + +Author: + + David N. Cutler (davec) 17-Jun-1994 + +Environment: + + Kernel mode only. + +Revision History: + + M001 kuriyama@oa2.kb.nec.co.jp Tue Jul 18 15:45:09 JST 1995 + - add check intel based bios flag + + M002 kuriyama@oa2.kb.nec.co.jp Thu Jul 20 15:16:52 JST 1995 + - add for DPI support (NO PCI DATA structure) + + S003 kuriyama@oa2.kb.nec.co.jp Tue Aug 15 14:09:30 JST 1995 + - bug fix for canopus PowerWindows 864PCI + +--*/ + + +#define USE_BIOS_EMULATOR + + + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "xm86.h" +#include "x86new.h" + +VOID +HalpReadPCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ); + +VOID +HalpWritePCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ); + +VOID +HalpReadPCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PSHORT Buffer, + IN ULONG Offset + ); + +VOID +HalpWritePCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PSHORT Buffer, + IN ULONG Offset + ); + +// M001 +++ +VOID +HalpReadPCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +VOID +HalpWritePCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ); +// M001 --- + +// +// Define global data. +// + + +ULONG HalpX86BiosInitialized = FALSE; +ULONG HalpEnableInt10Calls = FALSE; +PVOID HalpIoMemoryBase = NULL; +PVOID HalpIoControlBase=NULL; +PUCHAR HalpRomBase = NULL; + +ULONG ROM_Length; +#define BUFFER_SIZE (64*1024) +UCHAR ROM_Buffer[BUFFER_SIZE]; + +//#define R98_PCICONFIG_START ((PULONG)(0x18ca8800 | KSEG1_BASE)) + +extern KSPIN_LOCK HalpPCIConfigLock; +BOOLEAN HalpInitX86Emulator( + VOID) + +{ + ULONG ROM_size = 0; + PHYSICAL_ADDRESS PhysAddr; + UCHAR BaseClass, SubClass, ProgIf;// M001 + USHORT Cmd,SetCmd, VendorID, DeviceID, Slot; // M002 + PUCHAR ROM_Ptr, ROM_Shadow; + ULONG i; + ULONG r; + USHORT PciDataOffset; // M001 + PCI_SLOT_NUMBER PciSlot; + UCHAR header; + KIRQL Irql; + PhysAddr.HighPart = 0x00000000; + + +#if 1 + KeInitializeSpinLock (&HalpPCIConfigLock); + //kuku + KeRaiseIrql (PROFILE_LEVEL, &Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); + + + +#if 0 //tmp 707 // M001 + // First Check ISA BIOS.Becase PCEB 0-1M Positive Decode So + // I Can See ROM Image. + // Create a mapping to ISA memory space, unless one already exists + // + + HalpIoMemoryBase= (PVOID)0x40000000; + ROM_size = 0xD0000; // Map to end of option ROM space + + // + // Look for ISA option video ROM signature + // + ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000; + HalpRomBase = ROM_Ptr; + if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) { + // + // Copy ROM to RAM. PCI Spec says you can't execute from ROM. + // ROM and video RAM sometimes can't co-exist. + // + ROM_Length = *(ROM_Ptr+2) << 9; + if (ROM_Length <= BUFFER_SIZE) { + for (i=0; i> 16) & 0xf) { + + // + // Interrupt vector/stack space. + // + + case 0x0: + if (Offset > LOW_MEMORY_SIZE) { + x86BiosScratchMemory = 0; + return (PVOID)&x86BiosScratchMemory; + + } else { + return (PVOID)(&x86BiosLowMemory[0] + Offset); + } + + // + // The memory range from 0x10000 to 0x9ffff reads as zero + // and writes are ignored. + // + + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + x86BiosScratchMemory = 0; + return (PVOID)&x86BiosScratchMemory; + + // + // The memory range from 0xa0000 to 0xdffff maps to I/O memory. + // + + case 0xa: + case 0xb: + return (PVOID)(x86BiosIoMemory + Offset + Value); + + case 0xc: + case 0xd: + return (PVOID)(HalpRomBase + Offset); + + // + // The memory range from 0x10000 to 0x9ffff reads as zero + // and writes are ignored. + // + + case 0xe: + case 0xf: + x86BiosScratchMemory = 0; + return (PVOID)&x86BiosScratchMemory; + } + + // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning. + return (PVOID)NULL; +} + + +VOID HalpCopyROMs(VOID) +{ +ULONG i; +PUCHAR ROM_Shadow; + + if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) { + HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length); +#if defined(_X86_DBG_) + DbgPrint("HalpRomBase=%0x\n",HalpRomBase); +#endif // _X86_DBG_ + for (i=0; i> 8)); + WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16)); + WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24)); + + } else { + WRITE_REGISTER_ULONG(u.Long, Value); + } + + } else { + if (((ULONG)u.Word & 0x1) != 0) { + WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value)); + WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8)); + + } else { + WRITE_REGISTER_USHORT(u.Word, (USHORT)Value); + } + } + + return; +} + +VOID +x86BiosInitializeBios ( + IN PVOID BiosIoSpace, + IN PVOID BiosIoMemory + ) + +/*++ + +Routine Description: + + This function initializes x86 BIOS emulation. + +Arguments: + + BiosIoSpace - Supplies the base address of the I/O space to be used + for BIOS emulation. + + BiosIoMemory - Supplies the base address of the I/O memory to be + used for BIOS emulation. + +Return Value: + + None. + +--*/ + +{ + + // + // Zero low memory. + // + + memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE); + + // + // Save base address of I/O memory and I/O space. + // + + x86BiosIoSpace = (ULONG)BiosIoSpace; + x86BiosIoMemory = (ULONG)BiosIoMemory; + + // + // Initialize the emulator and the BIOS. + // + + XmInitializeEmulator(0, + LOW_MEMORY_SIZE, + x86BiosReadIoSpace, + x86BiosWriteIoSpace, + x86BiosTranslateAddress); + +#if defined(_X86_DBG_) + DbgPrint("\n EMU INIT \n"); //DBGDBG +#endif // _X86_DBG_ + x86BiosInitialized = TRUE; + return; +} + +XM_STATUS +x86BiosExecuteInterrupt ( + IN UCHAR Number, + IN OUT PXM86_CONTEXT Context, + IN PVOID BiosIoSpace OPTIONAL, + IN PVOID BiosIoMemory OPTIONAL + ) + +/*++ + +Routine Description: + + This function executes an interrupt by calling the x86 emulator. + +Arguments: + + Number - Supplies the number of the interrupt that is to be emulated. + + Context - Supplies a pointer to an x86 context structure. + +Return Value: + + The emulation completion status. + +--*/ + +{ + + XM_STATUS Status; + + // + // If a new base address is specified, then set the appropriate base. + // + + if (BiosIoSpace != NULL) { + x86BiosIoSpace = (ULONG)BiosIoSpace; + } + + if (BiosIoMemory != NULL) { + x86BiosIoMemory = (ULONG)BiosIoMemory; + } + + // + // Execute the specified interrupt. + // + + Status = XmEmulateInterrupt(Number, Context); + if (Status != XM_SUCCESS) { +#if defined(_X86_DBG_) + DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status); +#endif // _X86_DBG_ + } + + return Status; +} + +XM_STATUS +x86BiosInitializeAdapter ( + IN ULONG Adapter, + IN OUT PXM86_CONTEXT Context OPTIONAL, + IN PVOID BiosIoSpace OPTIONAL, + IN PVOID BiosIoMemory OPTIONAL + ) + +/*++ + +Routine Description: + + This function initializes the adapter whose BIOS starts at the + specified 20-bit address. + +Arguments: + + Adpater - Supplies the 20-bit address of the BIOS for the adapter + to be initialized. + +Return Value: + + The emulation completion status. + +--*/ + +{ + + PUCHAR Byte; + XM86_CONTEXT State; + USHORT Offset; + USHORT Segment; + XM_STATUS Status; + +#if defined(_X86_DBG_) + DbgPrint("\n BIOS INIT \n"); //DBGDBG +#endif // _X86_DBG_ + // + // If BIOS emulation has not been initialized, then return an error. + // + + if (x86BiosInitialized == FALSE) { + return XM_EMULATOR_NOT_INITIALIZED; + } + + // + // If an emulator context is not specified, then use a default + // context. + // + + if (ARGUMENT_PRESENT(Context) == FALSE) { + State.Eax = 0; + State.Ecx = 0; + State.Edx = 0; + State.Ebx = 0; + State.Ebp = 0; + State.Esi = 0; + State.Edi = 0; + Context = &State; + } + + // + // If a new base address is specified, then set the appropriate base. + // + + if (BiosIoSpace != NULL) { + x86BiosIoSpace = (ULONG)BiosIoSpace; + } + + if (BiosIoMemory != NULL) { + x86BiosIoMemory = (ULONG)BiosIoMemory; + } + + // + // If the specified adpater is not BIOS code, then return an error. + // + + Segment = (USHORT)((Adapter >> 4) & 0xf000); + Offset = (USHORT)(Adapter & 0xffff); + Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset); + if ((*Byte++ != 0x55) || (*Byte != 0xaa)) { + return XM_ILLEGAL_CODE_SEGMENT; + } + + // + // Call the BIOS code to initialize the specified adapter. + // + + Adapter += 3; + Segment = (USHORT)((Adapter >> 4) & 0xf000); + Offset = (USHORT)(Adapter & 0xffff); +#if defined(_X86_DBG_) + DbgPrint("\n Emcall BIOS start \n"); //DBGDBG +#endif // _X86_DBG_ + Status = XmEmulateFarCall(Segment, Offset, Context); +#if defined(_X86_DBG_) + DbgPrint("\n Emcall BIOS End \n"); //DBGDBG +#endif // _X86_DBG_ + if (Status != XM_SUCCESS) { +#if defined(_X86_DBG_) + DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status); +#endif // _X86_DBG_ + } + + return Status; +} + diff --git a/private/ntos/nthals/halr96b/mips/xxcalstl.c b/private/ntos/nthals/halr96b/mips/xxcalstl.c new file mode 100644 index 000000000..991432fee --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxcalstl.c @@ -0,0 +1,302 @@ +// #pragma comment(exestr, "@(#) xxcalstl.c 1.1 95/09/28 18:40:42 nec") +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + xxcalstl.c + +Abstract: + + + This module implements the calibration of the stall execution HAL + service, computes the count rate for the profile clock, and connects + the clock and profile interrupts for a MIPS R3000 or R4000 system. + +Author: + + David N. Cutler (davec) 26-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +Modification History: + + H001 Fri Aug 25 14:21:02 1995 kbnes!kisimoto + - change scale factor down range. for 250MHz. + +--*/ + +#include "halp.h" +#include "stdio.h" + +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalpCalibrateStall) +#pragma alloc_text(INIT, HalpStallInterrupt) + +#endif + +// +// Define global data used to calibrate and stall processor execution. +// + +ULONG HalpProfileCountRate; +ULONG volatile HalpStallEnd; +ULONG HalpStallScaleFactor; +ULONG volatile HalpStallStart; + +BOOLEAN +HalpCalibrateStall ( + VOID + ) + +/*++ + +Routine Description: + + This function calibrates the stall execution HAL service and connects + the clock and profile interrupts to the appropriate NT service routines. + + N.B. This routine is only called during phase 1 initialization. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the calibration is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + + ULONG Index; + KIRQL OldIrql; + + // + // Use a range of scale factors from 50ns down to 10ns assuming a + // five instruction stall loop. + // + + for (Index = 50; Index > 0; Index -= (Index < 20 ? 1 : 10)) { + + // + // Disable all interrupts and establish calibration parameters. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Set the scale factor, stall count, starting stall count, and + // ending stall count values. + // + + PCR->StallScaleFactor = 1000 / (Index * 5); + PCR->StallExecutionCount = 0; + HalpStallStart = 0; + HalpStallEnd = 0; + + // + // Enable interrupts and stall execution. + // + + KeLowerIrql(OldIrql); + + // + // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us. + // + + KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4); + + // + // If both the starting and ending stall counts have been captured, + // then break out of loop. + // + + if ((HalpStallStart != 0) && (HalpStallEnd != 0)) { + break; + } + + } + + // + // Compute the profile interrupt rate. + // + +#if defined(R3000) + + HalpProfileCountRate = (1000 * 1000 * 10) / MAXIMUM_INCREMENT; + +#endif + +#if defined(R4000) + + HalpProfileCountRate = + HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT); + +#endif + + // + // Compute the stall execution scale factor. + // + + HalpStallScaleFactor = (HalpStallEnd - HalpStallStart + + ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10); + + if (HalpStallScaleFactor <= 0) { + HalpStallScaleFactor = 1; + } + + PCR->StallScaleFactor = HalpStallScaleFactor; + + // + // Connect the real clock interrupt routine. + // + + PCR->InterruptRoutine[CLOCK2_LEVEL] = HalpClockInterrupt0; + + // + // Write the compare register and clear the count register, and + // connect the profile interrupt. + // + +#if defined(R4000) + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); + PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt; + +#endif + + return TRUE; +} + +VOID +KeStallExecutionProcessor ( + IN ULONG MicroSeconds + ) + +/*++ + +Routine Description: + + This function stalls execution of the current processor for the specified + number of microseconds. + +Arguments: + + MicroSeconds - Supplies the number of microseconds that execution is to + be stalled. + +Return Value: + + None. + +--*/ + +{ + + ULONG Index; + + // + // Use the stall scale factor to determine the number of iterations + // the wait loop must be executed to stall the processor for the + // specified number of microseconds. + // + + Index = MicroSeconds * PCR->StallScaleFactor; + do { + PCR->StallExecutionCount += 1; + Index -= 1; + } while (Index > 0); + + return; +} + +VOID +HalpStallInterrupt ( + VOID + ) + +/*++ + +Routine Description: + + This function serves as the stall calibration interrupt service + routine. It is executed in response to system clock interrupts + during the initialization of the HAL layer. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + // + // Acknowledge the interval timer interrupt. + // + +#if defined(_DUO_) + + READ_REGISTER_ULONG(&DMA_CONTROL->TimerInterruptAcknowledge.Long); + +#else + + READ_REGISTER_ULONG(&DMA_CONTROL->IntervalTimer.Long); + +#endif + + // + // If this is the very first interrupt, then wait for the second + // interrupt before starting the timing interval. Else, if this + // the second interrupt, then capture the starting stall count + // and clear the count register on R4000 processors. Else, if this + // is the third interrupt, then capture the ending stall count and + // the ending count register on R4000 processors. Else, if this is + // the fourth or subsequent interrupt, then simply dismiss it. + // + + if ((HalpStallStart == 0) && (HalpStallEnd == 0)) { + HalpStallEnd = 1; + + } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) { + HalpStallStart = PCR->StallExecutionCount; + HalpStallEnd = 0; + +#if defined(R4000) + + HalpWriteCompareRegisterAndClear(0); + +#endif + + } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) { + HalpStallEnd = PCR->StallExecutionCount; + +#if defined(R4000) + + HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0); + +#endif + + } + + return; +} diff --git a/private/ntos/nthals/halr96b/mips/xxclock.c b/private/ntos/nthals/halr96b/mips/xxclock.c new file mode 100644 index 000000000..c7ec77df5 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxclock.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\xxclock.c" diff --git a/private/ntos/nthals/halr96b/mips/xxidle.s b/private/ntos/nthals/halr96b/mips/xxidle.s new file mode 100644 index 000000000..faf3163a9 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxidle.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\xxidle.s" diff --git a/private/ntos/nthals/halr96b/mips/xxinithl.c b/private/ntos/nthals/halr96b/mips/xxinithl.c new file mode 100644 index 000000000..11dfa3c22 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxinithl.c @@ -0,0 +1,934 @@ +/* #pragma comment(exestr, "@(#) NEC(MIPS) xxinithl.c 1.2 95/10/17 01:19:57" ) */ +/*++ + +Copyright (c) 1995 NEC Corporation +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + xxinithl.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for a + MIPS R4000 system. + +Author: + + David N. Cutler (davec) 25-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + +Modification History for NEC R94A (MIPS R4400): + + H000 Wed Sep 14 19:38:36 JST 1994 kbnes!kishimoto + - HalInitSystem() + Define global spin locks used to synchronize + various LED operations, and initialize LED spin locks. + H001 Fri Oct 14 15:03:38 JST 1994 kbnes!kishimoto + - HalInitSystem(),HalpBugCheckCallback(),HalpBusError() + Modify to read the 33-bit register. + Bacause the InvalidAddress register of R94A is 33-bits long. + And original compile errors are modified. + H002 Fri Oct 21 14:25:22 JST 1994 kbnes!kishimoto + - call HalR94aDebugPrint to display debug infomation. + A001 Mon Oct 24 17:19:06 JST 1994 ataka@oa2.kb.nec.co.jp + - Call HalpInitBusHandlers + H003 Mon Nov 21 22:01:43 1994 kbnes!kishimoto + - TEMP TEMP : + comment out HalpInitializeX86DisplayAdapter() for R94A BBM + M004 Fri Jan 06 10:53:32 JST 1995 kbnes!A.kuriyama + - HalpPrintMdl() call + H005 Mon Jan 16 02:10:42 1995 kbnes!kishimoto + - initialize PCI configuration register spin lock + M006 kuriyama@oa2.kb.nec.co.jp Fri Mar 31 17:15:35 JST 1995 + - add _IPI_LIMIT_ support + S007 kuriyama@oa2.kb.nec.co.jp Mon Apr 03 10:31:37 JST 1995 + - delete PrintMdl ( ifdef _PRINT_MDL_ ) + S008 kuriyama@oa2.kb.nec.co.jp Mon May 22 02:11:30 JST 1995 + - add support for esm + M009 kuriyama@oa2.kb.nec.co.jp Mon Jun 05 02:53:50 JST 1995 + - add search NMI interface aread + S010 kuriayam@oa2.kb.nec.co.jp Mon Jun 05 04:44:09 JST 1995 + - NMI interface bug fix + M011 kuriyama@oa2.kb.nec.co.jp Fri Jun 16 19:13:45 JST 1995 + - add support for esm Ecc 1bit/2bit error logging + M012 kuriyama@oa2.kb.nec.co.jp Thu Jun 22 10:52:21 JST 1995 + - add ecc 1bit safty flag + M013 kisimoto@oa2.kb.nec.co.jp Thu Jul 20 19:21:44 JST 1995 + - Merge build 1057 halx86 + H014 kisimoto@oa2.kb.nec.co.jp Sat Aug 12 14:28:46 1995 + - Removed IPI_LIMIT, BBMLED code, J94C definitions, + and rearrange comments. + M015 kuriyama@oa2.kb.nec.co.jp Wed Aug 23 19:32:18 JST 1995 + - add for x86bios support + H016 kisimoto@oa2.kb.nec.co.jp Tue Sep 5 20:43:22 1995 + - add initialization of spinlock to support + PCI Fast Back-to-back transfer. + M017 nishi@oa2.kb.nec.co.jp Tue Sep 18 20:43:22 1995 + - add Software Power Off, when system panic is occured +--*/ + +#include "halp.h" +/* Start M017 */ +#define HEADER_FILE +#include "kxmips.h" +/* End M017 */ + + +// +// M015 +// Define for x86bios emulator use. +// + +// PCHAR K351UseBios=NULL; +VOID HalpCopyROMs(VOID); +extern PVOID HalpIoMemoryBase; +extern PVOID HalpIoControlBase; + +typedef +VOID +(*PHALP_CONTROLLER_SETUP) ( + VOID + ); + +typedef +VOID +(*PHALP_DISPLAY_CHARACTER) ( + UCHAR + ); + +VOID +HalpDisplayINT10Setup ( +VOID); + +VOID HalpOutputCharacterINT10 ( + IN UCHAR Character ); + +VOID HalpScrollINT10 ( + IN UCHAR line + ); + +VOID HalpDisplayCharacterVGA ( + IN UCHAR Character ); + +BOOLEAN +HalpInitializeX86DisplayAdapter( + VOID + ); + +extern PHALP_DISPLAY_CHARACTER HalpDisplayCharacter; +extern PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup; + +// +// M012 +// Define Ecc safety flags +// + +#define CHECKED 1 +#define NOT_CHECKED 0 +#define RUNNING 1 +#define NOT_RUNNING 0 + +// +// M012 +// Define Ecc safety variables +// + +UCHAR HalpAnotherCheckedECC = NOT_CHECKED; +UCHAR HalpAnotherRunningECC = NOT_RUNNING; + + +// +// Define forward referenced prototypes. +// + +#if defined(_PRINT_MDL_) // M004,S007 +VOID +HalpPrintMdl ( + PLOADER_PARAMETER_BLOCK LoaderBlock + ); +#endif // _PRINT_MDL_ + +VOID +HalpSearchNMIInterface ( // M009 + PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +ULONG HalpNMIInterfaceAddress = 0; + +extern +VOID // M011 +HalpSetInitDisplayTimeStamp( + VOID + ); + +extern +ULONG // M011 +HalpEccError( + IN ULONG EccDiagnostic, + IN ULONG MemoryFailed + ); + +VOID +HalpBugCheckCallback ( + IN PVOID Buffer, + IN ULONG Length + ); + +BOOLEAN +HalpBusError ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame, + IN PVOID VirtualAddress, + IN PHYSICAL_ADDRESS PhysicalAddress + ); + +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalInitSystem) +#pragma alloc_text(INIT, HalInitializeProcessor) +#pragma alloc_text(INIT, HalStartNextProcessor) + +#endif + +// +// Define global spin locks used to synchronize various HAL operations. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; +KSPIN_LOCK HalpPCIConfigLock; // H005 +KSPIN_LOCK Ecc1bitDisableLock; // M011 +KSPIN_LOCK Ecc1bitRoutineLock; // M012 +KSPIN_LOCK HalpPCIBackToBackLock; // H016 +#if defined(_IPI_LIMIT_) +KSPIN_LOCK HalpIpiRequestLock; +#endif //_IPI_LIMIT_ + +// +// Define bug check information buffer and callback record. +// + +typedef struct _HALP_BUGCHECK_BUFFER { + ULONG FailedAddress; + ULONG DiagnosticLow; + ULONG DiagnosticHigh; +} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER; + +HALP_BUGCHECK_BUFFER HalpBugCheckBuffer; + +KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord; + +UCHAR HalpComponentId[] = "hal.dll"; + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for a + MIPS R3000 or R4000 system. + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + +{ + + ULONG FailedAddress; + PKPRCB Prcb; + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS ZeroAddress; + ULONG AddressSpace; + LARGE_INTEGER registerLarge; // H001 + + UCHAR ModeNow; // M017 + KIRQL OldIrql; // M017 + ENTRYLO Pte[2]; // M017 + + // + // Initialize the HAL components based on the phase of initialization + // and the processor number. + // + + Prcb = PCR->Prcb; + PCR->DataBusError = HalpBusError; + PCR->InstructionBusError = HalpBusError; + if ((Phase == 0) || (Prcb->Number != 0)) { + + + /* Start M017 */ + if (Prcb->Number == 0) { + + // + // for software controlled power supply. + // +#if defined(_MRCPOWER_) + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + Pte[0].PFN = MRC_TEMP_PHYSICAL_BASE >> PAGE_SHIFT; + + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + // + // set second page to global and not valid. + // + + Pte[0].C = UNCACHED_POLICY; + Pte[1].G = 1; + Pte[1].V = 0; + + // + // Map MRC using virtual address of DMA controller. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); + + // + // MRC Mode bit change to 0 ( Power Off interrupt is NMI ) + // + ModeNow = READ_REGISTER_UCHAR( + &MRC_CONTROL->Mode, + ); + + WRITE_REGISTER_UCHAR( + &MRC_CONTROL->Mode, + ModeNow & 0x02, + ); + + KeLowerIrql(OldIrql); + +#endif // _MRCPOWER_ + } + /* End M017*/ + + // + // Phase 0 initialization. + // + // N.B. Phase 0 initialization is executed on all processors. + // + // Verify that the processor block major version number conform + // to the system that is being loaded. + // + + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheck(MISMATCHED_HAL); + } + + // + // Map the fixed TB entries. + // + + HalpMapFixedTbEntries(); + + // + // If processor 0 is being initialized, then initialize various + // variables, spin locks, and the display adapter. + // + + if (Prcb->Number == 0) { + +#if 0 + // + // M013 + // Fill in handlers for APIs which this hal supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + HalRegisterBusHandler = HaliRegisterBusHandler; + HalHandlerForBus = HaliHandlerForBus; + HalHandlerForConfigSpace = HaliHandlerForConfigSpace; + HalQueryBusSlots = HaliQueryBusSlots; + HalSlotControl = HaliSlotControl; + HalCompleteSlotControl = HaliCompleteSlotControl; +#endif + + // + // Set the number of process id's and TB entries. + // + + **((PULONG *)(&KeNumberProcessIds)) = 256; + **((PULONG *)(&KeNumberTbEntries)) = 48; + + // + // Set the interval clock increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNextTimeIncrement = MAXIMUM_INCREMENT; + HalpNextIntervalCount = 0; + + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // + // M013 + // Set DMA I/O coherency attributes. + // + + KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP); + + // + // Initialize all spin locks. + // + +#if defined(_DUO_) + + KeInitializeSpinLock(&HalpBeepLock); + KeInitializeSpinLock(&HalpDisplayAdapterLock); + KeInitializeSpinLock(&HalpSystemInterruptLock); +#if defined(_IPI_LIMIT_) + KeInitializeSpinLock(&HalpIpiRequestLock); +#endif //_IPI_LIMIT_ + +#endif + + KeInitializeSpinLock(&Ecc1bitDisableLock); // M011 + KeInitializeSpinLock(&Ecc1bitRoutineLock); // M012 + KeInitializeSpinLock(&HalpPCIConfigLock); // H005 + KeInitializeSpinLock(&HalpPCIBackToBackLock); // H016 + + // + // Set address of cache error routine. + // + + KeSetCacheErrorRoutine(HalpCacheErrorRoutine); + + // + // Initialize the display adapter. + // + + // temp + +// TmpInitNvram(); + +#if DBG + printNvramData(); +#endif // DBG + + HalpInitializeDisplay0(LoaderBlock); + + // + // Allocate map register memory. + // + +#if defined(_PRINT_MDL_) + HalpPrintMdl(LoaderBlock); // M004,S007 +#endif //_PRINT_MDL + + HalpSearchNMIInterface(LoaderBlock); // M009 + + HalpAllocateMapRegisters(LoaderBlock); + + // + // Initialize and register a bug check callback record. + // + + KeInitializeCallbackRecord(&HalpCallbackRecord); + + KeRegisterBugCheckCallback(&HalpCallbackRecord, + HalpBugCheckCallback, + &HalpBugCheckBuffer, + sizeof(HALP_BUGCHECK_BUFFER), + &HalpComponentId[0]); + } + + // + // H001 + // Clear memory address error registers. + // + +#if defined(_DUO_) + +#if defined(_R94A_) + + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + FailedAddress = registerLarge.LowPart; + +#else + + FailedAddress = (ULONG)((volatile DMA_REGISTERS *)DMA_VIRTUAL_BASE)->InvalidAddress.Long; + +#endif + +#endif + + FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; // H001 + + // + // Initialize interrupts + // + + HalpInitializeInterrupts(); + + return TRUE; + + } else { + + // + // Phase 1 initialization. + // + // N.B. Phase 1 initialization is only executed on processor 0. + // + // Complete initialization of the display adapter. + // + + HalpRegisterInternalBusHandlers (); // M013 + + if (HalpInitializeDisplay1(LoaderBlock) == FALSE) { + return FALSE; + + } else { + + // + // Map I/O space, calibrate the stall execution scale factor, + // and create DMA data structures. + // + + HalpMapIoSpace(); + + HalpSetInitDisplayTimeStamp(); // S008 + + HalpCalibrateStall(); + + HalpCreateDmaStructures(); + + // + // M015 + // for x86bios emulator. bios copy + // + + HalpCopyROMs(); + + // + // Map EISA memory space so the x86 bios emulator emulator can + // initialze a video adapter in an EISA slot. + // + + ZeroAddress.QuadPart = 0; + AddressSpace = 0; + + HalTranslateBusAddress(Isa, + 0, + ZeroAddress, + &AddressSpace, + &PhysicalAddress); + + HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress, + PAGE_SIZE * 256, + FALSE); + + // + // M014 + // reset EISA io/memory base for HalCallBios() use. + // + HalpIoControlBase = HalpEisaControlBase; + HalpIoMemoryBase = HalpEisaMemoryBase; + + return TRUE; + } + } +} + +VOID +HalpBugCheckCallback ( + IN PVOID Buffer, + IN ULONG Length + ) + +/*++ + +Routine Description: + + This function is called when a bug check occurs. Its function is + to dump the state of the memory error registers into a bug check + buffer. + +Arguments: + + Buffer - Supplies a pointer to the bug check buffer. + + Length - Supplies the length of the bug check buffer in bytes. + +Return Value: + + None. + +--*/ + +{ + + PHALP_BUGCHECK_BUFFER DumpBuffer; + LARGE_INTEGER registerLarge; // H001 + + // + // Capture the failed memory address and diagnostic registers. + // + + DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer; + +#if defined(_DUO_) + +#if defined(_R94A_) // H001 + + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + DumpBuffer->DiagnosticLow = registerLarge.LowPart; + + +#else + + DumpBuffer->DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long; + +#endif + + DumpBuffer->DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart; + +#else + + DumpBuffer->DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long; + + DumpBuffer->DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long; + +#endif + + DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; + return; +} + +BOOLEAN +HalpBusError ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame, + IN PVOID VirtualAddress, + IN PHYSICAL_ADDRESS PhysicalAddress + ) + +/*++ + +Routine Description: + + This function provides the default bus error handling routine for NT. + + N.B. There is no return from this routine. + +Arguments: + + ExceptionRecord - Supplies a pointer to an exception record. + + ExceptionFrame - Supplies a pointer to an exception frame. + + TrapFrame - Supplies a pointer to a trap frame. + + VirtualAddress - Supplies the virtual address of the bus error. + + PhysicalAddress - Supplies the physical address of the bus error. + +Return Value: + + None. + +--*/ + +{ + + ULONG DiagnosticHigh; + ULONG DiagnosticLow; + ULONG FailedAddress; + LARGE_INTEGER registerLarge; // H001 + + // + // Bug check specifying the exception code, the virtual address, the + // failed memory address, and either the ECC diagnostic registers or + // the parity diagnostic registers depending on the platform. + // + +#if defined(_DUO_) + +#if !defined(_R94A_) + + DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long; + +#endif + + DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart; + +#else + + DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long; + DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long; + +#endif + + FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; + + // start M011 + { + ULONG returnValue; + KIRQL OldIrql; + + // + // Call Ecc 1bit/2bit error routine. + // if 1bit error return TRUE.(OS run continue) + // Otherwise bugcheck. + // + + if (DiagnosticHigh & 0x66000000) { + + KeRaiseIrql(HIGH_LEVEL,&OldIrql); + returnValue = HalpEccError(DiagnosticHigh, FailedAddress); + KeLowerIrql(OldIrql); + + if (returnValue == 2) { + KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff, + (ULONG)VirtualAddress, + FailedAddress, + DiagnosticLow, + DiagnosticHigh); + + return FALSE; + } + + } else { // M012 + + READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); + DiagnosticLow = registerLarge.LowPart; + + if (DiagnosticLow & 1) { + + KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff, + (ULONG)VirtualAddress, + FailedAddress, + DiagnosticLow, + DiagnosticHigh); + + return FALSE; + } + } + } + + return TRUE; + +} + +VOID +HalInitializeProcessor ( + IN ULONG Number + ) + +/*++ + +Routine Description: + + This function is called early in the initialization of the kernel + to perform platform dependent initialization for each processor + before the HAL Is fully functional. + + N.B. When this routine is called, the PCR is present but is not + fully initialized. + +Arguments: + + Number - Supplies the number of the processor to initialize. + +Return Value: + + None. + +--*/ + +{ + return; +} + +BOOLEAN +HalStartNextProcessor ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PKPROCESSOR_STATE ProcessorState + ) + +/*++ + +Routine Description: + + This function is called to start the next processor. + +Arguments: + + LoaderBlock - Supplies a pointer to the loader parameter block. + + ProcessorState - Supplies a pointer to the processor state to be + used to start the processor. + +Return Value: + + If a processor is successfully started, then a value of TRUE is + returned. Otherwise a value of FALSE is returned. If a value of + TRUE is returned, then the logical processor number is stored + in the processor control block specified by the loader block. + +--*/ + +{ + +#if defined(_DUO_) + + PRESTART_BLOCK NextRestartBlock; + ULONG Number; + PKPRCB Prcb; + + // + // If the address of the first restart parameter block is NULL, then + // the host system is a uniprocessor system running with old firmware. + // Otherwise, the host system may be a multiprocessor system if more + // than one restart block is present. + // + // N.B. The first restart parameter block must be for the boot master + // and must represent logical processor 0. + // + + NextRestartBlock = SYSTEM_BLOCK->RestartBlock; + if (NextRestartBlock == NULL) { + return FALSE; + } + + // + // Scan the restart parameter blocks for a processor that is ready, + // but not running. If a processor is found, then fill in the restart + // processor state, set the logical processor number, and set start + // in the boot status. + // + + Number = 0; + do { + if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) && + (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) { + RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE)); + NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0; + NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir; + Prcb = (PKPRCB)(LoaderBlock->Prcb); + Prcb->Number = (CCHAR)Number; + Prcb->RestartBlock = NextRestartBlock; + NextRestartBlock->BootStatus.ProcessorStart = 1; + return TRUE; + } + + Number += 1; + NextRestartBlock = NextRestartBlock->NextRestartBlock; + } while (NextRestartBlock != NULL); + +#endif + + return FALSE; +} + +VOID +HalpVerifyPrcbVersion( + VOID + ) + +/*++ + +Routine Description: + + This function ? + +Arguments: + + None. + + +Return Value: + + None. + +--*/ + +{ + + return; +} + +VOID +HalpSearchNMIInterface ( + PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + PLIST_ENTRY NextMd; + PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; + ULONG FirmwareParmanentCount = 0; + + // + // Get the lower bound of the free physical memory and the + // number of physical pages by walking the memory descriptor lists. + // + + NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; + + while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { + + MemoryDescriptor = CONTAINING_RECORD(NextMd, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if (MemoryDescriptor->MemoryType == MemoryFirmwarePermanent) { + + if (++FirmwareParmanentCount == 2) { // S010 + HalpNMIInterfaceAddress = MemoryDescriptor->BasePage << PAGE_SHIFT; +#if DBG + DbgPrint("NMI Interface was found!\n"); + DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType); + DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage); + DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount); +#endif // DBG + } +#if DBG + DbgPrint("Firmware Parmanent entry was found!\n"); + DbgPrint("MemoryType = %d ",MemoryDescriptor->MemoryType); + DbgPrint("BasePage = %010x ",MemoryDescriptor->BasePage); + DbgPrint("PageCount = %5d\n",MemoryDescriptor->PageCount); +#endif // DBG + } + NextMd = MemoryDescriptor->ListEntry.Flink; + } +} diff --git a/private/ntos/nthals/halr96b/mips/xxinitnt.c b/private/ntos/nthals/halr96b/mips/xxinitnt.c new file mode 100644 index 000000000..2b57adb0d --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxinitnt.c @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\xxinitnt.c" diff --git a/private/ntos/nthals/halr96b/mips/xxipiint.s b/private/ntos/nthals/halr96b/mips/xxipiint.s new file mode 100644 index 000000000..266246f51 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxipiint.s @@ -0,0 +1,11 @@ +// +// This file simply includes the main code from the halfxs directory after +// undef'ed NT_UP if necessary. +// + + +#if defined(NT_UP) +#undef NT_UP +#endif + +#include "..\halfxs\mips\xxipiint.s" diff --git a/private/ntos/nthals/halr96b/mips/xxmvmem.s b/private/ntos/nthals/halr96b/mips/xxmvmem.s new file mode 100644 index 000000000..1a6364214 --- /dev/null +++ b/private/ntos/nthals/halr96b/mips/xxmvmem.s @@ -0,0 +1,264 @@ +// .ident "@(#) xxmvmem.s 1.1 95/09/28 18:42:46 nec" +// +// Stolen from rtl xxmvmem.s this source can be used for r94a +// beta machine only. +// +// 1995.1.5 kbnes!A.Kuriyama +// +// +// TITLE("Compare, Move, Zero, and Fill Memory Support") +//++ +// +// Copyright (c) 1990 Microsoft Corporation +// +// Module Name: +// +// xxmvmem.s +// +// Abstract: +// +// This module implements functions to compare, move, zero, and fill +// blocks of memory. If the memory is aligned, then these functions +// are very efficient. +// +// N.B. These routines MUST preserve all floating state since they are +// frequently called from interrupt service routines that normally +// do not save or restore floating state. +// +// Author: +// +// David N. Cutler (davec) 11-Apr-1990 +// +// Environment: +// +// User or Kernel mode. +// +// Revision History: +// +//-- + +#include "halmips.h" + + SBTTL("View Memory") +//++ +// +// PVOID +// HalViewMemory ( +// IN PVOID Destination, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function zeros memory by first aligning the destination address to +// a longword boundary, and then zeroing 32-byte blocks, followed by 4-byte +// blocks, followed by any remaining bytes. +// +// Arguments: +// +// Destination (a0) - Supplies a pointer to the memory to zero. +// +// Length (a1) - Supplies the length, in bytes, of the memory to be zeroed. +// +// Return Value: +// +// The destination address is returned as the function value. +// +//-- + + LEAF_ENTRY_S(HalViewMemory, _TEXT$00) + + move a2,zero // set fill pattern + b HalpFillMemory // + + + SBTTL("Fill Memory") +//++ +// +// PVOID +// HalFillMemory ( +// IN PVOID Destination, +// IN ULONG Length, +// IN UCHAR Fill +// ) +// +// Routine Description: +// +// This function fills memory by first aligning the destination address to +// a longword boundary, and then filling 32-byte blocks, followed by 4-byte +// blocks, followed by any remaining bytes. +// +// Arguments: +// +// Destination (a0) - Supplies a pointer to the memory to fill. +// +// Length (a1) - Supplies the length, in bytes, of the memory to be filled. +// +// Fill (a2) - Supplies the fill byte. +// +// N.B. The alternate entry memset expects the length and fill arguments +// to be reversed. +// +// Return Value: +// +// The destination address is returned as the function value. +// +//-- + + ALTERNATE_ENTRY(Halmemset) + + move a3,a1 // swap length and fill arguments + move a1,a2 // + move a2,a3 // + + ALTERNATE_ENTRY(HalFillMemory) + + and a2,a2,0xff // clear excess bits + sll t0,a2,8 // duplicate fill byte + or a2,a2,t0 // generate fill word + sll t0,a2,16 // duplicate fill word + or a2,a2,t0 // generate fill longword + +// +// Fill memory with the pattern specified in register a2. +// + +HalpFillMemory: // + move v0,a0 // set return value + subu t0,zero,a0 // compute bytes until aligned + and t0,t0,0x3 // isolate residual byte count + subu t1,a1,t0 // reduce number of bytes to fill + blez t1,60f // if lez, less than 4 bytes to fill + move a1,t1 // set number of bytes to fill + beq zero,t0,10f // if eq, already aligned + lwr t5,0(a0) // fill unaligned bytes + addu a0,a0,t0 // align destination address + +// +// Check for 32-byte blocks to fill. +// + +10: and t0,a1,32 - 1 // isolate residual bytes + subu t1,a1,t0 // subtract out residual bytes + addu t2,a0,t1 // compute ending block address + beq zero,t1,40f // if eq, no 32-byte blocks to fill + move a1,t0 // set residual number of bytes + +// +// Fill 32-byte blocks. +// + +#if defined(R4000) + + and t0,a0,1 << 2 // check if destintion quadword aligned + beq zero,t0,20f // if eq, yes + lw t5,0(a0) // store destination longword + addu a0,a0,4 // align destination address + addu a1,a1,t1 // recompute bytes to fill + subu a1,a1,4 // reduce count by 4 + b 10b // + +// +// The destination is quadword aligned. +// + +20: dsll a3,a2,32 // duplcate pattern to upper 32-bits + dsrl a2,a3,32 // + or a3,a3,a2 // + dmtc1 a3,f0 // set pattern value + and t0,t1,1 << 5 // test if even number of 32-byte blocks + beq zero,t0,30f // if eq, even number of 32-byte blocks + +// +// Fill one 32-byte block. +// + + .set noreorder + ldc1 f2,0(a0) // fill 32-byte block + ldc1 f2,8(a0) // + ldc1 f2,16(a0) // + addu a0,a0,32 // advance pointer to next block + beq a0,t2,40f // if ne, no 64-byte blocks to fill + ldc1 f2,-8(a0) // + .set reorder + +// +// Fill 64-byte block. +// + + .set noreorder +30: ldc1 f2,0(a0) // fill 32-byte block + ldc1 f2,8(a0) // + ldc1 f2,16(a0) // + ldc1 f2,24(a0) // + ldc1 f2,32(a0) // + ldc1 f2,40(a0) // + ldc1 f2,48(a0) // + addu a0,a0,64 // advance pointer to next block + bne a0,t2,30b // if ne, more 32-byte blocks to fill + ldc1 f2,-8(a0) // + .set reorder + +#endif + +// +// Fill 32-byte blocks. +// + +#if defined(R3000) + + .set noreorder +20: lw a2,0(a0) // fill 32-byte block + lw a2,4(a0) // + lw a2,8(a0) // + lw a2,12(a0) // + addu a0,a0,32 // advance pointer to next block + lw a2,-4(a0) // + lw a2,-8(a0) // + lw a2,-12(a0) // + bne a0,t2,20b // if ne, more 32-byte blocks to fill + lw a2,-16(a0) // + .set reorder + +#endif + +// +// Check for 4-byte blocks to fill. +// + +40: and t0,a1,4 - 1 // isolate residual bytes + subu t1,a1,t0 // subtract out residual bytes + addu t2,a0,t1 // compute ending block address + beq zero,t1,60f // if eq, no 4-byte block to fill + move a1,t0 // set residual number of bytes + +// +// Fill 4-byte blocks. +// + + .set noreorder +50: addu a0,a0,4 // advance pointer to next block + bne a0,t2,50b // if ne, more 4-byte blocks to fill + lw t5,-4(a0) // fill 4-byte block + .set reorder + +// +// Check for 1-byte blocks to fill. +// + +60: addu t2,a0,a1 // compute ending block address + beq zero,a1,80f // if eq, no bytes to fill + +// +// Fill 1-byte blocks. +// + + .set noreorder +70: addu a0,a0,1 // advance pointer to next block + bne a0,t2,70b // if ne, more 1-byte block to fill + lb t5,-1(a0) // fill 1-byte block + .set reorder + +80: j ra // return + + .end HalViewMemory -- cgit v1.2.3