diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halr98b/mips | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halr98b/mips')
58 files changed, 35225 insertions, 0 deletions
diff --git a/private/ntos/nthals/halr98b/mips/allstart.c b/private/ntos/nthals/halr98b/mips/allstart.c new file mode 100644 index 000000000..debb7dcf6 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/allstart.c @@ -0,0 +1,412 @@ + +/*++ + +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. + +--*/ + +/* + */ + + +#include "halp.h" + +KINTERRUPT HalpEifInterrupt[R98B_MAX_CPU]; + +// +// This is Interrupt Level define. +// HalpIntLevelofIpr[HalpMachineType][Ipr] = INT X +// +UCHAR HalpIntLevelofIpr[R98_CPU_NUM_TYPE][NUMBER_OF_IPR_BIT]={ + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,5,5,5,5}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,4,4,4,4} +}; + +// +// This is Interrupt connect pattern. +// [NumberOfCpu][IPR] meas what connect cpu(Affinity But UCHAR. when use you must Cast Affinity) +// +UCHAR HalpIntConnectPattern[R98B_MAX_CPU][NUMBER_OF_IPR_BIT]={ +// At 1 Processor System +{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1, + 0,0,0x0,0x1,1,1,1,1,0,0,0,0,0,0,0,0, 0x1,0x1,0x1,0x1,0,0,0,0,0x1,0x1,0,0,0,0x1,0x1,0}, +// At 2 Processor System +// {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1, // snes kai +{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,2,2,2,2,0,0,0,2,2,2, + 0,0,0x0,0x3,1,1,1,1,0,0,0,0,0,0,0,0, 0x3,0x3,0x3,0x3,0,0,0,0,0x3,0x3,0,0,0,0x3,0x3,0}, +// At 3 Processor System +{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,4,2,2,0,0,0,2,4,4, + 0,0,0x0,0x7,1,1,1,1,0,0,0,0,0,0,0,0, 0x7,0x7,0x7,0x7,0,0,0,0,0x7,0x7,0,0,0,0x7,0x7,0}, +// At 4 Processor System +{0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,8,2,2,0,0,0,2,4,8, + 0,0,0x0,0xF,1,1,1,1,0,0,0,0,0,0,0,0, 0xF,0xF,0xF,0xF,0,0,0,0,0xf,0xf,0,0,0,0xF,0xF,0} +}; + + +extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; + +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. + +--*/ + +{ + ULONG ipr; + PULONG Vp; + ULONG NumCpu; + KIRQL OldIrql; + ULONG Value[2]; + ULONG IntNo; + + ULONG MagBuffer; + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + // + // In This Time I know Number Of CPU. + // + NumCpu = **((PULONG *)(&KeNumberProcessors)); + + // + // Number to Array Index. + // + NumCpu--; + + + for(ipr=0;ipr<64; ipr++){ + if((HalpIntConnectPattern[NumCpu][ipr] & (1 <<PCR->Number))== 0 ){ + // + // This Interrupt Connect Target CPU Not for me. So Set + // ~~~ + Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][ HalpIntLevelofIpr[HalpMachineCpu][ipr] ].Enable); + + if( ipr < 32){ + Vp[0] &= ~(0x1 << ipr); + Vp[1] &= 0xffffffff; + }else{ + Vp[0] &= 0xffffffff; + Vp[1] &= ~(0x1 << (ipr-32)); + } + + } + } + // + // Enable Interrupt at Columnbs + // At This Interrupt Mask is perfact. + // + Value[0] = (ULONG)0xFFFFFFFF; + Value[1] = (ULONG)0xFFFFFFFF; + // + // ReBuild Mask + // + for(IntNo=0 ; IntNo< 6 ;IntNo++){ + Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][IntNo].Enable); + Value[0] &= ~Vp[0]; + Value[1] &= ~Vp[1]; + + } + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + WRITE_REGISTER_ULONG( Vp++,Value[0]); + WRITE_REGISTER_ULONG( Vp, Value[1]); + + // 2CPU + // Reset Interrupt of do Mask. + // + Vp = (PULONG)&(COLUMNBS_LCNTL)->IPRR; + WRITE_REGISTER_ULONG( Vp++,Value[0]); + WRITE_REGISTER_ULONG( Vp, Value[1]); + + // + // ECC ERROR CHECK START + // +#if 1 // ECC 1bit error/Multi bit error enable + if (PCR->Number == 0) { + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ + MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ) +; + MagBuffer &= ECC_ERROR_ENABLE; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, MagBuffer ) +; + } + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ + MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ) +; + MagBuffer &= ECC_ERROR_ENABLE; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, MagBuffer ) +; + } + } +#endif + + KeLowerIrql(OldIrql); + +#if DBG + DbgPrint("All Pro 0 CPU= %x :MKR = Low = 0x%x High = 0x%x\n",PCR->Number,Value[0],Value[1]); +#endif + + + + // + // Restart all timer interrupt. because, generate interrupt for same time + // All CPU + + if (PCR->Number == 0) { + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->TCIR, + TCIR_ALL_CLOCK_RESTART| 0x000f0000); + } + + +#if 0 + // + // F/W Setup. So Never Fix. + // + if (PCR->Number == 0) { + IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRI); + DbgPrint(" PONCE_PERRI 0= 0x%x\n",IntNo); + IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRM); + DbgPrint(" PONCE_PERRM 0= 0x%x\n",IntNo); +#if 0 + // + // Ponce #0 PCI Error Eif Enable. + // Future implement. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,PONCE_PXERR_PMDER); + // + // PCI Error Eif inhibit off. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI,PONCE_PXERR_PMDER); +#else //test kbnes + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); + // + // PCI Error Eif inhibit off. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI, PONCE_PXERR_PPERM)); + + +#endif + // + // Ponce #1 PCI Error Eif Enable. + // Future implement. + // +#if 0 + + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); + // + // PCI Error Eif inhibit off. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, (PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); +#else //SNES tst + IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRI); + DbgPrint(" PONCE_PERRI 1= 0x%x\n",IntNo); + IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRM); + DbgPrint(" PONCE_PERRM 1= 0x%x\n",IntNo); + + + + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); + // + // PCI Error Eif inhibit off. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, PONCE_PXERR_PPERM)); + + +#endif + } +#endif + + // + // On phase 0 EIF_VECTOR: direct connect by hal. so early interrupt imprement!! + // After This time. Eif Vector can share with ather device( MRC Driver) + // + + KeInitializeInterrupt( + &HalpEifInterrupt[PCR->Number], + HalpHandleEif, + NULL, + NULL, + EIF_VECTOR, + (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]), + (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]), + LevelSensitive, + TRUE, + PCR->Number, + FALSE + ); + + KeConnectInterrupt( &HalpEifInterrupt[PCR->Number]); + + PCR->InterruptRoutine[UNDEFINE_TLB_VECTOR] = (PKINTERRUPT_ROUTINE)HalpIoTlbLimitOver; + + // F/W Setup. So Never Fix. + // + // + // Columnbs Error Eif and NMI Enable. + // Future implement. + // + // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK,0x0); + // + // inhibit off. + // + // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRI,0x0); + + // + // If the number of processors in the host configuration is one, + // all Interrupt connect processor 0. + // + +#if DBG + DbgPrint("SecondLevelIcacheFillSize = 0x%x\n",PCR->SecondLevelIcacheFillSize); +#endif + + return HalpConnectIoInterrupt(NumCpu); + +} + +// +// +// Which MPU X IPR Bit X Connect +// N.B +// All CPU Execute!! +// + +BOOLEAN +HalpConnectIoInterrupt( + IN ULONG NumCpu + ) +{ + PULONG IntTg; + PUCHAR Cnpttn; + UCHAR Number; + ULONG OldIntGValue; + ULONG ipr; + + + ULONG PhysicalNumber; + + Cnpttn = &HalpIntConnectPattern[NumCpu][0]; + Number = PCR->Number; + + // + // If Interrupt for me!! then do so myself. + // Ipr 44 of max device interrupt. upper 44 is ipi or clock or profile + // or eif. etc... + // + KiAcquireSpinLock(&HalpIprInterruptLock); + for(ipr=0;ipr< 43;ipr++){ + // + // BroadCast Type Implement OK!!. + // N.B + // But INT Dispatcher not Supported. + // + if(Cnpttn[ipr] & (0x1 << Number)){ + HalpResetValue[ipr].Cpu = (UCHAR)Number; + IntTg = (PULONG) &PONCE_CNTL(HalpResetValue[ipr].Ponce)->INTTG[10 - HalpResetValue[ipr].IntGResetBit]; + +#if 0 + // + // Broadcast But Imprement Not Complete. + // + // + OldIntGValue = READ_REGISTER_ULONG( IntTg ); + OldIntGValue &= 0xf0; +#else + // + // Device Interrupt Connect to 1 CPU Only. + // Not Broadcast + // + OldIntGValue = 0x0; +#endif + + PhysicalNumber=HalpLogicalCPU2PhysicalCPU[Number]; + WRITE_REGISTER_ULONG( + IntTg, + (OldIntGValue | (0x10 << PhysicalNumber)) + ); + } + } + KiReleaseSpinLock(&HalpIprInterruptLock); + // + // if eisa interrupt connect to me! + // Initialize EISA bus interrupts. + // + if(HalpResetValue[EISA_DISPATCH_VECTOR - DEVICE_VECTORS].Cpu == Number){ + HalpCreateEisaStructures(); + } + + return TRUE; + +} +// +// Default All Interrupt Disable. +// +ULONG HalpInterruptPonceMask[PONCE_MAX] = { 0x000007ff,0x000007ff,0x000007ff}; + +// +// +// This function Enable or Disable Interrupt connect to Ponce. +// +BOOLEAN +HalpInterruptFromPonce( + IN ULONG Vector, + IN ULONG Enable + ) +{ + ULONG Ponce; + ULONG IprBitNum; + + IprBitNum = Vector - DEVICE_VECTORS; //SNES + // + // Check interrupt was connected to ponce!!. + // + if( HalpResetValue[IprBitNum].IntGResetBit > INTSA0) + return FALSE; + + Ponce = HalpResetValue[IprBitNum].Ponce; + + KiAcquireSpinLock(&HalpSystemInterruptLock); + + // Bit X + // 1: Enable Interrupt + // 0: Disable Interrupt + if(Enable){ + HalpInterruptPonceMask[Ponce] &= (ULONG) ~(0x1 << + HalpResetValue[IprBitNum].IntGResetBit); + }else{ + HalpInterruptPonceMask[Ponce] |= (ULONG) (0x1 << + HalpResetValue[IprBitNum].IntGResetBit); + + } + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTM,HalpInterruptPonceMask[Ponce]); + + KiReleaseSpinLock(&HalpSystemInterruptLock); + +} diff --git a/private/ntos/nthals/halr98b/mips/cacherr.h b/private/ntos/nthals/halr98b/mips/cacherr.h new file mode 100644 index 000000000..94e009714 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/cacherr.h @@ -0,0 +1,225 @@ +// +// Error Log Offset +// + +#ifndef _CHELOG_H +#define _CHELOG_H + +// +// For R10000 +// + +#define R10_FATAL_ERR 0x00 +#define R10_NORMAL_ERR 0x80 + +#define R10_ICHE 0x80 +#define R10_DCHE 0x81 +#define R10_SCHE_2BIT 0x82 +#define R10_SYSAD_PARITY 0x83 +#define R10_CHER_IN_CHER 0x84 +#define R10_SCHE_1BIT 0x86 + +#define R10_St2 0x0a +#define R10_St3 0x0b +#define R10_ErrEPC 0x20 +#define R10_Status 0x28 +#define R10_Config 0x2c +#define R10_PRid 0x30 +#define R10_CacheEr 0x34 +#define R10_BrDiag 0x38 +#define R10_PC_Ctrl 0x40 +#define R10_PC_Count 0x44 +#define R10_p_count 0x48 +#define R10_s_count 0x4c +#define R10_CheAdd_1bit 0x50 +#define R10_CheAdd 0x54 +#define R10_TagHi 0x58 +#define R10_TagLo 0x5c +#define R10_Cache_data0_Hi 0x60 +#define R10_Cache_data0_Lo 0x64 +#define R10_Cache_data1_Hi 0x68 +#define R10_Cache_data1_Lo 0x6c +#define R10_Cache_data2_Hi 0x70 +#define R10_Cache_data2_Lo 0x74 +#define R10_Cache_data3_Hi 0x78 +#define R10_Cache_data3_Lo 0x7c +#define R10_Cache_data4_Hi 0x80 +#define R10_Cache_data4_Lo 0x84 +#define R10_Cache_data5_Hi 0x88 +#define R10_Cache_data5_Lo 0x8c +#define R10_Cache_data6_Hi 0x90 +#define R10_Cache_data6_Lo 0x94 +#define R10_Cache_data7_Hi 0x98 +#define R10_Cache_data7_Lo 0x9c +#define R10_ECC0 0xa0 +#define R10_ECC1 0xa4 +#define R10_ECC2 0xa8 +#define R10_ECC3 0xac +#define R10_ECC4 0xb0 +#define R10_ECC5 0xb4 +#define R10_ECC6 0xb8 +#define R10_ECC7 0xbc + +#define R10_BrDiag_Hi 0x38 +#define R10_BrDiag_Lo 0x3c + +/* + * R10000 CacheErr register bit structure define + */ +#define R10CHE_KIND_MASK 0xc0000000 /* Kind of Cache error */ +#define R10CHE_KIND_I 0x00000000 /* I-Cache error */ +#define R10CHE_KIND_D 0x40000000 /* D-Cache error */ +#define R10CHE_KIND_S 0x80000000 /* S-Cache error */ +#define R10CHE_KIND_Y 0xc0000000 /* System I/F error */ +#define R10CHE_EW 0x20000000 /* Duplicated cache error */ +#define R10CHE_EE 0x10000000 /* Fatal error(D/Y) */ +#define R10CHE_D_MASK 0x0c000000 /* Data aray(I/D/S/Y) */ +#define R10CHE_D_WAY0 0x04000000 /* way0 */ +#define R10CHE_D_WAY1 0x08000000 /* way1 */ +#define R10CHE_TA_MASK 0x03000000 /* Tag Address aray(I/D/S) */ +#define R10CHE_TA_WAY0 0x01000000 /* way0 */ +#define R10CHE_TA_WAY1 0x02000000 /* way1 */ +#define R10CHE_TS_MASK 0x00c00000 /* Tag State aray(I/D) */ +#define R10CHE_TS_WAY0 0x00400000 /* way0 */ +#define R10CHE_TS_WAY1 0x00800000 /* way1 */ +#define R10CHE_TM_MASK 0x00300000 /* Tag Mod aray(D) */ +#define R10CHE_TM_WAY0 0x00100000 /* way0 */ +#define R10CHE_TM_WAY1 0x00200000 /* way1 */ +#define R10CHE_SA 0x02000000 /* SysAD address parity error */ +#define R10CHE_SC 0x01000000 /* SysCmd parity error */ +#define R10CHE_SR 0x00800000 /* SysResp parity error */ +#define R10CHE_PIDX_BLK 0x00003fC0 /* Primary block index */ +#define R10CHE_PIDX_DW 0x00003ff8 /* Primary double word index */ +#define R10CHE_SIDX_BLK 0x007fffC0 /* Secondary block index */ +#define R10CHE_BLK_SHIFT 6 /* block index shift */ +#define R10CHE_DW_SHIFT 3 /* double word index shift */ + +/* + * R10000 Cache Instruction Opecode define + */ +#define IndexInvalidate_I 0x00 +#define IndexLoadTag_I 0x04 +#define IndexStoreTag_I 0x08 +#define HitInvalidate_I 0x10 +#define CacheBarrier_I 0x14 +#define IndexLoadData_I 0x18 +#define IndexStoreData_I 0x1c + +#define IndexWriteBack_D 0x01 +#define IndexLoadTag_D 0x05 +#define IndexStoreTag_D 0x09 +#define HitInvalidate_D 0x11 +#define HitWriteBack_D 0x15 +#define IndexLoadData_D 0x19 +#define IndexStoreData_D 0x1d + +#define IndexWriteBack_S 0x03 +#define IndexLoadTag_S 0x07 +#define IndexStoreTag_S 0x0b +#define HitInvalidate_S 0x13 +#define HitWriteBack_S 0x17 +#define IndexLoadData_S 0x1b +#define IndexStoreData_S 0x1f + + + +#define branchdiag $22 + +#if 0 +/* dmfc0 rt, rd */ +#define DMFC0( rt, rd ) \ + .word 0x40200000 | (rt<<16) | (rd<<11) +/* dmfc0 rt, rd */ +#define DMTC0( rt, rd ) \ + .word 0x40a00000 | (rt<<16) | (rd<<11) +/* mfpc rt, reg */ +#define MFPC( rt, reg ) \ + .word 0x4000c801 | (rt<<16) | (reg<<1) +/* mtpc rt, reg */ +#define MTPC( rt, reg ) \ + .word 0x4080c801 | (rt<<16) | (reg<<1) +/* mfps rt, reg */ +#define MFPS( rt, reg ) \ + .word 0x4000c800 | (rt<<16) | (reg<<1) +/* mtps rt, reg */ +#define MTPS( rt, reg ) \ + .word 0x4080c800 | (rt<<16) | (reg<<1) +#endif + + +// +// For R4400 +// + +#define EPC_cpu 0x0 +#define Psr_cpu 0x8 +#define CFG_cpu 0xc +#define PRID_cpu 0x10 +#define CHERR_cpu 0x14 +#define CheAdd_p 0x18 +#define CheAdd_s 0x1c +#define TagLo_p 0x20 +#define ECC_p 0x24 +#define TagLo_s 0x28 +#define ECC_s 0x2c +#define data_s 0x30 +#define Good_data_s 0x38 +#define Good_TagLo_s 0x40 +#define Good_ECC_s 0x44 +#define tag_synd_s 0x48 +#define data_synd_s 0x4c +#define xkphs_share 0x50 +//Error Code + +#define ICHE_EX 0x00 +#define ICHE_TAG 0x01 +#define ICHE_DAT 0x02 +#define ICHE_EB 0x03 +#define ICHE_UNKNOWN 0x0f + +#define DCHE_TAG_EX 0x10 +#define DCHE_TAG_CLEAN 0x11 +#define DCHE_TAG_DIRTY 0x12 +#define DCHE_TAG_UNKNOW 0x13 +#define DCHE_DAT_EX 0x14 +#define DCHE_DAT_DIRTY 0x16 +#define DCHE_UNKNOWN 0x1f + +#define SCHE_TAG_1BIT 0x20 +#define SCHE_TAG_2BIT 0x21 +#define SCHE_TAG_UNKNOW 0x23 +#define SCHE_DAT_EX 0x24 +#define SCHE_DAT_INV 0x25 +#define SCHE_DAT_1BIT 0x26 +#define SCHE_DAT_2BIT_C 0x27 +#define SCHE_DAT_2BIT_D 0x28 +#define SCHE_DAT_UNKNOW 0x29 +#define SCHE_UNKNOWN 0x2f + +#define SYSAD_PARITY 0x30 +// REG MASK + +#define CHERR_ER 0x80000000 +#define CHERR_EC 0x40000000 +#define CHERR_ED 0x20000000 +#define CHERR_ET 0x10000000 +#define CHERR_ES 0x08000000 +#define CHERR_EE 0x04000000 +#define CHERR_EB 0x02000000 +#define CHERR_EI 0x01000000 +#define CHERR_EW 0x00800000 +#define CHERR_SIDX 0x0003fff8 +#define CHERR_SIDX2 0x0003fff8 +#define CHERR_PIDX 0x00000007 + +#define R4CT_PSTAT_MASK 0x000000c0 +#define R4CT_PSTAT_DRE 0x000000c0 +#define R4CT_PTAG_MASK 0xffffff00 +#define R4CT_SSTAT_MASK 0x00001c00 +#define R4CT_SSTAT_DRE 0x00001400 +#define R4CT_SSTAT_INV 0x00000000 +#define R4CT_STAG_MASK 0xffffe000 + +#define CHERR_PSHF 12 + +#endif /* _CHELOG_H */ diff --git a/private/ntos/nthals/halr98b/mips/cacherr.s b/private/ntos/nthals/halr98b/mips/cacherr.s new file mode 100644 index 000000000..bcb23554f --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/cacherr.s @@ -0,0 +1,1435 @@ +// "@(#) NEC cacherr.s 1.2 94/10/17 11:02:44" +// TITLE("Cache Error Handling") +//++ +// +// Copyright (c) 1993-1994 Microsoft Corporation +// +// Module Name: +// +// cacherr.s +// +// Abstract: +// +// This module implements cache error handling. It is entered in KSEG1 +// directly from the cache error vector wiht ERL set in the processor +// state. +// +// N.B. All the code in this routine MUST run in KSEG1 and reference +// data only in KSEG1 until which time as any cache errors have +// been corrected. +// +// N.B. This routine is NOT COMPLETE. All cache errors result in a +// soft reset. +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" +#include "cacherr.h" + +// +// Define local save area for register state. +// + + .data +SavedAt:.space 4 // saved integer register at - a3 +SavedV0:.space 4 // +SavedV1:.space 4 // +SavedA0:.space 4 // +SavedA1:.space 4 // +SavedA2:.space 4 // +SavedA3:.space 4 // + + SBTTL("Cache Error Handling") +//++ +// +// VOID +// HalpCacheErrorRoutine ( +// VOID +// ) +// +// Routine Description: +// +// This function is entered from the cache error vector executing +// in KSEG1. If the error is a single bit ECC error in the second +// level data cache or the error is in the primary instruction cache, +// then the error is corrected and execution is continued. Otherwise, +// a fatal system error has occured and control is transfered to the +// soft reset vector. +// +// N.B. No state has been saved when this routine is entered. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpCacheErrorRoutine) + +// +// Save volatile registers needed to fix cache error. +// + + .set noreorder + .set noat +//K001 +// la k0,SavedAt // get address of register save area +// li k1,KSEG1_BASE // convert address of KSEG1 address +// or k0,k0,k1 // +// sw AT,0(k0) // save registers AT - a3 +// sw v0,4(k0) // +// sw v1,8(k0) // +// sw a0,12(k0) // +// sw a1,16(k0) // +// sw a2,20(k0) // + li k1,0xb9800310 // Get CPU# + lw k0,0x0(k1) + li k1,0x0f000000 + and k0,k0,k1 + srl k0,k0,24 + li k1,0x4 + sub k0,k0,k1 + mtc0 k0,lladdr + nop + nop + nop + nop + li k1,0xd + sll k0,k0,k1 + la k1,HalpCacheErrorStack + add k0,k0,k1 + add k0,k0,0x2000 + li k1,KSEG1_BASE + or k0,k0,k1 + subu k0,k0,TrapFrameLength +#if !defined(NT_40) + sw sp,TrIntSp(k0) // save integer register sp + move sp,k0 // set new stack pointer + cfc1 k1,fsr // get floating status register + sw gp,TrIntGp(sp) // save integer register gp + sw s8,TrIntS8(sp) // save integer register s8 + sw k1,TrFsr(sp) // save current FSR + mfc0 k0,psr + nop + nop + nop + sw k0,TrPsr(sp) // save processor state + sw ra,TrIntRa(sp) // save integer register ra + move s8,sp + sw AT,TrIntAt(s8) // save assembler temporary register + sw v0,TrIntV0(s8) // save integer register v0 + sw v1,TrIntV1(s8) // save integer register v1 + sw a0,TrIntA0(s8) // save integer registers a0 - a3 + sw a1,TrIntA1(s8) // + sw a2,TrIntA2(s8) // + sw a3,TrIntA3(s8) // + sw t0,TrIntT0(s8) // save integer registers t0 - t2 + sw t1,TrIntT1(s8) // + sw t2,TrIntT2(s8) // + sw t3,TrIntT3(s8) // save integer register t3 - t9 + sw t4,TrIntT4(s8) // + sw t5,TrIntT5(s8) // + sw t6,TrIntT6(s8) // + sw t7,TrIntT7(s8) // + sw t8,TrIntT8(s8) // + sw t9,TrIntT9(s8) // + mflo t3 // get multiplier/quotient lo and hi + mfhi t4 // + sw t3,TrIntLo(s8) // save multiplier/quotient lo and hi + sw t4,TrIntHi(s8) // + mfc0 a2,errorepc + nop + nop + nop + sw a2,TrFir(s8) // save exception PC +#else + sd sp,TrXIntSp(k0) // save integer register sp + move sp,k0 // set new stack pointer + cfc1 k1,fsr // get floating status register + sd gp,TrXIntGp(sp) // save integer register gp + sd s8,TrXIntS8(sp) // save integer register s8 + sw k1,TrFsr(sp) // save current FSR + mfc0 k0,psr + nop + nop + nop + sw k0,TrPsr(sp) // save processor state + sd ra,TrXIntRa(sp) // save integer register ra + move s8,sp + sd AT,TrXIntAt(s8) // save assembler temporary register + sd v0,TrXIntV0(s8) // save integer register v0 + sd v1,TrXIntV1(s8) // save integer register v1 + sd a0,TrXIntA0(s8) // save integer registers a0 - a3 + sd a1,TrXIntA1(s8) // + sd a2,TrXIntA2(s8) // + sd a3,TrXIntA3(s8) // + sd t0,TrXIntT0(s8) // save integer registers t0 - t2 + sd t1,TrXIntT1(s8) // + sd t2,TrXIntT2(s8) // + sd t3,TrXIntT3(s8) // save integer register t3 - t7 + sd t4,TrXIntT4(s8) // + sd t5,TrXIntT5(s8) // + sd t6,TrXIntT6(s8) // + sd t7,TrXIntT7(s8) // + sd s0,TrXIntS0(s8) // save integer registers s0 - s7 + sd s1,TrXIntS1(s8) // + sd s2,TrXIntS2(s8) // + sd s3,TrXIntS3(s8) // + sd s4,TrXIntS4(s8) // + sd s5,TrXIntS5(s8) // + sd s6,TrXIntS6(s8) // + sd s7,TrXIntS7(s8) // + sd t8,TrXIntT8(s8) // save integer registers t8 - t9 + sd t9,TrXIntT9(s8) // + mflo t3 // get multiplier/quotient lo and hi + mfhi t4 // + sd t3,TrXIntLo(s8) // save multiplier/quotient lo and hi + sd t4,TrXIntHi(s8) // + mfc0 a2,errorepc + nop + nop + nop + sw a2,TrFir(s8) // save exception PC + +#endif + move a3,k0 + +// +// Get the current processor state and cache error register, and check +// if the error can be corrected. +// + + mfc0 a0,lladdr + nop + nop + nop + li t1,0x1 // Log Format For FW + sll t3,t1,a0 + li t1,0xb9800388 // NVRAM enable + li t0,0x00040000 + sw t0,0x0(t1) + li t0,0xbf09fd64 // NVRAM log For FW + lw t1,0x0(t0) + or t3,t1,t3 + sb t3,0x0(t0) +#if 0 + li t1,0xb9800388 // NVRAM disable + li t0,0x04040000 + sw t0,0x0(t1) +#endif + mfc0 a1,cacheerr // get cache error state + nop + nop + nop + la t1,HalpCacheErrorHwLog + li t2,KSEG1_BASE + or t1,t1,t2 +// +// Check CPU +// + +// li a1,0x00000000 + + mfc0 t2,prid + nop + nop + nop + nop + and t2,t2,0xff00 // isolate processor id + xor t2,t2,0x0900 // check if r10000 processor + beq zero,t2,t5clog // if eq, r10000 processor + + + +// +// R4400 log +// + + addi t2,t1,0x20 + .set at + .set reorder + +// +// ****** temp ****** +// +// The following code is temporary and will be removed when full cache +// error support is included. +// +// ****** temp ****** +// +// K001 For cacheErrorLog + +// jal HalpCacheErrorLog +// nop +// +// b SoftReset // ****** all error soft rest +/******************************** + * cache error routine + * + * v0 = return code (return value) + * + * a0 = log field address (argument) + * a1 = error code address (argument) + * a2 = TagLo reg + * a3 = ECC reg + * t0 = cache virtual address + * t1 = Cache error reg + * t2 = d-cache virtual address for s-cache + * t3 = xkphs address + * t4 - t7 temprary data + * t8 = a2(TagLo) save + * t9 = return address + ********************************/ +//LEAF(che_log) + + .set noreorder +// DMFC0 (T8, D_ERROREPC) + move v1,a0 // CPU # + + move a0,t2 // Data addr + move t2,a1 + move a1,t1 // Header addr + move t1,t2 // CacheError REg + move t8,a2 // Error Epc +// mfc0 t7, C0_SR + move t7,a3 // PSR + mfc0 t6, config + mfc0 t5, prid +// Log + sw t8,EPC_cpu(a0) + sw t7,Psr_cpu(a0) + sw t6,CFG_cpu(a0) + sw t5,PRID_cpu(a0) + sw t1,CHERR_cpu(a0) +// mfc0 t1, C0_CACHEERR +// or t4, t7, (SR_DE | SR_KX | SR_ERL) + or t4,t7,(0x1<<PSR_DE) + mtc0 t4, psr + nop + nop + nop + .set reorder + + and t4, t1, CHERR_EE # sysad parity error? + bnez t4, sysad_log + + and t4, t1, CHERR_EC # primary cache error? + bnez t4, sche_log + + and t4, t1, CHERR_ER # p-inst cache error? + bnez t4, dche_log + +/* + * primary instruction cache parity error + */ + and t0, t1, CHERR_PIDX # K1(p) address +// sll t0, t0,CHERR_PSHFT +// sll t0, t0,12 + and t4, t1, CHERR_SIDX2 + or t0, t4 + or t0, KSEG0_BASE + + .set noreorder + cache 4, 0(t0) # I-cache index load tag + nop + nop + nop + mfc0 a2, taglo + mfc0 a3, ecc + .set reorder + + sw t0, CheAdd_p(a0) # save cache address + sw a2, TagLo_p(a0) # save TagLo + sw a3, ECC_p(a0) # save ECC + + and t4, t1, CHERR_ES # external reference? + bnez t4, iche_log_ex # then degrade error + + and t4, t1, CHERR_EB # also occured data error? + bnez t4, iche_log_eb # then fatal error + + and t4, t1, CHERR_ET # tag error? + bnez t4, iche_log_tag # then fatal error + + and t4, t1, CHERR_ED # data error? + bnez t4, iche_log_dat # then degrade error + +// li t4, FATAL_ERR # else fatal error +// sw t4, (a1) + li v0, ICHE_UNKNOWN + j iche_log_end + +iche_log_dat: +// # li t4, RECOVER_ERR +// # sw t4, (a1) + li v0, ICHE_DAT + j iche_log_end + +iche_log_tag: +// # li t4, FATAL_ERR +// # sw t4, (a1) + li v0, ICHE_TAG + j iche_log_end + +iche_log_eb: +// li t4, FATAL_ERR + sw t4, (a1) + li v0, ICHE_EB + j iche_log_end + +iche_log_ex: +// # li t4, RECOVER_ERR +// # sw t4, (a1) + li v0, ICHE_EX + +iche_log_end: + .set noreorder + mtc0 zero,taglo + nop + cache 8, 0(t0) //# I-cache index store tag(invalid) + cache 20,0(t0) //# I-cache fill + cache 8, 0(t0) //# I-cache index store tag(invalid) + .set reorder + j che_log_end + +/* + * primary data cache parity error + */ +dche_log: + and t0, t1, CHERR_SIDX2 //# K1(p) address + or t0, KSEG0_BASE + +dche_log_loop: + .set noreorder + cache 5, 0(t0) //# D-cache index load tag + nop + nop + nop + mfc0 a2, taglo + mfc0 a3, ecc + .set reorder + + sw t0, CheAdd_p(a0) //# save cache address + sw a2, TagLo_p(a0) //# save TagLo + sw a3, ECC_p(a0) //# save ECC + + and t4, t1, CHERR_ET //# tag error? + beqz t4, dche_log_dat //# else data error +//# +//# Tag field error +//# + jal tag_parity_chk //# check tag parity + bnez v0, dche_tag_parity + + add t0, 0x1000 //# check next PIDX + bltu t0, 0x80004000, dche_log_loop + //# less than 16K then loop +// li t4, FATAL_ERR # else fatal error +// sw t4, (a1) + li v0, DCHE_TAG_UNKNOW + j che_log_end + +dche_tag_parity: + and t4, t1, CHERR_ES //# external reference? + bnez t4, dche_tag_ex //# then fatal error + + and t4, a2, R4CT_PSTAT_MASK //# dirty? + beq t4, R4CT_PSTAT_DRE, dche_tag_dirty + beqz t4, dche_tag_clean + + and t4, a2, R4CT_PTAG_MASK //# k1(s) address + sll t4, 4 + and t5, t1, CHERR_SIDX2 + or t4, t5 + and t4, CHERR_SIDX + or t4, KSEG0_BASE + + .set noreorder + cache 7, 0(t4) //# S-cache index load tag + nop + nop + nop + mfc0 t5, taglo + mfc0 t6, ecc + .set reorder + + sw t4, CheAdd_s(a0) //# save cache address + sw t5, TagLo_s(a0) //# save TagLo + sw t6, ECC_s(a0) //# save ECC + + and t7, t5, R4CT_SSTAT_MASK //# dirty? + beq t7, R4CT_SSTAT_DRE, dche_tag_dirty + +dche_tag_clean: +// li t4, RECOVER_ERR +// sw t4, (a1) + li v0, DCHE_TAG_CLEAN + j dche_log_end + +dche_tag_dirty: +// li t4, FATAL_ERR +// sw t4, (a1) + li v0, DCHE_TAG_DIRTY + j dche_log_end + +dche_tag_ex: +// li t4, FATAL_ERR +// sw t4, (a1) + li v0, DCHE_TAG_EX + j dche_log_end + + //# + //# Data field error +// # +dche_log_dat: + and t4, t1, CHERR_ED //# DATA error? + bnez t4, dche_dat //# then data error + +// li t4, FATAL_ERR //# else fatal error +// sw t4, (a1) + li v0, DCHE_UNKNOWN + j che_log_end + +dche_dat: + and t4, t1, CHERR_ES //# external reference? + beqz t4, dche_dat_chk //# else data error check + +// li t4, FATAL_ERR //# then fatal error +// sw t4, (a1) + li v0, DCHE_DAT_EX + j che_log_end + +dche_dat_chk: +/* For NT + and t4, a2, R4CT_PSTAT_MASK //# invalid? + beqz t4, dche_dat_next + + move t8, a2 //# save TagLo + + and t3, a2, R4CT_PTAG_MASK //# xkphs cached address + DSLL32 (T3, T3, 0) + DSRL (T3, T3, 28) + and t4, t1, CHERR_SIDX2 + or t3, t4 + li t4, XKPHYSEGMENT_HI_CCS + DSLL32 (T4, T4, 0) + or t3, t4 + + LD (A2, 0, T3) # load erronious data + SD (T3, xkphs_share, A0) + SD (A2, data_s, A0) + + # jal dat_parity_chk # check data parity + move a2, t8 # resotore TagLo + # bnez v0, dche_dat_parity + + .set noreorder + cache 1, 0(t0) # D-cache index writevack invalidate + lw zero, (t0) # D-cache dummy load + mtc0 zero, C0_TAGLO + nop + cache 9, 0(t0) # D-cache index store tag(invalid) + .set reorder + +dche_dat_next: + add t0, 0x1000 # check next PIDX + bltu t0, 0x80004000, dche_log_loop + # less than 16K then loop + + li t4, FATAL_ERR # all D-cache error is fatal + sw t4, (a1) +*/ + li v0, DCHE_DAT_DIRTY + j che_log_end + +/* comment out 1993.11.12 + + li t4, FATAL_ERR # else fatal error + sw t4, (a1) + li v0, DCHE_DAT_UNKNOW + j che_log_end + +dche_dat_parity: + and t4, a2, R4CT_PSTAT_MASK # dirty? + beq t4, R4CT_PSTAT_DRE, dche_dat_dirty + bnez t4, dche_dat_dirty + +dche_dat_clean: + li t4, RECOVER_ERR + sw t4, (a1) + li v0, DCHE_DAT_CLEAN + j dche_log_end + +dche_dat_dirty: + li t4, FATAL_ERR + sw t4, (a1) + li v0, DCHE_DAT_DIRTY +*/ + +dche_log_end: + .set noreorder + mtc0 zero,taglo + nop + cache 9, 0(t0) # D-cache index store tag(invalid) + lw zero, (t0) # D-cache dummy load + cache 9, 0(t0) # D-cache index store tag(invalid) + .set reorder + + j che_log_end + +/* + * secondary cache error + */ +sche_log: + and t2, t1, CHERR_PIDX # K1(p) address +// sll t2, t2,CHERR_PSHFT + sll t2, t2,12 + and t4, t1, CHERR_SIDX2 + or t2, t4 + or t2, KSEG0_BASE + sw t2, CheAdd_p(a0) # save cache address + + and t4, t1, CHERR_EI # store miss error? + beqz t4, sche_log_tag # else tag error + + .set noreorder + mtc0 zero, taglo + nop + cache 9, 0(t2) # D-cache index store tag(invalid) + .set reorder + +sche_log_tag: + and t0, t1, CHERR_SIDX # K1(s) address + or t0, KSEG0_BASE + + .set noreorder + cache 7, 0(t0) # S-cache index load tag + nop + nop + nop + mfc0 a2, taglo + mfc0 a3, ecc + .set reorder + + sw t0, CheAdd_s(a0) # save cache address + sw a2, TagLo_s(a0) # save TagLo + sw a3, ECC_s(a0) # save ECC + + and t4, t1, CHERR_ET # tag error? + beqz t4, sche_log_dat # else data error + +// # +// # Tag field error +// # + move k0,v1 + jal tag_ecc_chk //# check tag ecc + sw v1, tag_synd_s(a0) + move v1,k0 + sw a2, Good_TagLo_s(a0) + beq v0, SCHE_TAG_1BIT, sche_tag_1bit + beq v0, SCHE_TAG_UNKNOW, sche_tag_noerr + +sche_tag_2bit: + and t2, ~63 # 64byte boundary + .set noreorder + mtc0 zero, taglo + nop + cache 9, 0(t2) # D-cache index store tag(invalid) + cache 9, 16(t2) + cache 9, 32(t2) + cache 9, 48(t2) + cache 11, 0(t0) # S-cache index store tag(invalid) + .set reorder + +// li t4, FATAL_ERR + j che_log_end + +sche_tag_1bit: + .set noreorder + mtc0 a2, taglo + nop + cache 11, 0(t0) # S-cache index store tag(modify) + .set reorder + +sche_tag_noerr: + and t4, t1, CHERR_ED # data error? + beqz t4, che_log_end # else end + +sche_log_dat: + and t4, t1, CHERR_ED # data error? + bnez t4, sche_dat_0 + +// li t4, FATAL_ERR # else fatal error +// sw t4, (a1) + li v0, SCHE_UNKNOWN + j che_log_end + +sche_dat_0: + and t4, t1, CHERR_ES # external reference? +// *tmp* +// beqz t4, sche_dat_1 + +// li t4, FATAL_ERR # then fatal error +// sw t4, (a1) +// li v0, SCHE_DAT_EX + li v0, SCHE_DAT_UNKNOW + j sche_log_end +/* +sche_dat_1: + and t4, a2, R4CT_SSTAT_MASK # dirty? + bne t4, R4CT_SSTAT_INV, sche_dat_chk + + li t4, FATAL_ERR # then fatal error + sw t4, (a1) + li v0, SCHE_DAT_INV + j sche_log_end + +sche_dat_chk: + move t8, a2 # save TagLo + + and t3, a2, R4CT_STAG_MASK # xkphs cached address + DSLL32 (T3, T3, 0) + DSRL (T3, T3, 28) + and t4, t1, CHERR_SIDX + or t3, t4 + li t4, XKPHYSEGMENT_HI_CCS + DSLL32 (T4, T4, 0) + or t3, t4 + + LD (A2, 0, T3) # load erronious data + SD (T3, xkphs_share, A0) + SD (A2, data_s, A0) + jal dat_ecc_chk # check data ecc + + sw v1, data_synd_s(a0) + SD (A2, Good_data_s, A0) + sw a3, Good_ECC_s(a0) + move v1, a2 # save good data + move a2, t8 # resotore TagLo + beq v0, SCHE_DAT_2BIT_C, sche_dat_2bit + beq v0, SCHE_DAT_UNKNOW, sche_dat_unknown + + SD (V1, 0, T3) # modified data + j sche_log_end + +sche_dat_2bit: + and t4, a2, R4CT_SSTAT_MASK # dirty? + beq t4, R4CT_SSTAT_DRE, sche_dat_dirty + +sche_dat_clean: + lw zero, (t0) # dummy read + + li t4, RECOVER_ERR + sw t4, (a1) + j sche_log_end + +sche_dat_dirty: + li v0, SCHE_DAT_2BIT_D + SD (V1, 0, T3) # rewrite error data + +sche_dat_unknown: + li t4, FATAL_ERR + sw t4, (a1) +*/ +sche_log_end: + and t2, ~63 # 64byte boundary + + .set noreorder + cache 1, 0(t2) # D-cache index write back invalidate + cache 1, 16(t2) + cache 1, 32(t2) + cache 1, 48(t2) + cache 3, 0(t0) # S-cache index write back invalidate + .set reorder + + j che_log_end + +/* + * System address data parity error + */ +sysad_log: +// li t4, FATAL_ERR +// sw t4, (a1) + li v0, SYSAD_PARITY + +che_log_end: +//For Log Function areg + move t0,a0 + move a0,v1 +/* lw a2,EPC_cpu(t0) + lw a1,CHERR_cpu(t0) +*/ + move a2,v0 + j HalpCacheErrorLog +//tmp lw t5, Status(a0) # load Status +/* + .set noreorder + mfc0 t4, cacheerr + mtc0 t5, psr + nop + nop + .set reorder + +// tmp + and t4, CHERR_EW # cache error in chelog? + beqz t4, che_log_end2 + + li t4, FATAL_ERR + sw t4, (a1) + li v0, CHER_IN_CHER + +che_log_end2: + j t9 # return +*/ +// END(che_log) + +// +// R10000 log +// + +t5clog: +// Get Log data. + .set noreorder + + move v1,a0 + move a0,t1 # a0 = data address + + move t8,a2 # t8 = ErrorEpc + move t7,a3 # t7 = Status + mfc0 t6,config # t6 = Config + mfc0 t5,prid # t5 = Prid + move t1,a1 # t1 = cache error state + + or t4,t7,( 1 << PSR_ERL ) + mtc0 t4,psr + dmfc0 t3,branchdiag +// mfps t2,$0 +// mfpc t0,$0 + move t2,zero + move t0,zero + + .set reorder + +// Set log data. + sw t8,R10_ErrEPC(a0) # save ErrEPC + sw t7,R10_Status(a0) # save Status + sw t6,R10_Config(a0) # save Config + sw t5,R10_PRid(a0) # save Prid + sw t1,R10_CacheEr(a0) # save CacheErr + sw t3,R10_BrDiag_Hi(a0) # save BranchDiag + srl t4,t3,16 + srl t4,t4,16 + sw t4,R10_BrDiag_Lo(a0) + sw t2,R10_PC_Ctrl(a0) # save PC Control + sw t0,R10_PC_Count(a0) # save PC Count + + li t0,KSEG0_BASE # t0 = cache address + + li t4,R10CHE_KIND_MASK + and t4,t1,t4 + +// I-cache error + li v0,R10_ICHE + li t5,R10CHE_KIND_I + beq t4,t5,t5_iche_log # I-cache parity error? + +// D-cache error + li v0,R10_DCHE + li t5,R10CHE_KIND_D + beq t4,t5,t5_dche_log # D-cache parity error? + +// S-cache error + li v0,R10_SCHE_2BIT + li t5,R10CHE_KIND_S + beq t4,t5,t5_sche_log # S-cache ECC error? + +// SysAd error + li v0,R10_SYSAD_PARITY +// li t4,R10_FATAL_ERR +// sw t4,(a1) + and t4,t1,(R10CHE_SA | R10CHE_SC | R10CHE_SR) + bne t4,zero,t5_log_end # Sys I/F fatal error + + +t5_sche_log: +// Make cache addr + and t4,t1,R10CHE_SIDX_BLK + or t0,t4 + and t4,t1,(R10CHE_D_WAY1 | R10CHE_TA_WAY1) + sne t4,0 + or t0,t4 # t0 = cache way address + +// TagHi & TagLo + .set noreorder + cache IndexLoadTag_S, 0(t0) # load tag + mfc0 t4,taghi + mfc0 t5,taglo + .set reorder + + sw t0,R10_CheAdd(a0) # save cache address + sw t4,R10_TagHi(a0) # save TagHi + sw t5,R10_TagLo(a0) # save TagLo + +// Cache data & ECC + addu t3,t0,64 # t3 = cacne address increment + addu t7,a0,64 # t7 = data save address increment + addu t8,a0,32 # t8 = ECC save address increment + +load_Scache_loop: + subu t3,8 # new cache address + subu t7,8 # new data save address + subu t8,4 # new ECC save address + + .set noreorder + cache IndexLoadData_S,0(t3) # load data + mfc0 t4,taghi + mfc0 t5,taglo + mfc0 t6,ecc + .set reorder + + sw t4,R10_Cache_data0_Hi(t7) # save data high + sw t5,R10_Cache_data0_Lo(t7) # save data low + sw t6,R10_ECC0(t8) # save ECC + + bne t3,t0,load_Scache_loop # 8 times + + .set noreorder + cache IndexWriteBack_S,0(t0) + .set reorder + +// li t4,R10_FATAL_ERR +// sw t4,(a1) + + j t5_log_end + + +// I-cache +t5_iche_log: +// Make cache addr + and t4, t1, R10CHE_PIDX_BLK + or t0, t4 + and t4, t1, (R10CHE_D_WAY1 | R10CHE_TA_WAY1 | R10CHE_TS_WAY1) + sne t4, 0 + or t0, t4 # t0 = cache way address + +// TagHi & TagLo + .set noreorder + cache IndexLoadTag_I, 0(t0) # load tag + mfc0 t4,taghi + mfc0 t5,taglo + .set reorder + + sw t0,R10_CheAdd(a0) # save cache address + sw t4,R10_TagHi(a0) # save TagHi + sw t5,R10_TagLo(a0) # save TagLo + +// Cache data & ECC + addu t3,t0,64 # t3 = cacne address increment + addu t7,a0,64 # t7 = data save address increment + addu t8,a0,32 # t8 = ECC save address increment + +load_Icache_loop: + subu t3,4 # new cache address + subu t7,4 # new data save address + subu t8,2 # new ECC save address + + .set noreorder + cache IndexLoadData_I,0(t3) # load data + mfc0 t4,taghi + mfc0 t5,taglo + mfc0 t6,ecc + .set reorder + + sw t5,R10_Cache_data0_Hi(t7) # save data low + sll t4,8 + or t6,t4 + sh t6,R10_ECC0(t8) # save ECC + + bne t3,t0,load_Icache_loop # 16 times + +// Cache invalidate + .set noreorder + cache IndexInvalidate_I, 0(t0) + .set reorder + +// li t4,NORMAL_ERR +// sw t4,(a1) + + j t5_log_end + + +// D-cache +t5_dche_log: +// Make cache addr + and t4,t1,R10CHE_PIDX_DW + or t0,t4 + and t4,t1,(R10CHE_D_WAY1|R10CHE_TA_WAY1|R10CHE_TS_WAY1|R10CHE_TM_WAY1) + sne t4,0 + or t0,t4 # t0 = cache way address + +// TagHi & TagLo + .set noreorder + cache IndexLoadTag_D,0(t0) # load tag + mfc0 t4,taghi + mfc0 t5,taglo + .set reorder + + sw t0,R10_CheAdd(a0) # save cache address + sw t4,R10_TagHi(a0) # save TagHi + sw t5,R10_TagLo(a0) # save TagLo + +// Cache data & ECC + and t0,0xffffffe1 # 32 bytes boundary block + addu t3,t0,32 # t3 = cacne address increment + addu t7,a0,64 # t7 = data save address increment + addu t8,a0,32 # t8 = ECC save address increment + +load_Dcache_loop: + subu t3,4 # new cache address + subu t7,8 # new data save address + subu t8,4 # new ECC save address + + .set noreorder + cache IndexLoadData_D,0(t3) # load data + mfc0 t5,taglo + mfc0 t6,ecc + .set reorder + + sw t5,R10_Cache_data0_Lo(t7) # save data low + sw t6,R10_ECC0(t8) # save ECC + + bne t3,t0,load_Dcache_loop # 8 times + + .set noreorder + cache IndexWriteBack_D,0(t0) + .set reorder + +// li t4,FATAL_ERR +// sw t4,(a1) + +t5_log_end: + .set noreorder + + lw t5,R10_Status(a0) # save Status + mfc0 t4,cacheerr + mtc0 t5,psr + nop + nop + + .set reorder + + and t4,R10CHE_EW # cache error in chelog? + beqz t4,t5_che_log_end + + li v0,R10_CHER_IN_CHER +// li t4,FATAL_ERR +// sw t4,(a1) + +t5_che_log_end: + + move a1,a0 + move a2,v0 + move a0,v1 + j HalpCacheErrorLog + + .end HalpCacheErrorRoutine + + +/********************************* + * cache psued failure + * + * a0 = error code (argument) + ********************************/ +/* +//LEAF(psued_che) + + LEAF_ENTRY(psude_che) + + .set noreorder + li t0, PSUED_ADDRESS # error address + lw t1, (t0) + mfc0 t4, psr # save SR + sw t1, (t0) + li t6, 1 + or t5, t4, (SR_CE | SR_DE) + mtc0 t6, ecc # ECC error + mtc0 t5, psr # set CE,DE bit + .set reorder + + beqz a0, sche_yellow + li t1, 0xbadfaced + sw t1,(t0) # D-cache parity error + j psued_end + +sche_yellow: + .set noreorder + cache 1, (t0) # S-cache 2bit error + nop +psued_end: + mtc0 C0_SR,t4 # restore sr + j ra + nop + .set reorder + + END(psued_che) +*/ + + .set at + .set reorder + +// +// ****** temp ****** +/********************************* + * 32bit tag parity check + * + * v0 = return code (return value) + * 0 -- no error + * 1 -- error + * + * a0 = log field address (argument) : not used and not broken + * a1 = error code address (argument) : not used and not broken + * a2 = check data (argument) + * t0 = cache virtual address : not used and not broken + * t1 = Cache error reg : not used and not broken + * t2 = TagLo reg : not used and not broken + * t3 = ECC reg : not used and not broken + * t4 - t7 temprary data + ********************************/ +LEAF_ENTRY(tag_parity_chk) + .set reorder + li t4, 1 # target check bit + move v0, zero # Hparity bit and return value + +ptag_chk_loop: + and t5, a2, t4 + sne t5, 0 + xor v0, t5 # calcurate parity + sll t4, 1 + bnez t4, ptag_chk_loop # loop 31 times + j ra + +// END(tag_parity_chk) + .end tag_parity_chk + +/********************************* + * 64bit data parity check + * + * v0 = return code (return value) + * 0 -- no error + * 1 -- error + * + * a0 = log field address (argument) : not used and not broken + * a1 = error code address (argument) : not used and not broken + * a2 = 64bit data (argument) + * a3 = 8bit check data (argument) + * t0 = cache virtual address : not used and not broken + * t1 = Cache error reg : not used and not broken + * t2 = TagLo reg : not used and not broken + * t3 = ECC reg : not used and not broken + * t4 - t7 temprary data + ********************************/ +#if 0 +LEAF(dat_parity_chk) + .set reorder + li t4, 1 # target check bit + li t5, 1 # target parity bit + li t6, 8 # byte counter + move v0, zero # Hparity bit and return value + +pdat_chk_loop: + and t7, a2, t4 + sne t7, 0 + xor v0, t7 # calcurate parity + DSLL (T4, T4, 1) + + subu t6, 1 # if 1byte check end? + bnez t6, pdat_chk_skip # else skip + + and t7, a3, t5 # then check parity bit + sne t7, 0 + xor v0, t7 # calcurate parity + xor v0, 1 # odd parity, not even 1993.11.7 + sll t5, 1 + li t6, 8 # reload byte counter + + beqz v0, pdat_chk_skip # if no parity error then continue + j ra # else error return + +pdat_chk_skip: + bnez t4, pdat_chk_loop # loop 63 times + j ra + + END(dat_parity_chk) +#endif + +/********************************* + * 2nd cache tag ECC check + * + * v0 = return code (return value) + * 0x20 -- SCHE_TAG_1BIT + * 0x21 -- SCHE_TAG_2BIT + * 0x23 -- SCHE_TAG_UNKNOW + * v1 = tag syndrome (return value) + * + * a0 = log field address (argument) : not used and not broken + * a1 = error code address (argument) : not used and not broken + * a2 = 2nd Tag erronious data (argument, return value) + * t0 = cache virtual address : not used and not broken + * t1 = Cache error reg : not used and not broken + * t2 = TagLo reg : not used and not broken + * t3 = ECC reg : not used and not broken + * t4 - t7 temprary data + ********************************/ +LEAF_ENTRY(tag_ecc_chk) + .set reorder + li t4, 1 # target check bit + la t5, tag_synd # tag syndrome data + move v1, zero # tag syndrome and return value + +// # make syndrome data +tag_ecc_loop1: + and t6, a2, t4 + beqz t6, tag_ecc_skip0 + lbu t7, (t5) # make syndrome + xor v1, t7 # +tag_ecc_skip0: + sll t4, 1 + addu t5, 1 + bnez t4, tag_ecc_loop1 # loop 31 times + + bnez v1, tag_ecc_err # if no error + li v0, SCHE_TAG_UNKNOW # then unknown error + j ra + +// # modify data +tag_ecc_err: + li t4, 1 # target check bit + la t5, tag_synd # tag syndrome data + +tag_ecc_loop2: + lbu t7, (t5) # 1bit error + beq v1, t7, tag_ecc_1bit # then 1bit error + + sll t4, 1 + addu t5, 1 + bnez t4, tag_ecc_loop2 # loop 31 times + + li v0, SCHE_TAG_2BIT # 2bit error + j ra + +tag_ecc_1bit: + xor a2, t4 # modified data + li v0, SCHE_TAG_1BIT # 1bit error + j ra + +tag_synd: + .byte 0x01 # ECC 0 (bit 25) + .byte 0x02 # ECC 1 (bit 26) + .byte 0x04 # ECC 2 (bit 27) + .byte 0x08 # ECC 3 (bit 28) + .byte 0x10 # ECC 4 (bit 29) + .byte 0x20 # ECC 5 (bit 30) + .byte 0x40 # ECC 6 (bit 31) + .byte 0x45 # Pidx 0 (bit 19) + .byte 0x29 # Pidx 1 (bit 20) + .byte 0x51 # Pidx 2 (bit 21) + .byte 0x13 # CS 0 (bit 22) + .byte 0x49 # CS 1 (bit 23) + .byte 0x25 # CS 2 (bit 24) + .byte 0x07 # STag 00 (bit 00) + .byte 0x16 # STag 01 (bit 01) + .byte 0x26 # STag 02 (bit 02) + .byte 0x46 # STag 03 (bit 03) + .byte 0x0d # STag 04 (bit 04) + .byte 0x0e # STag 05 (bit 05) + .byte 0x1c # STag 06 (bit 06) + .byte 0x4c # STag 07 (bit 07) + .byte 0x31 # STag 08 (bit 08) + .byte 0x32 # STag 09 (bit 09) + .byte 0x38 # STag 10 (bit 10) + .byte 0x70 # STag 11 (bit 11) + .byte 0x61 # STag 12 (bit 12) + .byte 0x62 # STag 13 (bit 13) + .byte 0x64 # STag 14 (bit 14) + .byte 0x68 # STag 15 (bit 15) + .byte 0x0b # STag 16 (bit 16) + .byte 0x15 # STag 17 (bit 17) + .byte 0x23 # STag 18 (bit 18) + +// END(tag_ecc_chk) + .end tag_ecc_chk +#if 0 +/********************************* + * 2nd cache 64bit data ECC check + * + * v0 = return code (return value) + * 0x26 -- SCHE_DAT_1BIT + * 0x27 -- SCHE_DAT_2BIT_C + * 0x29 -- SCHE_DAT_UNKNOW + * v1 = data syndrome (return value) + * + * a0 = log field address (argument) : not used and not broken + * a1 = error code address (argument) : not used and not broken + * a2 = 2nd 64bit data erronious data (argument, return value) + * a3 = 8bit ECC data (argument, return value) + * t0 = cache virtual address : not used and not broken + * t1 = Cache error reg : not used and not broken + * t2 = TagLo reg : not used and not broken + * t3 = ECC reg : not used and not broken + * t4 - t7 temprary data + ********************************/ +LEAF(dat_ecc_chk) + .set reorder + li t4, 1 # target check bit + la t5, dat_synd # data syndrome address + move v1, zero # data syndrome and return value + + # make syndrome data +dat_ecc_loop1: + and t6, a2, t4 + beqz t6, dat_ecc_skip0 + lbu t7, (t5) # make syndrome of data + xor v1, t7 # +dat_ecc_skip0: + addu t5, 1 + DSLL (T4, T4, 1) + bnez t4, dat_ecc_loop1 # loop 63 times + + li t4, 1 # target check bit +dat_ecc_loop2: + and t6, a3, t4 + beqz t6, dat_ecc_skip1 + lbu t7, (t5) # make syndrome of data + xor v1, t7 # +dat_ecc_skip1: + sll t4, 1 + addu t5, 1 + bne t4, 0x100, dat_ecc_loop2 # loop 7 times + + bnez v1, dat_ecc_err # if error + li v0, SCHE_DAT_UNKNOW # else unknown error + j ra + + # modify data +dat_ecc_err: + li t4, 1 # target check bit + la t5, dat_synd # tag syndrome data + +dat_ecc_loop3: + lbu t7, (t5) # 1bit error + beq v1, t7, dat_ecc_1bit # then 1bit error + + DSLL (T4, T4, 1) + addu t5, 1 + bnez t4, dat_ecc_loop3 # loop 63 times + + li t4, 1 # target check bit + +dat_ecc_loop4: + lbu t7, (t5) # 1bit error + beq v1, t7, dat_ecc_1bit2 # then 1bit error + + sll t4, 1 + addu t5, 1 + bne t4, 0x100, dat_ecc_loop4 # loop 7 times + + li v0, SCHE_DAT_2BIT_C # 2bit error + j ra + +dat_ecc_1bit2: + xor a3, t4 # modified ECC + j dat_ecc_1bitend + +dat_ecc_1bit: + xor a2, t4 # modified data +dat_ecc_1bitend: + li v0, SCHE_DAT_1BIT # 1bit error + j ra + +dat_synd: + .byte 0x13 # Data 00 (bit 00) + .byte 0x23 # Data 01 (bit 01) + .byte 0x43 # Data 02 (bit 02) + .byte 0x83 # Data 03 (bit 03) + .byte 0x2f # Data 04 (bit 04) + .byte 0xf1 # Data 05 (bit 05) + .byte 0x0d # Data 06 (bit 06) + .byte 0x07 # Data 07 (bit 07) + .byte 0xd0 # Data 08 (bit 08) + .byte 0x70 # Data 09 (bit 09) + .byte 0x4f # Data 10 (bit 10) + .byte 0xf8 # Data 11 (bit 11) + .byte 0x61 # Data 12 (bit 12) + .byte 0x62 # Data 13 (bit 13) + .byte 0x64 # Data 14 (bit 14) + .byte 0x68 # Data 15 (bit 15) + .byte 0x1c # Data 16 (bit 16) + .byte 0x2c # Data 17 (bit 17) + .byte 0x4c # Data 18 (bit 18) + .byte 0x8c # Data 19 (bit 19) + .byte 0x15 # Data 20 (bit 20) + .byte 0x25 # Data 21 (bit 21) + .byte 0x45 # Data 22 (bit 22) + .byte 0x85 # Data 23 (bit 23) + .byte 0x19 # Data 24 (bit 24) + .byte 0x29 # Data 25 (bit 25) + .byte 0x49 # Data 26 (bit 26) + .byte 0x89 # Data 27 (bit 27) + .byte 0x1a # Data 28 (bit 28) + .byte 0x2a # Data 29 (bit 29) + .byte 0x4a # Data 30 (bit 30) + .byte 0x8a # Data 31 (bit 31) + .byte 0x51 # Data 32 (bit 32) + .byte 0x52 # Data 33 (bit 33) + .byte 0x54 # Data 34 (bit 34) + .byte 0x58 # Data 35 (bit 35) + .byte 0x91 # Data 36 (bit 36) + .byte 0x92 # Data 37 (bit 37) + .byte 0x94 # Data 38 (bit 38) + .byte 0x98 # Data 39 (bit 39) + .byte 0xa1 # Data 40 (bit 40) + .byte 0xa2 # Data 41 (bit 41) + .byte 0xa4 # Data 42 (bit 42) + .byte 0xa8 # Data 43 (bit 43) + .byte 0x31 # Data 44 (bit 44) + .byte 0x32 # Data 45 (bit 45) + .byte 0x34 # Data 46 (bit 46) + .byte 0x38 # Data 47 (bit 47) + .byte 0x16 # Data 48 (bit 48) + .byte 0x26 # Data 49 (bit 49) + .byte 0x46 # Data 50 (bit 50) + .byte 0x86 # Data 51 (bit 51) + .byte 0x1f # Data 52 (bit 52) + .byte 0xf2 # Data 53 (bit 53) + .byte 0x0b # Data 54 (bit 54) + .byte 0x0e # Data 55 (bit 55) + .byte 0xb0 # Data 56 (bit 56) + .byte 0xe0 # Data 57 (bit 57) + .byte 0x8f # Data 58 (bit 58) + .byte 0xf4 # Data 59 (bit 59) + .byte 0xc1 # Data 60 (bit 60) + .byte 0xc2 # Data 61 (bit 61) + .byte 0xc4 # Data 62 (bit 62) + .byte 0xc8 # Data 63 (bit 63) + + .byte 0x01 # ECC 0 (bit 0) + .byte 0x02 # ECC 1 (bit 1) + .byte 0x04 # ECC 2 (bit 2) + .byte 0x08 # ECC 3 (bit 3) + .byte 0x10 # ECC 4 (bit 4) + .byte 0x20 # ECC 5 (bit 5) + .byte 0x40 # ECC 6 (bit 6) + .byte 0x80 # ECC 7 (bit 7) + + END(dat_ecc_chk) +#endif diff --git a/private/ntos/nthals/halr98b/mips/cirrus.h b/private/ntos/nthals/halr98b/mips/cirrus.h new file mode 100644 index 000000000..9f9846aaf --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/cirrus.h @@ -0,0 +1,298 @@ +#ident "@(#) NEC cirrus.h 1.2 94/11/21 13:58:39" +/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.7 94/02/03 18:58:17" ) */ +/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.6 94/01/28 11:50:02" ) */ +/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.4 93/10/29 12:25:02" ) */ +/*++ + +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 + * + * M002 1994.2.2 A. Kuriyama @ oa2 + * - Bug fix + * + * Modify : Video Memory Physical Address + * + * + * 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 + * + *************************************************************** + * + * S001 1994.06.06 T.Samezima + * + * - Modify for R98 MIPS R4400 + * + * Change : LA_MASK + * + * S002 '94.11/21 T.Samezima + * Chg invalid S001 + * + */ + +// +// 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 */ + +/* START M002 */ +#define LA_MASK 0xe // S001, S002 +/* END M002 */ +#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/halr98b/mips/cmdcnst.h b/private/ntos/nthals/halr98b/mips/cmdcnst.h new file mode 100644 index 000000000..ea2bba221 --- /dev/null +++ b/private/ntos/nthals/halr98b/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/halr98b/mips/esmnvram.h b/private/ntos/nthals/halr98b/mips/esmnvram.h new file mode 100644 index 000000000..cded099f2 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/esmnvram.h @@ -0,0 +1,271 @@ +/*++ + +Copyright (C) 1994, 1995 NEC Corporation + +File Name: + + esmnvram.h + +Abstract: + + This module contains the definitions for the extended NVRAM. + +Author: + + +Modification History: + + - M000 12/22/94 - created by Takehiro Ueda (tueda@oa2.kbnes.nec.co.jp) + - M001 11/22/95 - modified by Masayuki Fujii (masa@oa2.kbnes.nec.co.jp) + - M002 02/12/96 - modified by Masayuki Fujii (masa@oa2.kbnes.nec.co.jp) +--*/ + + +#pragma pack(1) + + +// +// define structures for each area of NVRAM +// + + +// +// WAS & PS common infromation for ECC memory error +// + +typedef struct _MEM_ERR_REC { + UCHAR mem_status; + UCHAR err_count; +} MEM_ERR_REC, *pMEM_ERR_REC; + + +// +// setting for ALIVE information area +// + +typedef struct _ALIVE_AREA_INFO { + USHORT offset_alive; +} ALIVE_AREA_INFO, *pALIVE_AREA_INFO; + + +// +// setting for ECC 1bit error information area +// + +typedef struct _ECC1_ERR_AREA_INFO { + USHORT offset_1biterr; + USHORT size_rec; + USHORT num_rec; + USHORT offset_latest; + ULONG read_data_latest; + UCHAR err_count_group0; + UCHAR err_count_group1; + UCHAR err_count_group2; + UCHAR err_count_group3; + UCHAR err_count_group4; + UCHAR err_count_group5; + UCHAR err_count_group6; + UCHAR err_count_group7; +} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO; + + +// +// setting for ECC 2bit error information area +// + +typedef struct _ECC2_ERR_AREA_INFO { + USHORT offset_2biterr; + USHORT size_rec; + USHORT num_rec; + USHORT offset_latest; + ULONG read_data_latest; + UCHAR simm_flag_group1; + UCHAR simm_flag_group2; + UCHAR simm_flag_group3; + UCHAR simm_flag_group4; + CHAR reserved[4]; +} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO; + + +// +// setting for system error information area +// + +typedef struct _SYSTEM_ERR_AREA_INFO { + USHORT offset_systemerr; + USHORT size_rec; + USHORT num_rec; + USHORT offset_latest; +} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO; + + +// +// setting for critical error information area +// + +typedef struct _CRITICAL_ERR_AREA_INFO { + USHORT offset_critical; + USHORT size_rec; + USHORT num_rec; + USHORT offset_latest; +} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO; + + +// +// setting for reduction information area +// + +typedef struct _RED_AREA_INFO { + USHORT offset_red; +} RED_AREA_INFO, *pRED_AREA_INFO; + + +// +// setting for reserved area +// + +typedef struct _RESERVE_AREA_INFO { + USHORT offset_reserve; +} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO; + + +// +// system information structure +// 49 bytes +// + +typedef struct _SYS_INFO { + UCHAR system_flag; + CHAR reserved1[3]; // for 4 byte alignment + CHAR sys_description[32]; + ULONG serial_num; + ULONG magic; + CHAR reserved2[4]; // reserved +} SYS_INFO, *pSYS_INFO; + + +// +// NVRAM header structure +// 640 bytes +// + +typedef struct _NVRAM_HEADER { + MEM_ERR_REC mem_err_map[256]; // common area for NT & NW + UCHAR nvram_flag; + CHAR when_formatted[14]; + CHAR reserved[3]; // for 4 byte alignment + ALIVE_AREA_INFO alive; + ECC1_ERR_AREA_INFO ecc1bit_err; + ECC2_ERR_AREA_INFO ecc2bit_err; + SYSTEM_ERR_AREA_INFO system_err; + CRITICAL_ERR_AREA_INFO critical_err_log; + RED_AREA_INFO red; + RESERVE_AREA_INFO reserve; + SYS_INFO system; +} NVRAM_HEADER, *pNVRAM_HEADER; + + +// +// ALIVE, pager call information structure +// 80 bytes +// + +typedef struct _ALIVE_INFO { + UCHAR alert_level; + CHAR primary_destination[16]; + CHAR secondary_destinaiton[16]; + CHAR reserved[47]; // reserved +} ALIVE_INFO, *pALIVE_INFO; + + +// +// ECC 1bit error information structure +// + +typedef struct _ECC1_ERR_REC { + UCHAR record_flag; + ULONG err_address; + CHAR when_happened[14]; + ULONG syndrome; + UCHAR specified_group; + UCHAR specified_simm; +} ECC1_ERR_REC, *pECC1_ERR_REC; + + +// +// ECC 2bit error information structure +// + +typedef struct _ECC2_ERR_REC { + UCHAR record_flag; + ULONG err_address; + CHAR when_happened[14]; + ULONG syndrome; + UCHAR specified_group; + UCHAR specified_simm; +} ECC2_ERR_REC, *pECC2_ERR_REC; + + +// +// stop error information structure +// + +typedef struct _STOP_ERR_REC { + UCHAR record_flag; + CHAR when_happened[14]; + CHAR err_description[496]; + CHAR reserved[1]; // reserved +} STOP_ERR_REC, *pSTOP_ERR_REC; + + +// +// critical error information structure +// + +typedef struct _CRITICAL_ERR_REC { + UCHAR record_flag; + CHAR when_happened[14]; + CHAR source[20]; + CHAR err_description[80]; + UCHAR error_code; + CHAR reserved[12]; // reserved +} CRITICAL_ERR_REC, *pCRITICAL; + + +// +// memory reduction information structure +// + +typedef struct _MEM_RED_INF { + ULONG simm_red_inf; + CHAR simm_rfu0[4]; // reserved + ULONG simm_stp_inf; + CHAR simm_rfu1[4]; // reserved + ULONG simm_phy_inf; + CHAR simm_rfu2[12]; // reserved +} MEM_RED_INF, *pMEM_RED; + + +// +// SIMM size information structure +// + +typedef struct _MEM_CAP_INF { + CHAR simm_phy_cap[64]; +} MEM_CAP_INF, *pMEM_CAP; + + +// +// CPU reduction information structure +// + +typedef struct _CPU_RED_INF { + ULONG cpu_red_inf; + ULONG cpu_stp_inf; + ULONG cpu_phy_inf; + CHAR cpu_rfu[4] ; // reserved +} CPU_RED_INF, *pCPU_RED; + + +#pragma pack() + diff --git a/private/ntos/nthals/halr98b/mips/glint.h b/private/ntos/nthals/halr98b/mips/glint.h new file mode 100644 index 000000000..156c3efcc --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/glint.h @@ -0,0 +1,580 @@ +// #ident "@(#) glint.h 1.1 95/06/30 05:27:26 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/halr98b/mips/halp.h b/private/ntos/nthals/halr98b/mips/halp.h new file mode 100644 index 000000000..25f675868 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/halp.h @@ -0,0 +1,674 @@ +/* + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + halp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + interfaces. + +--*/ + +#ifndef _HALP_ +#define _HALP_ + +#if defined(NT_UP) +#undef NT_UP +#endif + + +#include "nthal.h" +#include "hal.h" + +#include "r98bdef.h" +#include "r98breg.h" +#include "rxhalp.h" +#include "hali.h" + +#include "xm86.h" +#include "x86new.h" + +extern PVOID HalpEisaControlBase; +extern PVOID HalpRealTimeClockBase; +extern PVOID HalpEisaMemoryBase; + +// +// 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 +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 + ); + +BOOLEAN +HalpInitializeX86DisplayAdapter( + VOID + ); + +VOID +HalpResetX86DisplayAdapter( + VOID + ); + + +VOID +HalpInt0Dispatch( + VOID + ); + +VOID +HalpInt1Dispatch( + VOID + ); + +VOID +HalpInt2Dispatch( + VOID + ); + +VOID +HalpInt3Dispatch( + VOID + ); + +VOID +HalpInt4Dispatch( + VOID + ); + +VOID +HalpInt5Dispatch( + VOID + ); + +VOID +HalpInitDisplayStringIntoNvram( + VOID + ); + + +VOID +HalpTimerDispatch( + VOID + ); + +VOID +HalpEifDispatch( + VOID + ); + +VOID +HalpOutputSegment( + IN ULONG Number, + IN UCHAR Data + ); + +VOID +HalpDisplaySegment( + IN ULONG Number, + IN UCHAR Data + ); + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +BOOLEAN +HalpCreateEisaStructures ( + VOID + ); + +BOOLEAN +HalpCreatePciStructures ( + VOID + ); + +ULONG +HalpPonceNumber ( + IN ULONG BusNumber + ); + +PADAPTER_OBJECT +HalpAllocateEisaAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor + ); + +VOID +HalpEisaMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ); + + +KIRQL +HalpMapNvram ( + IN PENTRYLO SavedPte + ); + +VOID +HalpUnmapNvram ( + IN PENTRYLO SavedPte, + IN KIRQL OldIrql + ); + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + + +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector + ); + +// +// I change parameter on following large Register access function. +// v-masank@microsoft.com +// 5/21/96 +// +VOID +HalpReadLargeRegister( + IN volatile PULONGLONG VirtualAddress, + OUT PULONGLONG Buffer + ); + +VOID +HalpWriteLargeRegister( + IN volatile PULONGLONG VirtualAddress, + IN PULONGLONG Buffer + ); + +VOID +HalpRegisterNmi( + VOID + ); + +VOID +HalpAllocateMapRegisters( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + + +BOOLEAN +HalpHandleEif( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +ULONG +HalpGetCause( + VOID + ); + + +VOID +HalpNmiHandler( + VOID + ); + +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 +); + +VOID +HalpEccMultiBitError( + IN ULONG MagellanAllError, + IN UCHAR magSet + ); + +VOID +HalpEcc1bitError( + VOID + ); + +VOID +HalpInitDisplayStringIntoNvram( + VOID + ); + +VOID +HalpSetInitDisplayTimeStamp( + VOID + ); + +VOID +HalpSuccessOsStartUp( + VOID + ); + +VOID +HalpChangePanicFlag( + IN ULONG NewPanicFlg, + IN UCHAR NewLogFlg, + IN UCHAR CurrentLogFlgMask + ); + +ULONG +HalpReadPhysicalAddr( + IN ULONG PhysicalAddr + ); + + +VOID +HalStringIntoBuffer( + IN UCHAR Character + ); + +VOID +HalStringIntoBufferStart( + IN ULONG Column, + IN ULONG Row + ); + +VOID +HalpStringBufferCopyToNvram( + VOID + ); + + +VOID +HalpLocalDeviceReadWrite( + IN ULONG Offset, + IN OUT PUCHAR Data, + IN ULONG ReadWrite + ); + +VOID +HalpMrcModeChange( + UCHAR Mode + ); + + +ULONG +HalpReadAndWritePhysicalAddr( + IN ULONG PhysicalAddr + ); + +VOID +WRITE_REGISTER_ULONGLONG( + IN PVOID, + IN PVOID + ); + +VOID +READ_REGISTER_ULONGLONG( + IN PVOID, + IN PVOID + ); + + + +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 + ); + + +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + + +NTSTATUS +HalpAdjustEisaResourceList ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +HalpGetEisaData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); +BOOLEAN +HalpTranslateEisaBusAddress ( + 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 +HalpTranslatePCIBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + + +#if DBG + + +VOID +HalpTestPciPrintResult( + IN PULONG Buffer, + IN ULONG Length +); + + +VOID +R98DebugOutPut( + ULONG DebugPrintLevel, // Debug Level + PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte. + PCSZ DebugMessage, // For DISPLAY or SIO + ... + ); + + + +#define R98DbgPrint(_x_) R98DebugOutPut _x_ +#else +#define R98DbgPrint(_x_) +#endif + + +#ifdef RtlMoveMemory +#undef RtlMoveMemory +#undef RtlCopyMemory +#undef RtlFillMemory +#undef RtlZeroMemory + +#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length)) +VOID +RtlMoveMemory ( + PVOID Destination, + CONST VOID *Source, + ULONG Length + ); + +VOID +RtlFillMemory ( + PVOID Destination, + ULONG Length, + UCHAR Fill + ); + +VOID +RtlZeroMemory ( + PVOID Destination, + ULONG Length + ); + +#endif // #ifdef RtlMoveMemory + + +// +// Define external references. +// + +extern KSPIN_LOCK HalpBeepLock; +extern KSPIN_LOCK HalpDisplayAdapterLock; +extern ULONG HalpProfileCountRate; +extern ULONG HalpStallScaleFactor; +extern KSPIN_LOCK HalpSystemInterruptLock; +extern KSPIN_LOCK HalpIprInterruptLock; +extern KSPIN_LOCK HalpDieLock; +extern KSPIN_LOCK HalpLogLock; + + +extern UCHAR HalpChangeIntervalFlg[]; +extern ULONG HalpChangeIntervalCount; +extern ULONG HalpNextTimeIncrement; +extern ULONG HalpCurrentTimeIncrement; +extern ULONG HalpNextIntervalCount; +extern ULONG HalpNewTimeIncrement; + +extern ULONG HalpNvramValid; +extern USHORT ErrBufferArea; + +LONG HalpECC1bitDisableFlag; +LONG HalpECC1bitDisableTime; +ULONG HalpECC1bitScfrBuffer; +extern volatile ULONG HalpNMIFlag; +extern ULONG HalpNMIHappend[R98B_MAX_CPU]; + + +// +// +// Resource usage information +// + + +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; +#if defined(NT_40) + ULONG Length; +#else + USHORT Length; +#endif + } Element[]; +} ADDRESS_USAGE; + +#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; + +extern ADDRESS_USAGE HalpDefaultPcIoSpace; +extern ADDRESS_USAGE HalpEisaIoSpace; +extern ADDRESS_USAGE HalpMapRegisterMemorySpace; + +#define HalpRegisterAddressUsage(a) \ + (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a); + + +#define IRQ_PREFERRED 0x02 +#define IRQ_VALID 0x01 + + +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse +); + +// +// 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; + +BOOLEAN +HalpIoTlbLimitOver( + IN PKINTERRUPT Interrupt + ); + +#endif // _HALP_ diff --git a/private/ntos/nthals/halr98b/mips/j4cache.s b/private/ntos/nthals/halr98b/mips/j4cache.s new file mode 100644 index 000000000..5a4a772a9 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/j4cache.s @@ -0,0 +1,1190 @@ +// "@(#) NEC j4cache.s 1.5 94/12/06 10:46:13" +// TITLE("Cache Flush") +//++ +// +// Copyright (c) 1991-1994 Microsoft Corporation +// +// Module Name: +// +// j4cache.s +// +// Abstract: +// +// This module implements the code necessary for cache operations on +// a MIPS R4000. +// +//-- + +#include "halmips.h" + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.08/22 T.Samezima on SNES + * + * Add define _DUO_ + * + * K001 94/10/11 N.Kugimoto + * Fix 807 Base + * K002 94/12/06 N.Kugimoto + * Fix Mem32 + */ + +#define _DUO_ // S001 + +// +// Define cache operations constants. +// + +#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache) +#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache) +#define FLUSH_BASE 0xfffe0000 // flush base address +#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) // + + SBTTL("Change Color Page") +//++ +// +// VOID +// HalChangeColorPage ( +// IN PVOID NewColor, +// IN PVOID OldColor, +// IN ULONG PageFrame +// ) +// +// Routine Description: +// +// This function changes the color of a page if the old and new colors +// do not match. +// +// The algorithm used to change colors for a page is as follows: +// +// 1. Purge (hit/invalidate) the page from the instruction cache +// using the old color. +// +// 2. Purge (hit/invalidate) the page from the data cache using +// the old color. +// +// Arguments: +// +// NewColor (a0) - Supplies the page aligned virtual address of the +// new color of the page to change. +// +// OldColor (a1) - Supplies the page aligned virtual address of the +// old color of the page to change. +// +// PageFrame (a2) - Supplies the page frame number of the page that +// is changed. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 3 * 4 // fill +CpRa: .space 4 // saved return address +CpFrameLength: // length of stack frame +CpA0: .space 4 // (a0) +CpA1: .space 4 // (a1) +CpA2: .space 4 // (a2) +CpA3: .space 4 // (a3) + + NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero) + + subu sp,sp,CpFrameLength // allocate stack frame + sw ra,CpRa(sp) // save return address + + PROLOGUE_END + + and a0,a0,COLOR_BITS // isolate new color bits + and a1,a1,COLOR_BITS // isolate old color bits + beq a0,a1,10f // if eq, colors match + sw a1,CpA1(sp) // save old color bits + sw a2,CpA2(sp) // save page frame + +// +// Purge the instruction cache using the old page color. +// + + move a0,a1 // set color value + move a1,a2 // set page frame number + li a2,PAGE_SIZE // set length of purge + jal HalPurgeIcachePage // purge instruction cache page + +// +// Flush the data cache using the old page color. +// + + lw a0,CpA1(sp) // get old color bits + lw a1,CpA2(sp) // get page frame number + li a2,PAGE_SIZE // set length of purge + jal HalFlushDcachePage // purge data cache page +10: lw ra,CpRa(sp) // get return address + addu sp,sp,CpFrameLength // deallocate stack frame + j ra // return + + .end HalChangeColorPage + + SBTTL("Flush Data Cache Page") +//++ +// +// VOID +// HalFlushDcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function flushes (hit/writeback/invalidate) up to a page of data +// from the data cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is flushed. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is flushed. +// +// Length (a2) - Supplies the length of the region in the page that is +// flushed. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalFlushDcachePage) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color and offset bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set flush block size + .set at + .set reorder + +// +// Flush a page from the data cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to flush + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Flush the primary data cache only. +// + +20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Flush the primary and secondary data caches. +// + + .set noreorder + .set noat +40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalFlushDcachePage + + SBTTL("Purge Data Cache Page") +//++ +// +// VOID +// HalPurgeDcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function purges (hit/invalidate) up to a page of data from the +// data cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is purged. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is purged. +// +// Length (a2) - Supplies the length of the region in the page that is +// purged. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalPurgeDcachePage) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set purge block size + .set at + .set reorder + +// +// Purge data from the data cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Purge the primary data cache only. +// + +20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Purge the primary and secondary data caches. +// + + .set noreorder + .set noat +40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalPurgeDcachePage + + SBTTL("Purge Instruction Cache Page") +//++ +// +// VOID +// HalPurgeIcachePage ( +// IN PVOID Color, +// IN ULONG PageFrame, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function purges (hit/invalidate) up to a page fo data from the +// instruction cache. +// +// Arguments: +// +// Color (a0) - Supplies the starting virtual address and color of the +// data that is purged. +// +// PageFrame (a1) - Supplies the page frame number of the page that +// is purged. +// +// Length (a2) - Supplies the length of the region in the page that is +// purged. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalPurgeIcachePage) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy + and a0,a0,COLOR_MASK // isolate color bits + li t0,FLUSH_BASE // get base flush address + or t0,t0,a0 // compute color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a0,a0,0x1000 // isolate TB entry index + beql zero,a0,10f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +10: mfc0 t3,wired // get TB entry index + lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size + lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size + bnel zero,v0,15f // if ne, second level cache present + move t4,v0 // set purge block size + .set at + .set reorder + +// +// Purge data from the instruction cache. +// + +15: DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + subu t6,t4,1 // compute block size minus one + and t7,t0,t6 // compute offset in block + addu a2,a2,t6 // round up to next block + addu a2,a2,t7 // + nor t6,t6,zero // complement block size minus one + and a2,a2,t6 // truncate length to even number + beq zero,a2,30f // if eq, no blocks to purge + and t8,t0,t6 // compute starting virtual address + addu t9,t8,a2 // compute ending virtual address + bne zero,v0,40f // if ne, second level cache present + subu t9,t9,t4 // compute ending loop address + +// +// Purge the primary instruction cache only. +// + +20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block + bne t8,t9,20b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + +30: ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + +// +// Purge the primary and secondary instruction caches. +// + + .set noreorder + .set noat +40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block + bne t8,t9,40b // if ne, more blocks to invalidate + addu t8,t8,t4 // compute next block address + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + j ra // return + + .end HalPurgeIcachePage + + SBTTL("Sweep Data Cache") +//++ +// +// VOID +// HalSweepDcache ( +// VOID +// ) +// +// Routine Description: +// +// This function sweeps (index/writeback/invalidate) the entire data cache. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepDcache) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + DISABLE_INTERRUPTS(t5) // disable interrupts K002 + + lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size + lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + + +// +// Sweep the primary data cache. +// + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + nop + nop + nop + nop + nop + bne zero,t3,12f // if ne, not r10000 processor + nop + cache INDEX_WRITEBACK_INVALIDATE_D,1(a0) // writeback/invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +12: + + + +#if defined(_MIPS_R4600) //K001 + + nop // fill + cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index + +#endif + + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + + lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size + lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size + beq zero,t1,30f // if eq, no second level cache + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + +// +// Sweep the secondary data cache. +// + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index + nop + nop + nop + nop + nop + bne zero,t3,22f // if ne, not r10000 processor + nop + cache INDEX_WRITEBACK_INVALIDATE_SD,1(a0) // writeback/invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +22: + bne a0,a1,20b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + +30: + ENABLE_INTERRUPTS(t5) // enable interrupts K002 + j ra // return + + .end HalSweepDcache + + SBTTL("Sweep Data Cache Range") +//++ +// +// VOID +// HalSweepDcacheRange ( +// IN PVOID BaseAddress, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function sweeps (index/writeback/invalidate) the specified range +// of virtual addresses from the primary data cache. +// +// Arguments: +// +// BaseAddress (a0) - Supplies the base address of the range that is swept +// from the data cache. +// +// Length (a1) - Supplies the length of the range that is swept from the +// data cache. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepDcacheRange) + +#if DBG + + lw t0,KeDcacheFlushCount // get address of dcache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result conditionally + +#endif + + DISABLE_INTERRUPTS(t5) // disable interrupts K002 + + and a0,a0,COLOR_MASK // isolate color and offset bits + or a0,a0,KSEG0_BASE // convert to physical address + lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size + addu a1,a0,a1 // compute ending cache address + subu a1,a1,t0 // compute ending block address + +// +// Sweep the primary data cache. +// + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + + nop + nop + nop + nop + nop + bne zero,t3,12f // if ne, not r10000 processor + nop + cache INDEX_WRITEBACK_INVALIDATE_D,1(a0) // writeback/invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +12: +#if defined(_MIPS_R4600) + + nop // fill + cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index + +#endif + + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts K002 + + j ra // return + + .end HalSweepDcacheRange + + SBTTL("Sweep Instruction Cache") +//++ +// +// VOID +// HalSweepIcache ( +// VOID +// ) +// +// Routine Description: +// +// This function sweeps (index/invalidate) the entire instruction cache. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepIcache) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size + beq zero,t1,20f // if eq, no second level cache + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + +// +// Sweep the secondary instruction cache. +// + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line + nop + nop + nop + nop + nop + bne zero,t3,12f // if ne, not r10000 processor + nop + cache INDEX_INVALIDATE_SI,1(a0) // invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +12: + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + +20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size + lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + li a0,KSEG0_BASE // set starting index value + addu a1,a0,t0 // compute ending cache address + subu a1,a1,t1 // compute ending block address + +// +// Sweep the primary instruction cache. +// + +#if defined(_MIPS_R4600) + + DISABLE_INTERRUPTS(t0) // disable interrupts + +#endif + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + nop + nop + nop + nop + nop + bne zero,t3,32f // if ne, not r10000 processor + nop + cache INDEX_INVALIDATE_I,1(a0) // invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +32: + +#if defined(_MIPS_R4600) //K001 + + nop // fill + cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index + +#endif + + bne a0,a1,30b // if ne, more to invalidate + addu a0,a0,t1 // compute address of next block + .set at + .set reorder + +#if defined(_MIPS_R4600) + + ENABLE_INTERRUPTS(t0) // enable interrupts + +#endif + + j ra // return + + .end HalSweepIcache + + SBTTL("Sweep Instruction Cache Range") +//++ +// +// VOID +// HalSweepIcacheRange ( +// IN PVOID BaseAddress, +// IN ULONG Length +// ) +// +// Routine Description: +// +// This function sweeps (index/invalidate) the specified range of addresses +// from the instruction cache. +// +// Arguments: +// +// BaseAddress (a0) - Supplies the base address of the range that is swept +// from the instruction cache. +// +// Length (a1) - Supplies the length of the range that is swept from the +// instruction cache. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalSweepIcacheRange) + +#if DBG + + lw t0,KeIcacheFlushCount // get address of icache flush count + lw t1,0(t0) // increment the count of flushes + addu t1,t1,1 // + sw t1,0(t0) // store result + +#endif + + and a0,a0,COLOR_MASK // isolate color and offset bits + or a0,a0,KSEG0_BASE // convert to physical address + lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size + addu a1,a0,a1 // compute ending cache address + subu a1,a1,t0 // compute ending block address + +// +// Sweep the primary instruction cache. +// + +#if defined(_MIPS_R4600) + + DISABLE_INTERRUPTS(t1) // disable interrupts + +#endif + + .set noreorder + .set noat +//For T5 + mfc0 t4,prid + nop + nop + nop + nop + and t4,t4,0xff00 // isolate processor id + xor t3,t4,0x900 // check if r10000 processor +10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + nop + nop + nop + nop + nop + bne zero,t3,12f // if ne, not r10000 processor + nop + cache INDEX_INVALIDATE_I,1(a0) // invalidate on index way 1 for t5 + nop + nop + nop + nop + nop +12: + +#if defined(_MIPS_R4600) + + nop // fill + cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index + +#endif + + bne a0,a1,10b // if ne, more to invalidate + addu a0,a0,t0 // compute address of next block + .set at + .set reorder + +#if defined(_MIPS_R4600) + + ENABLE_INTERRUPTS(t1) // enable interrupts + +#endif + + j ra // return + + .end HalSweepIcacheRange + + SBTTL("Zero Page") +//++ +// +// VOID +// HalZeroPage ( +// IN PVOID NewColor, +// IN PVOID OldColor, +// IN ULONG PageFrame +// ) +// +// Routine Description: +// +// This function zeros a page of memory. +// +// The algorithm used to zero a page is as follows: +// +// 1. Purge (hit/invalidate) the page from the instruction cache +// using the old color iff the old color is not the same as +// the new color. +// +// 2. Purge (hit/invalidate) the page from the data cache using +// the old color iff the old color is not the same as the new +// color. +// +// 3. Create (create/dirty/exclusive) the page in the data cache +// using the new color. +// +// 4. Write zeros to the page using the new color. +// +// Arguments: +// +// NewColor (a0) - Supplies the page aligned virtual address of the +// new color of the page that is zeroed. +// +// OldColor (a1) - Supplies the page aligned virtual address of the +// old color of the page that is zeroed. +// +// PageFrame (a2) - Supplies the page frame number of the page that +// is zeroed. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 + .space 3 * 4 // fill +ZpRa: .space 4 // saved return address +ZpFrameLength: // length of stack frame +ZpA0: .space 4 // (a0) +ZpA1: .space 4 // (a1) +ZpA2: .space 4 // (a2) +ZpA3: .space 4 // (a3) + + NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero) + + subu sp,sp,ZpFrameLength // allocate stack frame + sw ra,ZpRa(sp) // save return address + + PROLOGUE_END + + and a0,a0,COLOR_BITS // isolate new color bits + and a1,a1,COLOR_BITS // isolate old color bits + sw a0,ZpA0(sp) // save new color bits + sw a2,ZpA2(sp) // save page frame + +// +// If the old page color is not equal to the new page color, then change +// the color of the page. +// + + beq a0,a1,10f // if eq, colors match + jal KeChangeColorPage // chagne page color + +// +// Create dirty exclusive cache blocks and zero the data. +// + +10: lw a3,ZpA0(sp) // get new color bits + lw a1,ZpA2(sp) // get page frame number + + .set noreorder + .set noat + lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy + li t0,FLUSH_BASE // get base flush address + or t0,t0,a3 // compute new color virtual address + sll t1,a1,ENTRYLO_PFN // shift page frame into position + or t1,t1,PROTECTION_BITS // merge protection bits + or t1,t1,v0 // merge cache policy + and a3,a3,0x1000 // isolate TB entry index + beql zero,a3,20f // if eq, first entry + move t2,zero // set second page table entry + move t2,t1 // set second page table entry + move t1,zero // set first page table entry +20: mfc0 t3,wired // get TB entry index + lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size + lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size + .set at + .set reorder + + DISABLE_INTERRUPTS(t5) // disable interrupts + + .set noreorder + .set noat + mfc0 t6,entryhi // get current PID and VPN2 + srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address + sll t7,t7,ENTRYHI_VPN2 // + and t6,t6,0xff << ENTRYHI_PID // isolate current PID + or t7,t7,t6 // merge PID with VPN2 of virtual address + mtc0 t7,entryhi // set VPN2 and PID for probe + mtc0 t1,entrylo0 // set first PTE value + mtc0 t2,entrylo1 // set second PTE value + mtc0 t3,index // set TB index value + nop // fill + tlbwi // write TB entry - 3 cycle hazzard + addu t9,t0,PAGE_SIZE // compute ending address of block + dmtc1 zero,f0 // set write pattern + bne zero,v0,50f // if ne, second level cache present + and t8,t4,0x10 // test if 16-byte cache block + +// +// Zero page in primary data cache only. +// + +#if defined(_DUO_) + +30: sdc1 f0,0(t0) // zero 64-byte block + sdc1 f0,8(t0) // + sdc1 f0,16(t0) // + sdc1 f0,24(t0) // + sdc1 f0,32(t0) // + sdc1 f0,40(t0) // + sdc1 f0,48(t0) // + addu t0,t0,64 // advance to next 64-byte block + bne t0,t9,30b // if ne, more to zero + sdc1 f0,-8(t0) // + +#else + +30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block + addu t0,t0,t4 // compute next block address + bne zero,t8,40f // if ne, 16-byte cache line + sdc1 f0,-16(t0) // + sdc1 f0,-24(t0) // zero 16 bytes + sdc1 f0,-32(t0) // +40: bne t0,t9,30b // if ne, more blocks to zero + sdc1 f0,-8(t0) // zero 16 bytes + +#endif + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + lw ra,ZpRa(sp) // get return address + addu sp,sp,ZpFrameLength // deallocate stack frame + j ra // return + +// +// Zero page in primary and secondary data caches. +// + + .set noreorder + .set noat + +#if defined(_DUO_) + +50: sdc1 f0,0(t0) // zero 64-byte block + sdc1 f0,8(t0) // + sdc1 f0,16(t0) // + sdc1 f0,24(t0) // + sdc1 f0,32(t0) // + sdc1 f0,40(t0) // + sdc1 f0,48(t0) // + addu t0,t0,64 // advance to next 64-byte block + bne t0,t9,50b // if ne, more to zero + sdc1 f0,-8(t0) // + +#else + +50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block + addu v1,v0,t0 // compute ending primary block address +60: addu t0,t0,t4 // compute next block address + bne zero,t8,70f // if ne, 16-byte primary cache line + sdc1 f0,-16(t0) // + sdc1 f0,-24(t0) // zero 16 bytes + sdc1 f0,-32(t0) // +70: bne t0,v1,60b // if ne, more primary blocks to zero + sdc1 f0,-8(t0) // zero 16 bytes + bne t0,t9,50b // if ne, more secondary blocks to zero + nop // fill + +#endif + + .set at + .set reorder + + ENABLE_INTERRUPTS(t5) // enable interrupts + + lw ra,ZpRa(sp) // get return address + addu sp,sp,ZpFrameLength // deallocate stack frame + j ra // return + + .end HalZeroPage diff --git a/private/ntos/nthals/halr98b/mips/j4flshbf.s b/private/ntos/nthals/halr98b/mips/j4flshbf.s new file mode 100644 index 000000000..b9a1cda9b --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/j4flshbf.s @@ -0,0 +1,58 @@ +// "@(#) NEC j4flshbf.s 1.2 94/10/17 11:11:16" +#if defined(R4000) + +// TITLE("Miscellaneous Kernel Functions") +//++ +// +// Copyright (c) 1991-1994 Microsoft Corporation +// +// Module Name: +// +// j3flshbf.s +// +// Abstract: +// +// This module implements the system dependent kernel function to flush +// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz +// system. +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + SBTTL("Flush Write Buffer") +//++ +// +// NTSTATUS +// KeFlushWriteBuffer ( +// VOID +// ) +// +// Routine Description: +// +// This function flushes the write buffer on the current processor. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(KeFlushWriteBuffer) + + sync // synchronize writes + j ra // return + + .end KeFlushWritebuffer + +#endif diff --git a/private/ntos/nthals/halr98b/mips/j4flshio.c b/private/ntos/nthals/halr98b/mips/j4flshio.c new file mode 100644 index 000000000..868141c2a --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/j4flshio.c @@ -0,0 +1,212 @@ +/*++ + +Copyright (c) 1991-1994 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. + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#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; + + // + // R98 I/O Cache Supported So Nothing to Do Dma Operation!!. + // + if (DmaOperation == TRUE){ + return; + } + + + // + // 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/halr98b/mips/j4prof.c b/private/ntos/nthals/halr98b/mips/j4prof.c new file mode 100644 index 000000000..7fdd27e98 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/j4prof.c @@ -0,0 +1,340 @@ + +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + j4prof.c + +Abstract: + + This module contains the code to start and stop the profiling interrupt + and to compute the profiling interval for a MIPS R98B system. + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + +// +// Define one second and round values. +// + +#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units +#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns + +// +// Define static data. +// + +LARGE_INTEGER HalpPerformanceCounter[8]; + +ULONG HalpProfileInterval = DEFAULT_PROFILETIMER_INTERVAL; + + +LARGE_INTEGER +KeQueryPerformanceCounter ( + OUT PLARGE_INTEGER Frequency OPTIONAL + ) + +/*++ + +Routine Description: + + This routine returns the current performance counter value and the + performance counter frequency. + +Arguments: + + Frequency - Supplies an optional pointer to a variable which receives + the performance counter frequency in Hertz. + +Return Value: + + The current performance counter value is returned as the function + value. + +--*/ + +{ + + ULONG CurrentCount; + KIRQL OldIrql; + LARGE_INTEGER PerformanceCounter; + + // + // Raise IRQL to PROFILE_LEVEL, read the current value of the count + // register, read the performance counter, and lower IRQL to its + // previous value. + // + // N.B. The minimum, maximum, and default values for the profile + // count are chosen such that count register only overflows + // after about 20 seconds at 50mhz. Therefore, there is never + // a problem with the counter wrapping in the following code. + // + + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + CurrentCount = HalpReadCountRegister(); + PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number]; + KeLowerIrql(OldIrql); + + // + // If the frequency parameter is specified, then return the performance + // counter frequency as the current system time frequency. + // + + if (ARGUMENT_PRESENT(Frequency) != FALSE) { + *Frequency = RtlConvertUlongToLargeInteger(HalpProfileCountRate); + } + + // + // Return the value of the performance counter. + // + + return RtlLargeIntegerAdd(PerformanceCounter, + RtlConvertUlongToLargeInteger(CurrentCount)); +} + +VOID +HalCalibratePerformanceCounter ( + IN volatile PLONG Number + ) + +/*++ + +Routine Description: + + This routine resets the performance counter value for the current + processor to zero. The reset is done such that the resulting value + is closely synchronized with other processors in the configuration. + +Arguments: + + Number - Supplies a pointer to count of the number of processors in + the configuration. + +Return Value: + + None. + +--*/ + +{ + + KSPIN_LOCK Lock; + KIRQL OldIrql; + PKPRCB Prcb; + + // + // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and + // wait until the number is zero. + // + + KeInitializeSpinLock(&Lock); + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) { + do { + } while (*Number !=0); + } + + // + // Write the compare register, clear the count register, and zero the + // performance counter for the current processor. + // + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT); + + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long, + DEFAULT_PROFILETIMER_COUNT); + + + Prcb = KeGetCurrentPrcb(); + HalpPerformanceCounter[Prcb->Number].LowPart = 0; + HalpPerformanceCounter[Prcb->Number].HighPart = 0; + + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3); + + + // + // Restore IRQL to its previous value and return. + // + + KeLowerIrql(OldIrql); + return; +} + +ULONG +HalSetProfileInterval ( + IN ULONG Interval + ) + +/*++ + +Routine Description: + + This routine sets the profile interrupt interval. + +Arguments: + + Interval - Supplies the desired profile interval in 100ns units. + +Return Value: + + The actual profile interval. + +--*/ + +{ + + + + // + // If the specified profile interval is less that the minimum profile + // interval or greater than the maximum profile interval, then set the + // profile interval to the minimum or maximum as appropriate. + // + + + if (Interval < MINIMUM_PROFILETIMER_INTERVAL) { + Interval = MINIMUM_PROFILETIMER_INTERVAL; + + } else if (Interval > MAXIMUM_PROFILETIMER_INTERVAL) { + Interval = MAXIMUM_PROFILETIMER_INTERVAL; + } + + HalpProfileInterval = Interval; + + + return HalpProfileInterval; +} + +VOID +HalStartProfileInterrupt ( + KPROFILE_SOURCE Reserved + ) + +/*++ + +Routine Description: + + This routine computes the profile count value, writes the compare + register, clears the count register, and updates the performance + counter. + + N.B. This routine must be called at PROFILE_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + PKPRCB Prcb; + ULONG PreviousCount; + + ULONG TempValue; + + + // + // Compute the profile count from the current profile interval. + // + + // The R98A/B machines use the External Interrupt for + // the profile and clock interrupt. The hardware requires the + // value decremented by 1 + + TempValue = HalpProfileInterval * COLUMBUS_CLOCK_FREQUENCY / 1000 / 10 - 1; + + // + // Write the compare register and clear the count register. + // + // SR2 - Columbus chip Internal Countdown register. The Columbus + // chip decrements this register every Columbus cycle (COLUMBUS_CLOCK_FREQUENCY). + // When the value is zero it signals the External Interrupt + // CR2 - Columbus chip clock control register. This enables countdown register + // and external interrupts. + PreviousCount = HalpWriteCompareRegisterAndClear(TempValue); + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long, TempValue); + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3); + + + // + // Update the performance counter by adding in the previous count value. + // + + Prcb = KeGetCurrentPrcb(); + HalpPerformanceCounter[Prcb->Number] = + RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number], + RtlConvertUlongToLargeInteger(PreviousCount)); + + return; +} + +VOID +HalStopProfileInterrupt ( + KPROFILE_SOURCE Reserved + ) + +/*++ + +Routine Description: + + This routine sets the default count value, writes the compare + register, clears the count register, and updates the performance + counter. + + N.B. This routine must be called at PROFILE_LEVEL while holding the + profile lock. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + PKPRCB Prcb; + ULONG PreviousCount; + + // + // Write the compare register and clear the count register. + // + // Columbus hardware specifies SET VALUE AS VALUE MINUS ONE + PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT-1); + + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMSR2.Long, + DEFAULT_PROFILETIMER_COUNT-1); + WRITE_REGISTER_ULONG( &(COLUMNBS_LCNTL)->TMCR2.Long, 0x3); + + + // + // Update the performance counter by adding in the previous count value. + // + + Prcb = KeGetCurrentPrcb(); + HalpPerformanceCounter[Prcb->Number] = + RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number], + RtlConvertUlongToLargeInteger(PreviousCount)); + + return; +} diff --git a/private/ntos/nthals/halr98b/mips/jxbeep.c b/private/ntos/nthals/halr98b/mips/jxbeep.c new file mode 100644 index 000000000..d39405c78 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxbeep.c @@ -0,0 +1,131 @@ +#ident "@(#) NEC jxbeep.c 1.2 94/10/17 11:22:04" +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxbeep.c + +Abstract: + + This module implements the HAL speaker "beep" routines for a MIPS + system. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#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; + NMI_STATUS NmiStatus; + 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. + // + + *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus); + NmiStatus.SpeakerGate = 0; + NmiStatus.SpeakerData = 0; + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus)); + + // + // 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 { + + // + // 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)); + + // + // Set the speaker timer to the correct mode. + // + + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff)); + WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8)); + + // + // Start the speaker. + // + + NmiStatus.SpeakerGate = 1; + NmiStatus.SpeakerData = 1; + WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus)); + Result = TRUE; + } + } + + // + // Release the beep spin lock and lower IRQL to its previous value. + // + + KeReleaseSpinLock(&HalpBeepLock, OldIrql); + return Result; +} diff --git a/private/ntos/nthals/halr98b/mips/jxdisp.c b/private/ntos/nthals/halr98b/mips/jxdisp.c new file mode 100644 index 000000000..03b9d0c7e --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxdisp.c @@ -0,0 +1,3544 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxdisp.c + +Abstract: + + This module implements the HAL display initialization and output routines + for a MIPS R4000 or R10000 R98x system. + +History: + +--*/ + +/* + * NEW CODE for R98B + * 1995/09/11 K.Kitagaki + * + * S001 1995/11/10 T.Samezima + * add x86 bios and GLiNT logic + * + */ + +#include "halp.h" +#include "jazzvdeo.h" +#include "jzvxl484.h" +#include <jaginit.h> +#include "cirrus.h" +#include "modeset.h" +#include "mode542x.h" +#include "string.h" +#include <tga.h> +#include <glint.h> // S001 +#include <rgb525.h> // S001 + +#include "pci.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, HalpInitializeDisplay0) +#pragma alloc_text(INIT, HalpInitializeDisplay1) + +#endif + +// S001 vvv +#define _GLINT60HZ_ + +#if defined(R96DBG) +#define DispDbgPrint(STRING) \ + DbgPrint STRING; +#else +#define DispDbgPrint(STRING) +#endif + +// +// for x86bios emulate +// +PCHAR K351UseBios=NULL; + +PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters; + +#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 + ); + +VOID +HalpDisplayCharacterOld ( + IN UCHAR Character + ); + +VOID +HalpOutputCharacterOld ( + IN PUCHAR Glyph + ); +// S001 ^^^ + +VOID +HalpDisplayCirrusSetup ( + VOID + ); + +BOOLEAN +HalpCirrusInterpretCmdStream ( + PUSHORT pusCmdStream + ); + +VOID +HalpDisplayTgaSetup( + VOID + ); + +VOID +Write_Dbg_Uchar( + PUCHAR, + UCHAR + ); + +// S001 vvv +#if 0 +VOID +RGB525_WRITE( + ULONG dac, + ULONG offset, + UCHAR data ); + +VOID +RGB525_SET_REG( + ULONG dac, + ULONG index, + UCHAR data ); +#endif + +VOID +HalpDisplayGlintSetup( + VOID + ); +// S001 ^^^ + +// +// 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)(0x1c403000 | KSEG1_BASE)) +#define CIRRUS_OFFSET ((PUSHORT)0x3b0) +#define PCI_0_IO_BASE 0x1c000000 // S001 +#define PCI_1_IO_BASE 0x1c400000 +#define CIRRUS_CONTROL_BASE_OFFSET 0x3000 +#define CIRRUS_MEMORY_BASE_LOW 0xa0000000 + +#define KSEG1_BASE 0xa0000000 + +#define TGA_REGISTER_BASE ((ULONG)0x403ff000) +#define PONCE_ADDR_REG ((PULONG)(0x1a000008 | KSEG1_BASE)) +#define PONCE_DATA_REG ((PULONG)(0x1a000010 | KSEG1_BASE)) +#define PONCE_PERRM ((PULONG)(0x1a000810 | KSEG1_BASE)) +#define PONCE_PAERR ((PULONG)(0x1a000800 | KSEG1_BASE)) +#define PONCE_PERST ((PULONG)(0x1a000820 | KSEG1_BASE)) + +// S001 vvv +#define GLINT_CONTROL_REGISTER_BASE ((ULONG)0x403ff000) +#define GLINT_VIDEO_REGISTER_BASE ((ULONG)0x403fe000) +#define RGB525_REGISTER_BASE ((ULONG)0x403fd000) + +// +// Define controller setup routine type. +// + +typedef +VOID +(*PHALP_CONTROLLER_SETUP) ( + VOID + ); + +typedef +VOID +(*PHALP_DISPLAY_CHARACTER) ( + UCHAR + ); + +typedef +VOID +(*PHALP_SCROLL_SCREEN) ( + UCHAR + ); + +PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL; +// S001 ^^^ + +// +// 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; // S001 + +// +// Define display variables. +// + +BOOLEAN HalpDisplayOwnedByHal; +ENTRYLO HalpDisplayPte; +ULONG HalpDisplayControlBase = 0; +ULONG HalpDisplayMemoryBase = 0; +ULONG HalpDisplayResetRegisterBase = 0; +PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL; +MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData; +BOOLEAN HalpDisplayTypeUnknown = FALSE; +ULONG HalpDisplayPCIDevice = FALSE; + +LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0}; +LARGE_INTEGER HalpTgaPhigicalVideo = {0,0}; +LARGE_INTEGER HalpTgaPhigicalVideoCont = {0,0}; +// S001 vvv +LARGE_INTEGER HalpGlintPhygicalVideo = {0,0}; +LARGE_INTEGER HalpGlintPhygicalVideoCont = {0,0}; +ULONG HalpDisplayType16BPP = FALSE; +// S001 ^^^ + + +ULONG HalpCirrusAlive=FALSE; + +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; + +BOOLEAN +HalpCheckPCIDevice ( + IN PCI_SLOT_NUMBER Slot + ); + +volatile PULONG HalpPonceConfigAddrReg = PONCE_ADDR_REG; +volatile PULONG HalpPonceConfigDataReg = PONCE_DATA_REG; +volatile PULONG HalpPoncePerrm = PONCE_PERRM; +volatile PULONG HalpPoncePaerr = PONCE_PAERR; +volatile PULONG HalpPoncePerst = PONCE_PERST; + +// S001 vvv +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 PUSHORT Buffer, + IN ULONG Offset + ); + +VOID +HalpWritePCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUSHORT Buffer, + IN ULONG Offset + ); + +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 + ); +// S001 ^^^ + +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++; + } + } +} + + +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; + + HalpPonceConfigAddrReg = PONCE_ADDR_REG; + HalpPonceConfigDataReg = PONCE_DATA_REG; + HalpPoncePerrm = PONCE_PERRM; + HalpPoncePaerr = PONCE_PAERR; + HalpPoncePerst = PONCE_PERST; + + // + // 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; + + // + // Find the configuration entry for the first display controller. + // + + DispDbgPrint(("Hal: HalpInitializeDisplay0\n")); // S001 + + MatchKey = 0; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + DisplayController, + &MatchKey); + + DispDbgPrint(("Hal: ConfigurationEntry Found\n")); // S001 + + 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. + // + + // S001 vvv + if (LoaderBlock->LoadOptions != NULL) { + Options = LoaderBlock->LoadOptions; + // + // Why link error occure? + // So, I change. + // v-masank@microsoft.com + // 5/21/96 + // + //strupr(Options); + K351UseBios = strstr(Options, "USEBIOS"); + } + if(K351UseBios!=NULL){ + DispDbgPrint(("HAL: Use X86BIOS emulation\n")); + + HalpDisplayControllerSetup = HalpDisplayINT10Setup; + HalpDisplayCharacter = HalpDisplayCharacterVGA; + HalpDisplayControlBase = PCI_0_IO_BASE; + }else + // S001 ^^^ + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "necvdfrb")) { + DispDbgPrint(("necvdfrb Config found\n")); + + HalpDisplayControllerSetup = HalpDisplayCirrusSetup; + HalpCirrusAlive =TRUE; + HalpDisplayCharacter = HalpDisplayCharacterOld; // S001 + HalpDisplayControlBase = PCI_1_IO_BASE + CIRRUS_CONTROL_BASE_OFFSET; + HalpDisplayMemoryBase = CIRRUS_MEMORY_BASE_LOW; + HalpDisplayPCIDevice = TRUE; + + } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"10110004")) { + // + // for DEC21030 PCI + // + DispDbgPrint(("DEC G/A found\n")); + + HalpDisplayControllerSetup = HalpDisplayTgaSetup; + HalpDisplayCharacter = HalpDisplayCharacterOld; // S001 + HalpDisplayPCIDevice = TRUE; + + Slot.u.bits.FunctionNumber = 0; + + for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ + DispDbgPrint(("DEC G/A found 2vvvv\n")); + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + +#if defined (DBG7) + DbgPrint("DEVICE-VENDER=0x%x\n",ReadValue); +#endif + DispDbgPrint(("DEC G/A found 200\n")); + + if (ReadValue == 0x00041011){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); + +#if defined (DBG7) + DbgPrint("PCI-COMMAND=0x%x\n",ReadValue); +#endif + + if ((ReadValue & 0x00000002) == 0x2){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); +#if defined (DBG7) + DbgPrint("DISPLAY-MEMORY-BASE=0x%x\n",ReadValue); +#endif + HalpDisplayControlBase = + (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + HalpDisplayControlBase |= 0x40000000; +#if defined (DBG7) + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x14); + DbgPrint("DISPLAY-IO-BASE=0x%x\n",ReadValue); + DbgPrint("DEC G/A HalpDisplayControlBase=0x%x\n",HalpDisplayControlBase); +#endif + DispDbgPrint(("DEC G/A found 2\n")); + + } else { + + DispDbgPrint(("DEC G/A found 2-1\n")); + + return FALSE; + } + } + } + + DispDbgPrint(("DEC G/A found 3-0\n")); + + if (HalpNumberOfPonce == 2){ + + DispDbgPrint(("DEC G/A found 3\n")); + + HalpPonceConfigAddrReg += 0x400; + HalpPonceConfigDataReg += 0x400; + HalpPoncePerrm += 0x400; + HalpPoncePaerr += 0x400; + HalpPoncePerst += 0x400; + + for (Slot.u.bits.DeviceNumber = 5; Slot.u.bits.DeviceNumber < 7; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + +#if defined (DBG7) + DbgPrint("DEVICE-VENDER=0x%x\n",ReadValue); +#endif + + if (ReadValue == 0x00041011){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); + +#if defined (DBG7) + DbgPrint("PCI-COMMAND=0x%x\n",ReadValue); +#endif + + if ((ReadValue & 0x00000002) == 0x2){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); +#if defined (DBG7) + DbgPrint("DISPLAY-MEMORY-BASE=0x%x\n",ReadValue); +#endif + HalpDisplayControlBase = + (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + HalpDisplayControlBase |= 0x80000000; + +#if defined (DBG7) + DbgPrint("DEC G/A HalpDisplayControlBase=0x%x\n",HalpDisplayControlBase); + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x14); + DbgPrint("DISPLAY-IO-BASE=0x%x\n",ReadValue); +#endif + + DispDbgPrint(("DEC G/A found 4\n")); + + } else { + + DispDbgPrint(("DEC G/A found 4-1\n")); + + return FALSE; + } + } + } + } else { + + DispDbgPrint(("DEC G/A found 5\n")); + + HalpPonceConfigAddrReg += 0x800; + HalpPonceConfigDataReg += 0x800; + HalpPoncePerrm += 0x800; + HalpPoncePaerr += 0x800; + HalpPoncePerst += 0x800; + + for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 5; 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; + HalpDisplayControlBase |= 0xC0000000; + } else { + return FALSE; + } + } + } + } + // S001 vvv + } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"3D3D0001")) { + + ULONG ponceNumber; + ULONG glintFound=FALSE; + + // + // for GLINT 300SX PCI + // + + DispDbgPrint(("Hal: GLiNT config entry found\n")); + + HalpDisplayControllerSetup = HalpDisplayGlintSetup; + HalpDisplayCharacter = HalpDisplayCharacterOld; + HalpDisplayPCIDevice = TRUE; + HalpDisplayType16BPP = TRUE; + + // + // FunctionNumber always zero + // + + Slot.u.bits.FunctionNumber = 0; + + for (ponceNumber = 0; ponceNumber < R98B_MAX_PONCE ; ponceNumber++) { + ULONG startDevNum; + ULONG endDevNum; + ULONG addressOffset; + + HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400); + HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400); + HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400); + HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400); + HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400); + + addressOffset = (ponceNumber+1) * 0x40000000; + + DispDbgPrint(("Hal: search GLiNT board on PONCE#%d\n", ponceNumber)); + + switch(ponceNumber){ + case 0: + startDevNum = 2; + endDevNum = 5; + break; + + case 1: + if (HalpNumberOfPonce == 3) { + DispDbgPrint(("Hal: Skip PONCE#1\n")); + continue; + } + startDevNum = 3; + endDevNum = 6; + break; + + case 2: + if (HalpNumberOfPonce == 2) { + DispDbgPrint(("Hal: Skip PONCE#2\n")); + continue; + } + startDevNum = 1; + endDevNum = 4; + break; + + default: + continue; + } + + for (Slot.u.bits.DeviceNumber = startDevNum; + Slot.u.bits.DeviceNumber <= endDevNum; + Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (ReadValue == 0x00013d3d){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x4); + + DispDbgPrint(("Hal: GLiNT found on PONCE#%d, Device=%d\n", ponceNumber,Slot.u.bits.DeviceNumber)); + + // + // GLINT 300SX has no I/O space regions + // + + if (ReadValue & 0x2){ + + // + // Control Registers + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + HalpDisplayControlBase = (ReadValue & 0xfffffff0); + HalpDisplayControlBase |= addressOffset; + + DispDbgPrint(("Hal: GLiNT HalpDisplayControlBase=0x%08lx\n", HalpDisplayControlBase)); + // + // Framebuffer + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + HalpDisplayMemoryBase = (ReadValue & 0xfffffff0); + HalpDisplayMemoryBase |= addressOffset; + + DispDbgPrint(("Hal: GLiNT HalpDisplayMemoryBase=0x%08lx\n", HalpDisplayMemoryBase)); + // + // Revision ID + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x08); + + HalpGlintRevisionId = (ReadValue & 0x000000ff); + + DispDbgPrint(("Hal: GLiNT HalpGlintRevisionId=0x%08lx\n", HalpGlintRevisionId)); + + // + // Enable ROM. + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x30); + ReadValue |= 0x1; + HalpWritePCIConfigUlongByOffset(Slot,&ReadValue, 0x30); + + glintFound = TRUE; + + break; + + } else { + DispDbgPrint(("Hal: GLiNT have not I/O space\n")); + + return FALSE; + + } + } + } + + if(glintFound == TRUE) { + DispDbgPrint(("Hal: GLiNT adapter already found\n")); + break; + } + } + + } else { + DispDbgPrint(("DisplayTypeUnknown\n")); + + HalpDisplayControllerSetup = HalpDisplayINT10Setup; + HalpDisplayCharacter = HalpDisplayCharacterVGA; + HalpDisplayControlBase = PCI_0_IO_BASE; + HalpDisplayTypeUnknown = TRUE; + // S001 ^^^ + } + + Child = ConfigurationEntry->Child; + + DispDbgPrint(("Hal: parameters read start\n")); + + RtlMoveMemory((PVOID)&HalpMonitorConfigurationData, + Child->ConfigurationData, + Child->ComponentEntry.ConfigurationDataLength); + + // + // Compute character output display parameters. + // + + HalpDisplayText = + HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight; + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpScrollLine = + 1024 * HalpCharacterHeight; + // S001 vvv + } else if (HalpDisplayType16BPP) { + HalpScrollLine = + HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight * sizeof(USHORT); + // S001 ^^^ + } else { + HalpScrollLine = + HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight; + } + + HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpDisplayWidth = + 1024 / HalpCharacterWidth; + + }else{ + + HalpDisplayWidth = + HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth; + } + + DispDbgPrint(("Hal: HalpDisplayText = %d\n", HalpDisplayText)); + DispDbgPrint(("Hal: HalpDisplayWidth = %d\n", HalpDisplayWidth)); + DispDbgPrint(("Hal: HalpScrollLine = %d\n", HalpScrollLine)); + DispDbgPrint(("Hal: HalpScrollLength = %d\n", HalpScrollLength)); + + // + // Scan the memory allocation descriptors and allocate a free page + // to map the video memory and control registers, and initialize the + // PDE entry. + // + + DispDbgPrint(("Hal: Mem get \n")); + + 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; + + Pte.C = UNCACHED_POLICY; + + // + // 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))); + + // S001 vvv + if (HalpDisplayControllerSetup == HalpDisplayINT10Setup) { + + HalpCirrusPhigicalVideo.HighPart = 1; + HalpCirrusPhigicalVideo.LowPart = 0x40000000; + + Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + }else + // S001 ^^^ + if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { + + HalpCirrusPhigicalVideo.HighPart = 1; + HalpCirrusPhigicalVideo.LowPart = CIRRUS_MEMORY_BASE_LOW; + + 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; + +#if defined (DBG7) + DbgPrint("DEC G/A HalpTgaPhigicalVideo.HighPart=0x%x\n",HalpTgaPhigicalVideo.HighPart); + DbgPrint("DEC G/A HalpTgaPhigicalVideo.LowPart=0x%x\n",HalpTgaPhigicalVideo.LowPart); +#endif + + Pte.PFN = (HalpTgaPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + + } + // S001 vvv + 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); + } + // S001 ^^^ + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + Pte.C = UNCACHED_POLICY; + + // + // 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) { + HalpTgaPhigicalVideo.HighPart = 1; + HalpTgaPhigicalVideo.LowPart = HalpDisplayControlBase; + Pte.PFN = (HalpDisplayControlBase >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpTgaPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + *PageFrame = Pte; + + // S001 vvv + } 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){ + DispDbgPrint(("HAL: Map x86 and cirrus control register\n")); + + Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT; + + for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) { + *PageFrame-- = Pte; + DispDbgPrint(("HAL: Map index %x pfn %x\n",Index,Pte.PFN)); + Pte.PFN -= 1; + } + // S001 ^^^ + } else { + + // + // Page table for the video registers. + // + + Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + *PageFrame = Pte; + } + + // + // Initialize the display controller. + // + + // S001 vvv + if(HalpDisplayControllerSetup == HalpDisplayINT10Setup){ + if (HalpInitializeX86DisplayAdapter()) { +// HalpDisplayControllerSetup(); // initialize twice bugbug + }else{ + return FALSE; + } + } + // S001 ^^^ + HalpDisplayControllerSetup(); + + HalpInitDisplayStringIntoNvram(); + + 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; + + HalpSetInitDisplayTimeStamp(); + + 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. + +--*/ + +{ + HalpSuccessOsStartUp(); + + // + // Set HAL ownership of the display to false. + // + + HalpResetDisplayParameters=ResetDisplayParameters; // S001 + HalpMrcModeChange((UCHAR)MRC_OP_DUMP_ONLY_NMI); + HalpDisplayOwnedByHal = FALSE; + + DispDbgPrint(("HAL: DisplayOwnedByHal = FALSE, DispResetRoutine = 0x%x\n", + (ULONG)HalpResetDisplayParameters)); + + 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, dac_dmyread; + +#if defined(DBCS) && defined(_MIPS_) + 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 ) { + DispDbgPrint(("HAL: 640x480 60Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + DispDbgPrint(("HAL: 640x480 72Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_640x480_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 800: + if( verticalFrequency < 58 ) { + DispDbgPrint(("HAL: 800x600 56Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_800x600_256_56); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 66 ) { + DispDbgPrint(("HAL: 800x600 60Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_800x600_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + DispDbgPrint(("HAL: 800x600 72Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_800x600_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 1024: + if( verticalFrequency < 52 ) { + DispDbgPrint(("HAL: 1024x768 87Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 65 ) { + DispDbgPrint(("HAL: 1024x768 60Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 78 ) { + DispDbgPrint(("HAL: 1024x768 70Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { + DispDbgPrint(("HAL: 1024x768 87Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + default: + DispDbgPrint(("HAL: 640x480 60Hz setup\n")); + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); +// return; + } +#else // defined(DBCS) && defined(_MIPS_) + + switch (HalpMonitorConfigurationData.HorizontalResolution) { + case 640: + + DispDbgPrint(("640x480 setup\n")); + + HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + case 800: + + DispDbgPrint(("800x600 setup\n")); + + HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + case 1024: + + DispDbgPrint(("1024x768 setup\n")); + + HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + default: + return; + } +#endif // defined(DBCS) && defined(_MIPS_) + + DispDbgPrint(("color set\n")); + + dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT; + dac_dmyread = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_STATE_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); + READ_PORT_UCHAR((PUCHAR)dac_dmyread); + + 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)); + READ_PORT_UCHAR((PUCHAR)dac_dmyread); + + // + // 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; + + 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 }; + const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 }; + const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; + + const UCHAR Vga_Ini_ColorTable[48] = + { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, + 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_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, + 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 + }; + + DispDbgPrint(("TGA Set Up IN\n")); + + // + // 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; + } else { + PLLbits = (PVOID)PLLbits640x480_60; + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 ){ + if( VerticalFrequency > 66 ){ + PLLbits = (PVOID)PLLbits800x600_72; + } else { + PLLbits = (PVOID)PLLbits800x600_60; + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 ){ + PLLbits = (PVOID)PLLbits1024x768_60; + } else { + PLLbits = (PVOID)PLLbits640x480_60; + } + + // 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); + } + } +#if defined (DBG7) + DbgPrint("TGA Set Up 1\n"); + + DbgPrint("TGA_REGISTER_BASE=0x%x\n",TGA_REGISTER_BASE); + DbgPrint("COMMAND_STATUS=0x%x\n",COMMAND_STATUS); + DbgPrint("TGA_REGISTER_BASE + COMMAND_STATUS=0x%x\n",(READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ))); +#endif + + // Verify 21030 is idle ( check busy bit on Command Status Register ) + while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ + } +#if defined (DBG7) + DbgPrint("TGA Set Up 2\n"); +#endif + + // 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 ){ + } +#if defined (DBG7) + DbgPrint("TGA Set Up 3\n"); +#endif + + // 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), 0x3c294a0 ); // K1001 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001 + 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), 0x1a7a4c8 ); // K1001 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x2681cc8 ); // K1001 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 ); + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 ){ + //60Hz Only + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x4889300 ); // // K1001 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 ); + } else { + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001 + 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 ); +#if defined (DBG7) + DbgPrint("TGA Set Up 4\n"); +#endif + + KeStallExecutionProcessor(10000L); +#if defined (DBG7) + DbgPrint("TGA Set Up 5\n"); +#endif + + // 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; +#if defined (DBG7) + DbgPrint("TGA Set Up End\n"); +#endif + + 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; + ULONG NowDisplayControlBase; + ULONG NowDisplayMemoryBase; + PENTRYLO PageFrame; + ENTRYLO Pte; + LONG Index; + PCI_SLOT_NUMBER Slot; + ULONG ReadValue; + ULONG cpu; + + // + // 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. + // + +// DispDbgPrint(("HalDisplayString\n")); + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + KiAcquireSpinLock(&HalpDisplayAdapterLock); + + // S001 vvv + HalpPonceConfigAddrReg = PONCE_ADDR_REG; + HalpPonceConfigDataReg = PONCE_DATA_REG; + HalpPoncePerrm = PONCE_PERRM; + HalpPoncePaerr = PONCE_PAERR; + HalpPoncePerst = PONCE_PERST; + // S001 ^^^ + + 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; + + if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + + HalpPonceConfigAddrReg += 0x400; + HalpPonceConfigDataReg += 0x400; + HalpPoncePerrm += 0x400; + HalpPoncePaerr += 0x400; + HalpPoncePerst += 0x400; + + Slot.u.bits.DeviceNumber = 4; + + HalpReadPCIConfigUlongByOffset( Slot,&ReadValue,0x14); + + DispDbgPrint(("CirrusControlBase:=0x%x\n",ReadValue)); + + NowDisplayControlBase = (ReadValue & 0x0000fc00) + PCI_1_IO_BASE; + HalpReadPCIConfigUlongByOffset( Slot,&ReadValue,0x10); + + DispDbgPrint(("NowDisplayControlBase = 0x%x\n",NowDisplayControlBase)); + DispDbgPrint(("CirrusMemoryBase:=0x%x\n",ReadValue)); + + NowDisplayMemoryBase = (ReadValue & 0xff000000) + 0x80000000; + + DispDbgPrint(("NowDisplayMemoryBase = 0x%x\n",NowDisplayMemoryBase)); + + } else { + + for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 6; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){ + // + // DEC 21030 + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + DispDbgPrint(("DECControlBase:=0x%x\n",ReadValue)); + NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + NowDisplayControlBase |= 0x40000000; + NowDisplayMemoryBase = 0; + + // S001 vvv + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){ + // + // GLINT 300SX + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0); + NowDisplayControlBase |= 0x40000000; + DispDbgPrint(("HAL:GLiNTCtrlBase=0x%08lx,Now=0x%08lx\n", + ReadValue, NowDisplayControlBase)); + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + NowDisplayMemoryBase = (ReadValue & 0xfffffff0); + NowDisplayMemoryBase |= 0x40000000; + DispDbgPrint(("HAL:GLiNTMemBase =0x%08lx,Now=0x%08lx\n", + ReadValue, NowDisplayMemoryBase)); + // S001 ^^^ + } + } + if (HalpNumberOfPonce == 2){ + + HalpPonceConfigAddrReg += 0x400; + HalpPonceConfigDataReg += 0x400; + HalpPoncePerrm += 0x400; + HalpPoncePaerr += 0x400; + HalpPoncePerst += 0x400; + + for (Slot.u.bits.DeviceNumber = 5; Slot.u.bits.DeviceNumber < 7; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){ + // + // DEC 21030 + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + NowDisplayControlBase |= 0x80000000; + NowDisplayMemoryBase = 0; + // S001 vvv + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){ + // + // GLINT 300SX + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0); + NowDisplayControlBase |= 0x80000000; + DispDbgPrint(("HAL:GLiNTCtrlBase=0x%08lx,Now=0x%08lx\n", + ReadValue, NowDisplayControlBase)); + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + NowDisplayMemoryBase = (ReadValue & 0xfffffff0); + NowDisplayMemoryBase |= 0x80000000; + DispDbgPrint(("HAL:GLiNTMemBase =0x%08lx,Now=0x%08lx\n", + ReadValue, NowDisplayMemoryBase)); + // S001 ^^^ + } + } + } else { + HalpPonceConfigAddrReg += 0x800; + HalpPonceConfigDataReg += 0x800; + HalpPoncePerrm += 0x800; + HalpPoncePaerr += 0x800; + HalpPoncePerst += 0x800; + + for (Slot.u.bits.DeviceNumber = 1; Slot.u.bits.DeviceNumber < 5; Slot.u.bits.DeviceNumber++){ + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0); + + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup && ReadValue == 0x00041011){ + + // + // DEC 21030 + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue,0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0) + TGA_REG_SPC_OFFSET; + NowDisplayControlBase |= 0xC0000000; + NowDisplayMemoryBase = 0; + + // S001 vvv + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup && ReadValue == 0x00013d3d){ + // + // GLINT 300SX + // + + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x10); + NowDisplayControlBase = (ReadValue & 0xfffffff0); + NowDisplayControlBase |= 0xc0000000; + HalpReadPCIConfigUlongByOffset(Slot,&ReadValue, 0x18); + NowDisplayMemoryBase = (ReadValue & 0xfffffff0); + NowDisplayMemoryBase |= 0xc0000000; + // S001 ^^^ + } + } + } + } + + // + // 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; + Pte.C = UNCACHED_POLICY; + + PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { + HalpCirrusPhigicalVideo.HighPart = 1; + HalpCirrusPhigicalVideo.LowPart = HalpDisplayMemoryBase; + Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + + } else 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); + // S001 vvv + } else if (HalpDisplayControllerSetup == HalpDisplayGlintSetup) { + HalpGlintPhygicalVideo.HighPart = 1; + HalpGlintPhygicalVideo.LowPart = HalpDisplayMemoryBase; + Pte.PFN = (HalpGlintPhygicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpGlintPhygicalVideo.HighPart << (32 - PAGE_SHIFT); + // S001 ^^^ + } + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { + + // + // Page table for the video registers. + // + + Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + *PageFrame = Pte; + + } else 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; + // S001 vvv + } 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; + // S001 ^^^ + } + } + } + + // + // 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) { + // S001 vvv + + DispDbgPrint(("HAL: Re Initialize Controller\n")); + DispDbgPrint(("HAL: Str = %s\n",String)); + + 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. + // + + DispDbgPrint(("HAL: Call x86 reset routine\n")); + + if (HalpResetDisplayParameters(80, 50)) { + } + } + // S001 ^^^ + + if(HalpNMIFlag == 0){ + // + // Non NMI. It is Panic. + // + HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI); + // + // Do not make eif. retun only at dump key + // + for (cpu=0;cpu < R98B_MAX_CPU;cpu++) + HalpNMIHappend[cpu] = 1; + } + + DispDbgPrint(("HAL: Call DisplayControllerSetup\n")); + + HalpDisplayControllerSetup(); + HalpInitDisplayStringIntoNvram(); +// HalpResetX86DisplayAdapter(); /* for X86 */ + } + + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + // + // Display characters until a null byte is encountered. + // + + while (*String != 0) { + HalpDisplayCharacter(*String++); + } + + 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; + + KiReleaseSpinLock(&HalpDisplayAdapterLock); + + 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; // S001 + 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 { +#if 0 + RtlMoveMemory((PVOID)VIDEO_MEMORY_BASE, + (PVOID)(VIDEO_MEMORY_BASE + HalpScrollLine), + HalpScrollLength); +#else + HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE, + (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), + HalpScrollLength); +#endif + + // S001 vvv + if (HalpDisplayType16BPP) { + DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + HalpScrollLength); // M022 + } 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; + } + } + // S001 ^^^ + } + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + } else if (Character == '\r') { + HalpColumn = 0; + + HalpStringBufferCopyToNvram(); + HalStringIntoBufferStart( HalpColumn, HalpRow ); + + } else { + HalStringIntoBuffer( Character ); + + if ((Character < HalpFontHeader->FirstCharacter) || + (Character > HalpFontHeader->LastCharacter)) { + Character = HalpFontHeader->DefaultCharacter; + } + + Character -= HalpFontHeader->FirstCharacter; + HalpOutputCharacterOld((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset); + } + + return; +} + +// S001 vvv +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); + } + } + + //========================================================================= + // + // 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') { + HalpColumn = 0; + } else if (Character == 0x7f) { /* DEL character */ + if (HalpColumn != 0) { + HalpColumn -= 1; + HalpOutputCharacterINT10(0); + HalpColumn -= 1; + } else /* do nothing */ + ; + } else if (Character >= 0x20) { + // 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() */ +// S001 ^^^ + +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; // S001 + 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. + // + + // S001 vvv + if (HalpDisplayType16BPP) { + DestinationShort = (PUSHORT)(VIDEO_MEMORY_BASE + + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth * sizeof(USHORT))); + } else { + Destination = (PUCHAR)(VIDEO_MEMORY_BASE + + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth)); + } + // S001 ^^^ + + 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) { + // S001 vvv + if (HalpDisplayType16BPP) { + if (FontValue >> 31) + *DestinationShort++ = (USHORT)0xffff; + else + *DestinationShort++ = (USHORT)0x000f; + }else{ + *Destination++ = (UCHAR) (FontValue >> 31) ^ 1; + } + // S001 ^^^ + FontValue <<= 1; + } + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + Destination += + (1024 - HalpCharacterWidth); + // S001 vvv + } else if (HalpDisplayType16BPP){ + DestinationShort += + (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); + // S001 ^^^ + } else { + Destination += + (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); + } + } + HalpColumn += 1; + return; +} + +VOID +Write_Dbg_Uchar( + PUCHAR Ioadress, + UCHAR Moji + ) +{ +// DispDbgPrint(("Disply I/O Adress %x Char %x \n",Ioadress,Moji)); + + WRITE_PORT_UCHAR(Ioadress,Moji); +} + +// S001 vvv +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 + 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; + HalpScrollLine = 160; + HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); + + HalpDisplayOwnedByHal = TRUE; + + HalpResetX86DisplayAdapter(); // for compaq q-vision reset + + // + // Load 8x8 font 80x50 on VGA + // + Eax = 0x1112; // AH = 11 AL=12 + Ebx = 0; + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + + // + // 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); + +} +// S001 ^^^ +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; + + // + // Disable PCI-MasterAbort interrupt during configration read. + // + +// DispDbgPrint(("Hal: Chk perrmAddr=0x%x, paerrAddr=0x%x\n",HalpPoncePerrm, HalpPoncePaerr)); + + OrigData = READ_REGISTER_ULONG(HalpPoncePerrm); + +// DispDbgPrint(("Hal: origdata perrm data=0x%08lx\n",OrigData)); + + WRITE_REGISTER_ULONG(HalpPoncePerrm, OrigData | 0x00800000); + + // + // 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; + +// DispDbgPrint(("Hal: deviceNum=%d, funcNum=%d\n",Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber)); + + // + // Synchronize with PCI configuration + // + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + IdValue = READ_REGISTER_ULONG(HalpPonceConfigDataReg); + + // + // Release spinlock + // + + if ((USHORT)(IdValue & 0xffff) == 0xffff){ + + // + // waiting until ReceivedMasterAbort bit is set + // + +// DispDbgPrint(("Hal: chk 0\n")); +// DispDbgPrint(("Hal: PERRI = 0x%x\n",READ_REGISTER_ULONG((PULONG)0xba000818))); +// DispDbgPrint(("Hal: paerr = 0x%x\n",READ_REGISTER_ULONG(HalpPoncePaerr))); + + // + // clear the ReceivedMasterAbort bit + // + + WRITE_REGISTER_ULONG(HalpPoncePerst, 0x00800000); + + // + // Clear memory address error registers. + // + +// { +// LARGE_INTEGER registerLarge; +// READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge); +// } + +// DispDbgPrint(("Hal: chk 1\n")); + + ReturnValue = FALSE; + + } else { + +// DispDbgPrint(("Hal: chk 2\n")); + + ReturnValue = TRUE; + + } + + // + // Restore the PCIInterruptEnable register. + // + + WRITE_REGISTER_ULONG(HalpPoncePerrm, OrigData); + +// DispDbgPrint(("Hal: chk 3\n")); + + return ReturnValue; +} +// S001 vvv +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 */ + DispDbgPrint(("Hal: GLiNT Display setup\n")); + + if ( HalpGlintRevisionId == 0){ + Video->RefDivCount = RGB525_PLL_REFCLK_40_MHz; + } else { + Video->RefDivCount = RGB525_PLL_REFCLK_50_MHz; + } + + // + // 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_ + + DispDbgPrint(("HAL: VerticalResolution=%d\n",HalpMonitorConfigurationData.VerticalResolution)); + DispDbgPrint(("HAL: horizontalTotal=%d\n",horizontalTotal)); + DispDbgPrint(("HAL: verticalTotal=%d\n",verticalTotal)); + + // + // Initialize video data + // + + /* get timing values for named resolution */ + + if ( HalpMonitorConfigurationData.HorizontalResolution == 1280 + && HalpMonitorConfigurationData.VerticalResolution == 1024 + && VerticalFrequency == 75) + { + DispDbgPrint(("HAL: GLiNT 1280x1024 75Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 1024x768 75Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 1024x768 60Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 800x600 75Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 800x600 60Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 640x480 60Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 640x480 75Hz setup\n")); + 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) + { + DispDbgPrint(("HAL: GLiNT 1280x1024 57Hz setup\n")); + 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) + // + + DispDbgPrint(("HAL: GLiNT 1024x768 60Hz setup (default setting)\n")); + 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) * 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; +} + +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 + // + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_ULONG(HalpPonceConfigDataReg); + + return; +} + +VOID +HalpReadPCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUSHORT Buffer, + IN ULONG Offset + ) +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + if (!HalpCheckPCIDevice(Slot)) { + *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; + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_USHORT((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG))); + + return; +} + +VOID +HalpReadPCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + if (!HalpCheckPCIDevice(Slot)) { + *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; + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + *Buffer = READ_REGISTER_UCHAR((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG))); + + return; +} + +VOID +HalpWritePCIConfigUlongByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PULONG Buffer, + IN ULONG Offset + ) +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + if (!HalpCheckPCIDevice(Slot)) { + *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; + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + WRITE_REGISTER_ULONG(HalpPonceConfigDataReg, *Buffer); + + return; +} + +VOID +HalpWritePCIConfigUshortByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUSHORT Buffer, + IN ULONG Offset + ) +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + if (!HalpCheckPCIDevice(Slot)) { + *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; + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + WRITE_REGISTER_USHORT((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)),*Buffer); + + return; +} + +VOID +HalpWritePCIConfigUcharByOffset ( + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + R94A_PCI_CONFIGURATION_ADDRESS_REG ConfigAddressValue; + USHORT StatusValue; + KIRQL OldIrql; + + if (!HalpCheckPCIDevice(Slot)) { + *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; + + WRITE_REGISTER_ULONG(HalpPonceConfigAddrReg, *((PULONG) &ConfigAddressValue)); + + WRITE_REGISTER_UCHAR((PUCHAR)HalpPonceConfigDataReg + (Offset % sizeof(ULONG)), *Buffer); + + return; +} +// S001 ^^^ diff --git a/private/ntos/nthals/halr98b/mips/jxebsup.c b/private/ntos/nthals/halr98b/mips/jxebsup.c new file mode 100644 index 000000000..2b513060c --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxebsup.c @@ -0,0 +1,1178 @@ +/*++ + +Copyright (c) 1990-1994 Microsoft Corporation + +Module Name: + + jxebsup.c + +Abstract: + + The module provides the EISA bus support for R98B systems. + +--*/ + +#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 + ); + +// +// 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; + + +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; // S004 + + 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 (channelNumber) { + 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; // S004 + + 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; + KIRQL oldIrql; + UCHAR charBuffer; + + + // + // 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_DISPATCH_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch; + + // + // Raise the IRQL while the EISA interrupt controller is initalized. + // + KeRaiseIrql(EISA_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; + + // + // Restore IRQL level. + // + + KeLowerIrql(oldIrql); + + + // + // EISA Interrupt to PONCE Enable!!. + // + HalpInterruptFromPonce(EISA_DISPATCH_VECTOR ,1); //SNES + + // + // 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 + ); + + + + charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus ); + // + // IOCHK# NMI Disable and Clear + // PERR# PCI System Board Error Disable + // + charBuffer = ((charBuffer & 0x03) | 0x0C); + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, + charBuffer + ); + // + // Disbale Bus Timeout,Fail Safe NMI adn Software NMI + // + charBuffer = READ_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl + ); + + charBuffer = (charBuffer & 0x01); + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, + charBuffer ); + + return(TRUE); +} + + +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 + ); + + } + +} +// +// +//extern KSPIN_LOCK HalpIoMapSpinLock; +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; + KIRQL Irql; + + BytePtr = (PUCHAR) &Offset; + +// ASSERT(Offset >= 0x100000); // S009 + + + // + // grab the spinlock for the system DMA controller + // Internal Floppy Device used ESC DMA and May be diffirent Onprocessor + // with EISA Drivers OnProcessor. + // So grab. + + KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql ); + + + 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) + ); + + } + KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql); + 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) + ); + } + + KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql); + +} + + +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 EISA 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 +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; + + // + // Read the interrupt vector. + // + + interruptVector = (UCHAR)READ_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->INTAC); + + + // + // 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) { + //K001 Start + if(interruptVector == 7|| interruptVector==15 ){ + + PVOID IsrPortAddr; + UCHAR IsrValue; + +#define OCW3_READ_ISR 0x0B +#define OCW3_READ_IRR 0x0A + + // + // Master or Slave ? + // + IsrPortAddr = (interruptVector == 7) ? + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0: + &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0; + + // SetUp to ISR Regsiter + WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR ); + // Read ISR Register + IsrValue=READ_REGISTER_UCHAR( IsrPortAddr ); + // Resume to IRR Register + WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR); + + if(!IsrValue){ + // This is a spurious interrupt!!. No Call Driver. + goto NocallDriver; + } + } + // K001 End + + // + // Mask the upper bits off since the vector is only a byte and + // dispatch to the secondary interrupt service routine. + // + + interruptVector &= 0xff; + dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]); + interruptObject = CONTAINING_RECORD(dispatchCode, + KINTERRUPT, + DispatchCode); + + returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject); + +NocallDriver: + + // + // 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 = HalHandleNMI(NULL, NULL); +// } + + } else { + returnValue = FALSE; + } + + return returnValue; +} + + +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. + +--*/ +{ + KeBugCheck(NMI_HARDWARE_FAILURE); + return(TRUE); +} diff --git a/private/ntos/nthals/halr98b/mips/jxenvirv.c b/private/ntos/nthals/halr98b/mips/jxenvirv.c new file mode 100644 index 000000000..e6cef4381 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxenvirv.c @@ -0,0 +1,691 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxenvirv.c + +Abstract: + + This module implements the HAL get and set environment variable routines + for a R98B system. + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "arccodes.h" +#include "rxnvr.h" +#include "string.h" + +// +// Define base address at which to map NVRAM. +// +// +// Define local upcase macro. +// + +#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c)) + +KIRQL +HalpMapNvram ( + IN PENTRYLO SavedPte + ) + +/*++ + +Routine Description: + + This function is called to map the NVRAM into the address space of + the current process. + +Arguments: + + SavedPte - Supplies a pointer to an array which receives the old NVRAM + PTE values. + +Return Value: + + The previous IRQL is returned as the function value. + +--*/ + +{ + + KIRQL OldIrql; + // + // disable nvram Write protection. Set Write Enable + // +#if 0 + // + // No Gard. for Driver. Fix. + // + + + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_WNVWINH); +#endif + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + return OldIrql; +} + +VOID +HalpUnmapNvram ( + IN PENTRYLO SavedPte, + IN KIRQL OldIrql + ) + +/*++ + +Routine Description: + + This function is called to unmap the NVRAM from the address space of + the current process. + +Arguments: + + SavedPte - Supplies a pointer to an array which contains the old NVRAM + PTE values. + + OldIrql - Supplies the previous IRQL value. + +Return Value: + + None. + +--*/ + +{ + +#if 0 + // N.B For Driver. + // + + // + // Set nvram write protect + // + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_NVWINH|STSR_WNVWINH); +#endif + // + // Unmap the NVRAM from the address space of the current process. + // + + 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_MEMORY_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_MEMORY_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_MEMORY_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; + ENTRYLO SavedPte[2]; + ARC_STATUS Status; + ULONG ValueIndex; + ULONG VariableIndex; + +#if defined(DBG1) + DbgPrint("NVRAM 0S\n"); +#endif + + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(&SavedPte[0]); + + // + // 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_MEMORY_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(&SavedPte[0], OldIrql); + +#if defined(DBG1) + DbgPrint("NVRAM 0E\n"); +#endif + + 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; + ENTRYLO SavedPte[2]; + ARC_STATUS Status; + ULONG TopIndex; + ULONG VariableIndex; + ULONG VariableLength; + ULONG ValueEnd; + ULONG ValueIndex; + ULONG ValueLength; + +#if DBG + DbgPrint("NVRAM 1S\n"); +#endif + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(&SavedPte[0]); + Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_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(&SavedPte[0], OldIrql); +#if DBG + DbgPrint("NVRAM 1E\n"); +#endif + + + return Status; +} + + diff --git a/private/ntos/nthals/halr98b/mips/jxmapio.c b/private/ntos/nthals/halr98b/mips/jxmapio.c new file mode 100644 index 000000000..e1daa9da5 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxmapio.c @@ -0,0 +1,124 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxmapio.c + +Abstract: + + This module implements the mapping of HAL I/O space a MIPS R98B + system. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.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, HalpMapIoSpace) + +#endif + +// +// Define global data used to locate the EISA control space and the realtime +// clock registers. +// + +PVOID HalpEisaControlBase; +PVOID HalpEisaMemoryBase; +PVOID HalpRealTimeClockBase; + +BOOLEAN +HalpMapIoSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz + system. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ +#if defined(_R98B_) + // + // R98B EISA Control area can access KSEG1_BASE. + // N.B Implement below 64K + // But above 64K I/O area can't !! + + // + // set EISA control space. + // + + HalpEisaControlBase = (PVOID)(KSEG1_BASE + EISA_CNTL_PHYSICAL_BASE_LOW); + + // + // set realtime clock registers. + // + + HalpRealTimeClockBase = (PVOID)(KSEG1_BASE + RTCLOCK_PHYSICAL_BASE); + return TRUE; +#else // #if !defined(_R98B_) + + PHYSICAL_ADDRESS physicalAddress; + + // + // Map EISA control space. Map all 16 slots. This is done so the NMI + // code can probe the cards. + // + + physicalAddress.HighPart = 0; + physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE; + HalpEisaControlBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE * 16, + FALSE); + + // + // Map realtime clock registers. + // + + physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE; + HalpRealTimeClockBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + + // + // If either mapped address is NULL, then return FALSE as the function + // value. Otherwise, return TRUE. + // + + + if ((HalpEisaControlBase == NULL) || (HalpRealTimeClockBase == NULL)) { + return FALSE; + } else { + return TRUE; + } +#endif // #if defined(_R98B_) + +} diff --git a/private/ntos/nthals/halr98b/mips/jxmaptb.c b/private/ntos/nthals/halr98b/mips/jxmaptb.c new file mode 100644 index 000000000..db2b8a931 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxmaptb.c @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxmaptb.c + +Abstract: + + This module implements the mapping of fixed TB entries for a MIPS R98B + system. It also sets the instruction and data cache line sizes for a + R98 system. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#define HEADER_FILE +#include "kxmips.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, HalpMapFixedTbEntries) + +#endif + +BOOLEAN +HalpMapFixedTbEntries ( + VOID + ) + +/*++ + +Routine Description: + + This routine is return only. + +Arguments: + + None. + +Return Value: + + Returns TRUE. + +--*/ + +{ + return TRUE; +} + + + + + + diff --git a/private/ntos/nthals/halr98b/mips/jxport.c b/private/ntos/nthals/halr98b/mips/jxport.c new file mode 100644 index 000000000..674276641 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxport.c @@ -0,0 +1,779 @@ + +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxport.c + +Abstract: + + This module implements the code that provides communication between + the kernel debugger on a MIPS R98system and the host + system. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "jazzserp.h" + +#define HEADER_FILE +#include "kxmips.h" + + +VOID +HalpGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ); + + +#pragma alloc_text(INIT,HalpGetDivisorFromBaud) + + +// +// BUGBUG Temporarily, we use counter to do the timeout +// + +#define TIMEOUT_COUNT 1024*512 + +// +// BUGBUG Temp until we have a configuration manager. +// + +PUCHAR KdComPortInUse = NULL; +BOOLEAN KdUseModemControl = FALSE; + +// +// Define serial port read and write addresses. +// + +#define SP_READ ((PSP_READ_REGISTERS )(SERIAL0_PHYSICAL_BASE|KSEG1_BASE)) +#define SP_WRITE ((PSP_WRITE_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE)) + +// +// Define forward referenced prototypes. +// + +SP_LINE_STATUS +KdReadLsr ( + IN BOOLEAN WaitReason + ); + +// +// Define baud rate divisor to be used on the debugger port. +// + +SHORT HalpBaudRateDivisor = 0; + + +ULONG +HalpGetByte ( + IN PCHAR Input, + IN BOOLEAN Wait + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + + Wait - Supplies a boolean value that detemines whether a timeout + is applied to the input operation. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error is encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + + SP_LINE_STATUS LsrByte; + UCHAR DataByte; + ULONG TimeoutCount; + + // + // Attempt to read a byte from the debugger port until a byte is + // available or until a timeout occurs. + // + + TimeoutCount = Wait ? TIMEOUT_COUNT : 1; + do { + TimeoutCount -= 1; + + // + // Wait until data is available in the receive buffer. + // + + KeStallExecutionProcessor(1); + LsrByte = KdReadLsr(TRUE); + if (LsrByte.DataReady == 0) { + continue; + } + + // + // Read input byte and store in callers buffer. + // + + *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer); + + // + // If using modem controls, then skip any incoming data while + // ReceiveData not set. + // + + if (KdUseModemControl) { + DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) { + continue; + } + } + + // + // Return function value as the not of the error indicators. + // + + if (LsrByte.ParityError || + LsrByte.FramingError || + LsrByte.OverrunError || + LsrByte.BreakIndicator) { + return CP_GET_ERROR; + } + + return CP_GET_SUCCESS; + } while(TimeoutCount != 0); + + return CP_GET_NODATA; +} + +BOOLEAN +KdPortInitialize ( + PDEBUG_PARAMETERS DebugParameters, + PLOADER_PARAMETER_BLOCK LoaderBlock, + BOOLEAN Initialize + ) + +/*++ + +Routine Description: + + This routine initializes the serial port used by the kernel debugger + and must be called during system initialization. + +Arguments: + + DebugParameter - Supplies a pointer to the debug port parameters. + + LoaderBlock - Supplies a pointer to the loader parameter block. + + Initialize - Specifies a boolean value that determines whether the + debug port is initialized or just the debug port parameters + are captured. + +Return Value: + + A value of TRUE is returned is the port was successfully initialized. + Otherwise, a value of FALSE is returned. + +--*/ + +{ + + PCONFIGURATION_COMPONENT_DATA ConfigurationEntry; + UCHAR DataByte; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + PCM_SERIAL_DEVICE_DATA DeviceData; + PCM_PARTIAL_RESOURCE_LIST List; + ULONG MatchKey; + ULONG BaudRate; + ULONG BaudClock; + + + // + // Find the configuration information for the first serial port. + // + + if (LoaderBlock != NULL) { + MatchKey = 0; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + SerialController, + &MatchKey); + + } else { + ConfigurationEntry = NULL; + } + + if (DebugParameters->BaudRate != 0) { + BaudRate = DebugParameters->BaudRate; + } else { + BaudRate = 19200; + } + + // + // If the serial configuration entry was not found or the frequency + // specified is not supported, then default the baud clock to 800000. + // + + BaudClock = 8000000; + if (ConfigurationEntry != NULL) { + List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData; + Descriptor = &List->PartialDescriptors[List->Count]; + DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor; + if ((DeviceData->BaudClock == 1843200) || + (DeviceData->BaudClock == 4233600) || + (DeviceData->BaudClock == 8000000)) { + BaudClock = DeviceData->BaudClock; + } + } + + HalpGetDivisorFromBaud( + BaudClock, + BaudRate, + &HalpBaudRateDivisor + ); + + // + // If the debugger is not being enabled, then return. + // + + if (Initialize == FALSE) { + return TRUE; + } + + KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE; + + + // + // Clear the divisor latch, clear all interrupt enables, and reset and + // disable the FIFO's. + // + + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0); + WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0); + DataByte = 0; + ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1; + ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte); + + // + // Set the divisor latch and set the baud rate. + // + ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); + WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF)); + + WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8)); + + // + // Clear the divisor latch and set the character size to eight bits + // with one stop bit and no parity checking. + // + + DataByte = 0; + ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS; + WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte); + + // + // Set data terminal ready and request to send. + // + + DataByte = 0; + ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1; + ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1; + WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte); + + // + // Free the TB entry if one was allocated. + // + return TRUE; +} + +ULONG +KdPortGetByte ( + OUT PUCHAR Input + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger. + + N.B. It is assumed that the IRQL has been raised to the highest + level, and necessary multiprocessor synchronization has been + performed before this routine is called. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error is encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + + return HalpGetByte(Input, TRUE); +} + +ULONG +KdPortPollByte ( + OUT PUCHAR Input + ) + +/*++ + +Routine Description: + + This routine gets a byte from the serial port used by the kernel + debugger iff a byte is available. + + N.B. It is assumed that the IRQL has been raised to the highest + level, and necessary multiprocessor synchronization has been + performed before this routine is called. + +Arguments: + + Input - Supplies a pointer to a variable that receives the input + data byte. + +Return Value: + + CP_GET_SUCCESS is returned if a byte is successfully read from the + kernel debugger line. + + CP_GET_ERROR is returned if an error encountered during reading. + + CP_GET_NODATA is returned if timeout occurs. + +--*/ + +{ + + ULONG Status; + + // + // Save port status, map the serial controller, get byte from the + // debugger port is one is avaliable, restore port status, unmap + // the serial controller, and return the operation status. + // + + KdPortSave(); + Status = HalpGetByte(Input, FALSE); + KdPortRestore(); + return Status; +} + +VOID +KdPortPutByte ( + IN UCHAR Output + ) + +/*++ + +Routine Description: + + This routine puts a byte to the serial port used by the kernel debugger. + + N.B. It is assumed that the IRQL has been raised to the highest level, + and necessary multiprocessor synchronization has been performed + before this routine is called. + +Arguments: + + Output - Supplies the output data byte. + +Return Value: + + None. + +--*/ + +{ + + UCHAR DataByte; + + if (KdUseModemControl) { + // + // Modem control, make sure DSR, CTS and CD are all set before + // sending any data. + // + + for (; ;) { + DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend && + ((PSP_MODEM_STATUS)&DataByte)->DataSetReady && + ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) { + break; + } + + KdReadLsr(FALSE); + } + } + + // + // Wait for transmit ready. + // + + while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 ); + + // + // Wait for data set ready. + // + +// do { +// LsrByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); +// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0); + + // + // Transmit data. + // + + WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output); + return; +} + +VOID +KdPortRestore ( + VOID + ) + +/*++ + +Routine Description: + + This routine restores the state of the serial port after the kernel + debugger has been active. + + N.B. This routine performs no function on the Jazz system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + // + // Free the TB entry if one was allocated. + // + return; +} + +VOID +KdPortSave ( + VOID + ) + +/*++ + +Routine Description: + + This routine saves the state of the serial port and initializes the port + for use by the kernel debugger. + + N.B. This routine performs no function on the Jazz system. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + return; +} + +SP_LINE_STATUS +KdReadLsr ( + IN BOOLEAN WaitReason + ) + +/*++ + +Routine Description: + + Returns current line status. + + If status which is being waited for is ready, then the function + checks the current modem status and causes a possible display update + of the current statuses. + +Arguments: + + WaitReason - Suuplies a boolean value that determines whether the line + status is required for a receive or transmit. + +Return Value: + + The current line status is returned as the function value. + +--*/ + +{ + + static UCHAR RingFlag = 0; + UCHAR DataLsr, DataMsr; + + // + // Get the line status for a recevie or a transmit. + // + + DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus); + if (WaitReason) { + + // + // Get line status for receive data. + // + + if (((PSP_LINE_STATUS)&DataLsr)->DataReady) { + return *((PSP_LINE_STATUS)&DataLsr); + } + + } else { + + // + // Get line status for transmit empty. + // + + if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) { + return *((PSP_LINE_STATUS)&DataLsr); + } + } + + DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus); + RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2; + if (RingFlag == 3) { + + // + // The ring indicate line has toggled, use modem control from + // now on. + // + + KdUseModemControl = TRUE; + } + + return *((PSP_LINE_STATUS) &DataLsr); +} + +VOID +HalpGetDivisorFromBaud( + IN ULONG ClockRate, + IN LONG DesiredBaud, + OUT PSHORT AppropriateDivisor + ) + +/*++ + +Routine Description: + + This routine will determine a divisor based on an unvalidated + baud rate. + +Arguments: + + ClockRate - The clock input to the controller. + + DesiredBaud - The baud rate for whose divisor we seek. + + AppropriateDivisor - Given that the DesiredBaud is valid, the + SHORT pointed to by this parameter will be set to the appropriate + value. If the requested baud rate is unsupportable on the machine + return a divisor appropriate for 19200. + +Return Value: + + none. + +--*/ + +{ + + SHORT calculatedDivisor; + ULONG denominator; + ULONG remainder; + + // + // Allow up to a 1 percent error + // + + ULONG maxRemain18 = 18432; + ULONG maxRemain30 = 30720; + ULONG maxRemain42 = 42336; + ULONG maxRemain80 = 80000; + ULONG maxRemain; + + // + // Reject any non-positive bauds. + // + + denominator = DesiredBaud*(ULONG)16; + + if (DesiredBaud <= 0) { + + *AppropriateDivisor = -1; + + } else if ((LONG)denominator < DesiredBaud) { + + // + // If the desired baud was so huge that it cause the denominator + // calculation to wrap, don't support it. + // + + *AppropriateDivisor = -1; + + } else { + + if (ClockRate == 1843200) { + maxRemain = maxRemain18; + } else if (ClockRate == 3072000) { + maxRemain = maxRemain30; + } else if (ClockRate == 4233600) { + maxRemain = maxRemain42; + } else { + maxRemain = maxRemain80; + } + + calculatedDivisor = (SHORT)(ClockRate / denominator); + remainder = ClockRate % denominator; + + // + // Round up. + // + + if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) { + + calculatedDivisor++; + } + + + // + // Only let the remainder calculations effect us if + // the baud rate is > 9600. + // + + if (DesiredBaud >= 9600) { + + // + // If the remainder is less than the maximum remainder (wrt + // the ClockRate) or the remainder + the maximum remainder is + // greater than or equal to the ClockRate then assume that the + // baud is ok. + // + + if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) { + calculatedDivisor = -1; + } + + } + + // + // Don't support a baud that causes the denominator to + // be larger than the clock. + // + + if (denominator > ClockRate) { + + calculatedDivisor = -1; + + } + + // + // Ok, Now do some special casing so that things can actually continue + // working on all platforms. + // + + if (ClockRate == 1843200) { + + if (DesiredBaud == 56000) { + calculatedDivisor = 2; + } + + } else if (ClockRate == 3072000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 13; + } + + } else if (ClockRate == 4233600) { + + if (DesiredBaud == 9600) { + calculatedDivisor = 28; + } else if (DesiredBaud == 14400) { + calculatedDivisor = 18; + } else if (DesiredBaud == 19200) { + calculatedDivisor = 14; + } else if (DesiredBaud == 38400) { + calculatedDivisor = 7; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 5; + } + + } else if (ClockRate == 8000000) { + + if (DesiredBaud == 14400) { + calculatedDivisor = 35; + } else if (DesiredBaud == 56000) { + calculatedDivisor = 9; + } + + } + + *AppropriateDivisor = calculatedDivisor; + + } + + + if (*AppropriateDivisor == -1) { + + HalpGetDivisorFromBaud( + ClockRate, + 19200, + AppropriateDivisor + ); + + } + + +} diff --git a/private/ntos/nthals/halr98b/mips/jxreturn.c b/private/ntos/nthals/halr98b/mips/jxreturn.c new file mode 100644 index 000000000..58340ee80 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxreturn.c @@ -0,0 +1,181 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxreturn.c + +Abstract: + + This module implements the HAL return to firmware function. + +--*/ + +/* + * S001 1995/12/01 T.Samezima + * add x86 bios logic + * + */ + +#include "halp.h" +#define HEADER_FILE +#include "kxmips.h" + +// +// Define keyboard registers structure. +// + +typedef struct _KBD_REGISTERS { + union { + UCHAR Output; + UCHAR Input; + } Data; + UCHAR Pad0; + UCHAR Pad1; + UCHAR Pad2; + 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; + ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp; //S001 + + volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)(KEYBOARD_PHYSICAL_BASE|KSEG1_BASE); + // + // Disable Interrupts. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Case on the type of return. + // + + switch (Routine) { + case HalHaltRoutine: + + // + // Hang looping. + // + + for (;;) { + } + + case HalPowerDownRoutine: + + // S001 vvv + // + // Reset ISA Display Adapter to 80x25 color text mode. + // + + Eax = 0x12; // AH = 0 AL = 0x12 + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + // S001 ^^^ + + // + // Send Powerdown Command to the MRC. + // + + for (;TRUE;) { + { + UCHAR Data; + Data = 0x1; + HalpLocalDeviceReadWrite(MRC_SWPOWEROFF, &Data, LOCALDEV_OP_WRITE); + } + } + + case HalRestartRoutine: + case HalRebootRoutine: + case HalInteractiveModeRoutine: +#if 1 + { +#if 0 + DbgPrint("Hal return 0\n"); +#endif + HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI); +#if 0 + DbgPrint("Hal return 1\n"); +#endif + + } +#endif + + + // S001 vvv + // + // Reset ISA Display Adapter to 80x25 color text mode. + // + + Eax = 0x12; // AH = 0 AL = 0x12 + HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp); + // S001 ^^^ + + // + // Reset ISA Display Adapter to 80x25 color text mode. + // + + HalpResetX86DisplayAdapter(); + + // + // 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/halr98b/mips/jxsysint.c b/private/ntos/nthals/halr98b/mips/jxsysint.c new file mode 100644 index 000000000..ad8ddc460 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxsysint.c @@ -0,0 +1,327 @@ + +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxsysint.c + +Abstract: + + This module implements the HAL enable/disable system interrupt, and + request interprocessor interrupt routines for R98B + +--*/ + + +#include "halp.h" + + +// +// Define Ipi Interrupt Reqest value table. +// Index is Mask +// IntIR register target Cpu bit is Not Mask. +// Mask High Bit is IntIR Target CPU Bit Low. +// +ULONG HalpIpiIntRequestMask[] = { + IntIR_REQUEST_IPI | (0), //0: error!!. + IntIR_REQUEST_IPI | (ToNODE4), //1: to CPU #0 + IntIR_REQUEST_IPI | ( ToNODE5), //2: to CPU #1 + IntIR_REQUEST_IPI | (ToNODE4|ToNODE5 ), //3: to CPU #0 #1 + IntIR_REQUEST_IPI | ( ToNODE6), //4: to CPU #2 + IntIR_REQUEST_IPI | (ToNODE4| ToNODE6), //5: to CPU #0 #2 + IntIR_REQUEST_IPI | ( ToNODE5|ToNODE6), //6: to CPU #1 #2 + IntIR_REQUEST_IPI | (ToNODE4|ToNODE5|ToNODE6 ), //7: to CPU #0 #1 #2 + IntIR_REQUEST_IPI | ( ToNODE7), //8: to CPU #3 + IntIR_REQUEST_IPI | (ToNODE4| ToNODE7), //9: to CPU #0 #3 + IntIR_REQUEST_IPI | ( ToNODE5| ToNODE7), //10:to CPU #1 #3 + IntIR_REQUEST_IPI | (ToNODE4|ToNODE5| ToNODE7), //11:to CPU #0 #1 #3 + IntIR_REQUEST_IPI | ( ToNODE6|ToNODE7), //12:to CPU #2 #3 + IntIR_REQUEST_IPI | (ToNODE4| ToNODE6|ToNODE7), //13:to CPU #0 #2 #3 + IntIR_REQUEST_IPI | ( ToNODE5|ToNODE6|ToNODE7), //14:to CPU #1 #2 #3 + IntIR_REQUEST_IPI | (ToNODE4|ToNODE5|ToNODE6|ToNODE7) //15:to CPU #0 #1 #2 #3 + + }; + + +extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; + +ULONG +HalpAffinity2Physical ( + IN ULONG Mask + ); + + + +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); + +#if defined(DBG3) + DbgPrint("HAL Vector Disable Vector=0x%x\n",Vector); +#endif + + + + // + // If the vector number is within the range of the EISA interrupts, then + // disable the EISA interrrupt. + // + if (Vector >= EISA_VECTORS && Vector <= MAXIMUM_EISA_VECTORS){ +#if defined(DBG3) + DbgPrint("HAL Vector Disable EISA=0x%x\n",Vector); +#endif + + HalpDisableEisaInterrupt(Vector); + } + + // + // If the vector number is within the range of builtin devices, then + // disable the builtin device interrupt. + // + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + if ((Vector >= (DEVICE_VECTORS )) && (Vector <= MAXIMUM_DEVICE_VECTORS)) { +#if defined(DBG3) + DbgPrint("HAL Vector DIable EISA=0x%x\n",Vector); +#endif + + HalpInterruptFromPonce(Vector,0); + } + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + 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); + +#if defined(DBG3) + DbgPrint("HAL Vector Enable in =0x%x\n",Vector); +#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 <= MAXIMUM_EISA_VECTORS){ +#if DBG + DbgPrint("HAL Vector Enable EISA=0x%x\n",Vector); +#endif + + HalpEnableEisaInterrupt( Vector, InterruptMode); + } + + // + // If the vector number is within the range of builtin devices, then + // enable the builtin device interrupt. + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + if ((Vector >= (DEVICE_VECTORS )) && (Vector <= MAXIMUM_DEVICE_VECTORS)) { +#if defined(DBG3) + DbgPrint("HAL Vector Enable internal or PCI=0x%x\n",Vector); +#endif + + // + // enable interrupt from ponce. + // + HalpInterruptFromPonce(Vector,1); + } + +#if defined(DBG3) + DbgPrint("HAL Vector Enable Out =0x%x\n",Vector); +#endif + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + KeLowerIrql(OldIrql); + return TRUE; +} + +// +// IPI function. +// +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. + +--*/ + +{ + + ULONG IntIR; + + + + ULONG Maskp; + ULONG PhysicalNumber; + + if(!Mask){ + return; + } + + Maskp=HalpAffinity2Physical(Mask); + PhysicalNumber=HalpLogicalCPU2PhysicalCPU[(ULONG)((PCR->Prcb)->Number)]; + + + // + // Request an interprocessor interrupt on each of the specified target + // processors. + // + IntIR = HalpIpiIntRequestMask[(Maskp & 0xf)] | + ( (ATLANTIC_CODE_IPI_FROM_CPU0 + PhysicalNumber) << IntIR_CODE_BIT); + +#if defined(DBG3) + DbgPrint("IntIR = 0x%x\n",IntIR); +#endif + + // + // write IntIR Register. make ipi!! + // + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->IntIR,IntIR); + + return; +} + + + +ULONG +HalpAffinity2Physical ( + IN ULONG Mask + ) + + +/*++ + +Routine Description: + + This routine translate logical affinity into physical affinity. + +Arguments: + + Mask Losical Affinity + +Return Value: + + Physical Affinity + +--*/ +{ + + ULONG i,j,PhysicalAffinity; + + i=0; + j=0; + PhysicalAffinity=0; + + for(i=0;i<4;i++){ + + if(Mask&0x1==0x1){ + j=HalpLogicalCPU2PhysicalCPU[i]; + PhysicalAffinity=PhysicalAffinity|(0x1<<j); + } + Mask=(Mask>>1); + } + + return PhysicalAffinity; +} + diff --git a/private/ntos/nthals/halr98b/mips/jxtime.c b/private/ntos/nthals/halr98b/mips/jxtime.c new file mode 100644 index 000000000..c2678cd45 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxtime.c @@ -0,0 +1,319 @@ +#ident "@(#) NEC jxtime.c 1.4 94/11/22 20:09:27" +/*++ + +Copyright (c) 1991-1994 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. + +Environment: + + Kernel mode + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/23 T.Samezima + * + * Change Irql Level + * + *********************************************************************** + * + * S002 94.07/5 T.Samezima + * + * Change Register access mask + * + * + */ + +#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. + // + +#if defined(NT_40) + KeRaiseIrql( HIGH_LEVEL, &OldIrql); +#else + KeRaiseIrql((KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][CLOCK_VECTOR - DEVICE_VECTORS]), &OldIrql); +#endif + + 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. + // + +#if defined(NT_40) + KeRaiseIrql( HIGH_LEVEL, &OldIrql); +#else + KeRaiseIrql((KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][CLOCK_VECTOR - DEVICE_VECTORS]), &OldIrql); +#endif + + 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. + +--*/ + +{ + + // + // 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. + // + + /* Start S002 */ + Register |= 0x80; + /* End S002 */ + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + Register); + + // + // Read the realtime clock register value. + // + + return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase); +} + +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. + +--*/ + +{ + + // + // 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. + // + + /* Start S002 */ + Register |= 0x80; + /* End S002 */ + + WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable, + Register); + + // + // Write the realtime clock register value. + // + + WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value); + return; +} diff --git a/private/ntos/nthals/halr98b/mips/jxusage.c b/private/ntos/nthals/halr98b/mips/jxusage.c new file mode 100644 index 000000000..2d6809693 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/jxusage.c @@ -0,0 +1,541 @@ + +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + jxusage.c + +Abstract: + +Author: + + Ken Reneris (kenr) + +Environment: + + Kernel mode only. + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +// +// Array to remember hal's IDT usage +// +#if !defined(_R98B_) // CMP001 +extern ADDRESS_USAGE *HalpAddressUsageList; +extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif // _R98B_ + +UCHAR HalName[] = "NEC Mips HAL Frontier 3.00"; + +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 (_R98B_) +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 // _R98B_ + + +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; + + + // + // 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(_R98B_) + for(i=0; i < EISA_VECTORS; i++) { + 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) { + // + // 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); +} + + +VOID +HalReportResourceUsage( + VOID + ) +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ +{ + + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + + HalpReportResourceUsage ( + &UHalName, // descriptive name +#if 1 + PCIBus // device space interface type +#else + Internal +#endif + ); + + RtlFreeUnicodeString (&UHalName); + + // Get PCI RegInfo. + // + // + // + HalpInitializePciBus (); + + // + // SVP Board Check!! + // + HalpSVPSlotDetect(); +#if DBG + HalpDisplayAllBusRanges(); + DbgPrint("HAL Report finished\n"); +#endif +} + diff --git a/private/ntos/nthals/halr98b/mips/mipsdat.c b/private/ntos/nthals/halr98b/mips/mipsdat.c new file mode 100644 index 000000000..e50fbfe7e --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/mipsdat.c @@ -0,0 +1,137 @@ +/*++ + +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: + + +--*/ + +#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 R98_MAPREGISTER_BASE 100 + + +ADDRESS_USAGE HalpMapRegisterMemorySpace = { + NULL, CmResourceTypeMemory, InternalUsage, + { + R98_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001 + 0, 0 + } +}; + +// +// from ixdat.c +// + +UCHAR HalpSzBreak[] = "BREAK"; +UCHAR HalpSzPciLock[] = "PCILOCK"; + +// +// 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 +// +// +#if defined(MIPS) +IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[] +#else +IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif + diff --git a/private/ntos/nthals/halr98b/mips/mode542x.h b/private/ntos/nthals/halr98b/mips/mode542x.h new file mode 100644 index 000000000..00445a6d9 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/mode542x.h @@ -0,0 +1,1302 @@ +#ident "@(#) NEC mode542x.h 1.3 95/07/05 13:10:57" +/*++ + +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/halr98b/mips/modeset.h b/private/ntos/nthals/halr98b/mips/modeset.h new file mode 100644 index 000000000..b699eacc7 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/modeset.h @@ -0,0 +1,86 @@ +#ident "@(#) NEC modeset.h 1.1 94/07/05 14:06:24" +/* #pragma comment(exestr, "@(#) NEC(MIPS) modeset.h 1.3 93/10/29 12:25:59" ) */ +/*++ + +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/halr98b/mips/pcip.h b/private/ntos/nthals/halr98b/mips/pcip.h new file mode 100644 index 000000000..d0337f7d3 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/pcip.h @@ -0,0 +1,189 @@ +#ident "@(#) NEC pcip.h 1.4 95/06/19 11:13:40" + +// +// 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_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) + + +#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 + ); + +NTSTATUS +HalpGetISAFixedPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ); + + +VOID +HalpPCIPin2SystemLine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + +VOID +HalpPCISystemLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + + +// +// Prototypes for functions in ixpcibrd.c +// + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN ULONG StartPciBus, //R98B + 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/halr98b/mips/r98bdef.h b/private/ntos/nthals/halr98b/mips/r98bdef.h new file mode 100644 index 000000000..6166a583e --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/r98bdef.h @@ -0,0 +1,228 @@ +/* +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + r98bdef.h + +Abstract: + + This module is the header file that describes hardware addresses + for the r98B system. + +Author: + + + +Revision History: + +--*/ + +#ifndef _R98BDEF_ +#define _R98BDEF_ + +// +// Define the size of the DMA translation table. +// +#define DMA_TRANSLATION_LIMIT 0x5000 // translation table limit + +// +// Define the maximum number of map registers allowed per allocation. +// +// 2M 2M 2M +// + PONCE0: PONCE1: +// | | | +// | +-------------+ +// + +// + +// EISA/ISA +// Max 3 Slot + Internal Floppy(Use ESC DMA channel #2) = 4 --> 512K *4 = 2M +// +// 2M is for 1M Logical Area Reserv!!. +// +#define DMA_TRANSLATION_RESERV 0x1000 // 4k /8 = 2M +#define DMA_REQUEST_LIMIT ((DMA_TRANSLATION_LIMIT-DMA_TRANSLATION_RESERV)/(sizeof(TRANSLATION_ENTRY) * 16)) +// +//#define DMA_REQUEST_LIMIT (DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY) * 4)) +// +// N.B +// May be 1 page reserved for PCEB Prefetch cycle. +// It Cause Ponce I/O TLB page fault. +// +#define DMA_REQUEST_EISA_LIMIT (DMA_REQUEST_LIMIT-1) +#define EISA_MAX_DEVICE 3 + + +#define R98B_MAX_CPU 4 + +#define R98B_MAX_MAGELLAN 2 + +#define R98B_MAX_PONCE 3 //R100 + +#define R98_CPU_R4400 0 +#define R98_CPU_R10000 1 +#define R98_CPU_NUM_TYPE 2 + +#define DEVICE_VECTORS 32 +#define EISA_DISPATCH_VECTOR (13+DEVICE_VECTORS) +#define PARALLEL_VECTOR (14+DEVICE_VECTORS) // Parallel device interrupt vector +#define NET_VECTOR (29+DEVICE_VECTORS) // ethernet device interrupt vector +#define SCSI0_VECTOR (31+DEVICE_VECTORS) // SCSI device interrupt vector +#define SCSI1_VECTOR (30+DEVICE_VECTORS) // SCSI device interrupt vector +#define UNDEFINE_TLB_VECTOR (35+DEVICE_VECTORS) // TLB undefine address interrupt vector +#define MOUSE_VECTOR (36+DEVICE_VECTORS) // Mouse device interrupt vector +#define KEYBOARD_VECTOR (37+DEVICE_VECTORS) // Keyboard device interrupt vector +#define SERIAL1_VECTOR (38+DEVICE_VECTORS) // Serial device 1 interrupt vector +#define SERIAL0_VECTOR (39+DEVICE_VECTORS) // Serial device 0 interrupt vector +#define IPI_VECTOR3 (48+DEVICE_VECTORS) // IPI From #3 +#define IPI_VECTOR2 (49+DEVICE_VECTORS) // IPI From #2 +#define IPI_VECTOR1 (50+DEVICE_VECTORS) // IPI From #1 +#define IPI_VECTOR0 (51+DEVICE_VECTORS) // IPI From #0 +#define PROFILE_VECTOR (56+DEVICE_VECTORS) // Define Profile interrupt vector +#define CLOCK_VECTOR (57+DEVICE_VECTORS) // Define Clock interrupt vector + +#define EIF_VECTOR (61+DEVICE_VECTORS) // EIF Vector + +#define ECC_1BIT_VECTOR (62+DEVICE_VECTORS) // ECC 1bit Error interrupt vector + +//SNES #define MAXIMUM_DEVICE_VECTORS 43 // IPR Bit 43 +#define MAXIMUM_DEVICE_VECTORS (43+DEVICE_VECTORS) +// +// Define EISA device interrupt vectors. +// +#define EISA_VECTORS 16 +#define MAXIMUM_EISA_VECTORS (15 + EISA_VECTORS) // maximum EISA vector + +#define INT0_LEVEL 3 // PCR->InterruptRoutine[3] +#define INT1_LEVEL 4 // PCR->InterruptRoutine[4] +#define INT2_LEVEL 5 // PCR->InterruptRoutine[5] +#define INT3_LEVEL 6 // PCR->InterruptRoutine[6] +#define INT4_LEVEL 7 // PCR->InterruptRoutine[7] +#define INT5_LEVEL 8 // PCR->InterruptRoutine[8] + +#define EISA_LEVEL INT0_LEVEL // R98B/R98A same +#define NUMBER_OF_INT 6 + +// +// Define the minimum and maximum system time increment values in 100ns units. +// + +#define MAXIMUM_INCREMENT (10 * 1000 * 10) +#define MINIMUM_INCREMENT (1 * 1000 * 10) + +// +// +// Time increment in 1us units +// The Columbus chip clock frequency is 1.024 MHZ +#define COLUMBUS_CLOCK_FREQUENCY 1024 + +// The hardware expects that this value is decremented by one +#define CLOCK_INTERVAL (((MAXIMUM_INCREMENT * COLUMBUS_CLOCK_FREQUENCY) / 1000) / 10) + +// +// 1 Interval != 1 micro sec. ==> 1 Interval = 1/1.024 microsec +// 1 Count (H/W register) is 1/1.024 microsec +// +#define DEFAULT_PROFILETIMER_INTERVAL (500 * 10) // = 500 us (100ns units) +#define MAXIMUM_PROFILETIMER_INTERVAL (64000 * 10) // = 64 ms (100ns units) +#define DEFAULT_PROFILETIMER_COUNT (MAXIMUM_PROFILETIMER_INTERVAL / 10) //Set count value +#define MINIMUM_PROFILETIMER_INTERVAL (40 * 10) // = 40 us (100ns units) + + + + +// +// Chip Set Addr +// +#define COLUMNBS_LPHYSICAL_BASE 0x19800000 +#define COLUMNBS_GPHYSICAL_BASE 0x19000000 +#define PONCE_PHYSICAL_BASE 0x1a000000 +#define MAGELLAN_0_PHYSICAL_BASE 0x18000000 +#define MAGELLAN_1_PHYSICAL_BASE 0x18020000 +#define LOCALDEV_PHYSICAL_BASE 0x1f0f0000 + + + +#define EISA_CONTROL_PHYSICAL_BASE 0x1C000000 // physical base of EISA control +#define SERIAL0_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+0x3f8) //serial +#define KEYBOARD_PHYSICAL_BASE (EISA_CONTROL_PHYSICAL_BASE+0x60) //serial +// +// R98X have 2 I/O Area(per Ponce). But Not Use apper area!!. +// used lower area only. +// +#define PCI_CNTL_PHYSICAL_BASE 0x1c000000 +#define PCI_MAX_CNTL_SIZE 0x400000 //4M + +// +// R98X PCI Memory area size 1Gmax. Not 4G!!. +// +#define PCI_MAX_MEMORY_SIZE 0x40000000 //1G max +#define PCI_MEMORY_PHYSICAL_BASE_LOW 0x40000000 +#define PCI_MEMORY_PHYSICAL_BASE_HIGH 0x1 + +// Ponce #0 have EISA/ISA. +// +#define EISA_MEMORY_PHYSICAL_BASE_LOW PCI_MEMORY_PHYSICAL_BASE_LOW +#define EISA_MEMORY_PHYSICAL_BASE_HIGH PCI_MEMORY_PHYSICAL_BASE_HIGH + +#define EISA_CNTL_PHYSICAL_BASE PCI_CNTL_PHYSICAL_BASE +#define EISA_CNTL_PHYSICAL_BASE_LOW PCI_CNTL_PHYSICAL_BASE +#define EISA_CNTL_PHYSICAL_BASE_HIGH 0x0 + +// +// RTC Register +// +#define RTCLOCK_PHYSICAL_BASE 0x1c000071 // physical base of realtime clock + +// +// Actually nvram start at +// +#define NVRAM_ACTUALLY_PHYSICAL_BASE 0x1F080000 // physical base of NonVolatile RAM +// +// s/w read/write ble erea this address +// +#define NVRAM_PHYSICAL_BASE 0x1F082000 // physical base of NonVolatile RAM For S/W +#define NVRAM_MEMORY_BASE (KSEG1_BASE + NVRAM_PHYSICAL_BASE) + +// +// R4400 cause register. +// +#define CAUSE_INT_PEND_BIT 0xA //Int0 base + +// +// Local Device Function Operation. +// +#define LOCALDEV_OP_READ 0x1 +#define LOCALDEV_OP_WRITE 0x0 + + +// +// Local Device MRC Function Operation. +// +#define MRC_OP_DUMP_ONLY_NMI 0x1 +#define MRC_OP_DUMP_AND_POWERSW_NMI 0x0 + +// +// ECC 1bit/Multi bit Error Operation. +// +#define ECC_1BIT_ENABLE 0xfffffff5 +#define ECC_MULTI_ENABLE 0xfffffffa +#define ECC_ERROR_DISABLE 0x0000000f +#define ECC_ERROR_ENABLE 0xfffffff0 +#define MAGELLAN_ERRI_OFFSET 0x2330 + +// +// Define cause register read macro +// + +#define READ_CAUSE_REGISTER(reg) \ + .set noreorder; \ + .set noat; \ + mfc0 reg,cause; \ + nop; \ + nop; \ + .set at; \ + .set reorder; + + +#endif // _R98BDEF_ diff --git a/private/ntos/nthals/halr98b/mips/r98breg.h b/private/ntos/nthals/halr98b/mips/r98breg.h new file mode 100644 index 000000000..5fc5e2f67 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/r98breg.h @@ -0,0 +1,649 @@ + +#ifndef _R98BREG_ +#define _R98BREG_ + + +#include <r98bdef.h> +// +// R98B Chip Set Register Define +// +// +// Define COLUMBS register structure. +// +typedef struct _COLUMNBUS_REGISTER { + ULONG Long; + ULONG Fill; +} COLUMNBUS_REGISTER, *PCOLUMNBUS_REGISTER; + +typedef struct _COLUMNBUS_LARGE_REGISTER { +// ULONG Low; +// ULONG High; + + ULONGLONG Llong; +} COLUMNBUS_LARGE_REGISTER, *PCOLUMNBUS_LARGE_REGISTER; + +typedef volatile struct _COLUMNBUS_REGISTERS { + // offset(H) + COLUMNBUS_LARGE_REGISTER IPR; // 0x0 + COLUMNBUS_LARGE_REGISTER MKR; // 0x8 + COLUMNBUS_LARGE_REGISTER IPRR; // 0x10 + COLUMNBUS_REGISTER IPSR; // 0x18 + COLUMNBUS_REGISTER MKRR; // 0x20 + COLUMNBUS_REGISTER MKSR; // 0x28 + COLUMNBUS_REGISTER NMIR; // 0x30 + COLUMNBUS_REGISTER NMIRST; // 0x38 + COLUMNBUS_REGISTER TMSR1; // 0x40 + COLUMNBUS_REGISTER TMR1; // 0x48 + COLUMNBUS_REGISTER TOVCT1; // 0x50 + COLUMNBUS_REGISTER TMCR1; // 0x58 + COLUMNBUS_REGISTER TMSR2; // 0x60 + COLUMNBUS_REGISTER TMR2; // 0x68 + COLUMNBUS_REGISTER TOVCT2; // 0x70 + COLUMNBUS_REGISTER TMCR2; // 0x78 + COLUMNBUS_REGISTER WDTSR; // 0x80 + COLUMNBUS_REGISTER WDT; // 0x88 + COLUMNBUS_REGISTER WDTCR; // 0x90 + COLUMNBUS_REGISTER IRLEV; // 0x98 + COLUMNBUS_REGISTER Reserved1[12]; // 0xa0-0xF8 + COLUMNBUS_REGISTER SYNDM; // 0x100 + COLUMNBUS_REGISTER SDMRST; // 0x108 + COLUMNBUS_REGISTER Reserved2[14]; // 0x110 + COLUMNBUS_REGISTER STCON; // 0x180 + COLUMNBUS_REGISTER STSAD; // 0x188 + COLUMNBUS_REGISTER STADMK; // 0x190 + COLUMNBUS_REGISTER STDATH; // 0x198 + COLUMNBUS_REGISTER STDATL; // 0x1a0 + COLUMNBUS_REGISTER Reserved21; // 0x1a8 + COLUMNBUS_REGISTER Reserved3[10]; // 0x1b0 - 0x1f8 + COLUMNBUS_REGISTER CTAddr; // 0x200 + COLUMNBUS_REGISTER CTDataA; // 0x208 + COLUMNBUS_REGISTER CTDataB; // 0x210 + COLUMNBUS_REGISTER CTCTL; // 0x218 + COLUMNBUS_REGISTER EVCNT1H; // 0x220 + COLUMNBUS_REGISTER EVCNT1L; // 0x228 + COLUMNBUS_REGISTER EVCNTCR1; // 0x230 + COLUMNBUS_REGISTER Reserved4[25]; // 0x238- 0x2F8 + COLUMNBUS_REGISTER CNFG; // 0x300 + COLUMNBUS_REGISTER DISN; // 0x208 + COLUMNBUS_REGISTER REVR; // 0x310 + COLUMNBUS_REGISTER AERR; // 0x318 + COLUMNBUS_REGISTER FERR; // 0x320 + COLUMNBUS_REGISTER ERRMK; // 0x328 + COLUMNBUS_REGISTER ERRI; // 0x330 + COLUMNBUS_REGISTER ERRST; // 0x338 + COLUMNBUS_REGISTER NMIM; // 0x340 + COLUMNBUS_REGISTER EAHI; // 0x348 + COLUMNBUS_REGISTER EALI; // 0x350 + COLUMNBUS_REGISTER AERR2; // 0x358 + COLUMNBUS_REGISTER FERR2; // 0x360 + COLUMNBUS_REGISTER ERRMK2; // 0x368 + COLUMNBUS_REGISTER ERRI2; // 0x370 + COLUMNBUS_REGISTER ERRST2; // 0x378 + COLUMNBUS_REGISTER NMIM2; // 0x380 + COLUMNBUS_REGISTER STSR; // 0x388 + COLUMNBUS_REGISTER EVCNT0H; // 0x390 + COLUMNBUS_REGISTER EVCNT0L; // 0x398 + COLUMNBUS_REGISTER EVCNTCR0; // 0x3a0 + COLUMNBUS_REGISTER MODE; // 0x3a8 + COLUMNBUS_REGISTER Reserved5[10]; // 0x3b0- 0x3f8 + COLUMNBUS_REGISTER RRMT0H; // 0x400 + COLUMNBUS_REGISTER RRMT0L; // 0x408 + COLUMNBUS_REGISTER RRMT1H; // 0x410 + COLUMNBUS_REGISTER RRMT1L; // 0x418 + COLUMNBUS_REGISTER RRMT2H; // 0x420 + COLUMNBUS_REGISTER RRMT2L; // 0x428 + COLUMNBUS_REGISTER RRMT3H; // 0x430 + COLUMNBUS_REGISTER RRMT3L; // 0x438 + COLUMNBUS_REGISTER RRMT4H; // 0x440 + COLUMNBUS_REGISTER RRMT4L; // 0x448 + COLUMNBUS_REGISTER RRMT5H; // 0x450 + COLUMNBUS_REGISTER RRMT5L; // 0x458 + COLUMNBUS_REGISTER RRMT6H; // 0x460 + COLUMNBUS_REGISTER RRMT6L; // 0x468 + COLUMNBUS_REGISTER RRMT7H; // 0x470 + COLUMNBUS_REGISTER RRMT7L; // 0x478 + COLUMNBUS_REGISTER RRMT8H; // 0x480 + COLUMNBUS_REGISTER RRMT8L; // 0x488 + COLUMNBUS_REGISTER RRMT9H; // 0x490 + COLUMNBUS_REGISTER RRMT9L; // 0x498 + COLUMNBUS_REGISTER RRMT10H; // 0x4a0 + COLUMNBUS_REGISTER RRMT10L; // 0x4a8 + COLUMNBUS_REGISTER RRMT11H; // 0x4b0 + COLUMNBUS_REGISTER RRMT11L; // 0x4b8 + COLUMNBUS_REGISTER RRMT12H; // 0x4c0 + COLUMNBUS_REGISTER RRMT12L; // 0x4c8 + COLUMNBUS_REGISTER RRMT13H; // 0x4d0 + COLUMNBUS_REGISTER RRMT13L; // 0x4d8 + COLUMNBUS_REGISTER RRMT14H; // 0x4e0 + COLUMNBUS_REGISTER RRMT14L; // 0x4e8 + COLUMNBUS_REGISTER RRMT15H; // 0x4f0 + COLUMNBUS_REGISTER RRMT15L; // 0x4f8 + COLUMNBUS_REGISTER HPT0; // 0x500 + COLUMNBUS_REGISTER HPT1; // 0x508 + COLUMNBUS_REGISTER HPT2; // 0x510 + COLUMNBUS_REGISTER HPT3; // 0x518 + COLUMNBUS_REGISTER HPT4; // 0x520 + COLUMNBUS_REGISTER HPT5; // 0x528 + COLUMNBUS_REGISTER HPT6; // 0x530 + COLUMNBUS_REGISTER HPT7; // 0x538 + COLUMNBUS_REGISTER HPT8; // 0x540 + COLUMNBUS_REGISTER HPT9; // 0x548 + COLUMNBUS_REGISTER NRTY1; // 0x550 + COLUMNBUS_REGISTER Reserved6[5]; // 0x558-0x57f + COLUMNBUS_REGISTER IntIR; // 0x580 + COLUMNBUS_REGISTER RCIR; // 0x588 + COLUMNBUS_REGISTER TCIR; // 0x590 + COLUMNBUS_REGISTER HPTIR; // 0x598 + COLUMNBUS_REGISTER CBIR; // 0x5a0 + COLUMNBUS_REGISTER Reserved7[11]; // 0x5a8-0x5f8 + COLUMNBUS_REGISTER SIOCNT; // 0x600 + COLUMNBUS_REGISTER SIODAT; // 0x608 + COLUMNBUS_REGISTER ERRNOD; // 0x610 + COLUMNBUS_REGISTER ERNDRS; // 0x618 + COLUMNBUS_REGISTER Reserved8[28]; // 0x620-0x6f8 + COLUMNBUS_REGISTER ARTYCT; // 0x700 + COLUMNBUS_REGISTER DRTYCT; // 0x708 + COLUMNBUS_REGISTER TOSR; // 0x710 + COLUMNBUS_REGISTER NRTY2; // 0x718 + +} COLUMNBUS_REGISTERS, *PCOLUMNBUS_REGISTERS; + + + +#define COLUMNBS_GADDR_SHIFT 12 +// +// How to Access Local Area +// +#define COLUMNBS_LCNTL ((volatile PCOLUMNBUS_REGISTERS)(KSEG1_BASE | COLUMNBS_LPHYSICAL_BASE)) +// +// How to Access Gloabal Area +// N.B parameter is Node +// Columbs #0: NODE 4 +// Columbs #1: NODE 5 +// Columbs #2: NODE 6 +// Columbs #3: NODE 7 +// +#define COLUMNBS_GCNTL( Node ) ((volatile PCOLUMNBUS_REGISTERS)(KSEG1_BASE | \ + COLUMNBS_GPHYSICAL_BASE | \ + ((Node) << COLUMNBS_GADDR_SHIFT))) +// +// IPR Register +// +#define NUMBER_OF_IPR_BIT 64 + +// +// TMCRX Register Bit Define +// +#define TIMER_NOOP 0x00 +#define TIMER_STOP 0x1 +#define TIMER_START 0x2 +#define TIMER_RELOAD_START 0x3 + +// +// TCIR Register Bit Define +// +#define TCIR_CLOCK_CMD_SHIFT 26 +#define TCIR_PROFILE_CMD_SHIFT 24 +#define TCIR_ALL_CLOCK_RESTART (TIMER_RELOAD_START << TCIR_CLOCK_CMD_SHIFT) + +// +// STSR Register Bit Define +// +#define STSR_EIF 0x80000000 +#define STSR_EIFMK 0x40000000 +#define STSR_FREEZ 0x20000000 +#define STSR_NMIMK 0x08000000 +#define STSR_NVWINH 0x04000000 +#define STSR_NVBINH 0x02000000 +#define STSR_WEIF 0x00800000 +#define STSR_WEIFMK 0x00400000 +#define STSR_WFREEZ 0x00200000 +#define STSR_WNMIMK 0x00080000 +#define STSR_WNVWINH 0x00040000 +#define STSR_WNVBINH 0x00020000 +#define STSR_CLBER 0x00008000 +#define STSR_WAMRST 0x00004000 +#define STSR_EFIFOEMP 0x00000800 +#define STSR_ITVPND 0x00000400 +#define STSR_WRPND 0x00000200 +#define STSR_CTEXE 0x00000100 +#define STSR_MPU 0x00000080 +#define STSR_ENDIAN 0x00000040 +#define STSR_SCSIZE 0x0000001c + +// +// IntIR Register define +// +#define IntIR_REQUEST_IPI 0x80000000 // Interrupt Kick +#define IntIR_CODE_BIT 24 // Bit 24-30 is interrupt code +#define ATLANTIC_CODE_IPI_FROM_CPU0 0xC +#define ToNODE4 0x00080000 // to CPU#0 +#define ToNODE5 0x00040000 // to CPU#1 +#define ToNODE6 0x00020000 // to CPU#2 +#define ToNODE7 0x00010000 // to CPU#3 + +// +// ERRNOD Register define +// +#define ERRNOD_NODE0 0x0008 //PONCE#0 +#define ERRNOD_NODE1 0x0004 //PONCE#1 +#define ERRNOD_NODE4 0x8000 //CPU#0 +#define ERRNOD_NODE5 0x4000 //CPU#1 +#define ERRNOD_NODE6 0x2000 //CPU#2 +#define ERRNOD_NODE7 0x1000 //CPU#3 +#define ERRNOD_NODE8 0x0080 //Magellan#0 +#define ERRNOD_NODE9 0x0040 //Magellan#1 +#define ERRNOD_EISANMI 0x0200 //EISANMI +#define ERRNOD_ALARM 0x0100 //ALARM + + +// +// CNFG Register define +// +// +#define CNFG_CONNECT0_PONCE0 0x80000000 //it is Ponce 0 +#define CNFG_CONNECT1_PONCE1 0x40000000 //it is Ponce 1 +#define CNFG_CONNECT4_CPU0 0x08000000 //it is CPU #0 +#define CNFG_CONNECT4_CPU1 0x04000000 //it is CPU #1 +#define CNFG_CONNECT4_CPU2 0x02000000 //it is CPU #2 +#define CNFG_CONNECT4_CPU3 0x01000000 //it is CPU #3 +#define CNFG_CONNECT4_MAGELLAN0 0x00800000 //it is MAGELLAN 0 +#define CNFG_CONNECT4_MAGELLAN1 0x00400000 //it is MAGELLAN 1 + + +#define ERRNOD_ALLNODE ((ERRNOD_NODE0|ERRNOD_NODE1| \ + ERRNOD_NODE4|ERRNOD_NODE5| \ + ERRNOD_NODE6|ERRNOD_NODE7| \ + ERRNOD_NODE8|ERRNOD_NODE9)) + +// +// NMIR Register define +// +// +#define NMIR_EXNMI 0x0008 //DUMP Key +#define NMIR_WDTOV 0x0004 //watch dog timer +#define NMIR_CLBNMI 0x0002 //COLUMBUS Internal +#define NMIR_UNANMI 0x0001 //F/W,S/W + +// +// ******************************************************************** +// PONCE Register +// +typedef struct _PONCE_REGISTER { + ULONG Long; + ULONG Fill; +}PONCE_REGISTER,*PPONCE_REGISTER; +// +// PONCE Register define +// +typedef volatile struct _PONCE_REGISTERS { + + PONCE_REGISTER INTAC; //0x000 + PONCE_REGISTER CONFA; //0x008 + PONCE_REGISTER CONFD; //0x010 + PONCE_REGISTER PTBSR; //0x018 + PONCE_REGISTER Reserve0; //0x020 + PONCE_REGISTER PTLMR; //0x028 + PONCE_REGISTER Reserve1; //0x030 + PONCE_REGISTER TFLSR; //0x038 + PONCE_REGISTER Reserve2; //0x040 + PONCE_REGISTER TLBTG[8]; //0x048 + PONCE_REGISTER Reserve3[9]; //0x088 + PONCE_REGISTER ADCFR0; //0x0d0 + PONCE_REGISTER Reserve4; //0x0d8 + PONCE_REGISTER PMODR; //0x0e0 + PONCE_REGISTER Reserve5[3]; //0x0e8 + PONCE_REGISTER VENID; //0x100 + PONCE_REGISTER DEVID; //0x108 + PONCE_REGISTER PCMDN; //0x110 + PONCE_REGISTER PSTAT; //0x118 + PONCE_REGISTER REVID; //0x120 + PONCE_REGISTER CLASS; //0x128 + PONCE_REGISTER LTNCY; //0x130 + PONCE_REGISTER Reserve6[2]; //0x138 + PONCE_REGISTER TLBDT[8]; //0x148 + PONCE_REGISTER Reserve7[0xf]; //0x188 + + PONCE_REGISTER INTRG; //0x200 + PONCE_REGISTER INTM; //0x208 + PONCE_REGISTER INTPH; //0x210 + PONCE_REGISTER INTPL; //0x218 + PONCE_REGISTER INTTG[11]; //0x220 + PONCE_REGISTER INTCD[11]; //0x278 - 0x2c8 + PONCE_REGISTER CAFLS; //0x2d0 + PONCE_REGISTER CASEL; //0x2d8 + PONCE_REGISTER CADATH; //0x2e0 + PONCE_REGISTER CADATL; //0x2e8 + PONCE_REGISTER CATAGH; //0x2f0 + PONCE_REGISTER CATAGL; //0x2f8 + PONCE_REGISTER Reserve8[2]; //0x300 0x308 + PONCE_REGISTER REVR; //0x310 + PONCE_REGISTER AERR; //0x318 + PONCE_REGISTER FERR; //0x320 + PONCE_REGISTER ERRM; //0x328 + PONCE_REGISTER ERRI; //0x330 + PONCE_REGISTER ERRST; //0x338 + PONCE_REGISTER Reserve9; //0x340 + PONCE_REGISTER EAHI; //0x348 + PONCE_REGISTER EALI; //0x350 + PONCE_REGISTER Reservea[21]; //0x358 + PONCE_REGISTER RRMT0H; //0x400 + PONCE_REGISTER RRMT0L; //0x408 + PONCE_REGISTER RRMT1H; //0x410 + PONCE_REGISTER RRMT1L; //0x418 + PONCE_REGISTER RRMT2H; //0x420 + PONCE_REGISTER RRMT2L; //0x428 + PONCE_REGISTER RRMT3H; //0x430 + PONCE_REGISTER RRMT3L; //0x438 + PONCE_REGISTER RRMT4H; //0x440 + PONCE_REGISTER RRMT4L; //0x448 + PONCE_REGISTER RRMT5H; //0x450 + PONCE_REGISTER RRMT5L; //0x458 + PONCE_REGISTER RRMT6H; //0x460 + PONCE_REGISTER RRMT6L; //0x468 + PONCE_REGISTER RRMT7H; //0x470 + PONCE_REGISTER RRMT7L; //0x478 + PONCE_REGISTER Reserveb[16]; //0x480 + + PONCE_REGISTER HPT0; //0x500 + PONCE_REGISTER HPT1; //0x508 + PONCE_REGISTER HPT2; //0x510 + PONCE_REGISTER HPT3; //0x518 + PONCE_REGISTER HPT4; //0x520 + PONCE_REGISTER HPT5; //0x528 + PONCE_REGISTER HPT6; //0x530 + PONCE_REGISTER HPT7; //0x538 + PONCE_REGISTER HPT8; //0x540 + PONCE_REGISTER HPT9; //0x548 + PONCE_REGISTER Reservec[54]; //0x550 + + PONCE_REGISTER ANRC; //0x700 + PONCE_REGISTER DNRC; //0x708 + PONCE_REGISTER ABRMT; //0x710 + PONCE_REGISTER Reserved; //0x718 + PONCE_REGISTER ANKRL2; //0x720 + PONCE_REGISTER DISN; //0x728 + PONCE_REGISTER Reserved2[26]; //0x730 + + PONCE_REGISTER PAERR; //0x800 + PONCE_REGISTER PFERR; //0x808 + PONCE_REGISTER PERRM; //0x810 + PONCE_REGISTER PERRI; //0x818 + PONCE_REGISTER PERST; //0x820 + PONCE_REGISTER PTOL; //0x828 + PONCE_REGISTER Reservee; //0x830 + PONCE_REGISTER PNRT; //0x838 + PONCE_REGISTER PRCOL; //0x840 + PONCE_REGISTER PMDL; //0x848 + PONCE_REGISTER PRST; //0x850 + PONCE_REGISTER ERITTG[3]; //0x858,0x860,0x868 + PONCE_REGISTER ERITCD[3]; //0x870,0x878,0x880 + PONCE_REGISTER Reservef[0xf]; //0x888 + PONCE_REGISTER TRSM; //0x900 + PONCE_REGISTER TROM; //0x908 + PONCE_REGISTER TRAC; //0x910 + PONCE_REGISTER TRDS; //0x918 + PONCE_REGISTER TRDE; //0x920 + PONCE_REGISTER TRDO; //0x928 + PONCE_REGISTER Reserve10[2]; //0x930,0x938 + PONCE_REGISTER INTSM; //0x940 + +}PONCE_REGISTERS,*PPONCE_REGISTERS; + + +#define PONCE_ADDR_SHIFT 12 +#define PONCE_MAX 3 //R98[a-z] max Ponce is 3. +#define PONCE_ADDR_MASK (PONCE_MAX << PONCE_ADDR_SHIFT) + +#define PONCE_IOADDR_SHIFT 22 +// +// Ponce max pci device( Never PCI_MAX_DEVICES) +// +#define PONCE_PCI_MAX_DEVICES 21 + +// +// I/O TLB +// +#define PONCE_MAX_IOTLB_ENTRY 8 +// +// PONCE Register Access +// +#define PONCE_CNTL_BASE_SHIFT 12 +#define PONCE_CNTL(Ponce) ((volatile PPONCE_REGISTERS) \ + (KSEG1_BASE | PONCE_PHYSICAL_BASE | \ + ((Ponce) << PONCE_ADDR_SHIFT))) + + + +// +// PAERR,PFERR,PERRM,PERRI,PERST Registers Bit Define +// Bit31 - Bit21 only other is MBZ +// +#define PONCE_PXERR_PPERM 0x80000000 +#define PONCE_PXERR_PPERS 0x40000000 +#define PONCE_PXERR_PPERN 0x20000000 +#define PONCE_PXERR_PSERR 0x10000000 +#define PONCE_PXERR_PPCER 0x08000000 +#define PONCE_PXERR_PTOUT 0x04000000 +#define PONCE_PXERR_PROER 0x02000000 +#define PONCE_PXERR_PMDER 0x01000000 +#define PONCE_PXERR_PMABS 0x00800000 +#define PONCE_PXERR_PTABS 0x00400000 +#define PONCE_PXERR_PTABO 0x00200000 +#define PONCE_PXERR_MASK 0xFFE00000 + +// +// AERR,FERR,ERRM,ERRI,ERRST Registers Bit Define +// Bit31 - Bit9 only other is RFU +// +#define PONCE_XERR_ACPBERR 0x80000000 +#define PONCE_XERR_RRIBERR 0x40000000 +#define PONCE_XERR_ZERO 0x20000000 +#define PONCE_XERR_SNDERR 0x10000000 +#define PONCE_XERR_ABTMOT 0x08000000 +#define PONCE_XERR_ABWTLT 0x04000000 +#define PONCE_XERR_ABRTYOV 0x02000000 +#define PONCE_XERR_ABRERTOV 0x01000000 +#define PONCE_XERR_NERRR 0x00800000 +#define PONCE_XERR_UNADER 0x00400000 +#define PONCE_XERR_UNCMDER 0x00200000 +#define PONCE_XERR_BWDPER 0x00100000 +#define PONCE_XERR_SLWDPER 0x00080000 +#define PONCE_XERR_BDRPER 0x00040000 +#define PONCE_XERR_SLDRPER 0x00020000 +#define PONCE_XERR_ADPER 0x00010000 +#define PONCE_XERR_CDPER 0x00008000 +#define PONCE_XERR_RRPER 0x00004000 +#define PONCE_XERR_CHICT 0x00002000 +#define PONCE_XERR_STATUMT 0x00001000 +#define PONCE_XERR_TUAER 0x00000800 +#define PONCE_XERR_TIVER 0x00000400 +#define PONCE_XERR_MOVER 0x00000200 +#define PONCE_XERR_MASK 0xDFFFFE00 + + +// +// Dummy Read Registers Index +// +typedef enum _INTRG{ + PCIINTD, + PCIINTC, + PCIINTB, + PCIINTA3, + PCIINTA2, + PCIINTA1, + PCIINTA0, + INTSB1, + INTSB0, + INTSA1, + INTSA0, +}INTRG,*PINTRG; + + +// +// Dummy Read Registers +// +// +typedef enum _DUMMY_ADDR{ + DUMMY_A0, + DUMMY_A1, + DUMMY_A2, + DUMMY_A3, + DUMMY_A4, + DUMMY_A5 +}DUMMY_ADDR,*PDUMMY_ADDR; + +#define PONCE0 0x0 +#define PONCE1 0x1 + + +// +// Magellan registers +// +// + +typedef struct _MAGELLAN_REGISTER { + ULONG Long; + ULONG Fill; +}MAGELLAN_REGISTER,*PMAGELLAN_REGISTER; +// +// PONCE Register define +// + +typedef volatile struct _MAGELLAN_REGISTERS{ + MAGELLAN_REGISTER ADEC0; //0x0000 + MAGELLAN_REGISTER ADEC1; //0x0008 + MAGELLAN_REGISTER ADEC2; //0x0010 + MAGELLAN_REGISTER ADEC3; //0x0018 + MAGELLAN_REGISTER Reserved0[0x1c]; //0x0020 + MAGELLAN_REGISTER EAADEC0; //0x0100 + MAGELLAN_REGISTER EAADEC1; //0x0108 + MAGELLAN_REGISTER Reserved1[0x1de]; //0x0110 + MAGELLAN_REGISTER INLC; //0x1000 + MAGELLAN_REGISTER RCFD; //0x1008 + MAGELLAN_REGISTER Reserved2; //0x1010 + MAGELLAN_REGISTER DTRG; //0x1018 + MAGELLAN_REGISTER Reserved4[0x5d]; //0x1020 + MAGELLAN_REGISTER DISN; //0x1308 + MAGELLAN_REGISTER REVR; //0x1310 + MAGELLAN_REGISTER Reserved5[0x3d]; //0x1318 + MAGELLAN_REGISTER HPT0; //0x1500 + MAGELLAN_REGISTER HPT1; //0x1508 + MAGELLAN_REGISTER HPT2; //0x1510 + MAGELLAN_REGISTER HPT3; //0x1518 + MAGELLAN_REGISTER HPT4; //0x1520 + MAGELLAN_REGISTER HPT5; //0x1528 + MAGELLAN_REGISTER HPT6; //0x1530 + MAGELLAN_REGISTER HPT7; //0x1538 + MAGELLAN_REGISTER HPT8; //0x1540 + MAGELLAN_REGISTER HPT9; //0x1548 + MAGELLAN_REGISTER Reserved6[0x1b9]; //0x1550 + MAGELLAN_REGISTER AERR; //0x2318 + MAGELLAN_REGISTER FERR; //0x2320 + MAGELLAN_REGISTER ERRM; //0x2328 + MAGELLAN_REGISTER ERRI; //0x2330 + MAGELLAN_REGISTER ERRST; //0x2338 + MAGELLAN_REGISTER Reserved7; //0x2340 + MAGELLAN_REGISTER EIFM; //0x2348 + MAGELLAN_REGISTER EAHI; //0x2350 + MAGELLAN_REGISTER EALI; //0x2358 + MAGELLAN_REGISTER Reserved8[2]; //0x2360 + MAGELLAN_REGISTER CKE0; //0x2370 + MAGELLAN_REGISTER Reserved9; //0x2378 + MAGELLAN_REGISTER SECT; //0x2380 + MAGELLAN_REGISTER STS1; //0x2388 + MAGELLAN_REGISTER RSRG; //0x2390 + MAGELLAN_REGISTER DATM; //0x2398 + MAGELLAN_REGISTER DSRG; //0x23a0 + MAGELLAN_REGISTER SDLM; //0x23a8 + MAGELLAN_REGISTER Reserveda[0x18a]; //0x23b0 + MAGELLAN_REGISTER SDCR; //0x3000 + MAGELLAN_REGISTER Reservedb[0x27f]; //0x3008 + MAGELLAN_REGISTER RRMTH0; //0x4400 + MAGELLAN_REGISTER RRMTL0; //0x4408 + MAGELLAN_REGISTER RRMTH1; //0x4410 + MAGELLAN_REGISTER RRMTL1; //0x4418 + MAGELLAN_REGISTER RRMTH2; //0x4420 + MAGELLAN_REGISTER RRMTL2; //0x4428 + MAGELLAN_REGISTER RRMTH3; //0x4430 + MAGELLAN_REGISTER RRMTL3; //0x4438 + MAGELLAN_REGISTER RRMTH4; //0x4440 + MAGELLAN_REGISTER RRMTL4; //0x4448 + MAGELLAN_REGISTER RRMTH5; //0x4450 + MAGELLAN_REGISTER RRMTL5; //0x4458 + MAGELLAN_REGISTER RRMTH6; //0x4460 + MAGELLAN_REGISTER RRMTL6; //0x4468 + MAGELLAN_REGISTER RRMTH7; //0x4470 + MAGELLAN_REGISTER RRMTL7; //0x4478 + MAGELLAN_REGISTER Reservedc[0x170]; //0x4480 + MAGELLAN_REGISTER PCM; //0x5000 + MAGELLAN_REGISTER PCH; //0x5008 + MAGELLAN_REGISTER Reservedd[0x1e]; //0x5010 + MAGELLAN_REGISTER TMOD; //0x5100 + MAGELLAN_REGISTER TRA; //0x5108 + MAGELLAN_REGISTER Reservede[0x1e]; //0x5110 + MAGELLAN_REGISTER TRM0[0x20]; //0x5200 + MAGELLAN_REGISTER TRM1[0x20]; //0x5300 + MAGELLAN_REGISTER TRM2[0x20]; //0x5400 +}MAGELLAN_REGISTERS,*PMAGELLAN_REGISTERS; + + + +// +// How to Access Local Area +// +#define MAGELLAN_0_CNTL ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE | MAGELLAN_0_PHYSICAL_BASE)) +#define MAGELLAN_1_CNTL ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE | MAGELLAN_1_PHYSICAL_BASE)) + +#define MAGELLAN_X_CNTL(x) ((volatile PMAGELLAN_REGISTERS)(KSEG1_BASE |\ + ((x) ? MAGELLAN_1_PHYSICAL_BASE : MAGELLAN_0_PHYSICAL_BASE))) + +// +// Define LOCAL device Control register structure. +// +typedef struct _LOCAL_REGISTERS { // offset(H) + UCHAR LBCTL; // 0x0 + UCHAR Reserved0[15]; + UCHAR LBADL; // 0x10 + UCHAR Reserved1[7]; + UCHAR LBADH; // 0x18 + UCHAR Reserved2[7]; + UCHAR LBDT; // 0x20 +}LOCAL_REGISTERS, *PLOCAL_REGISTERS; + + +// +// LBCTL Regiser Bit define +// + +#define LBCTL_SWE 0x80 +#define LBCTL_SEMAPHORE 0x40 +#define LBCTL_CMD 0x10 +#define LBCTL_READ 0x08 + +// +// MRC Register Offset +// +#define MRCINT 0x0200 +#define MRCMODE 0x0208 +#define MRC_SWPOWEROFF 0x0230 +#define MRC_FDWRITEPROTECT 0x0250 + + +// +// ALARM Register Offset +// +#define ALARM_LOW 0x410 +#define ALARM_HIGH 0x411 +#define ALMINH_LOW 0x414 +#define ALMINH_HIGH 0x415 +#define ALMSNS_LOW 0x418 +#define ALMSNS_HIGH 0x419 + +// +// Define pointer to Local Device Control registers. +// +#define LOCAL_CNTL ((volatile PLOCAL_REGISTERS)(KSEG1_BASE | LOCALDEV_PHYSICAL_BASE)) + + +#endif _R98BREG_ diff --git a/private/ntos/nthals/halr98b/mips/rgb525.h b/private/ntos/nthals/halr98b/mips/rgb525.h new file mode 100644 index 000000000..9c157bc95 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rgb525.h @@ -0,0 +1,468 @@ +// #pragma comment(exestr, "@(#) rgb525.h 1.1 95/07/24 10:53:20 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/halr98b/mips/rxbusdat.c b/private/ntos/nthals/halr98b/mips/rxbusdat.c new file mode 100644 index 000000000..fdf6541bb --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxbusdat.c @@ -0,0 +1,290 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + rxbusdat.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: + + + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +// +// Prototype for system bus handlers +// + + +NTSTATUS +HalpHibernateHal ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler + ); + +NTSTATUS +HalpResumeHal ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler + ); + +#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; + +#if 0 + // + // Hibernate and resume the hal by getting notifications + // for when this bus is hibernated or resumed. Since it's + // the first bus to be added, it will be the last to hibernate + // and the first to resume + // + + Bus->HibernateBus = HalpHibernateHal; + Bus->ResumeBus = HalpResumeHal; +#endif + + // + // 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; + // + // R98B Build Other Bus (PCIBus) + // move to jxusage.c + // HalpInitializePciBus(); + +} + + + +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; + ULONG Ponce; + + // + // 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; + + // R98B must be MemorySpace!!. + Bus->BusAddresses->IO.SystemAddressSpace = 0; + Bus->BusAddresses->PrefetchMemory.Base = 1; + + switch(InterfaceType) { + + case PCIBus: + + Ponce = HalpPonceNumber((ULONG)BusNumber); + if(Ponce == 0){ + // Ponce 0: Below 64M is EISA/ISA Memory Area. + Bus->BusAddresses->Memory.Base = 0x04000000; + }else{ +// Bus->BusAddresses->Memory.Base = 0x0; + // Less than 16M is PCI DMA area. + Bus->BusAddresses->Memory.Base = 0x01000000; + } + Bus->BusAddresses->Memory.Limit = 0x3fffffff; //1G + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = PCI_MEMORY_PHYSICAL_BASE_LOW+ + PCI_MAX_MEMORY_SIZE * Ponce; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart + = PCI_MEMORY_PHYSICAL_BASE_HIGH; + if(Ponce == 0){ + // N.B + // Io Manager allocate PCI I/O area From high addr of I/O space. + // EISA I/O Addr is Slot dependent and R98B max eisa slot is 3. + // So EISA i/o addr is below 0x4000. Perhaps PCI and EISA I/O area + // not conflict. But When One of PCI Device big I/O area required + // whitch EISA Device Slot dependent I/O area. + // PCI device positive decode and EISA Device can't decode. + // EISA device can decode when PCEB substruct decode of PCI cycle. + // (Any Device can't positivedecode) + // So Set IO.Base EISA 4 slot I/O addr.(Never EISA Slot 4) + // +// Bus->BusAddresses->IO.Base = 0x00004000; + // + // 4000 - 4fff is dummy backward compatibility for scsi. + // It is Dummy Area. See + // + Bus->BusAddresses->IO.Base = 0x00005000; + }else{ + Bus->BusAddresses->IO.Base = 0x00000000; + } + Bus->BusAddresses->IO.Limit = 0x0000FFFF; //64K + + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = PCI_CNTL_PHYSICAL_BASE+ + PCI_MAX_CNTL_SIZE * Ponce; + + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->HighPart + = 0x0; + break; + + + case Internal: + + Bus->BusAddresses->Dma.Limit = 7; // 0-7 channel + Bus->BusAddresses->Memory.Base + = 0x00000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart + = 0x3FFFFFFF; // 1G + Bus->BusAddresses->Memory.SystemBase + = 0x00000000; + Bus->BusAddresses->IO.Base + = 0x00000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart + = 0x3FFFFFFF; // 1G + Bus->BusAddresses->IO.SystemBase + = 0x00000000; + break; + + + case Eisa: + case Isa: + + Bus->BusAddresses->Dma.Limit = 7; // 0-7 channel + + Bus->BusAddresses->Memory.Base = 0x00000000; + + if(InterfaceType == Eisa){ + Bus->BusAddresses->Memory.Limit = 0x03FFFFFF; //64M + }else{ + // + // ISA or Internal(XBus) + // + Bus->BusAddresses->Memory.Limit = 0x00FFFFFF; //16M + } + + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = EISA_MEMORY_PHYSICAL_BASE_LOW; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart + = EISA_MEMORY_PHYSICAL_BASE_HIGH; + + Bus->BusAddresses->IO.Base = 0x00000000; + + // + // Max Slot is 3 . Bad Alias . So 3fff --> 4fff + // + Bus->BusAddresses->IO.Limit = 0x00004fff; // For max 3 slot. + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = EISA_CNTL_PHYSICAL_BASE; + + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->HighPart + = 0; + break; + } + } + + return Bus; +} diff --git a/private/ntos/nthals/halr98b/mips/rxclock.s b/private/ntos/nthals/halr98b/mips/rxclock.s new file mode 100644 index 000000000..9c0010046 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxclock.s @@ -0,0 +1,368 @@ +// TITLE("Interval and Profile Clock Interrupts") +//++ +// +// Copyright (c) 1991-1994 Microsoft Corporation +// +// Module Name: +// +// r98clock.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interval and profile clock interrupts on a MIPS R4000 system. +// +//-- + +#include "halmips.h" +#include "r98bdef.h" + +#define ECC_ERROR_COUNT_LIMIT 1 +#define CNFG_CONNECT4_MAGELLAN0 0x00800000 //it is MAGELLAN 0 +#define CNFG_CONNECT4_MAGELLAN1 0x00400000 //it is MAGELLAN 1 + + + 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: +// +// a0 - 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 + + sw zero,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x50(zero) // Columnbs TOVCT1 reg. + + 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. +// + + la t0,HalpStartWDTFlag + lw t1,0x0(t0) + beq zero,t1,2f + la t2,HalpSetWDTCount + lw t1,0x0(t2) + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x80(zero) // Columnbs reg. + li t1,0x00000002 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +2: la t0,HalpStopWDTFlag + lw t1,0x0(t0) + beq zero,t1,3f + li t1,0x00000001 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +3: la t0,HalpSetWDTFlag + lw t1,0x0(t0) + beq zero,t1,4f + li t1,0x00000002 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +4: + +// +// Check ECC 1bit error flag. +// + + lw t0,HalpECC1bitDisableTime // get value of disable time + beq zero,t0,10f // if ne, check ecc 1bit + lw t1,HalpCurrentTimeIncrement // get current time increment + subu t0,t0,t1 // declement disable time + sw t0,HalpECC1bitDisableTime // + blez t0,5f // if lez, enable ecc 1bit + beq zero,zero,10f // not lez, + +5: sw zero,HalpECC1bitDisableTime // clear disable time + li t0,ECC_ERROR_COUNT_LIMIT // set new flag + sw t0,HalpECC1bitDisableFlag // + la t1,KSEG1_BASE+MAGELLAN_0_PHYSICAL_BASE+MAGELLAN_ERRI_OFFSET + lw t2,HalpPhysicalNode // check connect to Magellan + and t0,t2,CNFG_CONNECT4_MAGELLAN0 + bne t0,zero,7f + lw t0,0x0(t1) + and t0,ECC_1BIT_ENABLE + sw t0,0x0(t1) // enable ECC 1bit error +7: + and t0,t2,CNFG_CONNECT4_MAGELLAN1 + bne t0,zero,10f + la t1,KSEG1_BASE+MAGELLAN_1_PHYSICAL_BASE+MAGELLAN_ERRI_OFFSET + lw t0,0x0(t1) + and t0,ECC_1BIT_ENABLE + sw t0,0x0(t1) // enable ECC 1bit error + +// +// 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). +// + +10: 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 + + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x40(zero) // Columnbs TMSR1 reg. + + .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 + break BREAKIN_BREAKPOINT // break into the 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: +// +// a0 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpClockInterrupt1) + + sw zero,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x50(zero) // Columnbs TOVCT1 reg. + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + +#if 0 + la t2,HalpChangeIntervalFlg // get change flag of timer interval + lbu t1,PbNumber(t1) // get processor number + add t2,t1,t2 // check flag + lb t1,0x0(t2) // get change flag of this CPU + beq t1,zero,10f // if eq, no change timer interval + sb zero,0x0(t2) // clear change flag of timer interval + + lw t1,HalpChangeIntervalCount // get next interval count + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x40(zero) // Columnbs TMSR1 reg. +10: +#endif + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + lbu t4,PbNumber(t1) // get processor number + sll t4,t4,2 // compute address + la t0,HalpStartWDTFlag + addu t0,t0,t4 // + lw t1,0x0(t0) + beq zero,t1,12f + la t2,HalpSetWDTCount + addu t2,t2,t4 // + lw t1,0x0(t2) + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x80(zero) // Columnbs reg. + li t1,0x00000002 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +12: la t0,HalpStopWDTFlag + addu t0,t0,t4 // + lw t1,0x0(t0) + beq zero,t1,14f + li t1,0x00000001 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +14: la t0,HalpSetWDTFlag + addu t0,t0,t4 // + lw t1,0x0(t0) + beq zero,t1,16f + li t1,0x00000002 + sw t1,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x90(zero) // Columnbs reg. + sw zero,0x0(t0) +16: lw t1,__imp_KeUpdateRunTime // update system runtime + j t1 + + .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: +// +// a0 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpProfileInterrupt) + + .set noreorder + .set noat + + li t0,KSEG1_BASE + COLUMNBS_LPHYSICAL_BASE+0x70 + sw zero 0x0(t0) + + mfc0 t0,count // get current count value + addu t1,zero,3 // set initial count value + mtc0 t1,count // set new count register value + + .set at + .set reorder + + 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 // + + 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 + + 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/halr98b/mips/rxdisp.c b/private/ntos/nthals/halr98b/mips/rxdisp.c new file mode 100644 index 000000000..a006c603e --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxdisp.c @@ -0,0 +1,61 @@ +// +// Compile test for stub +// +// + +#include "halp.h" +#include "jazzvdeo.h" +#include "jzvxl484.h" +#include <jaginit.h> + +#include "cirrus.h" +#include "modeset.h" +#include "mode542x.h" + +#include "string.h" +#include <tga.h> + + +VOID +HalAcquireDisplayOwnership ( + IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters + ) + +{ + return; +} + +VOID +HalDisplayString ( + PUCHAR String + ) +{ return;} + +VOID +HalQueryDisplayParameters ( + OUT PULONG WidthInCharacters, + OUT PULONG HeightInLines, + OUT PULONG CursorColumn, + OUT PULONG CursorRow + ) +{ return;} + +VOID +HalSetDisplayParameters ( + IN ULONG CursorColumn, + IN ULONG CursorRow + ) +{return;} + +BOOLEAN +HalpInitializeDisplay0 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{return TRUE;} + +BOOLEAN +HalpInitializeDisplay1 ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +{return TRUE;} diff --git a/private/ntos/nthals/halr98b/mips/rxdspt.c b/private/ntos/nthals/halr98b/mips/rxdspt.c new file mode 100644 index 000000000..11aa9fc80 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxdspt.c @@ -0,0 +1,547 @@ +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + rxdspt.c + +Abstract: + + This module implements the interrupt dispatch routines for R98 + +Author: + + + +Environment: + + Kernel mode + +Revision History: + + +--*/ + + + +#include "halp.h" + +#include "bugcodes.h" + +// +// Define the context structure for use by the interrupt routine. +// + +typedef BOOLEAN (*PSECONDARY_DISPATCH)( + PVOID InterruptRoutine + ); + +typedef BOOLEAN (*PTIMER_DISPATCH)( + ULONG TrapFrame + ); + + +// +// Dummy Read Registers +// +// +volatile ULONG DUMMYADDRS[]={ + 0x1c0003f1|KSEG1_BASE, //FDC37C665 config register + 0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register + 0x1c0003f1|KSEG1_BASE, //FDC37C665 config register + 0x1c000023|KSEG1_BASE, //ESC Configuration register + 0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register + 0x19800610|KSEG1_BASE //Err node register + +}; + +// +// Following structures will be changed by HalAllProcessorsStarted() on +// boot up HAL. +// Because each interrupt connects each processor on boot up HAL. +// v-masank@microsoft.com +// + +INT_ENTRY HalpIntEntry[R98_CPU_NUM_TYPE][R98B_MAX_CPU][NUMBER_OF_INT]={ + +{// For R4400 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open} + + { // For CPU #0 + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1 + {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5 + }, + { // For CPU #1 + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1 + {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5 + }, + { // For CPU #2 + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1 + {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5 + }, + { // For CPU #3 + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1 + {32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5 + } + +}, + +{// For R10000 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open} + + + { + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4 + {NONE, 0 ,0,(ULONGLONG)0,0} //INT5 + }, + { + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4 + {NONE, 0 ,0,(ULONGLONG)0,0} //INT5 + }, + { + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4 + {NONE, 0 ,0,(ULONGLONG)0,0} //INT5 + }, + { + {0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0 + {16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1 + {56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2 + {48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3 + {61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4 + {NONE, 0 ,0,(ULONGLONG)0,0} //INT5 + } +} + +}; + +RESET_REGISTER HalpResetValue[NUMBER_OF_IPR_BIT]={ + {0,0,0,0}, //Bit 0 + {PONCE1,PCIINTD,0,DUMMY_A4}, //Bit 1 PCI I/O Slot#8-#10 INTD + {PONCE0,PCIINTD,0,DUMMY_A3}, //Bit 2 PCI I/O Slot#4-#7 INTD + {0x0,0x0,0,0}, //Bit 3 + + {PONCE1,PCIINTC,0,DUMMY_A4}, //Bit 4 PCI I/O Slot#8-#10 INTC + {PONCE0,PCIINTC,0,DUMMY_A3}, //Bit 5 PCI I/O Slot#4-#7 INTC + {0x0,0x0,0,0} , //Bit 6 + {PONCE1,PCIINTB,0,DUMMY_A4}, //Bit 7 PCI I/O Slot#8-#10 INTB + + {PONCE0,PCIINTB,0,DUMMY_A3}, //Bit8 PCI I/O Slot#4-#7 INTB + {0x0,0x0,0,0}, //Bit9 + {0x0,0x0,0,0}, //Bit10 + {0x0,0x0,0,0}, //Bit11 + + {0x0,0x0,0,0}, //Bit12 + {PONCE0,INTSA0,0x0,DUMMY_A3}, //Bit13 EISA Bridge + {PONCE1,INTSB0,0x0,DUMMY_A2}, //Bit14 Parallel + {PONCE0,INTSB0,0x0,DUMMY_A2}, //Bit15 FDC + + {0x0,0x0,0,0}, //Bit16 + {0x0,0x0,0,0}, //Bit17 + {0x0,0x0,0,0}, //Bit18 + {0x0,0x0,0,0}, //Bit19 + + {PONCE1,PCIINTA1,0x0,DUMMY_A4}, //Bit20 PCI I/O Slot#8 INTA + {PONCE1,PCIINTA0,0x0,DUMMY_A4}, //Bit21 PCI I/O Slot#9 INTA + {PONCE0,PCIINTA3,0x0,DUMMY_A3}, //Bit22 PCI I/O Slot#4 INTA + {PONCE0,PCIINTA2,0x0,DUMMY_A3}, //Bit23 PCI I/O Slot#5 INTA + + {PONCE0,PCIINTA1,0,DUMMY_A3}, //Bit24 PCI I/O Slot#6 INTA + {PONCE0,PCIINTA0,0,DUMMY_A3}, //Bit25 PCI I/O Slot#7 INTA + {0x0,0x0,0,0}, //Bit26 + {0x0,0x0,0,0}, //Bit27 + + {0x0,0x0,0,0}, //Bit28 + {PONCE1,INTSA0,0x0,DUMMY_A1}, //Bit29 LAN(Ethernet) + {PONCE1,PCIINTA3,0x0,DUMMY_A1}, //Bit30 SCSI#1(Narrow) + {PONCE1,PCIINTA2,0x0,DUMMY_A1}, //Bit31 SCSI#0(Wide) + + {0x0,0x0,0,0}, //Bit32 + {0x0,0x0,0,0}, //Bit33 + {0x0,0x0,0,0}, //Bit34 Tracer ponce Internal + {0x0,0x0,0,0}, //Bit35 TLB Undefine Address + + {PONCE1,INTSB1,0,DUMMY_A0}, //Bit36 Mouse + {PONCE1,INTSA1,0,DUMMY_A0}, //Bit37 KeyBoard + {PONCE0,INTSB1,0,DUMMY_A0}, //Bit38 SIO#1 + {PONCE0,INTSA1,0,DUMMY_A0}, //Bit39 SIO#0 + + { RFU,0,0,0}, //Bit40 + { RFU,0,0,0}, //Bit41 + { RFU,0,0,0}, //Bit42 + { RFU,0,0,0}, //Bit43 + +// Never Used This is no Device Interrupt. + + { RFU,0,0,0}, //Bit44 + { RFU,0,0,0}, //Bit45 + { RFU,0,0,0}, //Bit46 + { RFU,0,0,0}, //Bit47 + + { RFU,0,0,0}, //Bit48 From CPU#3 IPI + { RFU,0,0,0}, //Bit49 From CPU#2 IPI + { RFU,0,0,0}, //Bit50 From CPU#1 IPI + { RFU,0,0,0}, //Bit51 From CPU#0 IPI + + { RFU,0,0,0}, //Bit52 + { RFU,0,0,0}, //Bit53 + { RFU,0,0,0}, //Bit54 + { RFU,0,0,0}, //Bit55 + + { RFU,0,0,0}, //Bit56 Interval timer 2 Profile + { RFU,0,0,0}, //Bit57 Interval timer 1 Clock + { RFU,0,0,0}, //Bit58 + { RFU,0,0,0}, //Bit59 + + { RFU,0,0,0}, //Bit60 + { RFU,0,0,0}, //Bit61 EIF+MRCINT + { RFU,0,0,0}, //Bit62 Memory 1Bit Error + { RFU,0,0,0} //Bit63 + +}; + +// Thanks very much for pete-san's cooporation. +// Pete-san write most of following source code. +// v-masak@microsoft.com +// 5/17/96 + +#define HalpFindFirstSetMember(Set) \ + ((Set & 0xFF) ? HalpFindFirstSet[Set & 0xFF] : \ + ((Set & 0xFF00) ? HalpFindFirstSet[(Set >> 8) & 0xFF] + 8 : \ + ((Set & 0xFF0000) ? HalpFindFirstSet[(Set >> 16) & 0xFF] + 16 : \ + HalpFindFirstSet[(Set >> 24) & 0xff] + 24))) + +ULONG HalpFindFirstSet[256] = { + 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; + +PINT_ENTRY HalpIntEntryPointer; + +// +// I use LargeReigester access function for performance +// v-masank@microsoft.com +// I used 64 bit shift. +// v-masank@microsoft.com +// + +VOID +HalpGeneralDispatch( + IN ULONG TrapFrame, + IN ULONG IntNo + ) + +/*++ + +Routine Description: + + This is the general hal interrupt dispatch routine. This services hardware interrupts + for range ip[3..8] + + +Arguments: + + IN ULONG TrapFrame - This interrupts trapframe + IN ULONG IntNo - The current Interrupt Number range IntNo[0..5] maps to IP[3..8] + +Return Value: + + None. + +--*/ +{ + + volatile PULONGLONG Register; + ULONGLONG Enable; + volatile ULONGLONG IPR; + ULONGLONG IprBit; + ULONG ULIPR; + ULONG CpuNumber; + ULONG cnt; + ULONG IprBitNumber; + ULONG Ponce; + UCHAR Data; + ULONG StartBit; + // + // Get CpuNumber + // + CpuNumber = PCR->Number; + + // + // Get Enable table offset + // + cnt = CpuNumber * NUMBER_OF_INT; + // + // The interrupt controller on the R98A/B occasionally (rarely) sends + // an interrupt to multiple processors. One is the correct processor to + // handle the interrupt the other is not. The enable bit + // determines if this processor handles this interrupt. + // + // The table HalpIntEntryPointer gets initalized for the correct processor at boot + // (i.e., R98A or R98B). + + Enable=HalpIntEntryPointer[cnt+IntNo].Enable; + StartBit = HalpIntEntryPointer[cnt+IntNo].StartBitNo; + // + // Do until no more interrupts pending + // + do { + + // + // IPR register read + // + Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR); + HalpReadLargeRegister(Register,(PULONGLONG)&IPR); + + // MASK + // + // Determine if this Interrupt enabled for this processor + // + IPR = IPR & Enable; + // + // 28 is the largest interrupt bit vector possible on these machines + // StartBit is the starting bit position for this interrupt level + // Shift the 64 bit interrupt register into a 32 bit field + // to make the find first bit set operation easier + ULIPR = (ULONG) (IPR >> StartBit); + if(ULIPR==0){ + continue; // No interrupts handled by this processor + } + do{ + // + // Service all pending interrupts for this ip level + // + while(ULIPR!=0){ + + // + // Get Interrupt bit set No. on IPR. + // + IprBitNumber = HalpFindFirstSetMember(ULIPR) + StartBit; + IprBit = 1UI64 << IprBitNumber; // Save this value for clearing INT + // + // IPR register read + // IntNo 0 1 2 3 4 5 + // + // R98A Starting bit pos 0 16 32 56 48 61 + // R98B Starting bit pos 0 16 56 48 61 NA + // + // On the R98A/B Each interrupt level can have multiple + // concurrentinterrupt sources + // (e.g., the read of IPR can have more than 1 bit set + // + // + // Hardware Ip #of possible interrupt sources + // R98A R98B + // ip[3] 16 16 + // ip[4] 16 28 + // ip[5] 12 2 + // ip[6] 2 4 + // ip[7] 4 2 + // ip[8] 2 0 + // + // During initialization the HAL assigns affinity to interrupt sources. So that + // the interrupt always gets serviced on the same processor + + + + switch (IprBitNumber) { + + case 62: + // + // call Ecc Error service routine + // + ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[62+DEVICE_VECTORS]) + (PCR->InterruptRoutine[62+DEVICE_VECTORS]); + // + // Clear IPR + // + Register=(PULONGLONG) &((COLUMNBS_LCNTL)->IPRR); + HalpWriteLargeRegister(Register,&IprBit); + break; + case 61: + // + // This interrupt gets sent to all processors. + // Our friend the HalpDieLock controls exclusive access + // protecting the power switch interrupt service routine + // and for some reason the read/write of the Power interrupt + // register. + // + // + KiAcquireSpinLock(&HalpDieLock); + // + // It's EIF or MRC INT + // + ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[61+DEVICE_VECTORS]) + (PCR->InterruptRoutine[61+DEVICE_VECTORS]); + + + // HACK HACK HACK !! + HalpLocalDeviceReadWrite(MRCINT,&Data,LOCALDEV_OP_READ); + if( Data & 0x04){ + // + // At This time If MRCINT Register reported Power Interrupt. + // Power Driver failed or happenig ocurred. + // if anyone push DUMP KEY. Hal may be system reset. + // So Reset Power Interrupt. + // + + Data = 0x0; + HalpLocalDeviceReadWrite(MRCINT, &Data, LOCALDEV_OP_WRITE); + } + + KiReleaseSpinLock(&HalpDieLock); + + // + //Clear IPR + // + + Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR; + HalpWriteLargeRegister(Register,&IprBit); + break; + case 56: + case 57: + // + // Profile or Clock + // + ((PTIMER_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame); + // + //Clear IPR + // + + Register= (PULONGLONG)&(COLUMNBS_LCNTL)->IPRR; + HalpWriteLargeRegister(Register,&IprBit); + break; + case 48: + case 49: + case 50: + case 51: + + // + // Clear IPR + // + + Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR; + HalpWriteLargeRegister(Register,&IprBit); + + // + // IPI interrupts. One for each possible CPU + // + ((PTIMER_DISPATCH) PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame); + break; + default: + // + // Device Interrupt !! + // + Ponce = HalpResetValue[IprBitNumber].Ponce; + + + // + // 1. Clear INTRG register of PONCE + // + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG, + 0x1 << HalpResetValue[IprBitNumber].IntGResetBit); + + // + // 2. Call interrupt service routine + // + ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])( + PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS]); + + // + // 3. Dummy Read execute + // + + READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]); + READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]); + + // + // 4. Clear IPR Bit By IPRR Register + // + + Register = (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR; + HalpWriteLargeRegister(Register,&IprBit); + + // + // 5.Clear INTRG register of PONCE + // + + + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG, + 0x1 << (HalpResetValue[IprBitNumber].IntGResetBit + 21)); + + } // End Switch + // + // Clear the bit in the interrupt register + // that we just serviced + // + ULIPR = ULIPR & ~(1 << (IprBitNumber - StartBit)); + } // End while servicing current interrupt. Check for more + // + // Determine if another interrupt pending at the same level before leaving + // this dispatch routine. The hardware spec implies that there is + // a small window that the interrupt register has bits set before the + // cause register. So it suggests checking the interrupt register + // before the cause + // + // + // check new interrupt + // + // + // IPR register read + // + Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR); + HalpReadLargeRegister(Register,(PULONGLONG)&IPR); + + // MASK + // + // Determine if this Interrupt enabled for this processor + // + + IPR = IPR & Enable; + ULIPR = (ULONG) (IPR >> StartBit); + }while(ULIPR!=0); // End do-while + // + // Check cause register to see if an interrupt pending for the current level + // + } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+IntNo)); +} + diff --git a/private/ntos/nthals/halr98b/mips/rxecc.c b/private/ntos/nthals/halr98b/mips/rxecc.c new file mode 100644 index 000000000..677fe877e --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxecc.c @@ -0,0 +1,791 @@ +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + rxecc.c + +Abstract: + + This module implements the ECC 1bit/Multi bit Error interrupt service routine for R98B + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +/* + * + * NEW CODE '95.11/17 K.Kitagaki + * + */ + +#include "halp.h" +#include "esmnvram.h" +#include "rxesm.h" +#include "bugcodes.h" +#include "stdio.h" + +#if defined(ECC_DBG) +int +TmpInitNvram(void); +int +TmpInitNvram2(void); +#endif + +// +// 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 ESM_MM_SYUKUTAI_TOPOST_OFFSET 0x1d08 + + +#define TIME_STAMP_SIZE 14 + +// +// define value +// +#define NVRAM_VALID 3 +#define ECC_LOG_VALID_FLG 1 + +#define STRING_BUFFER_SIZE 512 + +#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10 + +#define ECC_1BIT_ENABLE_MASK 0x0000000a +#define ECC_1BIT_DISABLE_MASK 0xfffffff5 + +// +// Define global variable. This variable use in display string into nvram. +// +USHORT ErrBufferLatest; +USHORT ErrBufferArea; +USHORT ErrBufferStart; +USHORT ErrBufferEnd; +USHORT ErrBufferCurrent; +UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE]; + +LONG HalpECC1bitDisableFlag=1; +LONG HalpECC1bitDisableTime=0; +ULONG HalpECC1bitScfrBuffer=0; + +VOID +HalpEcc1Logger( + IN ULONG Node +); +VOID +HalpEcc2Logger( + IN ULONG Node +); +// +// Define macro +// + +#define GET_TIME(Buffer) { \ + TIME_FIELDS timeBuffer; \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + HalQueryRealTimeClock( &timeBuffer ); \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + sprintf( (Buffer), \ + "%04d%02d%02d%02d%02d%02d", \ + timeBuffer.Year, \ + timeBuffer.Month, \ + timeBuffer.Day, \ + timeBuffer.Hour, \ + timeBuffer.Minute, \ + timeBuffer.Second \ + ); \ +} + +#define DONT_NOTIFY_ECC1BIT { \ + ULONG buffer; \ + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ \ + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ); \ + buffer |= ECC_1BIT_ENABLE_MASK; \ + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, buffer); \ + } \ + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ \ + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ); \ + buffer |= ECC_1BIT_ENABLE_MASK; \ + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, buffer); \ + } \ +} + +#define NOTIFY_ECC1BIT { \ + ULONG buffer; \ + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ \ + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ); \ + buffer &= ECC_1BIT_DISABLE_MASK; \ + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, buffer); \ + } \ + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ \ + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ); \ + buffer &= ECC_1BIT_DISABLE_MASK; \ + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, buffer); \ + } \ +} + +#if 1 // suported + +VOID +HalpEcc1bitError( + VOID + ) + +/*++ + +Routine Description: + + This routine check ecc 1bit error and error log put in NVRAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + ULONG magSet; + USHORT infoOffset; + USHORT writeOffset; + ULONG sts1Buffer; + ULONG sdlmBuffer; + ULONG dsrgBuffer; + ULONG buffer; + ULONG i; + ULONG errAddr; + UCHAR dataBuf[36]; + UCHAR infoBuf[24]; + UCHAR tempBuf[24]; + + ULONG Ponce0AllError; + ULONG MagellanAdec; + ULONG Magellan0AllError = 0; + ULONG Magellan1AllError = 0; + ULONG simmMIN; + ULONG MemoryBlock; + volatile PULONG Registerp; + +#if defined(ECC_DBG) + DbgPrint("ECC 1Bit Error IN !!!\n"); +#endif + +// HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + Ponce0AllError = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->AERR); + + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ + Magellan0AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR ); + } + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ + Magellan1AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR ); + } + + // + // Check ECC 1bit error + // + + if ( Ponce0AllError & 0x00000200 ){ + if ( Magellan0AllError & 0x0000000a ){ + magSet = 0; +#if defined(ECC_DBG) + DbgPrint("Magellan#%x:AERR = %x\n",magSet,Magellan0AllError); +#endif + } else if ( Magellan1AllError & 0x0000000a ){ + magSet = 1; +#if defined(ECC_DBG) + DbgPrint("Magellan#%x:AERR = %x\n",magSet,Magellan1AllError); +#endif + } else { +#if defined(ECC_DBG) + DbgPrint("Magellan:OTHER ERR 1\n"); +#endif + return; + } + } else { +#if defined(ECC_DBG) + DbgPrint("Magellan:OTHER ERR 2\n"); +#endif + return; + } + + // + // read diagnosis registers. + // + + sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 ); + dsrgBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->DSRG ); + sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM ); + +#if defined(ECC_DBG) + DbgPrint("Magellan#%x:STS1 = %x\n",magSet,sts1Buffer); +#endif + + Registerp = (PULONG)&MAGELLAN_X_CNTL(magSet)->ADEC0; + MagellanAdec = READ_REGISTER_ULONG( Registerp + ((sts1Buffer>>30)<<1) ); + +#if defined(ECC_DBG) + DbgPrint("Magellan:ADEC%x = %x\n",(sts1Buffer>>30),MagellanAdec); +#endif + + simmMIN = (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MIN ) << 24; + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 1 ) { + MemoryBlock = 0x00000000; + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 2 ) { + MemoryBlock = 0x20000000; + } else { + return; + } + + // + // HW Logging + // + HalpEcc1Logger( 8 + magSet ); + +#if defined(ECC_DBG) + DbgPrint("Magellan:MemoryBlock = %x\n",MemoryBlock); + +// TmpInitNvram(); +#endif + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf ); + +// case MAGELLAN_ECC_1BIT_ERROR: + + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + +#if defined(ECC_DBG) + DbgPrint("Magellan:Nvram Save Routine IN !!!\n"); +#endif + infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET; + + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + // + // Disable and clear ECC 1bit error. + // + + DONT_NOTIFY_ECC1BIT; +#if defined(ECC_DBG) + DbgPrint("Magellan:ECC 1bit Disable\n"); +#endif + + WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->ERRST, 0x0a ); + WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDCR, 0x00 ); +#if defined(ECC_DBG) + DbgPrint("Magellan:ERRST, SDCR CLEAR\n"); +#endif + + do { + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR ); +#if defined(ECC_DBG) + DbgPrint("Magellan:AERR = %x\n", buffer); +// DbgBreakPoint(); +#endif + } while ( (buffer & 0x0000000a) != 0 ); + + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRST, 0x00000200 ); + + Registerp = (PULONG)&(COLUMNBS_LCNTL)->IPRR; + WRITE_REGISTER_ULONG( Registerp++, 0x40000000 ); +#if defined(ECC_DBG) + DbgPrint("Columbus:IPRR CLEAR\n"); +#endif + + // + // Check New error or Old error. + // + + // + // Error Address Generate + // + + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 0 ) { // B-MODE + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 24) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 14); +#if defined(ECC_DBG) + DbgPrint("ERROR_ADDR = %x\n",errAddr); +#endif + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 26) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 14) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 25); + } + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 1 ) { // M-MODE + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 25) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)( magSet << 6 )) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15); + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 27) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)( magSet << 6 )) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 15) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 16) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 26); + } + } + + + HalpReadAndWritePhysicalAddr( errAddr ); + + 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 ( (errAddr == ((pECC1_ERR_REC)dataBuf)->err_address) && + ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) { +#if defined(ECC_DBG) + DbgPrint("for loop break\n"); +#endif + break; + } + } + + if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) { +#if defined(ECC_DBG) + DbgPrint("goto next1bit P-1\n"); +#endif + goto next1bit; + } + + // + // wait 20 us. + // + + KeStallExecutionProcessor(20); + + // + // Enable ECC 1bit error. + // + + NOTIFY_ECC1BIT; +#if defined(ECC_DBG) + DbgPrint("Magellan:ECC 1bit Enable\n"); +#endif + + // + // Check ECC 1bit error. + // + + HalpReadPhysicalAddr( errAddr ); + + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR ); + + if( (buffer & 0x0000000a) == 0 ) { +#if defined(ECC_DBG) + DbgPrint("goto next1bit P-2\n"); +#endif + goto next1bit; + } +#if defined(ECC_DBG) + DbgPrint("Magellan:AERR = %x\n", buffer); +#endif + + // + // ECC 1bit error occur again. + // + + ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG; + + ((pECC1_ERR_REC)dataBuf)->err_address = errAddr; + + GET_TIME(tempBuf); + RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ), + (PVOID)tempBuf, + TIME_STAMP_SIZE + ); + + ((pECC1_ERR_REC)dataBuf)->syndrome = sdlmBuffer; + + ((pECC1_ERR_REC)dataBuf)->specified_group = + (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->ARE + magSet * 4); + + ((pECC1_ERR_REC)dataBuf)->specified_simm = + (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->BANK ); + + 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); + } + +next1bit: + +// if(returnValue == SIC_ECC_1BIT_ERROR) { + + DONT_NOTIFY_ECC1BIT; +#if defined(ECC_DBG) + DbgPrint("Magellan:ECC 1bit Disable\n"); +#endif + + WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->ERRST, 0x0a ); + + do { + buffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(magSet)->AERR ); + } while ( (buffer & 0x0000000a) != 0 ); + + WRITE_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDCR, 0x00 ); + + do { + sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 ); + sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM ); + } while ( ((sdlmBuffer) != 0) && ((sts1Buffer & 0x0a000000) == 0) ); + + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRST, 0x00000200 ); + + Registerp = (PULONG)&(COLUMNBS_LCNTL)->IPRR; + WRITE_REGISTER_ULONG( Registerp++, 0x40000000 ); + +#if defined(ECC_DBG) + DbgPrint("HalpECC1bitDisableFlag = %x\n",HalpECC1bitDisableFlag); +#endif + if(HalpECC1bitDisableFlag > 0) { + HalpECC1bitDisableFlag--; + if(HalpECC1bitDisableFlag > 0) { + NOTIFY_ECC1BIT; +#if defined(ECC_DBG) + DbgPrint("Magellan:ECC 1bit Enable\n"); +#endif + } + else { + HalpECC1bitDisableTime = ECC_1BIT_ERROR_DISABLE_TIME; + HalpECC1bitDisableFlag = 0; +#if defined(ECC_DBG) + DbgPrint("HalpECC1bitDisableTime = %x\n",HalpECC1bitDisableTime); +#endif + } + } + + return; +} + +#endif // don't suported yet + +VOID +HalpEccMultiBitError( + IN ULONG MagellanAllError, + IN UCHAR magSet + ) + +/*++ + +Routine Description: + + This routine check ecc multi bit error and error log put in NVRAM. + +Arguments: + + MagellanAllError - Magellan#0/#1 AERR register. + magSet - Magellan Number(#0 or #1). + +Return Value: + + None. + +--*/ + +{ + USHORT infoOffset; + USHORT writeOffset; + ULONG sts1Buffer; + ULONG sdlmBuffer; + ULONG dsrgBuffer; + ULONG errAddr; + UCHAR dataBuf[36]; + UCHAR infoBuf[24]; + UCHAR tempBuf[24]; + ULONG simmMIN; + ULONG MemoryBlock; + ULONG MagellanAdec; + ULONG syukuBuffer; + volatile PULONG Registerp; + +#if defined(ECC_DBG) + DbgPrint("ECC Multi Bit Error IN !!!\n"); +#endif + +// HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + + // + // read diagnosis registers. + // + + sts1Buffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->STS1 ); + dsrgBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->DSRG ); + sdlmBuffer = READ_REGISTER_ULONG( (PULONG) &MAGELLAN_X_CNTL(magSet)->SDLM ); + +#if defined(ECC_DBG) + DbgPrint("Magellan#%x:AERR = %x\n",magSet,MagellanAllError); + DbgPrint("Magellan#%x:STS1 = %x\n",magSet,sts1Buffer); +#endif + + Registerp = (PULONG)&MAGELLAN_X_CNTL(magSet)->ADEC0; + MagellanAdec = READ_REGISTER_ULONG( Registerp + ((sts1Buffer>>30)<<1) ); + +#if defined(ECC_DBG) + DbgPrint("Magellan:ADEC%x = %x\n",(sts1Buffer>>30),MagellanAdec); +#endif + + simmMIN = (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MIN ) << 24; + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 1 ) { + MemoryBlock = 0x00000000; + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->BLOCK ) == 2 ) { + MemoryBlock = 0x20000000; + } else { + return; + } + + // + // HW Logging + // + HalpEcc2Logger( 8 + magSet ); + +#if defined(ECC_DBG) + DbgPrint("Magellan:MemoryBlock = %x\n",MemoryBlock); + +// TmpInitNvram2(); +#endif + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf ); + + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + infoOffset = ECC_2BIT_ERROR_LOG_INFO_OFFSET; + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG; + + // + // Error address generate + // + + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 0 ) { // B-MODE + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 24) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 14); +#if defined(ECC_DBG) + DbgPrint("ERROR_ADDR = %x\n",errAddr); +#endif + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 26) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 6) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 14) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 25); + } + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->MAG ) == 1 ) { // M-MODE + if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 0 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 25) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)( magSet << 6 )) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 15); + } else if ( (UCHAR)( ((PADEC_REGISTER)&MagellanAdec)->SIMM_2 ) == 1 ) { + errAddr = MemoryBlock + simmMIN + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->RF) << 27) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL0_1) << 4) + + ((ULONG)( magSet << 6 )) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL2_9) << 7) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->COL10) << 15) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW0_9) << 16) + + ((ULONG)(((PSTS1_REGISTER)&sts1Buffer)->ROW10) << 26); + } + } + + GET_TIME(tempBuf); + RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ), + (PVOID)tempBuf, + TIME_STAMP_SIZE + ); + + ((pECC2_ERR_REC)dataBuf)->err_address = errAddr; + ((pECC2_ERR_REC)dataBuf)->syndrome = sdlmBuffer; + + ((pECC2_ERR_REC)dataBuf)->specified_group = + (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->ARE + magSet * 4); + + ((pECC2_ERR_REC)dataBuf)->specified_simm = + (UCHAR)( ((PSTS1_REGISTER)&sts1Buffer)->BANK ); + + 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); + + // + // MM sykutai to POST + // + syukuBuffer = 0x0f << ((((pECC2_ERR_REC)dataBuf)->specified_group) << 2 ); + HalNvramWrite( ESM_MM_SYUKUTAI_TOPOST_OFFSET, + 4, + (PVOID)&syukuBuffer); + + } + return; +} + +#if 0 // for test mode + +int +TmpInitNvram(void) +{ + UCHAR buf[256]; + ULONG i; + + buf[0]=0x77; + for(i=768; i<768+25*16; 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); + + +#if defined(ECC_DBG) + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET); + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET); +#endif + + // + // 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); + + return(0); +} + +int +TmpInitNvram2(void) +{ + UCHAR buf[256]; + ULONG i; + + buf[0]=0x77; + for(i=768+400; i<768+400+25*4; 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); + + +#if defined(ECC_DBG) + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET); + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET); +#endif + + // + // 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; + + HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET, + sizeof(ECC2_ERR_AREA_INFO), + buf); + + return(0); +} +#endif diff --git a/private/ntos/nthals/halr98b/mips/rxeif.c b/private/ntos/nthals/halr98b/mips/rxeif.c new file mode 100644 index 000000000..224715021 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxeif.c @@ -0,0 +1,694 @@ +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + rxeif.c + +Abstract: + + This module implements the Eif interrupt service routine for R98B + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + + +#include "halp.h" + +#include "bugcodes.h" +#include "eisa.h" +#include "stdio.h" + +extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; + +// +// define Columnbs buffer index +// + +typedef enum _COLUMNBS_BUFFER_INDEX { + COLUMNBS_AERR, + COLUMNBS_FERR, + COLUMNBS_ERRMK, + COLUMNBS_ERRI, + COLUMNBS_ERRST, + COLUMNBS_NMIM, + COLUMNBS_EAHI, + COLUMNBS_EALI, + COLUMNBS_AERR2, + COLUMNBS_FERR2, + COLUMNBS_ERRMK2, + COLUMNBS_ERRI2, + COLUMNBS_ERRST2, + COLUMNBS_NMIM2, + COLUMNBS_STSR, + COLUMNBS_ERRNOD, + COLUMNBS_MAX_REGISTER +}COLUMNBS_BUFFER_INDEX,*PCOLUMNBS_BUFFER_INDEX; + +// +// define MAGELLAN buffer index +// +typedef enum _MAGELLAN_BUFFER_INDEX { + MAGELLAN_AERR, + MAGELLAN_FERR, + MAGELLAN_ERRM, + MAGELLAN_ERRI, + MAGELLAN_ERRST, + MAGELLAN_EIFM, + MAGELLAN_EAHI, + MAGELLAN_EALI, + MAGELLAN_CKE0, + MAGELLAN_SECT, + MAGELLAN_STS1, + MAGELLAN_DATM, + MAGELLAN_DSRG, + MAGELLAN_MAX_REGISTER +}MAGELLAN_BUFFER_INDEX,*PMAGELLAN_BUFFER_INDEX; + + +// +// define PONCE buffer index +// +typedef enum _PONCE_BUFFER_INDEX { + PONCE_AERR, + PONCE_FERR, + PONCE_ERRM, + PONCE_ERRI, + PONCE_ERRST, + PONCE_EAHI, + PONCE_EALI, + PONCE_PAERR, + PONCE_PFERR, + PONCE_PERRM, + PONCE_PERRI, + PONCE_PERST, + PONCE_PTOL, + PONCE_MAX_REGISTER +}PONCE_BUFFER_INDEX,*PPONCE_BUFFER_INDEX; + +// +// System Diagnotics Registers of R98 +// +ULONG r98bDiagColumnbs[R98B_MAX_CPU][COLUMNBS_MAX_REGISTER]; +ULONG r98bDiagMagellan[R98B_MAX_MAGELLAN][MAGELLAN_MAX_REGISTER]; +ULONG r98bDiagPonce[R98B_MAX_PONCE][PONCE_MAX_REGISTER]; +ULONG r98bDiagEisaNmi; + + +volatile ULONG HalpNMIFlag=0; +ULONG HalpNMIHappend[R98B_MAX_CPU]; +ULONG HalpNmiSvp[R98B_MAX_CPU]; +ULONG HalpDumpFlag=0; + +#if DBG +ULONG HalpNMISecond[R98B_MAX_CPU]; +ULONG HalpResetCount[R98B_MAX_CPU]; + +#endif + + +BOOLEAN +HalpHandleEif( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ) + +/*++ + +Routine Description: + + This routine manage the eif interrupt + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + UCHAR messageBuffer[256]; + UCHAR charBuffer; + ULONG counter; + + UCHAR EisaPort; + ULONG port; + + ULONG displaycount; + ULONG CpuNo; + ULONG CpuNumber; + PCOLUMNBUS_REGISTER ColumnbusRegister; + ULONG i; + ULONG ERRNOD; + ULONG Cregisters; + volatile ULONG CpuCount=0; + ULONG PhysicalCpuNumber; + ULONG data1,data2,data3,data4; + + PULONG Vp; + ULONG Value[2]; + ULONG Magellan0AllError = 0; + ULONG Magellan1AllError = 0; + UCHAR Data; + + // I am .. + CpuNo=(PCR->Prcb)->Number; + CpuCount=**((PULONG *)(&KeNumberProcessors)); + +// DbgBreakPoint(); //for snes + + // + // Get Node. What happend NODE X!!. + // + PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNo]; + + + ERRNOD = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD ); + r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD] = ERRNOD; + + // + // First Check is MRC. This is Power SW Interrupt!!. + // + HalpLocalDeviceReadWrite(MRCINT,&Data,LOCALDEV_OP_READ); + if( Data & 0x04){ + Data = 0x0; + // + // Reset is MRC Interrupt debug Only. + // + // HalpLocalDeviceReadWrite(MRCINT, &Data, LOCALDEV_OP_WRITE); + + return FALSE; + + }else + + // + // Is This Alarm EIF? + // + if( ERRNOD & ERRNOD_ALARM ) { + // + // Second time DUMMY Read. + // + READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD ); + // + // Do Hwlogging + // + HalpEifReturnLog(); + + // + // We Reset Node Register. Now Register had Locked. + // If We Reset Node Register. Other CPU which EIF Broadcasted was + // Never aknowrege EIF Ocurred. So Quick Return. + // + //WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD,ERRNOD_ALARM ); + + return FALSE; + + } + + if(( (ERRNOD & ERRNOD_ALLNODE) == 0) && (HalpNMIFlag == 0) ){ + + // DbgBreakPoint(); + // Any Node Reported EIF. + // + return FALSE; + } + + + // + // + // We Will die. + // + + if(HalpNMIFlag == 0){ + for (i=0;i< R98B_MAX_CPU;i++) + HalpNMIHappend[i] = 1; + + } + + + // + // CHeck ECC Multi Bit Error + // + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ + Magellan0AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR ); + } + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ + Magellan1AllError = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR ); + } + + if ( Magellan0AllError & 0x00000005 ){ + HalpEccMultiBitError( Magellan0AllError, 0 ); + } else if ( Magellan1AllError & 0x00000005 ){ + HalpEccMultiBitError( Magellan1AllError, 1 ); + } + + // cpu #0 cpu #1 cpu #2 cpu #3 + // r98bDiagbuffers[] + // save H/W register Context of COLUMNBS. + // + + for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){ + PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNumber]; + ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(4+PhysicalCpuNumber)->AERR; + for(Cregisters = 0; Cregisters < COLUMNBS_ERRNOD;Cregisters++){ + r98bDiagColumnbs[PhysicalCpuNumber][Cregisters] = + READ_REGISTER_ULONG( (PULONG)ColumnbusRegister ); + ColumnbusRegister++; + } + + } + + // + // Save H/W register Context of Magellan. + // + for(i = 0; i < R98B_MAX_MAGELLAN ; i++){ + if( !(HalpPhysicalNode & (CNFG_CONNECT4_MAGELLAN0 >> i))){ + r98bDiagMagellan[i][MAGELLAN_AERR] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->AERR ); + r98bDiagMagellan[i][MAGELLAN_FERR] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->FERR ); + r98bDiagMagellan[i][MAGELLAN_ERRM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRM ); + r98bDiagMagellan[i][MAGELLAN_ERRI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRI ); +// r98bDiagMagellan[i][MAGELLAN_ERRST] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->ERRST); + +// r98bDiagMagellan[i][MAGELLAN_EIFM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EIFM ); + r98bDiagMagellan[i][MAGELLAN_EAHI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EAHI ); + r98bDiagMagellan[i][MAGELLAN_EALI] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->EALI ); + + r98bDiagMagellan[i][MAGELLAN_CKE0] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->CKE0 ); + r98bDiagMagellan[i][MAGELLAN_SECT] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->SECT ); + + r98bDiagMagellan[i][MAGELLAN_STS1] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->STS1 ); + r98bDiagMagellan[i][MAGELLAN_DATM] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->DATM ); + r98bDiagMagellan[i][MAGELLAN_DSRG] = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(i)->DSRG ); + } + } + + // + // Save H/W register Context of Ponce. + // + for(i = 0; i < HalpNumberOfPonce; i++){ + r98bDiagPonce[i][PONCE_AERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->AERR); + r98bDiagPonce[i][PONCE_FERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->FERR); + r98bDiagPonce[i][PONCE_ERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRM); + r98bDiagPonce[i][PONCE_ERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRI); + // + // THis Register is write only + // + //r98bDiagPonce[i][PONCE_ERRST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRST); + r98bDiagPonce[i][PONCE_EAHI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EAHI); + r98bDiagPonce[i][PONCE_EALI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EALI); + r98bDiagPonce[i][PONCE_PAERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PAERR); + r98bDiagPonce[i][PONCE_PFERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PFERR); + r98bDiagPonce[i][PONCE_PERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRM); + r98bDiagPonce[i][PONCE_PERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRI); + // + // This Register is Read Only..... + // +// r98bDiagPonce[i][PONCE_PERST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERST); + r98bDiagPonce[i][PONCE_PTOL] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PTOL); + } + + // + // Display EISA Nmi status. + // + + charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus); + r98bDiagEisaNmi = charBuffer << 24; + + charBuffer = READ_REGISTER_UCHAR( + &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl + ); + r98bDiagEisaNmi |= charBuffer << 16; + + // + // 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); + charBuffer = READ_PORT_UCHAR ((PUCHAR) port); + + if ((charBuffer & 0x80) == 0) { + // + // Found valid Eisa board, Check to see if it's + // if IOCHKERR is asserted. + // + charBuffer = READ_PORT_UCHAR ((PUCHAR) port+4); + if (charBuffer & 0x2) { + r98bDiagEisaNmi |= EisaPort; + } + } + } + + + // + // Display COLUMNBS Register + // + for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){ + displaycount = 0; + PhysicalCpuNumber=HalpLogicalCPU2PhysicalCPU[CpuNumber]; + sprintf( (char *)messageBuffer, "\nMPU Controller %1d Registers:\n",PhysicalCpuNumber ); + HalDisplayString( (char *)messageBuffer ); + + for(Cregisters = 0; Cregisters < COLUMNBS_MAX_REGISTER;Cregisters++){ + + sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagColumnbs[PhysicalCpuNumber][Cregisters] ); + + HalDisplayString( (char *)messageBuffer ); + if( (displaycount % 7) == 6 ) { + sprintf( (char *)messageBuffer, "\n"); + HalDisplayString( (char *)messageBuffer ); + } + displaycount++; + } + } + + + // + // Display MAGELLAN Register + // + for(i = 0; i < R98B_MAX_MAGELLAN ; i++){ + displaycount=0; + if( !(HalpPhysicalNode & (CNFG_CONNECT4_MAGELLAN0 >> i))){ + sprintf( (char *)messageBuffer, "\nMEMORY Controller %1d Registers:\n",i ); + HalDisplayString( (char *)messageBuffer ); + + for(Cregisters = 0; Cregisters < MAGELLAN_MAX_REGISTER;Cregisters++){ + sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagMagellan[i][Cregisters] ); + HalDisplayString( (char *)messageBuffer ); + if( (displaycount % 7) == 6 ) { + sprintf( (char *)messageBuffer, "\n"); + HalDisplayString( (char *)messageBuffer ); + } + displaycount++; + } + + }else{ + sprintf( (char *)messageBuffer, "\nMEMORY Controller %1d Not Present.",i ); + HalDisplayString( (char *)messageBuffer ); + } + } + + // + // Display PONCE Register + // + for(i = 0; i < HalpNumberOfPonce; i++){ + displaycount=0; + sprintf( (char *)messageBuffer, "\nPCI Controller %1d Registers:\n",i ); + HalDisplayString( (char *)messageBuffer ); + + for(Cregisters = 0; Cregisters < PONCE_MAX_REGISTER;Cregisters++){ + sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagPonce[i][Cregisters] ); + HalDisplayString( (char *)messageBuffer ); + if( (displaycount % 7) == 6 ) { + sprintf( (char *)messageBuffer, "\n"); + HalDisplayString( (char *)messageBuffer ); + } + displaycount++; + } + } + + + + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + Value[0]= READ_REGISTER_ULONG( Vp++); + Value[1]= READ_REGISTER_ULONG( Vp); + + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + WRITE_REGISTER_ULONG( Vp++,0xffffffff); + WRITE_REGISTER_ULONG( Vp, 0xffffffff); + + PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNo]; + +// if( ((HalpNMIFlag & 0xffff) == NMIR_EXNMI) && !HalpNmiSvp[PhysicalCpuNumber] ) { + if( ((HalpNMIFlag & 0xffff) == NMIR_EXNMI) && HalpDumpFlag ) { + HalpChangePanicFlag( 16, 0x05, 0x10); + } else { + HalpChangePanicFlag( 16, 0x01, 0x10); + } + + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + WRITE_REGISTER_ULONG( Vp++,Value[0]); + WRITE_REGISTER_ULONG( Vp, Value[1]); + + // + if( HalpNMIFlag != 0 ){ + // + // From Nmi. Nmi is supported by Cause EIF at nmi occured!!. + // + HalDisplayString("\nNMI: "); + + switch( HalpNMIFlag & 0xffff){ + case NMIR_EXNMI: +// if(HalpNmiSvp[PhysicalCpuNumber]) + if(HalpDumpFlag==0) + HalDisplayString("SVP issued NMI"); + else + HalDisplayString("Dump Switch Pressed"); + break; + case NMIR_WDTOV: + HalDisplayString("Time out of Watch-dog Timer occured"); + break; + case NMIR_CLBNMI: + HalDisplayString("MPU Controller Internal Error"); + break; + case NMIR_UNANMI: + HalDisplayString("Invalid Access"); + break; + default: + HalDisplayString("[Other ?]"); + } + + data1 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_AERR]; + data2 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_AERR2]; + data3 = HalpNMIFlag; + data4 = r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_NMIM]; + + HalpNmiLog(); + + }else { + // + // Acutually EIF Interrupt Occured! + // + + if( ( Magellan0AllError & 0x00000005 ) || + ( Magellan1AllError & 0x00000005 ) ){ + HalDisplayString("\nEIF: Uncorrectable Error in Memory"); + } + + HalDisplayString("\nEIF Reported: "); + sprintf( (char *)messageBuffer, "Exe CPU=No.%1d NodeR = %x ", + CpuNo, r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD]); + HalDisplayString( (char *)messageBuffer ); + + switch( r98bDiagColumnbs[PhysicalCpuNumber][COLUMNBS_ERRNOD] & 0xf3cc){ + case ERRNOD_NODE0 : + HalDisplayString("[ From PCI Controller 0]"); + data1 = r98bDiagPonce[0][PONCE_AERR]; + data2 = r98bDiagPonce[0][PONCE_FERR]; + data3 = r98bDiagPonce[0][PONCE_PAERR]; + data4 = r98bDiagPonce[0][PONCE_PFERR]; + break; + case ERRNOD_NODE1 : + HalDisplayString("[ From PCI Controller 1]"); + data1 = r98bDiagPonce[1][PONCE_AERR]; + data2 = r98bDiagPonce[1][PONCE_FERR]; + data3 = r98bDiagPonce[1][PONCE_PAERR]; + data4 = r98bDiagPonce[1][PONCE_PFERR]; + break; + case ERRNOD_NODE4 : + HalDisplayString("[ From MPU Controller 0]"); + data1 = r98bDiagColumnbs[0][COLUMNBS_AERR]; + data2 = r98bDiagColumnbs[0][COLUMNBS_AERR2]; + data3 = r98bDiagColumnbs[0][COLUMNBS_EAHI]; + data4 = r98bDiagColumnbs[0][COLUMNBS_EALI]; + break; + case ERRNOD_NODE5 : + HalDisplayString("[ From MPU Controller 1]"); + data1 = r98bDiagColumnbs[1][COLUMNBS_AERR]; + data2 = r98bDiagColumnbs[1][COLUMNBS_AERR2]; + data3 = r98bDiagColumnbs[1][COLUMNBS_EAHI]; + data4 = r98bDiagColumnbs[1][COLUMNBS_EALI]; + break; + case ERRNOD_NODE6 : + HalDisplayString("[ From MPU Controller 2]"); + data1 = r98bDiagColumnbs[2][COLUMNBS_AERR]; + data2 = r98bDiagColumnbs[2][COLUMNBS_AERR2]; + data3 = r98bDiagColumnbs[2][COLUMNBS_EAHI]; + data4 = r98bDiagColumnbs[2][COLUMNBS_EALI]; + break; + case ERRNOD_NODE7 : + HalDisplayString("[ From MPU Controller 3]"); + data1 = r98bDiagColumnbs[3][COLUMNBS_AERR]; + data2 = r98bDiagColumnbs[3][COLUMNBS_AERR2]; + data3 = r98bDiagColumnbs[3][COLUMNBS_EAHI]; + data4 = r98bDiagColumnbs[3][COLUMNBS_EALI]; + break; + case ERRNOD_NODE8 : + HalDisplayString("[ From MEMORY Controller 0]"); + data1 = r98bDiagMagellan[0][MAGELLAN_AERR]; + data2 = r98bDiagMagellan[0][MAGELLAN_FERR]; + data3 = r98bDiagMagellan[0][MAGELLAN_EAHI]; + data4 = r98bDiagMagellan[0][MAGELLAN_EALI]; + break; + case ERRNOD_NODE9 : + HalDisplayString("[ From MEMORY Controller 1]"); + data1 = r98bDiagMagellan[1][MAGELLAN_AERR]; + data2 = r98bDiagMagellan[1][MAGELLAN_FERR]; + data3 = r98bDiagMagellan[1][MAGELLAN_EAHI]; + data4 = r98bDiagMagellan[1][MAGELLAN_EALI]; + break; + case ERRNOD_EISANMI: + HalDisplayString("[ From EISA]"); + data1 = r98bDiagEisaNmi; + data2 = 0; + data3 = 0; + data4 = 0; + break; +// +// This case never happend. +// + case ERRNOD_ALARM : + HalDisplayString("[ From ALARM]"); + data1 = 0; + data2 = 0; + data3 = 0; + data4 = 0; + break; + + + default: + HalDisplayString("[Other ?]"); + data1 = 0; + data2 = 0; + data3 = 0; + data4 = 0; + } + // HwLog kusano + HalpEifLog(); + + } + + KeBugCheckEx(NMI_HARDWARE_FAILURE, + data1, + data2, + data3, + data4 + ); + +#if 1 // WORK_AROUND_BBM for compiler + return FALSE; +#endif +} + + +BOOLEAN +HalpIoTlbLimitOver( + PKINTERRUPT Interrupt + ) +{ + KIRQL irql; + ULONG data1,data2,data3,data4; + ULONG i; + ULONG displaycount; + UCHAR messageBuffer[256]; + ULONG Cregisters; + + KeRaiseIrql(HIGH_LEVEL, &irql); + KiAcquireSpinLock(&HalpDieLock); + + // + // Save H/W register Context of Ponce. + // + for(i = 0; i < HalpNumberOfPonce; i++){ + r98bDiagPonce[i][PONCE_AERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->AERR); + r98bDiagPonce[i][PONCE_FERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->FERR); + r98bDiagPonce[i][PONCE_ERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRM); + r98bDiagPonce[i][PONCE_ERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRI); + // + // THis Register is write only + // + //r98bDiagPonce[i][PONCE_ERRST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->ERRST); + r98bDiagPonce[i][PONCE_EAHI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EAHI); + r98bDiagPonce[i][PONCE_EALI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->EALI); + r98bDiagPonce[i][PONCE_PAERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PAERR); + r98bDiagPonce[i][PONCE_PFERR] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PFERR); + r98bDiagPonce[i][PONCE_PERRM] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRM); + r98bDiagPonce[i][PONCE_PERRI] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERRI); + // + // This Register is Read Only..... + // +// r98bDiagPonce[i][PONCE_PERST] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PERST); + r98bDiagPonce[i][PONCE_PTOL] = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(i)->PTOL); + } + + // + // Display PONCE Register + // + for(i = 0; i < HalpNumberOfPonce; i++){ + displaycount=0; + sprintf( (char *)messageBuffer, "\nPCI Controller %1d Registers:\n",i ); + HalDisplayString( (char *)messageBuffer ); + + for(Cregisters = 0; Cregisters < PONCE_MAX_REGISTER;Cregisters++){ + sprintf( (char *)messageBuffer, "0x%08lX,",r98bDiagPonce[i][Cregisters] ); + HalDisplayString( (char *)messageBuffer ); + if( (displaycount % 7) == 6 ) { + sprintf( (char *)messageBuffer, "\n"); + HalDisplayString( (char *)messageBuffer ); + } + displaycount++; + } + } + + if( r98bDiagPonce[1][PONCE_AERR] & (PONCE_XERR_TUAER | PONCE_XERR_TIVER) ){ + data1 = r98bDiagPonce[1][PONCE_AERR]; + data2 = r98bDiagPonce[1][PONCE_FERR]; + data3 = r98bDiagPonce[1][PONCE_PAERR]; + data4 = r98bDiagPonce[1][PONCE_PFERR]; + i = 1; + } else { + data1 = r98bDiagPonce[0][PONCE_AERR]; + data2 = r98bDiagPonce[0][PONCE_FERR]; + data3 = r98bDiagPonce[0][PONCE_PAERR]; + data4 = r98bDiagPonce[0][PONCE_PFERR]; + i = 0; + } + + HalpChangePanicFlag( 16, 0x01, 0x10); + + if ( data1 & PONCE_XERR_TUAER ){ + HalDisplayString("\nI/O TLB Logical Address Limit Over\n"); + } else { + HalDisplayString("\nI/O TLB Invalid\n"); + } + + sprintf( (char *)messageBuffer, " [ From PCI Controller %d]\n",i ); + HalDisplayString( (char *)messageBuffer ); + + KeBugCheckEx(NMI_HARDWARE_FAILURE, + data1, + data2, + data3, + data4 + ); + + KiReleaseSpinLock (&HalpDieLock); + KeLowerIrql (irql); + + return TRUE; +} diff --git a/private/ntos/nthals/halr98b/mips/rxesm.c b/private/ntos/nthals/halr98b/mips/rxesm.c new file mode 100644 index 000000000..d10a659a6 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxesm.c @@ -0,0 +1,761 @@ +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + rxesm.c + +Abstract: + + This module implements the ESM service routine for R98B + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + + +#include "rxesm.h" +#include "esmnvram.h" +#include "bugcodes.h" +#include "stdio.h" +#include "halp.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 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 global variable. This variable use in display string into nvram. +// +ULONG HalpNvramValid=FALSE; +ULONG CallCountOfInitDisplay=0; +USHORT ErrBufferLatest; +USHORT ErrBufferArea; +USHORT ErrBufferStart; +USHORT ErrBufferEnd; +USHORT ErrBufferCurrent; +ULONG HalpPanicFlg=0; +UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE]; +ULONG HalpNvramStringBufferCounter=0; + +UCHAR KernelPanicMessage[]="*** STOP: 0x"; + +extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; +extern ULONG HalpSvpEisaSlot; +extern ULONG HalpSvpWindow0; +extern ULONG HalpSvpWindow1; +extern ULONG HalpSvpWindow2; +extern ULONG HalpSvpGlobal; +extern ULONG HalpSvpAlive ; + +#define GET_TIME(Buffer) { \ + TIME_FIELDS timeBuffer; \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + HalQueryRealTimeClock( &timeBuffer ); \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + sprintf( (Buffer), \ + "%04d%02d%02d%02d%02d%02d", \ + timeBuffer.Year, \ + timeBuffer.Month, \ + timeBuffer.Day, \ + timeBuffer.Hour, \ + timeBuffer.Minute, \ + timeBuffer.Second \ + ); \ +} + +BOOLEAN +HalNvramWrite( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Write Byte Count + PVOID Buffer // Pointer Of Buffer Write to NVRAM +){ + // Write into NVRAM +#if defined(DBG1) + DbgPrint("NVRAM write start\n"); +#endif + return HalpNvramReadWrite(Offset,Count,Buffer,1); +#if defined(DBG1) + DbgPrint("NVRAM write end\n"); +#endif +} + +BOOLEAN +HalNvramRead( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Read Byte Count + PVOID Buffer // Pointer Of Buffer Read From NVRAM +){ + // Read From NVRAM +#if defined(DBG1) + DbgPrint("NVRAM read start\n"); +#endif + return HalpNvramReadWrite(Offset,Count,Buffer,0); +#if defined(DBG1) + DbgPrint("NVRAM read end\n"); +#endif +} + +BOOLEAN +HalpNvramReadWrite( + ULONG Offset, // Read/Write offset of ESM NVRAM + ULONG Count, // Read/Write Byte Count + PVOID Buffer, // read/Write Pointer + ULONG Write // Operation +){ + + ENTRYLO SavedPte[2]; + KIRQL OldIrql; + ULONG i; + // + // Check is addr . So decrement 1 + // + if( + Offset >=0 && + Count >=0 && + NVRAM_ESM_BASE+Offset <=NVRAM_ESM_END && + NVRAM_ESM_BASE+Offset+Count-1 <=NVRAM_ESM_END + + ){ + + if(Write){ + OldIrql = HalpMapNvram(&SavedPte[0]); + for(i=0;i<Count;i++){ + WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i),((PUCHAR)Buffer)[i]); + } + HalpUnmapNvram(&SavedPte[0], OldIrql); + }else{ + for(i=0;i<Count;i++){ + ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i)); + + } + } + + return TRUE; + + }else{ + + // + // It is no ESM NVRAM Erea. + return FALSE; + } + +} + + +#if 0 + +int +TmpInitNvram(void) +{ + UCHAR buf[256]; + ULONG i; + + buf[0]=0x00; + 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); + + +#if DBG + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_STATE_FLG_OFFSET); + DbgPrint("Hal: ESM setup = 0x%x\n",NVRAM_MAGIC_NO_OFFSET); +#endif + + // + // 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(SYSTEM_ERR_AREA_INFO), + buf); + + return(0); +} + +#endif + + +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){ + +#if 0 //test only + TmpInitNvram(); +#endif + // + // 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); + } +} + +VOID +HalpSetInitDisplayTimeStamp( + VOID + ) +{ + UCHAR buf[32]; + + // + // 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[32]; +// For WDT STOP and NVRAM set + volatile ULONG CpuCount=0; + ULONG PhysicalCpuNumber; + ULONG CpuNumber; + PUCHAR FwNvram; + UCHAR Bootflag; + PCOLUMNBUS_REGISTER ColumnbusRegister; + CpuCount=**((PULONG *)(&KeNumberProcessors)); + + if((NewPanicFlg>HalpPanicFlg)&(NewPanicFlg>0)){ + for(CpuNumber = 0; CpuNumber < CpuCount; CpuNumber++){ + PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[CpuNumber]; + ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(4+PhysicalCpuNumber)->WDTCR; + WRITE_REGISTER_ULONG( (PULONG)ColumnbusRegister,0x00000001); + } + (ULONG)FwNvram=0xbf081c00; + Bootflag=(*FwNvram); + *FwNvram=Bootflag|0x10; + // SVP EIF MASK + if(HalpSvpAlive){ + WRITE_PORT_UCHAR(HalpSvpGlobal + 0x49,0x00 ); + } + } + + + + 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<STRING_BUFFER_SIZE; i++) { + HalpNvramStringBuffer[i] = 0; + } + + HalpNvramStringBufferCounter=0; + + // + // set string position + // + + HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column; + HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row; +} + + +VOID +HalpStringBufferCopyToNvram( + VOID + ) +{ + UCHAR buf[4]; + USHORT count; + + // + // check nvram status. + // + + if(HalpNvramValid == FALSE) { + return; + } + + // + // if data size is zero, when return + // + + if( HalpNvramStringBufferCounter <= 2 ) { + return; + } + + HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0'; + + // + // check panic message + // + + for( count=0; ; count++) { + if( KernelPanicMessage[count] == '\0' ){ + HalpChangePanicFlag( 8, 0x01, 0x10); + break; + } + if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){ + break; + } + } + + // + // check message length + // + + for( count=2; ; count++) { + if( HalpNvramStringBuffer[count] == '\0' ){ + count++; + break; + } + } + +loop: + if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) { + HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer ); + ErrBufferCurrent += count; + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + + } else if( (count + 2 > 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 ); + } + } +} + + + +VOID +HalpLocalDeviceReadWrite( + IN ULONG Offset, + IN OUT PUCHAR Data, + IN ULONG ReadOp +) +/*++ + +Routine Description: + + This routine is Access Local Device + +Arguments: + Offset Register Offset of Local Device + Data Pointer of read or write data + ReadOp 1 is Read. + +Return Value: + + None + +--*/ +{ + ULONG stsr; + KIRQL oldirql; +#if DBG0 + DbgPrint("LOCAL: 1 \n"); +#endif + // NMI and EIF mask + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR,0x08080000) ; + KeRaiseIrql(HIGH_LEVEL, &oldirql); + + // + // Get H/W Semaphore + // + while (READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL) & LBCTL_SEMAPHORE ) + ; + +#if DBG0 + DbgPrint("LOCAL: 2\n"); +#endif + + // + // Set register Offset Hi Byte + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBADH, (UCHAR)(Offset >> 8) ); + +#if DBG0 + DbgPrint("LOCAL: 3\n"); +#endif + + + // + // Set register Offset Lo Byte + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBADL, (UCHAR)(Offset & 0xFF)); + +#if DBG0 + DbgPrint("LOCAL: 4\n"); +#endif + + if(ReadOp){ + // + // LBCTL Device read command Set. + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL, LBCTL_CMD|LBCTL_READ); + + }else{ + // + // Write data Set + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBDT,*Data); + // + // LBCTL Device Write command Set. + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL, LBCTL_CMD); + + } +#if DBG0 + DbgPrint("LOCAL: 5\n"); +#endif + + // + // pooling LBCTL cmmand bit + // + while (READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL) & LBCTL_CMD ) + ; + +#if DBG0 + DbgPrint("LOCAL: 6\n"); +#endif + + + // + // If Read Operation Data Get + // + if(ReadOp) + *Data = READ_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBDT); + +#if DBG0 + DbgPrint("LOCAL: 7\n"); +#endif + + // + // Finish!! + // + WRITE_REGISTER_UCHAR( (PUCHAR)&(LOCAL_CNTL)->LBCTL,LBCTL_SWE ); + + // EIF NMI enable + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR,0x00080000) ; + KeLowerIrql(oldirql); + +} + +VOID +HalLocalDeviceReadWrite( + IN ULONG Offset, + IN OUT PUCHAR Data, + IN ULONG ReadOp +) +/*++ + +Routine Description: + + This routine is Access Local Device for Driver + +Arguments: + Offset Register Offset of Local Device + Data Pointer of read or write data + ReadOp 1 is Read. + +Return Value: + + None + +--*/ +{ + HalpLocalDeviceReadWrite(Offset,Data,ReadOp); +} + + +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 + +--*/ +{ + + + UCHAR ModeNow; + // + // Read MRC Mode Register + // + HalpLocalDeviceReadWrite(MRCMODE,&ModeNow,LOCALDEV_OP_READ); + +#if DBG0 + DbgPrint("MRC Read : 1 = 0x%x\n",(UCHAR)ModeNow); +#endif + + // + // Write MRC Mode bit + // + + ModeNow = ((ModeNow & 0x02) | (Mode << 7)); +#if DBG0 + DbgPrint("MRC WRITE : 2 = 0x%x\n",(UCHAR)ModeNow); +#endif + + HalpLocalDeviceReadWrite(MRCMODE,&ModeNow,LOCALDEV_OP_WRITE); + +} + + + + + + + + + + + diff --git a/private/ntos/nthals/halr98b/mips/rxesm.h b/private/ntos/nthals/halr98b/mips/rxesm.h new file mode 100644 index 000000000..7fc976409 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxesm.h @@ -0,0 +1,84 @@ +/* +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + rxesm.h + +Abstract: + + This module is the header file that describes hardware addresses + for the r98B system. + +Author: + + + +Revision History: + +--*/ + +#ifndef _RXESM_ +#define _RXESM_ + +#include "halp.h" + +#define NVRAM_ESM_PHYSICAL_BASE 0x1f09e000 // See rxnvr.h +#define NVRAM_ESM_PHYSICAL_END 0x1f09ffff // See rxnvr.h +#define NVRAM_ESM_BASE (NVRAM_ESM_PHYSICAL_BASE + KSEG1_BASE) +#define NVRAM_ESM_END (NVRAM_ESM_PHYSICAL_END + KSEG1_BASE) + + + +// +// define value +// +#define NVRAM_VALID 3 +//#define NVRAM_MAGIC 0xff651026 +#define NVRAM_MAGIC 0xff951115 +#define STRING_BUFFER_SIZE 512 +#define TIME_STAMP_SIZE 14 + + +VOID +HalpMrcModeChange( + UCHAR Mode + ); + +// +// Define STS1 register +// +typedef struct _STS1_REGISTER { + ULONG COL0_1 : 2; + ULONG COL2_9 : 8; + ULONG COL10 : 1; + ULONG ROW0_9 : 10; + ULONG ROW10 : 1; + ULONG RF : 1; + ULONG RW : 1; + ULONG MBE1 : 1; + ULONG SBE1 : 1; + ULONG MBE0 : 1; + ULONG SBE0 : 1; + ULONG SIDE : 1; + ULONG BANK : 1; + ULONG ARE : 2; +} STS1_REGISTER, *PSTS1_REGISTER; + +// +// Define ADEC register +// +typedef struct _ADEC_REGISTER { + ULONG MIN : 7; + ULONG NOUSE1 : 1; + ULONG MAX : 7; + ULONG NOUSE2 : 9; + ULONG SIMM_1 : 1; + ULONG SIMM_2 : 1; + ULONG NOUSE3 : 1; + ULONG MAG : 1; + ULONG BLOCK : 3; + ULONG NOUSE4 : 1; +} ADEC_REGISTER, *PADEC_REGISTER; + +#endif // _RXESM_ diff --git a/private/ntos/nthals/halr98b/mips/rxhalp.h b/private/ntos/nthals/halr98b/mips/rxhalp.h new file mode 100644 index 000000000..d5b2f0e71 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxhalp.h @@ -0,0 +1,212 @@ +/* + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + rxhalp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + R98[a-z]* specific interfaces, defines and structures. + +Author: + + +Revision History: + +--*/ + +#ifndef _RXHALP_ +#define _RXHALP_ + + +// +// Define global data used to locate the EISA control space and the realtime +// clock registers. +// + +extern PVOID HalpEisaControlBase; +extern PVOID HalpEisaMemoryBase; +extern PVOID HalpRealTimeClockBase; + +extern ULONG HalpMachineCpu; +extern ULONG HalpNumberOfPonce; +extern ULONG HalpPhysicalNode; +extern UCHAR HalpIntLevelofIpr[R98_CPU_NUM_TYPE][NUMBER_OF_IPR_BIT]; +extern ULONG HalpStartPciBusNumberPonce[]; +extern ULONG HalpCirrusAlive; + +typedef struct _INT_ENTRY { + ULONG StartBitNo; + ULONG NumberOfBit; + ULONG Arbitar; + ULONGLONG Enable; // 1: Enable 0: Open + ULONGLONG Open; // This Int Group Open Bit +}INT_ENTRY,*PINT_ENTRY; + +extern INT_ENTRY HalpIntEntry[R98_CPU_NUM_TYPE][R98B_MAX_CPU][NUMBER_OF_INT]; + +// +// This is PONCE Interrupt relationship +// + +typedef struct _RESET_REGISTER { + UCHAR Ponce; //Connet Interrupt Ponce + UCHAR IntGResetBit; //ResetValue Bit Define + UCHAR Cpu; //Connet CPU Initialize at inittime. + UCHAR Dummy; //Dummy Read Addr Index +}RESET_REGISTER,*PRESET_REGISTER; + +extern RESET_REGISTER HalpResetValue[64]; + + +#define NONE (0xFFFFFFFF) +#define RFU ((UCHAR)(0xFF)) + + +// +// Define adapter object structure. +// + +typedef struct _ADAPTER_OBJECT { + CSHORT Type; + CSHORT Size; + struct _ADAPTER_OBJECT *MasterAdapter; + ULONG MapRegistersPerChannel; + PVOID AdapterBaseVa; + PVOID MapRegisterBase; + ULONG NumberOfMapRegisters; + struct _WAIT_CONTEXT_BLOCK *CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + KSPIN_LOCK SpinLock; + PRTL_BITMAP MapRegisters; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + UCHAR AdapterMode; + UCHAR Reserved; + PUCHAR SingleMaskPort; + PUCHAR PagePort; +} ADAPTER_OBJECT; + + +// I/O TLB Entry Format(PTE Format) +// 63 33 32 12 0 +// +---------+-------+----+-+ +// |MBZ | PFN |MBZ |V| +// +---------+-------+----+-+ +// Valid : 1 Valid +// : 0 InValid +// Define translation table entry structure. +// + +typedef volatile struct _TRANSLATION_ENTRY { + ULONG PageFrame; + ULONG Fill; +} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY; + + +#define PAGE_TABLE_ENTRY_VALID 0x1 + +// +// Define function prototypes. +// + +PADAPTER_OBJECT +HalpAllocateEisaAdapter( + IN PDEVICE_DESCRIPTION DeviceDescription + ); + +VOID +HalpAllocateMapRegisters( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +BOOLEAN +HalpCreateEisaStructures( + VOID + ); + +VOID +HalpDisableEisaInterrupt( + IN ULONG Vector + ); + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +VOID +HalpEisaMapTransfer( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ); + +VOID +HalpEnableEisaInterrupt( + IN ULONG Vector, + IN KINTERRUPT_MODE InterruptMode + ); + +BOOLEAN +HalpInterruptFromPonce( + IN ULONG Vector, + IN ULONG Enable + ); + +BOOLEAN +HalpConnectIoInterrupt( + IN ULONG NumCpu + ); + + +VOID +HalpSetupNmiHandler( + VOID + ); + +VOID +HalpCpuCheck( + VOID + ); + +VOID +HalpSVPSlotDetect( + VOID +); + + +VOID +HalpBusErrorLog( + VOID + ); + +VOID +HalpEifLog( + VOID + ); + +VOID +HalpEifReturnLog( + VOID + ); + +VOID +HalpNmiLog( + VOID + ); + +VOID +HalpHwLogger( + IN ULONG Type, + IN ULONG Context + ); + +#endif // _RXHALP_ diff --git a/private/ntos/nthals/halr98b/mips/rxhwlog.c b/private/ntos/nthals/halr98b/mips/rxhwlog.c new file mode 100644 index 000000000..d3308e395 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxhwlog.c @@ -0,0 +1,1409 @@ +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + rxhwlog.c + +Abstract: + + This module implements the ESM service routine for R98B + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "rxhwlog.h" +#include "eisa.h" +#include "stdio.h" + +UCHAR HwLogBuff[HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE+1024]; +extern ULONG HalpLogicalCPU2PhysicalCPU[]; +extern ULONG HalpNmiSvp[]; + +#define NMI_BUFFER_SIZE 64 + +ULONG HalpNMIBuf[R98B_MAX_CPU][NMI_BUFFER_SIZE]; + +#define GET_TIME2(Buffer) { \ + TIME_FIELDS timeBuffer; \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + HalQueryRealTimeClock( &timeBuffer ); \ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(EIF_VECTOR-DEVICE_VECTORS ));\ + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKRR,\ + 63-(ECC_1BIT_VECTOR-DEVICE_VECTORS ));\ + Header->YY = (timeBuffer.Year % 100) + ((timeBuffer.Year % 100) / 10) * 6; \ + Header->MM = timeBuffer.Month+ (timeBuffer.Month/ 10) * 6; \ + Header->DD = timeBuffer.Day + (timeBuffer.Day / 10) * 6; \ + Header->hh = timeBuffer.Hour + (timeBuffer.Hour / 10) * 6; \ + Header->mm = timeBuffer.Minute+(timeBuffer.Minute/10) * 6; \ + Header->ss = timeBuffer.Second+(timeBuffer.Second/10) * 6; \ +} + + +// +// Interrupt set register 2 ( 0xz447 ) +// +#define SVP_INTR2_SET_VIT3SET 0x0040 +#define SVP_WINDOW0_OFFSET 0x0000 // Window 0 start offset ( EISA I/O Space) +#define SVP_WINDOW1_OFFSET 0x0800 // Window 1 start offset ( EISA I/O Space) +#define SVP_WINDOW2_OFFSET 0x0c00 // Window 2 start offset ( EISA I/O Space) +#define SVP_GLOBAL_OFFSET 0x0400 // Global Window start offset ( EISA I/O Space) +// +// EISA Slot is 1 orign. so When HalpSvpEisaSLot is 0 SPV no slot in. +// +ULONG HalpSvpEisaSlot = 0; +ULONG HalpSvpWindow0; +ULONG HalpSvpWindow1; +ULONG HalpSvpWindow2; +ULONG HalpSvpGlobal; +ULONG HalpSvpAlive = FALSE; +ULONG HalpBusySvpFlag=0; +// For Cache + +// For Cache +VOID +HalpCacheErrorLog( + IN ULONG cpu, + IN PVOID pbuf, + IN ULONG errorcode +); +ULONG HalpCacheErrorStack[8196]; +UCHAR HalpCacheErrorHwLog[HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE]; +#define HEADER_CACHE 0x06 + +// +// SVP ISA Board Detect. This Borad is ISA but EISA Configration!!. +// So Search EISA Configration. +// +VOID +HalpSVPSlotDetect( + VOID +) +{ + ULONG SlotNumber; + ULONG DataLength; + ULONG CompressedId; + UCHAR Buf[ sizeof(CM_EISA_SLOT_INFORMATION) + sizeof(CM_EISA_FUNCTION_INFORMATION)]; + PCM_EISA_SLOT_INFORMATION SlotInformation; + PCM_EISA_FUNCTION_INFORMATION funcInformation; + ULONG i; + UCHAR Data; + + // + // SVP H/W Alive by F/W. + // + HalpLocalDeviceReadWrite(ALMSNS_HIGH,&Data,LOCALDEV_OP_READ); + // + // detected By F/W . + // + if( Data & 0x1){ + // + //F/W diag is fail !! + // + return; + } + + + for(SlotNumber =1 ;SlotNumber <= EISA_MAX_DEVICE;SlotNumber++){ + for (i =0;i<sizeof(CM_EISA_SLOT_INFORMATION) + sizeof(CM_EISA_FUNCTION_INFORMATION);i++) + Buf[i]=0; + + DataLength = HalGetBusData( + EisaConfiguration, + 0, //EISA Bus is 0 + SlotNumber, + Buf, + sizeof(CM_EISA_SLOT_INFORMATION) + + sizeof(CM_EISA_FUNCTION_INFORMATION) + ); + SlotInformation=( PCM_EISA_SLOT_INFORMATION)Buf; + funcInformation=( PCM_EISA_FUNCTION_INFORMATION)&Buf[sizeof(CM_EISA_SLOT_INFORMATION)]; + // + // 0x018ca338 == > NEC SVP (38 a3 8c 01) + // + // + if(((SlotInformation->CompressedId) &0xffffff)== 0x8ca338){ + HalpSvpEisaSlot = SlotNumber; + HalpSvpWindow0 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW0_OFFSET); + HalpSvpWindow1 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW1_OFFSET); + HalpSvpWindow2 = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_WINDOW2_OFFSET); + HalpSvpGlobal = ( (SlotNumber<< PAGE_SHIFT)|EISA_CNTL_PHYSICAL_BASE|KSEG1_BASE|SVP_GLOBAL_OFFSET); + break; + } +#if DBG + + DbgPrint("EISA Slot #%x DataLen= 0x%x\n",SlotNumber, DataLength ); + DbgPrint("EISA Slot #%x CompressedId = 0x%x\n",SlotNumber, SlotInformation->CompressedId); + DbgPrint("EISA Slot #%x RetunCode = 0x%x\n",SlotNumber, SlotInformation->ReturnCode); + DbgPrint("EISA Slot #%x Checksum = 0x%x\n",SlotNumber, SlotInformation->Checksum); + + DbgPrint("EISA Slot #%x FCompressedId = 0x%x\n",SlotNumber, funcInformation->CompressedId); + DbgPrint("EISA Slot #%x FMinorRevision= 0x%x\n",SlotNumber, funcInformation->MinorRevision); + DbgPrint("EISA Slot #%x FMajorRevision= 0x%x\n",SlotNumber, funcInformation->MajorRevision); + DbgPrint("EISA Slot #%x FFunctionFlags= 0x%x\n",SlotNumber, funcInformation->FunctionFlags); + + DbgPrint("EISA Slot #%x FTypeString = %s\n",SlotNumber, funcInformation->TypeString); +#endif + } + // + // Eisa Configration Ok. + // + if( HalpSvpEisaSlot){ + HalpSvpAlive = TRUE; +#if DBG + DbgPrint("SVP ALIVE\n" ); +#endif + } +} + +VOID +HalSvpIntToSvp( + VOID + ) +{ + + UCHAR Status; + UCHAR LockCode; + UCHAR LockCode2; + ULONG i; + + ULONG RetryCount =10; + UCHAR Code = 0x7; + + KiAcquireSpinLock(&HalpLogLock); + + + + Status = READ_PORT_UCHAR( HalpSvpWindow2 + 0xc1 ); + KeStallExecutionProcessor( 1000 ); // wait 1msec + + for( i = 0; (i < RetryCount ) && (Status != 0); i++ ){ + KeStallExecutionProcessor( 1000 ); // wait 1msec + Status = READ_PORT_UCHAR( HalpSvpWindow2 + 0xc1 ); + } + + if( Status != 0x00 ){ + // Flag on for dump + HalpBusySvpFlag = 1; + return; + } + + + LockCode = READ_PORT_UCHAR( HalpSvpGlobal + 0x58 ); + WRITE_PORT_UCHAR(HalpSvpGlobal + 0x58,0xff ); + LockCode2= READ_PORT_UCHAR( HalpSvpGlobal + 0x50 ); + WRITE_PORT_UCHAR(HalpSvpGlobal + 0x50,0xff ); + + WRITE_PORT_UCHAR( HalpSvpWindow2 + 0xc1, Code ); + + WRITE_PORT_UCHAR( HalpSvpGlobal + 0x58,LockCode ); + WRITE_PORT_UCHAR( HalpSvpGlobal + 0x50,LockCode2 ); + + WRITE_PORT_UCHAR( HalpSvpGlobal + 0x47,SVP_INTR2_SET_VIT3SET); + + KiReleaseSpinLock(&HalpLogLock); + + return; +} + + + + +VOID +NVRAM_HWLOG_WRITE( + IN PVOID Buff, + IN ULONG StartBlockNo, + IN ULONG NumBlock +){ + + ULONG i,j; + + + for(i=0;i<NumBlock;i++){ + for(j=0;j<HWLOG_RECORD_SIZE;j++){ + // + // Byte write only. + // + WRITE_REGISTER_UCHAR( + (PUCHAR)(NVRAM_HWLOG_BASE+ +// (PUCHAR)(NVRAM_HWLOG_BASE+HWLOG_RECORD_SIZE + + StartBlockNo * HWLOG_RECORD_SIZE + + i*HWLOG_RECORD_SIZE+ + j), + + ((PUCHAR)Buff)[i*HWLOG_RECORD_SIZE + j] + ); + } + } + + +} + + + +VOID +NVRAM_HWLOG_READ( + IN PVOID Buff, + IN ULONG StartBlockNo, + IN ULONG NumBlock +){ + + ULONG i,j; + + + for(i=0;i<NumBlock;i++){ + for(j=0;j<HWLOG_RECORD_SIZE;j++){ + // + // read + // + ((PUCHAR)Buff)[i*HWLOG_RECORD_SIZE + j]= READ_REGISTER_UCHAR( (PUCHAR)(NVRAM_HWLOG_BASE+ StartBlockNo * HWLOG_RECORD_SIZE + i*HWLOG_RECORD_SIZE+ j) ); + } + } + + +} + +VOID +HalpHwLogBuffInit( +){ + ULONG i; + for(i=0;i< HWLOG_RECORD_SIZE+HWLOG_REV1_RECORD_SIZE;i++) + HwLogBuff[i] = 0x0; +} + +VOID +HalpHwLogHeaderInit( + +){ + PHW_LOG_AREA_HEADER Header; + PUCHAR Sump; + ULONG i; + // + // Genelic Buffer Initialization to all 0x0 + // + HalpHwLogBuffInit(); + + Header = (PHW_LOG_AREA_HEADER)HwLogBuff; + // + // Build This record header + // + Header->Ident = (USHORT)HEADER_IDENT_REV0; + // + // Time Field is BCD + // + GET_TIME2(&(Header->YY)); + Header->RCT = HEADER_PANIC; + Header->ST1 = 0; + Header->ST2 = 0; + Header->ST3 = 0; + Header->DTLEN = HWLOG_REV1_RECORD_SIZE; + // + // Endian Convert to Big + // + Header->DTLEN = ( + ((Header->DTLEN & 0xFF) << 8) | + ((Header->DTLEN & 0xFF00) >> 8) + ); + Header->FRU1[0]=Header->FRU1[1] = 0; + Header->FRU2[0]=Header->FRU2[1] = 0; + + //Make Check Sum + Header->CSM = 0; + Sump = (PUCHAR) HwLogBuff; + for (i= 0; i<= 14; i++){ + Header->CSM += *(Sump+i); + } + Header->CSM = (UCHAR)( Header->CSM & 0xff); + // Header Build Conpleate!! + + +} + +BOOLEAN +HalpSetHwLog( + IN PVOID Buff, + IN ULONG NumBlock +){ + + PHWLOG_CONTROL_INFO Control; + HW_LOG_AREA_HEADER Header; + ULONG StartBlockNo; + ULONG AllFree; + ULONG RemainFree; + ULONG i; + UCHAR InBuff[sizeof(HWLOG_CONTROL_INFO)]; + PUCHAR Sump; + ULONG Csm; + ULONG FreeLen,Len; + +#if 0 //test only + // + // Get Control area + // + for (i = 0;i < sizeof(HWLOG_CONTROL_INFO);i++) + InBuff[i] = 0; + NVRAM_HWLOG_WRITE((PUCHAR)InBuff, 0x0,1); + +#endif + + + // + // Get Control area + // + for (i = 0;i < sizeof(HWLOG_CONTROL_INFO);i++) + InBuff[i] = READ_REGISTER_UCHAR( (PUCHAR)(NVRAM_HWLOG_BASE+i)); + + Control= ( PHWLOG_CONTROL_INFO)InBuff; + //Convert Endian to littl + Control->BASE = ( ((Control->BASE & 0xFF00) >> 8) | ((Control->BASE & 0x00FF) << 8) ); + Control->NREC = ( ((Control->NREC & 0xFF00) >> 8) | ((Control->NREC & 0x00FF) << 8) ); + Control->TBASE= ( ((Control->TBASE& 0xFF00) >> 8) | ((Control->TBASE& 0x00FF) << 8) ); + Control->TN = ( ((Control->TN & 0xFF00) >> 8) | ((Control->TN & 0x00FF) << 8) ); + Control->RBASE= ( ((Control->RBASE& 0xFF00) >> 8) | ((Control->RBASE& 0x00FF) << 8) ); + // + // Write Log Number + // This data Big endian + // + ((PHW_LOG_AREA_HEADER)Buff)->LGN = Control->LOGNUM; + Csm = 0; + Sump = (PUCHAR) Buff; + for (i= 0; i<= 14; i++){ + Csm += (ULONG)(*(Sump+i)); + } +// Csm = ((PHW_LOG_AREA_HEADER)Buff)->CSM + Control->LOGNUM; + ((PHW_LOG_AREA_HEADER)Buff)->CSM = (UCHAR)(Csm & 0xFF); + Control->RN = ( ((Control->RN & 0xFF00) >> 8) | ((Control->RN & 0x00FF) << 8) ); + + // + // Log Field Invalid + // +#if 1 + if ( (Control->STAT & 0x01) == 0 ){ + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + return FALSE; + } +#endif + + if ((Control->BASE < 0) || (NVRAM_HWLOG_MAX_ENTRY <= Control->BASE ) || + (Control->NREC < 0) || (NVRAM_HWLOG_MAX_ENTRY < Control->NREC ) || + (Control->RBASE < 0) || (NVRAM_HWLOG_MAX_ENTRY <= Control->RBASE) || + (Control->RN < 0) || (NVRAM_HWLOG_MAX_ENTRY < Control->RN )) + { + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + return FALSE; + } + + StartBlockNo = Control->RBASE+Control->RN; + + if(StartBlockNo > NVRAM_HWLOG_MAX_ENTRY) + StartBlockNo -= NVRAM_HWLOG_MAX_ENTRY; + + // + // We Can't Logging. as if used log area wrieted back disk. + // + if( + ( (NVRAM_HWLOG_MAX_ENTRY - Control->NREC) < NumBlock) || + ( (NVRAM_HWLOG_MAX_ENTRY - Control->NREC == 0)) + ){ + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + + return FALSE; + } + + // + // as if used log area writed back disk as posible. + // + if( + (NVRAM_HWLOG_MAX_ENTRY - Control->RN) < NumBlock && + (NVRAM_HWLOG_MAX_ENTRY - Control->NREC) >= NumBlock + ){ + + + RemainFree = (NVRAM_HWLOG_MAX_ENTRY - Control->RN); + + NVRAM_HWLOG_WRITE(Buff, StartBlockNo+1,RemainFree); + Control->NREC += (USHORT)RemainFree; + Control->RN += (USHORT)RemainFree; + NumBlock -= RemainFree; +#if 0 + Control->RBASE += (USHORT)NumBlock; + +#endif + // + // Move RBASE + // + FreeLen=0; + + do{ + // + // Read RBASE Header + // + + NVRAM_HWLOG_READ(&Header,Control->RBASE,1); + + // + // Check Header + // + + if(Header.Ident != HEADER_IDENT_REV0){ + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + return FALSE; + } + + // + // Check Csm + // + + Csm = 0; + Sump = (PUCHAR) &Header; + for (i= 0; i<= 14; i++){ + Csm += *(Sump+i); + } + Csm = (UCHAR)( Csm & 0xff); + if(Header.CSM!=Csm){ + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + return FALSE; + } + // + // FreeLen + // + Len=0; + Len = ( ((Header.DTLEN & 0xFF) << 8) | ((Header.DTLEN & 0xFF00) >> 8) ); + if(Len%32){ + Len=(Len/32)+1; + }else{ + Len=Len/32; + } + FreeLen=FreeLen+Len+1; + + // + // Move RBASE + // + Control->RBASE = Control->RBASE+(USHORT)FreeLen; + if(Control->RBASE >= NVRAM_HWLOG_MAX_ENTRY){ + Control->RBASE=Control->RBASE - NVRAM_HWLOG_MAX_ENTRY; + } + }while(FreeLen < NumBlock); + + Control->RN=Control->RN - (USHORT)FreeLen; + StartBlockNo = 0; + } + + NVRAM_HWLOG_WRITE(Buff, StartBlockNo+1,NumBlock); + + Control->RN += (USHORT)NumBlock; + if(Control->LOGNUM==0xff){ + Control->LOGNUM=0; + }else{ + Control->LOGNUM++; + } + Control->NREC += (USHORT)NumBlock; + + // + // Convet endian to big + // + Control->BASE = ( ((Control->BASE & 0xFF00) >> 8) | ((Control->BASE & 0x00FF) << 8) ); + Control->NREC = ( ((Control->NREC & 0xFF00) >> 8) | ((Control->NREC & 0x00FF) << 8) ); + Control->TBASE= ( ((Control->TBASE& 0xFF00) >> 8) | ((Control->TBASE& 0x00FF) << 8) ); + Control->TN = ( ((Control->TN & 0xFF00) >> 8) | ((Control->TN & 0x00FF) << 8) ); + Control->RBASE= ( ((Control->RBASE& 0xFF00) >> 8) | ((Control->RBASE& 0x00FF) << 8) ); + Control->RN = ( ((Control->RN & 0xFF00) >> 8) | ((Control->RN & 0x00FF) << 8) ); + + // + // Write fix HW Log Control Area. + // Block No = 0; + // Number of block = 1; + NVRAM_HWLOG_WRITE((PUCHAR)Control, 0x0,1); + + + // If SVP Board alive So write port of svp. + // IF EIF Occured SVP Board required reset port. + // + + if(HalpSvpAlive) + HalSvpIntToSvp(); + + return TRUE; +} + +VOID +HalpColumnbsSysbusLogger( + IN ULONG Node +){ + + PHW_LOG_COLUMNBS_SYSBUS_CONTEXT Buf; + PCOLUMNBUS_REGISTER ColumnbusRegister; + ULONG i; + ULONG PhysicalCpuNumber; + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + Buf = (PHW_LOG_COLUMNBS_SYSBUS_CONTEXT)HwLogBuff; + + // + // CPU Context. + // + Buf->EPC.Long = 0; + Buf->STATUS = 0; + Buf->CAUSE = 0; + Buf->CONFIG = 0; + Buf->LLADR = 0; + Buf->RPID = 0; + Buf->CASHEER = 0; + Buf->ERREPC.Long = 0; + + // + // This Register is local read Only. + // + Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); +#if 0 + // + // Error CPU detect + // + if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE4){ + Node = COLUMBUS0_NODE; + break; + else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE5) + Node = COLUMBUS1_NODE; + break; + else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE6) + Node = COLUMBUS2_NODE; + break; + else if( Buf->COLUMNBS_ERRNOD & ERRNOD_NODE7) + Node = COLUMBUS3_NODE; + break; + default : + break; + + } +#endif + // + // Erred Columbus H/W Register Context. + // + Buf->COLUMNBS_NMIR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIR); + Buf->COLUMNBS_CNFG = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->CNFG); + Buf->COLUMNBS_STSR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STSR); + // + // This Register is local read Only. + // +// Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + + Buf->COLUMNBS_AERR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR); + Buf->COLUMNBS_AERR2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR2); + Buf->COLUMNBS_FERR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->FERR); + Buf->COLUMNBS_FERR2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->FERR2); + Buf->COLUMNBS_ERRMK = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRMK); + Buf->COLUMNBS_ERRMK2= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRMK2); + Buf->COLUMNBS_ERRI = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRI); + Buf->COLUMNBS_ERRI2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ERRI2); + Buf->COLUMNBS_NMIM = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIM); + Buf->COLUMNBS_NMIM2 = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->NMIM2); + Buf->COLUMNBS_ARTYCT= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->ARTYCT); + Buf->COLUMNBS_DRTYCT= READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->DRTYCT); + Buf->COLUMNBS_REVR = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->REVR); + Buf->COLUMNBS_MODE = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->MODE); + Buf->IPR.Long = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->IPR); + Buf->IPR.Fill = READ_REGISTER_ULONG( ((PULONG)&COLUMNBS_GCNTL(Node)->IPR) +1); + Buf->MKR.Long = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->MKR); + Buf->MKR.Fill = READ_REGISTER_ULONG( ((PULONG)&COLUMNBS_GCNTL(Node)->MKR) +1); + +#if 1 + ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(Node)->RRMT0H; + + for(i=0;i< 8;i++){ + Buf->RRMTXX[i].Long = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister++) ); + Buf->RRMTXX[i].Fill = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister++) ); +// ColumnbusRegister++; + } + + // + // STCON Register Local Access Only. So We report when CPU == happned CPU. + // + PhysicalCpuNumber = Node & 0x3; + if(PhysicalCpuNumber == HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number]){ + Buf->COLUMNBS_SYNDM = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->SYNDM); + Buf->COLUMNBS_STCON = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON); + Buf->COLUMNBS_STSAD = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STSAD); + Buf->COLUMNBS_STADMK = READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STADMK); + + ColumnbusRegister = (PCOLUMNBUS_REGISTER)&COLUMNBS_GCNTL(Node)->STDATH; + + WRITE_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON, + Buf->COLUMNBS_STCON & 0x004fffff); + while(READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON ) & 0x00800000) + ; + for(i=0;i< 64;i++){ + Buf->TRACE[i].Long = READ_REGISTER_ULONG( (PULONG)ColumnbusRegister ); + Buf->TRACE[i].Fill = READ_REGISTER_ULONG( (PULONG)(ColumnbusRegister+1) ); +// ColumnbusRegister++; + } + WRITE_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->STCON, + Buf->COLUMNBS_STCON | 0x00800000 ); + } +#endif + + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + +} + +VOID +HalpMpuLogger( + IN ULONG Node +){ + HalpColumnbsSysbusLogger(Node); +} + + +// +// +// +VOID +HalpPoncePciBuserrLogger( + IN ULONG Node +){ + // + // + + PHW_LOG_PONCE_CONTEXT Buf; + ULONG Ponce; + PPONCE_REGISTER PonceRegister; + ULONG i; + + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + Buf = (PHW_LOG_PONCE_CONTEXT)HwLogBuff; + Ponce = Node; + // + // CPU Context. + // + Buf->EPC.Long = 0; + // + // Columbus H/W Register Context. + // + Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + Buf->PONCE_REVR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->REVR); + Buf->PONCE_AERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->AERR); + Buf->PONCE_FERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->FERR); + Buf->PONCE_ERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ERRM); + Buf->PONCE_ERRI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ERRI); + Buf->PONCE_EAHI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->EAHI); + Buf->PONCE_EALI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->EALI); + Buf->PONCE_PAERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PAERR); + Buf->PONCE_PFERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PFERR); + Buf->PONCE_PERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM); + Buf->PONCE_PERRI = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRI); + Buf->PONCE_PTOL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PTOL); + Buf->PONCE_PNRT = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PNRT); + Buf->PONCE_PRCOL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PRCOL); + Buf->PONCE_PMDL = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PMDL); + Buf->PONCE_ANRC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->ANRC); + Buf->PONCE_DNRC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->DNRC); + Buf->PONCE_PCMDN = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PCMDN); + Buf->PONCE_PSTAT = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PSTAT); + Buf->PONCE_REVID = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->REVID); + Buf->PONCE_LTNCY = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->LTNCY); + +#if 0 + PonceRegister = (PPONCE_REGISTER)&PONCE_CNTL(Ponce)->RRMT0H; + + for(i=0;i< 8;i++){ + Buf->PONCE_RRMTX[i].Long = READ_REGISTER_ULONG( (PULONG)PonceRegister ); + Buf->PONCE_RRMTX[i].Fill = READ_REGISTER_ULONG( (PULONG)(PonceRegister+1) ); + PonceRegister++; + } + + Buf->PONCE_TRSM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRSM); +// Buf->PONCE_TROM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TROM); + Buf->PONCE_TRAC = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRAC); + Buf->PONCE_TRDS = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->TRDS); +#endif + + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + +} + +VOID +HalpPonceSysbuserrLogger( + IN ULONG Node +){ + + HalpPoncePciBuserrLogger(Node); + +} + +VOID +HalpMagellanSysbuserrLogger( + IN ULONG Node +){ + + + PHW_LOG_MAGELLAN_SYSBUS_CONTEXT Buf; + ULONG Magellan; + ULONG i; + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + Buf = ( PHW_LOG_MAGELLAN_SYSBUS_CONTEXT)HwLogBuff; + Magellan = Node - MAGELLAN0_NODE; + // + // Magellan Context. + // + Buf->MAGELLAN_AERR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->AERR ); + Buf->MAGELLAN_FERR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->FERR ); + Buf->MAGELLAN_ERRM = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ERRM ); + Buf->MAGELLAN_ERRI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ERRI ); +#if 0 //non support + Buf->MAGELLAN_NMIM = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->NMIM ); +#endif + Buf->MAGELLAN_EAHI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAHI ); + Buf->MAGELLAN_EALI = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EALI ); + Buf->MAGELLAN_CKE0 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->CKE0 ); + Buf->MAGELLAN_SECT = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->SECT ); + Buf->MAGELLAN_STS1 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->STS1 ); + Buf->MAGELLAN_DATM.Long =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DATM ); + Buf->MAGELLAN_DSRG.Long =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DSRG ); + Buf->MAGELLAN_SDLM.Long = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->SDLM ); + + Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + + Buf->ECC1ERROR_COUNT = 0; + Buf->SIMM_ITF_RESULT = 0; + Buf->MEMORYMAP_ITF_RESULT =0; + + + Buf->MAGELLAN_INLC = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->INLC ); + Buf->MAGELLAN_RCFD = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->RCFD ); + Buf->MAGELLAN_DTRG = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->DTRG ); + Buf->MAGELLAN_REVR = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->REVR ); + Buf->MAGELLAN_ADECX[0] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC0 ); + Buf->MAGELLAN_ADECX[1] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC1 ); + Buf->MAGELLAN_ADECX[2] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC2 ); + Buf->MAGELLAN_ADECX[3] =READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->ADEC3 ); + Buf->MAGELLAN_EADECX[1]=READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAADEC0 ); + Buf->MAGELLAN_EADECX[2]=READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(Magellan)->EAADEC1 ); + Buf->EPC.Long = 0; + +#if 1 + // + // These registers are not S/W specification + // + Buf->MAGELLAN_TMODE = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD) ); + Buf->MAGELLAN_TRA = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRA) ); + + WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD), + Buf->MAGELLAN_TMODE & 0x7fffffff); + while( READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD) ) & 0x80000000) + ; + + i = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD ) ); + WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD), + i | 0x08000000); + while( !(READ_REGISTER_ULONG((PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD)) & 0x08000000) ) + ; + + for(i=0;i<32;i++){ + Buf->TRMX[i][0] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM0[i]) ); + Buf->TRMX[i][1] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM1[i]) ); + Buf->TRMX[i][2] = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TRM2[i]) ); + } + i = READ_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD ) ); + WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD), + i & 0xf7ffffff ); + WRITE_REGISTER_ULONG( (PULONG)(&MAGELLAN_X_CNTL(Magellan)->TMOD), + ( i & 0xf7ffffff ) | 0x80000000); +#endif + + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); +} + +// +// +VOID +HalpEcc1Logger( + IN ULONG Node +) +{ + HalpMagellanSysbuserrLogger(Node); +} + +// +// +VOID +HalpEcc2Logger( + IN ULONG Node +) +{ + HalpMagellanSysbuserrLogger(Node); +} + +VOID +HalpEisaLogger( + IN ULONG Node +){ + + PHW_LOG_EISA_CONTEXT Buf; + + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + Buf = ( PHW_LOG_EISA_CONTEXT)HwLogBuff; + + Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + + Buf->ESC_NMISC = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus); + Buf->ESC_NMIERTC = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable); + Buf->ESC_NMIESC = READ_REGISTER_UCHAR( + &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl + ); + Buf->ESC_SOFTNMI = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiIoInterruptPort); + + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + +} + +VOID +HalpCacheErrorLog( + IN ULONG cpu, + IN PVOID pbuf, + IN ULONG errorcode + ) +{ + UCHAR string[256]; + ULONG cacherr,errorepc; + + PHW_LOG_AREA_HEADER Header; + PUCHAR Sump; + ULONG i; + PHW_LOG_CACHE_ERROR PCache_err; + // + // Genelic Buffer Initialization to all 0x0 + // + + Header = (PHW_LOG_AREA_HEADER)pbuf; + // + // Build This record header + // + Header->Ident = (USHORT)HEADER_IDENT_REV0; + // + // Time Field is BCD + // + GET_TIME2(&(Header->YY)); + Header->RCT = HEADER_PANIC; + Header->ST1 = HEADER_CACHE; + Header->ST2 = (UCHAR)cpu; + Header->ST3 = (UCHAR)errorcode; + Header->DTLEN = HWLOG_REV1_RECORD_SIZE; + // + // Endian Convert to Big + // + Header->DTLEN = ( + ((Header->DTLEN & 0xFF) << 8) | + ((Header->DTLEN & 0xFF00) >> 8) + ); + Header->FRU1[0]=Header->FRU1[1] = 0; + Header->FRU2[0]=Header->FRU2[1] = 0; + Header->CSM = 0; + Sump = (PUCHAR) pbuf; + for (i= 0; i<= 14; i++){ + Header->CSM += *(Sump+i); + } + Header->CSM = (UCHAR)( Header->CSM & 0xff); + // Header Build Conpleate!! + // Set hw log + + HalpSetHwLog(pbuf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + + + // Display Error message + + PCache_err=(PHW_LOG_CACHE_ERROR)pbuf; + cacherr=PCache_err->CHERR_cpu; + errorepc=PCache_err->EPC_cpu; + sprintf(string,"CPU #%x Cache Error %x %x %x ",cpu,cacherr,errorepc,errorcode); + HalpChangePanicFlag( 16, 0x01, 0x10); + HalDisplayString(string); + for(;;){ +// DbgBreakPoint(); + } +} + +VOID +HalpCacheerrR4400Logger( + IN ULONG Node +){ + +} + +VOID +HalpCacheerrR10000Logger( + IN ULONG Node +){ + +} + +VOID +HalpNmiCpuContextCopy( + IN ULONG Node +){ + PHW_LOG_WDT_CONTEXT Buf; + ULONG Cpu; + + Buf = (PHW_LOG_WDT_CONTEXT)HwLogBuff; + + Cpu = Node - COLUMBUS0_NODE; + + Buf->Cpu.At.Long =HalpNMIBuf[Cpu][0]; + Buf->Cpu.V0.Long =HalpNMIBuf[Cpu][1]; + Buf->Cpu.V1.Long =HalpNMIBuf[Cpu][2]; + Buf->Cpu.A0.Long =HalpNMIBuf[Cpu][3]; + Buf->Cpu.A1.Long =HalpNMIBuf[Cpu][4]; + Buf->Cpu.A2.Long =HalpNMIBuf[Cpu][5]; + Buf->Cpu.A3.Long =HalpNMIBuf[Cpu][6]; + Buf->Cpu.T0.Long =HalpNMIBuf[Cpu][7]; + Buf->Cpu.T1.Long =HalpNMIBuf[Cpu][8]; + Buf->Cpu.T2.Long =HalpNMIBuf[Cpu][9]; + Buf->Cpu.T3.Long =HalpNMIBuf[Cpu][10]; + Buf->Cpu.T4.Long =HalpNMIBuf[Cpu][11]; + Buf->Cpu.T5.Long =HalpNMIBuf[Cpu][12]; + Buf->Cpu.T6.Long =HalpNMIBuf[Cpu][13]; + Buf->Cpu.T7.Long =HalpNMIBuf[Cpu][14]; + Buf->Cpu.T8.Long =HalpNMIBuf[Cpu][15]; + Buf->Cpu.T9.Long =HalpNMIBuf[Cpu][16]; + Buf->Cpu.GP.Long =HalpNMIBuf[Cpu][17]; + Buf->Cpu.SP.Long =HalpNMIBuf[Cpu][18]; + Buf->Cpu.FP.Long =HalpNMIBuf[Cpu][19]; + Buf->Cpu.RA.Long =HalpNMIBuf[Cpu][20]; + Buf->Cpu.STATUS =HalpNMIBuf[Cpu][21]; + Buf->Cpu.CAUSE =HalpNMIBuf[Cpu][22]; + + Buf->Cpu.EPC.Long =HalpNMIBuf[Cpu][23]; + Buf->Cpu.ERREPC.Long =HalpNMIBuf[Cpu][24]; + + Buf->Cpu.S0.Long = HalpNMIBuf[Cpu][25]; + Buf->Cpu.S1.Long = HalpNMIBuf[Cpu][26]; + Buf->Cpu.S2.Long = HalpNMIBuf[Cpu][27]; + Buf->Cpu.S3.Long = HalpNMIBuf[Cpu][28]; + Buf->Cpu.S4.Long = HalpNMIBuf[Cpu][29]; + Buf->Cpu.S5.Long = HalpNMIBuf[Cpu][30]; + Buf->Cpu.S6.Long = HalpNMIBuf[Cpu][31]; + Buf->Cpu.S7.Long = HalpNMIBuf[Cpu][32]; + + Buf->Cpu.K0.Long = 0; + + Buf->Cpu.ENTRYLO0.Long = HalpNMIBuf[Cpu][33]; + Buf->Cpu.ENTRYLO1.Long = HalpNMIBuf[Cpu][34]; + Buf->Cpu.BADVADDR.Long = HalpNMIBuf[Cpu][35]; + Buf->Cpu.ENTRYHI.Long = HalpNMIBuf[Cpu][36]; + + + Buf->Cpu.PAGEMASK = HalpNMIBuf[Cpu][37]; + Buf->Cpu.PRID = HalpNMIBuf[Cpu][38]; + Buf->Cpu.CONFIG = HalpNMIBuf[Cpu][39]; + Buf->Cpu.LLADDR = HalpNMIBuf[Cpu][40]; + Buf->Cpu.WATCHLO = HalpNMIBuf[Cpu][41]; + Buf->Cpu.WATCHHI = HalpNMIBuf[Cpu][42]; + Buf->Cpu.XCONTEXT.Long = HalpNMIBuf[Cpu][43]; + Buf->Cpu.ECC = HalpNMIBuf[Cpu][44]; + Buf->Cpu.CASEER = HalpNMIBuf[Cpu][45]; + Buf->Cpu.TAGLO = HalpNMIBuf[Cpu][46]; + Buf->Cpu.TAGHI = HalpNMIBuf[Cpu][47]; + +} + + + +VOID +HalpNmiWdtLogger( + IN ULONG Node +){ + + PHW_LOG_WDT_CONTEXT Buf; + + Buf = (PHW_LOG_WDT_CONTEXT)HwLogBuff; + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + HalpNmiCpuContextCopy(Node); + + Buf->COLUMNBS_NMIR = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIR); + Buf->COLUMNBS_CNFG = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG); + Buf->COLUMNBS_WDTSR= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->WDTSR); + Buf->COLUMNBS_WDT = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->WDT); + Buf->IPR.Long = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->IPR); + Buf->IPR.Fill = READ_REGISTER_ULONG( ((PULONG)&(COLUMNBS_LCNTL)->IPR+1)); + Buf->MKR.Long = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKR); + Buf->MKR.Fill = READ_REGISTER_ULONG( ((PULONG)&(COLUMNBS_LCNTL)->MKR+1)); + + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + +} + +VOID +HalpNmiSvpLogger( + IN ULONG Node +){ + + PHW_LOG_SVP_CONTEXT Buf; + + Buf = (PHW_LOG_SVP_CONTEXT)HwLogBuff; + + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + + HalpNmiCpuContextCopy(Node); + // + // Write Log Record + // + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + +} + +VOID +HalpNmiLog( + VOID +){ + ULONG PhysicalCpuNumber; + ULONG Node; + + PhysicalCpuNumber = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number]; + Node = PhysicalCpuNumber + COLUMBUS0_NODE; + + switch( HalpNMIFlag & 0xffff){ + case NMIR_EXNMI : +// if(HalpNmiSvp[PhysicalCpuNumber]) + HalpNmiSvpLogger(Node); + + + break; + case NMIR_WDTOV: + HalpNmiWdtLogger(Node); + break; +#if 0 + case NMIR_CLBNMI: + case NMIR_UNANMI: + HalpColumnbsSysbusLogger(Node); + break; +#endif + default: + if ( READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR) & HW_LOG_MPU_INTERNAL_AERR) + HalpMpuLogger(Node); + else + HalpColumnbsSysbusLogger(Node); + break; + } + + +} + + +VOID +HalpPowerLogger( + IN ULONG Node +// +// Node Not used. +// +// + +){ + + + PHW_LOG_POWER_CONTEXT Buf; + UCHAR Data; + PHW_LOG_AREA_HEADER Header; + // + // Builg Log Header + // + HalpHwLogHeaderInit(); + Header = (PHW_LOG_AREA_HEADER)HwLogBuff; + + Header->RCT = HEADER_NOT_PANIC; + Buf = (PHW_LOG_POWER_CONTEXT)HwLogBuff; + + Buf->COLUMNBS_ERRNOD= READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD); + + HalpLocalDeviceReadWrite(ALARM_LOW,&Data,LOCALDEV_OP_READ); + Buf->LOCAL_ALARM = (USHORT)Data; + HalpLocalDeviceReadWrite(ALARM_HIGH,&Data,LOCALDEV_OP_READ); + Buf->LOCAL_ALARM |= (USHORT)(Data << 8); + + + HalpLocalDeviceReadWrite(ALMINH_LOW, &Data,LOCALDEV_OP_READ); + Buf->LOCAL_ALMINH = (USHORT)Data; + HalpLocalDeviceReadWrite(ALMINH_HIGH,&Data,LOCALDEV_OP_READ); + Buf->LOCAL_ALMINH |= (USHORT)(Data << 8); + + + HalpSetHwLog(Buf,(HWLOG_REV1_RECORD_SIZE / HWLOG_RECORD_SIZE)+1); + + + +} + +VOID +HalpEifReturnLog( + VOID +){ + + HalpPowerLogger(0); + +} + + +VOID +HalpHwLogger( + IN ULONG Type, + IN ULONG Context +){ + + switch(Type){ + case HWLOG_MPU_INTERNAL: + HalpMpuLogger(Context); //fix + break; + case HWLOG_COLUMNBS_SYSBUS: + HalpColumnbsSysbusLogger(Context); //fix + break; + case HWLOG_PCI_BUSERROR: + HalpPoncePciBuserrLogger(Context); //fix + break; + case HWLOG_PONCE_SYSBUS: + HalpPonceSysbuserrLogger(Context); //fix + break; + case HWLOG_MAGELLAN_SYSBUS: + HalpMagellanSysbuserrLogger(Context); //fix + break; + case HWLOG_EISA: + HalpEisaLogger(Context); //fix + break; + case HWLOG_POWER: + HalpPowerLogger(Context); //fix + break; + case HWLOG_2BITERROR: + HalpEcc2Logger(Context); //fix + break; + case HWLOG_CACHEERR_R4400: + HalpCacheerrR4400Logger(Context); + break; + case HWLOG_CACHEERR_R10000: + case HWLOG_SYSCORERR: + HalpCacheerrR10000Logger(Context); + break; + case HWLOG_NMI_WDT: + HalpNmiWdtLogger(Context); + break; + + case HWLOG_NMI_SVP: + HalpNmiSvpLogger(Context); //fix + break; + case HWLOG_ECC1: + HalpEcc1Logger(Context); //fix + break; + default : + break; + } + +} + +// +// This Function Called HalpHandleEif() +// +VOID +HalpEifLog( + VOID +){ + ULONG Noder; + ULONG Node; + ULONG ErrorType; + ULONG Context; + + +#if 0 + // + // EIF logging only exec 1 cpu. + // + KiAcquireSpinLock(&HalpLogLock); +#endif + // + // Node Get By reported CPU. + // + Noder = (READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRNOD)& 0xf3cc); + + switch(Noder){ + case ERRNOD_NODE0 : + case ERRNOD_NODE1 : + if(Noder & ERRNOD_NODE0) + Node = PONCE0_NODE; + else + Node = PONCE1_NODE; + + if(READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Node)->AERR)) + ErrorType = HWLOG_PONCE_SYSBUS; //bugbug + else + ErrorType = HWLOG_PCI_BUSERROR; + break; + case ERRNOD_NODE4 : + case ERRNOD_NODE5 : + case ERRNOD_NODE6 : + case ERRNOD_NODE7 : + if(Noder & ERRNOD_NODE4) + Node = COLUMBUS0_NODE; + else if(Noder & ERRNOD_NODE5) + Node = COLUMBUS1_NODE; + else if(Noder & ERRNOD_NODE6) + Node = COLUMBUS2_NODE; + else if(Noder & ERRNOD_NODE7) + Node = COLUMBUS3_NODE; + + // + // Read AERR2 Register From EIF happend CPU. Not Reported CPU!! + // + if ( READ_REGISTER_ULONG( (PULONG)&COLUMNBS_GCNTL(Node)->AERR2) & HW_LOG_MPU_INTERNAL_AERR2) + ErrorType = HWLOG_MPU_INTERNAL; + else + ErrorType = HWLOG_COLUMNBS_SYSBUS; + + break; + case ERRNOD_NODE8 : + case ERRNOD_NODE9 : + + ErrorType = HWLOG_MAGELLAN_SYSBUS; + + if(Noder & ERRNOD_NODE8) + Node = MAGELLAN0_NODE; + else + Node = MAGELLAN1_NODE; + break; + + case ERRNOD_EISANMI: + ErrorType = HWLOG_EISA; + break; + + default: + // + // if There is no CPU Coused EIF. So Reported CPU set. + // + ErrorType = HWLOG_COLUMNBS_SYSBUS; + Node = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number] + COLUMBUS0_NODE; + break; + } + Context = Node; + HalpHwLogger(ErrorType, Context); + +#if 0 + KiReleaseSpinLock(&HalpLogLock); +#endif +} + + +// +// This Function Called HalpBusError() +// +VOID +HalpBusErrorLog( + VOID +){ + ULONG Node; + ULONG ErrorType; + ULONG Context; + + +// KiAcquireSpinLock(&HalpLogLock); + // + // Node Get By reported CPU. + // + Node = (READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->EAHI) & 0xF000) >> 12; + + switch(Node){ + case PONCE0_NODE: + case PONCE1_NODE: + ErrorType = HWLOG_PONCE_SYSBUS; + break; + case COLUMBUS0_NODE: + case COLUMBUS1_NODE: + case COLUMBUS2_NODE: + case COLUMBUS3_NODE: + ErrorType = HWLOG_COLUMNBS_SYSBUS; + break; + case MAGELLAN0_NODE: + case MAGELLAN1_NODE: + ErrorType = HWLOG_2BITERROR; + break; + default: + ErrorType = HWLOG_COLUMNBS_SYSBUS; + // + // This is safe code + // + Node = HalpLogicalCPU2PhysicalCPU[(PCR->Prcb)->Number] + COLUMBUS0_NODE; + break; + } + Context = Node; + HalpHwLogger(ErrorType, Context); + + +// KiReleaseSpinLock(&HalpLogLock); +} diff --git a/private/ntos/nthals/halr98b/mips/rxhwlog.h b/private/ntos/nthals/halr98b/mips/rxhwlog.h new file mode 100644 index 000000000..077f3816f --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxhwlog.h @@ -0,0 +1,469 @@ +/* +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + rxhwlog.h + +Abstract: + + This module is the header file that describes hardware addresses + for the r98B system. + +Author: + + + +Revision History: + +--*/ + +#ifndef _RXHWLOG_ +#define _RXHWLOG_ + +#include "halp.h" + + +#define NVRAM_HWLOG_PHYSIACL_ADDRESS 0x1F084000 +#define NVRAM_HWLOG_END 0x1F08C000 +#define NVRAM_HWLOG_BASE (KSEG1_BASE|NVRAM_HWLOG_PHYSIACL_ADDRESS) +#define NVRAM_HWLOG_MAX_ENTRY (((NVRAM_HWLOG_END - NVRAM_HWLOG_PHYSIACL_ADDRESS)\ + - sizeof(HWLOG_CONTROL_INFO)) / HWLOG_RECORD_SIZE) + +#define HWLOG_RECORD_SIZE 0x20 +#define HWLOG_REV1_RECORD_SIZE (0x200) +// +// Log Record RCT field +// +#define RCT_EPU 0x00 +#define RCT_MEMORY 0x01 +#define RCT_SYSBUS 0x03 +#define RCT_IOBUS 0x04 +#define RCT_CACHE 0x05 +#define RCT_SVP 0x06 +#define RCT_POWER 0x08 +#define RCT_COLUMNUS_SYSBUS 0x03 + + +// +// Log Record ST1 field +// PC: PCI BusNumber +// EC: Errcode +// MP: MPU Number +// +#define ST1_WDT_RUNOUT 0x00 +#define ST1_SVPNMI 0x08 +#define ST1_MPU 0x10 +#define ST1_SYS_IF_TRACE_LOG 0x12 +#define ST1_MEMORY_2BIT_ERR 0x00 +#define ST1_MEMORY_1BIT_HARD1 0x01 +#define ST1_MEMORY_1BIT_HARDN 0x02 +#define ST1_MEMORY_1BIT_HARD 0x03 +#define ST1_MEMORY_INTERNAL 0x10 +//#define ST1_COLUMNBUS_SYSBUS 0xEC +//#define ST1_PONCE_SYSBUS 0xEC +//#define ST1_MAGELLAN_SYSBUS 0xEC +#define ST1_SYSBUS_TRACE_LOG 0x09 +//#define ST1_PCI_BUS_ERR PC +#define ST1_EISA_BUS_ERR 0x07 +//#define ST1_CACHE_ERR_R4400 MP +//#define ST1_CACHE_ERR_R10000 MP +#define ST1_SVP_COM 0x01 +#define ST1_POWER_ALARM 0x20 +#define ST1_FAN_ALARM 0x21 +#define ST1_NPCI2_ALARM 0x22 +#define ST1_SVP_ALARM 0x23 + + +// +// Log Record DTLEN +// + +#define DTLEN_WDT 0x8001 +#define DTLEN_SVPNMI 0x6001 +#define DTLEN_MPU_INTERNAL 0x0002 +#define DTLEN_SYSTEM_IF_TRACE_LOG 0x0002 +#define DTLEN_ECC1_BIT 0x0002 + +// +// Log Record FRU1 +// +#define FRU1_WDT "MPUx" +#define FRU1_SVPNMI "MPUx" + +#pragma pack(1) + +typedef struct _MPU_REGISTER { + ULONG Long; + ULONG Fill; +} MPU_REGISTER, *PMPU_REGISTER; + +typedef struct _HWLOG_CONTROL_INFO { + USHORT PAD0; + USHORT BASE; + + USHORT PAD1; + USHORT NREC; + + USHORT PAD2; + UCHAR PAD3; + UCHAR LOGNUM; + + USHORT PAD4; + UCHAR PAD5; + UCHAR STAT; + + USHORT PAD6; + USHORT TBASE; + + USHORT PAD7; + USHORT TN; + + USHORT PAD8; + USHORT RBASE; + + USHORT PAD9; + USHORT RN; + +} HWLOG_CONTROL_INFO,*PHWLOG_CONTROL_INFO; + + +typedef struct _HW_LOG_AREA_HEADER { + USHORT Ident; + UCHAR YY; + UCHAR MM; + + UCHAR DD; + UCHAR hh; + UCHAR mm; + UCHAR ss; + + UCHAR RCT; + UCHAR ST1; + UCHAR ST2; + UCHAR ST3; + + USHORT DTLEN; + UCHAR LGN; + UCHAR CSM; + + ULONG FRU1[2]; + ULONG FRU2[2]; + +}HW_LOG_AREA_HEADER,*PHW_LOG_AREA_HEADER; + + +#define HEADER_IDENT_REV0 0xFFFFF +#define HEADER_PANIC 0x10 +#define HEADER_NOT_PANIC 0x11 +typedef struct _HW_LOG_CPU_CONTEXT { + MPU_REGISTER At; + MPU_REGISTER V0; + MPU_REGISTER V1; + MPU_REGISTER V2; + MPU_REGISTER A0; + MPU_REGISTER A1; + MPU_REGISTER A2; + MPU_REGISTER A3; + MPU_REGISTER T0; + MPU_REGISTER T1; + MPU_REGISTER T2; + MPU_REGISTER T3; + MPU_REGISTER T4; + MPU_REGISTER T5; + MPU_REGISTER T6; + MPU_REGISTER T7; + MPU_REGISTER S0; + MPU_REGISTER S1; + MPU_REGISTER S2; + MPU_REGISTER S3; + MPU_REGISTER S4; + MPU_REGISTER S5; + MPU_REGISTER S6; + MPU_REGISTER S7; + MPU_REGISTER T8; + MPU_REGISTER T9; + MPU_REGISTER K0; + MPU_REGISTER GP; + MPU_REGISTER SP; + MPU_REGISTER FP; + MPU_REGISTER RA; + MPU_REGISTER ENTRYLO0; + MPU_REGISTER ENTRYLO1; + MPU_REGISTER CONTEXT; + MPU_REGISTER BADVADDR; + MPU_REGISTER ENTRYHI; + ULONG STATUS; + ULONG CAUSE; + MPU_REGISTER EPC; + ULONG PAGEMASK; + ULONG PRID; + ULONG CONFIG; + ULONG LLADDR; + ULONG WATCHLO; + ULONG WATCHHI; + MPU_REGISTER XCONTEXT; + ULONG ECC; + ULONG CASEER; + ULONG TAGLO; + ULONG TAGHI; + MPU_REGISTER ERREPC; +}HW_LOG_CPU_CONTEXT,*PHW_LOG_CPU_CONTEXT; + + +typedef struct _HW_LOG_WDT_CONTEXT { + HW_LOG_AREA_HEADER Header; + HW_LOG_CPU_CONTEXT Cpu; + ULONG COLUMNBS_NMIR; + ULONG COLUMNBS_CNFG; + ULONG COLUMNBS_WDTSR; + ULONG COLUMNBS_WDT; + COLUMNBUS_REGISTER IPR; + COLUMNBUS_REGISTER MKR; +}HW_LOG_WDT_CONTEXT,*PHW_LOG_WDT_CONTEXT; + + +typedef struct _HW_LOG_SVP_CONTEXT { + HW_LOG_AREA_HEADER Header; + HW_LOG_CPU_CONTEXT Cpu; +}HW_LOG_SVP_CONTEXT,*PHW_LOG_SVP_CONTEXT; + + +typedef struct _HW_LOG_MPU_INTERNAL_CONTEXT { + HW_LOG_AREA_HEADER Header; + + MPU_REGISTER EPC; + ULONG STATUS; + ULONG CAUSE; + ULONG CONFIG; + ULONG LLADR; + ULONG RPID; + ULONG CASHEER; + MPU_REGISTER ERREPC; + + ULONG COLUMNBS_NMIR; + ULONG COLUMNBS_CNFG; + ULONG COLUMNBS_STSR; + ULONG COLUMNBS_ERRNOD; + ULONG COLUMNBS_AERR; + ULONG COLUMNBS_AERR2; + ULONG COLUMNBS_FERR; + ULONG COLUMNBS_FERR2; + ULONG COLUMNBS_ERRMK; + ULONG COLUMNBS_ERRMK2; + ULONG COLUMNBS_ERRI; + ULONG COLUMNBS_ERRI2; + ULONG COLUMNBS_NMIM; + ULONG COLUMNBS_NMIM2; + ULONG COLUMNBS_ARTYCT; + ULONG COLUMNBS_DRTYCT; + ULONG COLUMNBS_REVR; + ULONG COLUMNBS_MODE; + COLUMNBUS_REGISTER IPR; + COLUMNBUS_REGISTER MKR; + COLUMNBUS_REGISTER RRMTXX[8]; + ULONG COLUMNBS_SYNDM; + ULONG COLUMNBS_STCON; + ULONG COLUMNBS_STSAD; + ULONG COLUMNBS_STADMK; + COLUMNBUS_REGISTER TRACE[64]; +}HW_LOG_MPU_INTERNAL_CONTEXT,*PHW_LOG_MPU_INTERNAL_CONTEXT; + +#define HW_LOG_COLUMNBS_SYSBUS_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT +#define PHW_LOG_COLUMNBS_SYSBUS_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT + +#define HW_BUSERROR_MPU_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT +#define PHW_BUSERROR_MPU_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT + +#define HW_NMI_COLUMNBS_CONTEXT HW_LOG_MPU_INTERNAL_CONTEXT +#define PHW_NMI_COLUMNBS_CONTEXT PHW_LOG_MPU_INTERNAL_CONTEXT + +#define HW_LOG_ECC1_CONTEXT HW_LOG_MAGELLAN_SYSBUS_CONTEXT +#define PHW_LOG_ECC1_CONTEXT PHW_LOG_MAGELLAN_SYSBUS_CONTEXT + +#if 0 +typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_LOG_COLUMNBS_SYSBUS_CONTEXT; +typedef struct HW_LOG_COLUMNBS_SYSBUS_CONTEXT * PHW_LOG_COLUMNBS_SYSBUS_CONTEXT; +typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_BUSERROR_MPU_CONTEXT,*PHW_BUSERROR_MPU_CONTEXT; +typedef struct HW_LOG_MPU_INTERNAL_CONTEXT HW_NMI_COLUMNBS_CONTEXT,*PHW_NMI_COLUMNBS_CONTEXT; +typedef struct HW_LOG_MAGELLAN_SYSBUS_CONTEXT HW_LOG_ECC1_CONTEXT,*PHW_LOG_ECC1_CONTEXT; +#endif + +typedef struct _HW_LOG_SYSTEM_IF_CONTEXT { + HW_LOG_AREA_HEADER Header; + COLUMNBUS_REGISTER SYNDM; + COLUMNBUS_REGISTER STCON; + COLUMNBUS_REGISTER STSAD; + COLUMNBUS_REGISTER STADMK; + USHORT STDATHL[64][2]; +}HW_LOG_SYSTEM_IF_CONTEXT,*PHW_LOG_SYSTEM_IF_CONTEXT; + + + +typedef struct _HW_LOG_MAGELLAN_SYSBUS_CONTEXT { + HW_LOG_AREA_HEADER Header; + ULONG MAGELLAN_AERR; + ULONG MAGELLAN_FERR; + ULONG MAGELLAN_ERRM; + ULONG MAGELLAN_ERRI; + ULONG MAGELLAN_NMIM; + ULONG MAGELLAN_EAHI; + ULONG MAGELLAN_EALI; + ULONG MAGELLAN_CKE0; + ULONG MAGELLAN_SECT; + ULONG MAGELLAN_STS1; + MAGELLAN_REGISTER MAGELLAN_DATM; + MAGELLAN_REGISTER MAGELLAN_DSRG; + MAGELLAN_REGISTER MAGELLAN_SDLM; + ULONG COLUMNBS_ERRNOD; + ULONG ECC1ERROR_COUNT; + ULONG SIMM_ITF_RESULT; + ULONG MEMORYMAP_ITF_RESULT; + ULONG MAGELLAN_INLC; + ULONG MAGELLAN_RCFD; + ULONG MAGELLAN_DTRG; + ULONG MAGELLAN_REVR; + ULONG MAGELLAN_ADECX[4]; + ULONG MAGELLAN_EADECX[2]; + MPU_REGISTER EPC; + ULONG MAGELLAN_TMODE; + ULONG MAGELLAN_TRA; + ULONG TRMX[32][3]; +}HW_LOG_MAGELLAN_SYSBUS_CONTEXT,*PHW_LOG_MAGELLAN_SYSBUS_CONTEXT; + +typedef struct _HW_LOG_PONCE_CONTEXT { + HW_LOG_AREA_HEADER Header; + MPU_REGISTER EPC; + ULONG COLUMNBS_ERRNOD; + ULONG PONCE_REVR; + ULONG PONCE_AERR; + ULONG PONCE_FERR; + ULONG PONCE_ERRM; + ULONG PONCE_ERRI; + ULONG PONCE_EAHI; + ULONG PONCE_EALI; + ULONG PONCE_PAERR; + ULONG PONCE_PFERR; + ULONG PONCE_PERRM; + ULONG PONCE_PERRI; + ULONG PONCE_PTOL; + ULONG PONCE_PNRT; + ULONG PONCE_PRCOL; + ULONG PONCE_PMDL; + ULONG PONCE_ANRC; + ULONG PONCE_DNRC; + ULONG PONCE_PCMDN; + ULONG PONCE_PSTAT; + ULONG PONCE_REVID; + ULONG PONCE_LTNCY; + PONCE_REGISTER PONCE_RRMTX[8]; + ULONG PONCE_TRSM; + ULONG PONCE_TROM; + ULONG PONCE_TRAC; + ULONG PONCE_TRDS; + UCHAR PONCE_BUSTRACE[344]; //All 0 +}HW_LOG_PONCE_CONTEXT,*PHW_LOG_PONCE_CONTEXT; + +typedef struct _HW_LOG_SYSBUS_TRACE_CONTEXT { + HW_LOG_AREA_HEADER Header; + ULONG MAGELLAN_TMOD; + ULONG MAGELLAN_TRA; + ULONG TRMX[42][3]; +}HW_LOG_SYSBUS_TRACE_CONTEXT,*PHW_LOG_SYSBUS_TRACE_CONTEXT; + + +typedef struct _HW_LOG_EISA_CONTEXT { + HW_LOG_AREA_HEADER Header; + ULONG COLUMNBS_ERRNOD; + ULONG ESC_NMISC; + ULONG ESC_NMIERTC; + ULONG ESC_NMIESC; + ULONG ESC_SOFTNMI; +}HW_LOG_EISA_CONTEXT,*PHW_LOG_EISA_CONTEXT; + + + + +typedef struct _HW_LOG_SVP_CON_CONTEXT { + HW_LOG_AREA_HEADER Header; +}HW_LOG_SVP_CON_CONTEXT,*PHW_LOG_SVP_CON_CONTEXT; + + +typedef struct _HW_LOG_POWER_CONTEXT { + HW_LOG_AREA_HEADER Header; + ULONG COLUMNBS_ERRNOD; + USHORT LOCAL_ALARM; + USHORT LOCAL_ALMINH; +}HW_LOG_POWER_CONTEXT,*PHW_LOG_POWER_CONTEXT; + +#pragma pack(4) + + +#define HWLOG_MPU_INTERNAL 0x1 +#define HWLOG_COLUMNBS_SYSBUS 0x2 + +#define HWLOG_PCI_BUSERROR 0x100 +#define HWLOG_PONCE_SYSBUS 0x200 +#define HWLOG_MAGELLAN_SYSBUS 0x400 + +#define HWLOG_EISA 0x10 +#define HWLOG_POWER 0x20 +#define HWLOG_2BITERROR 0x40 + +#define HWLOG_CACHEERR_R4400 0x80 +#define HWLOG_CACHEERR_R10000 0x1000 +#define HWLOG_SYSCORERR 0x2000 +#define HWLOG_NMI_WDT 0x4000 + + +#define HWLOG_NMI_SVP 0x100000 +#define HWLOG_ECC1 0x200000 + + +#define HW_LOG_MPU_INTERNAL_AERR 0x37f +#define HW_LOG_MPU_INTERNAL_AERR2 0xffffffff + + +#define PONCE0_NODE 0 +#define PONCE1_NODE 1 +#define COLUMBUS0_NODE 4 +#define COLUMBUS1_NODE 5 +#define COLUMBUS2_NODE 6 +#define COLUMBUS3_NODE 7 + +#define MAGELLAN0_NODE 8 +#define MAGELLAN1_NODE 9 + +//Cache Error Log + +typedef struct _HW_LOG_CACHE_ERROR{ + HW_LOG_AREA_HEADER Header; + ULONG EPC_cpu; + ULONG Rev; + ULONG Psr_cpu; + ULONG CFG_cpu; + ULONG PRID_cpu; + ULONG CHERR_cpu; + ULONG CheAdd_p; + ULONG CheAdd_s; + ULONG TagLo_p; + ULONG ECC_p; + ULONG TagLo_s; + ULONG ECC_s; + LONGLONG data_s; + LONGLONG Good_data_s; + ULONG Good_TagLo_s; + ULONG Good_ECC_s; + ULONG tag_synd_s; + ULONG data_synd_s; + LONGLONG xkphs_share; +}HW_LOG_CACHE_ERROR,*PHW_LOG_CACHE_ERROR; + + + + +#endif // _RXHWLOG_ + + + + diff --git a/private/ntos/nthals/halr98b/mips/rxhwsup.c b/private/ntos/nthals/halr98b/mips/rxhwsup.c new file mode 100644 index 000000000..d4cc09ef1 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxhwsup.c @@ -0,0 +1,2124 @@ +/*++ + +Copyright (c) 1990-1993 Microsoft Corporation + +Module Name: + + rxhwsup.c + +Abstract: + + This module contains the HalpXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would normally reside in the internal.c module. + +Author: + + + +Environment: + + Kernel mode, local to I/O system + +Revision History: + + S001 96/2/9 T.Samezima + -Add TLB limit over check. + +--*/ + +#include "halp.h" +#include "bugcodes.h" +#include "eisa.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, HalpCreateDmaStructures) + +#endif + +extern POBJECT_TYPE IoAdapterObjectType; + +extern ULONG HalpLogicalCPU2PhysicalCPU[]; + +// +// 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 HalpInt0Interrupt; + +UCHAR DmaChannelMsg[] = "\nHAL: DMA channel x interrupted. "; + +// +// Pointer to phyiscal memory for map registers. +// + +ULONG HalpMapRegisterPhysicalBase; +ULONG HalpLogicalAddressLimit = 0; // S001 + +// +// The following is an array of adapter object structures for the internal DMA +// channels. +// + +// +// R98B AdapterObject for PCIBus is per PONCE +// +PADAPTER_OBJECT HalpPciAdapterObject[PONCE_MAX]; + +IO_ALLOCATION_ACTION +HalpAllocationRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context + ); + +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; + + // + // 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)) { + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + (0x100000 / PAGE_SIZE) + ); + + // + // Make sure this map register is valid for this adapter. + // No Check !! R98B 0-1M Never Free + + } + + 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); + + // + // R98B Must Be Cached!! + // + CacheEnabled =TRUE; + + // + // 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; + + // + // 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. + // R98 + + MapRegisterNumber = (ULONG)-1; + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + *NumberOfMapRegisters, + (0x100000 / PAGE_SIZE) + ); + + // + // Ensure that any allocated map registers are valid for this adapter. + // No Check. R98B 0-1M Never Free!!. + + 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, + (0x100000 / PAGE_SIZE), + *NumberOfMapRegisters + ); + MapRegisterNumber =(0x100000 / PAGE_SIZE) ; + + } + + // + // 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. + +--*/ + +{ + + 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; + + + // + // R98B Must Be Cached!! + // + CacheEnabled =TRUE; + + // + // 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; + ULONG Ponce; + + // + // 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 ) { +#if DBG + DbgPrint("NumberOfMapRegister REQUEST = 0x%x\n",*NumberOfMapRegisters); +#endif + *NumberOfMapRegisters = DMA_REQUEST_LIMIT; + + + } + + if (DeviceDescription->InterfaceType == PCIBus) { + + // + // Create a PCI adapter object. + // + Ponce = HalpPonceNumber(DeviceDescription->BusNumber); + + if (HalpPciAdapterObject[Ponce] == NULL) { + adapterObject = HalpAllocateAdapter(0, &HalpPciAdapterObject[Ponce], NULL); + HalpPciAdapterObject[Ponce] = adapterObject; + + } else { + adapterObject = HalpPciAdapterObject[Ponce]; + + } + + return(adapterObject); + + } + // + // If the request is for a unsupported bus then return NULL. + // + + if (DeviceDescription->InterfaceType != Isa && + DeviceDescription->InterfaceType != Eisa && + // + // R98B Internal(Xbus) floppy used ESC DMAC channel 2 + // + (DeviceDescription->InterfaceType == Internal && (DeviceDescription->DmaChannel !=2)) + ) { + + // + // This bus type is unsupported return NULL. + // + + return(NULL); + } + + // + // Create an adapter object. + // + + adapterObject = HalpAllocateEisaAdapter( DeviceDescription ); +// +// USE Limit DMA_REQUEST_LIMIT +// +// +#if 0 + if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / EISA_MAX_DEVICE) { + + *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / EISA_MAX_DEVICE; + } +#endif + return(adapterObject); +} + +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; + ULONG Ponce; + PTRANSLATION_ENTRY PageTableEntry; + ULONG i; + ULONG NodeMask; + + ULONG tst; //SNES + // + // 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 ); + // R98B + // Reserv 0 - (1M-1) Logical addr!!. + // + RtlSetBits ( + AdapterObject->MapRegisters, + 0x0, // Start 0 + 0x100 // 256 is 1M + ); + // R98B + // Reserv 15M - (16M-1) Logical addr!!. + // + //RtlSetBits ( + // AdapterObject->MapRegisters, + // 0xF00, // Start 15M + // 0x100 // END 16M-1 + //); + + // R98B + // Reserv Last 1 Logical addr!!. For PCEB Prefetch Cycle. + // + RtlSetBits ( + AdapterObject->MapRegisters, + DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))-1, // Last 1 page. + 0x1 // 1 page Reserved. + ); + + // + // 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. + // R98B Page Table must be Cached!!. + // + AdapterObject->MapRegisterBase = (PVOID) + (HalpMapRegisterPhysicalBase | KSEG0_BASE); + + // + // N.B This Version Selected + // PCEB Prefetch cycle may be Cause TLB refill!!. + // So Set Valid Bit All Entry.as We could't invalid transfer. + // ~~~~~~~~~~~~~~~~~ + // Another aprouch. + // When Request Mapregster at "NumberOfMapregister" + // reserve NumberOfMapregster+1.This one page for PCEB Prefetch + // cycle. Driver unknown plus 1 page. Hal know only. + // + PageTableEntry= (PTRANSLATION_ENTRY)AdapterObject->MapRegisterBase; + + for(i=0;i< DMA_TRANSLATION_LIMIT/ sizeof( TRANSLATION_ENTRY); i++){ + (PageTableEntry)->PageFrame = (ULONG) PAGE_TABLE_ENTRY_VALID; + (PageTableEntry)->Fill = (ULONG) 0; + PageTableEntry++; + } +#if defined(DBG5) + DbgPrint("HAL Channel init Master\n"); + DbgPrint("HAL Page Table is 0x%x\n",AdapterObject->MapRegisterBase); +#endif + + for(Ponce=0;Ponce < HalpNumberOfPonce; Ponce++){ + // + // I/O TLB Page Table Base Set. + // +#if defined(DBG5) + DbgPrint("HAL:Ponce No = 0x%x PTBSR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->PTBSR); +#endif + + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->PTBSR, + (HalpMapRegisterPhysicalBase) >> 1 //SNES + ); +#if defined(DBG5) + DbgPrint("HAL:Ponce No = 0x%x PTLMR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->PTLMR); + + tst=READ_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->PMODR, + ); + + DbgPrint("HAL:Ponce No = 0x%x PMODR data =0x%x\n",Ponce,tst); + tst |= 0x10000000; + + // + // I/O TLB Page Table Limit + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->PMODR, + tst + ); +#endif + + // + // I/O TLB Page Table Limit + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->PTLMR, + ((HalpMapRegisterPhysicalBase+MapRegisterSize)) >>1 + ); +#if defined(DBG5) + DbgPrint("HAL:Ponce No = 0x%x TFLSR addr =0x%x\n",Ponce,(PULONG)&PONCE_CNTL(Ponce)->TFLSR); +#endif + + // + // I/O TLB Entry All Flush!! + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->TFLSR, + 0x1 + ); + // + // Enable I/O TLB error. + // + NodeMask = 0; + for(i=0; i < **((PULONG *)(&KeNumberProcessors)); i++){ + NodeMask |= 0x10 << HalpLogicalCPU2PhysicalCPU[i]; + } + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->ERITTG[1], NodeMask ); + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->ERITTG[1], NodeMask ); + } + } + } 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; + + + + // + // 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. + // + // R98B mapregiser allways allocated 1M. + // 0-1M reserved hal. + // + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + 0x100000 / PAGE_SIZE + ); + + // + // Make sure this map register is valid for this adapter. + // No Check. Because 0-1M was never free. + + 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; + + + // + // 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)) { + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + Wcb->NumberOfMapRegisters, + 0x100000 / PAGE_SIZE + ); + + // + // Make sure this map register is valid for this adapter. + // R98B No Check!!. 0-1M Never free!! + // + + } + + 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. + +--*/ + +{ + + // This code is executed phase 1 on processor 0 + // + // 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). + // + + 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; + ULONG Ponce; + // + // Begin by determining where in the buffer this portion of the operation + // is taking place. + // + + 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); + + // S001 vvv + // Set the offset to point to the map register plus the offset. + // + + Offset += ((PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase) << PAGE_SHIFT; + + if ( Offset + *Length >= HalpLogicalAddressLimit ){ + UCHAR messageBuffer[256]; + + HalpChangePanicFlag( 16, 0x01, 0x10); + + HalDisplayString("\nHAL I/O TLB SETUP: Logical address limit over.\n"); + + sprintf( (char *)messageBuffer, " Offst=0x%08lx, Len =0x%08lx, Limit=0x%08lx\n", + Offset, *Length, HalpLogicalAddressLimit ); + HalDisplayString( (char *)messageBuffer ); + + sprintf( (char *)messageBuffer, " CurVa=0x%08lx, StrVa=0x%08lx, RegBs=0x%08lx, MsrBs=0x%08lx\n", + (ULONG)CurrentVa, (ULONG)Mdl->StartVa, (ULONG)MapRegisterBase, (ULONG)MasterAdapterObject->MapRegisterBase); + HalDisplayString( (char *)messageBuffer ); + + sprintf( (char *)messageBuffer, " AdObj=0x%08lx, Mdl =0x%08lx, Write=%d\n", + (ULONG)AdapterObject, (ULONG)Mdl, (ULONG)WriteToDevice ); + HalDisplayString( (char *)messageBuffer ); + + KeBugCheckEx(NMI_HARDWARE_FAILURE, + Offset, + *Length, + HalpLogicalAddressLimit, + 0 + ); + } + + // + // Setup I/O TLB entry. + // + + for (i = 0; i < NumberOfPages; i++) { + (DmaMapRegister++)->PageFrame = (ULONG) (*PageFrameNumber++ << PAGE_SHIFT) + | PAGE_TABLE_ENTRY_VALID; + } // S001 ^^^ +#if 0 + for(Ponce = 0;Ponce < HalpNumberOfPonce;Ponce++){ + // + // I/O TLB Entry All Flush!! + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->TFLSR, + 0x1 + ); + } + +#else + // + // Invalidate the translation entry. + // + if(NumberOfPages >= PONCE_MAX_IOTLB_ENTRY){ + + for(Ponce = 0;Ponce < HalpNumberOfPonce;Ponce++){ + // + // I/O TLB Entry All Flush!! + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->TFLSR, + 0x1 + ); + } + } else { + + for (i = 0; i < NumberOfPages; i++) { + + // + // I/O TLB Entry Flush!! + // + for(Ponce = 0;Ponce <HalpNumberOfPonce;Ponce++){ + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->TFLSR, + (Offset + i*PAGE_SIZE) & 0xFFFFF000 ); + } + } + } +#endif + // + // Are You BusMaster?. So Nothing to do anymore!!. + // + if ( AdapterObject == NULL) { + return(RtlConvertUlongToLargeInteger(Offset)); + } + // R98B + // Start the EISA DMA controller program. + // EISA DMA slave or ISA BusMaster or ISA Slave + + 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; + + if (AdapterObject == NULL) { + + // + // This is a master adadapter so there is nothing to do. + // + + return(TRUE); + } + + + // + // 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) + ); + + } + + 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); +} + + +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 count; + ULONG high; + KIRQL Irql; + + KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql ); + // + // 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)); + + } + KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql ); + + // + // The DMA counter has a bias of one and can only be 16 bit long. + // + + count = (count + 1) & 0xFFFF; + + return(count); +} + + +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; + + // S001 vvv + HalpLogicalAddressLimit = (DMA_TRANSLATION_LIMIT / sizeof(TRANSLATION_ENTRY)) << PAGE_SHIFT; +#if DBG + DbgPrint("HAL: HalpLogicalAddressLimit = 0x%x\n",HalpLogicalAddressLimit); +#endif + // S001 ^^^ +} diff --git a/private/ntos/nthals/halr98b/mips/rxinfo.c b/private/ntos/nthals/halr98b/mips/rxinfo.c new file mode 100644 index 000000000..2d616d754 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxinfo.c @@ -0,0 +1,95 @@ +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation +All rights reserved. + +Module Name: + + rxinfo.c + +Abstract: + +Environment: + + Kernel mode only. + +Revision History + +--*/ + + +#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/halr98b/mips/rxint.s b/private/ntos/nthals/halr98b/mips/rxint.s new file mode 100644 index 000000000..e2604fc68 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxint.s @@ -0,0 +1,1564 @@ +// +// TITLE("Interrupts service routine") +//++ +// +// Copyright (c) 1994 Kobe NEC Software +// +// Module Name: +// +// rxint.s +// +// Abstract: +// +// +// Author: +// +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// +//-- + +#include "halmips.h" +#include "r98bdef.h" + + + + SBTTL("HalpNmiHandler") +//++ +// K001 +// Routine Description: +// +// This routine is reset status Register on NMI. +// Return from this function EIF Interrupt Occur!! +// Argments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpNmiHandler) + .set noat + .set noreorder // + + // + // reset NMIR register, set NMI flag and save CPU register. + // + + li k0,0xb9800388 // Set Colombs STSR local address + li k1,0x08080000 // Disable NMI + sw k1,0x0(k0) // store value + la k0,HalpSvpAlive // SVP check + lw k1,0x0(k0) + nop + beq k1,zero,10f + nop + la k0,HalpLogLock +3: ll k1,0(k0) // get current lock value + bne zero,k1,3b // if ne, spin lock owned + nop + li k1,0x1 + sc k1,0(k0) // set spin lock owned + beq zero,k1,3b // if eq, store conditional failure + nop + la k0,HalpSvpGlobal // NMI clear + lw k1,0x0(k0) + li k0,0x80 + sb k0,0x42(k1) + sync + nop + nop + nop + nop + nop + nop + nop + + la k0,HalpSvpWindow2 // Nmi para clear + lw k1,0x0(k0) + lb k0,0xe6(k1) + sync + la k0,HalpSvpGlobal //Svp EIF MASK + lw k1,0x0(k0) + sb zero,0x49(k1) + sync + nop + nop + nop + nop + nop + nop + lb k0,0x58(k1) // Windows2 write lock + la k1,HalpNmiSvp + sw k0,0x0(k1) + sync + la k0,HalpSvpGlobal + lw k1,0x0(k0) + li k0,0xff + sb k0,0x58(k1) + sync + nop + nop + nop + nop + nop + nop + la k0,HalpSvpWindow2 // Nmi para clear + lw k1,0x0(k0) +4: + sb zero,0xe6(k1) + sync + nop + nop + nop + nop + nop + nop + nop + lb k0,0xe6(k1) + bne zero,k0,4b + nop + la k0,HalpNmiSvp // Svp Window2 lock + lw k1,0x0(k0) + la k0,HalpSvpGlobal + lw k0,0x0(k0) + nop + sb k1,0x58(k0) + sync + nop + nop + nop + nop + nop + nop + la k0,HalpLogLock // ZERO CLEAR + sw zero,0x0(k0) + nop + +// spinlock +// lw t0,KiPcr + PcCurrentThread(zero) // get address of current thread +#if 0 + la k0,HalpLogLock +5: ll k1,0(k0) // get current lock value + bne zero,k1,5b // if ne, spin lock owned + nop + li k1,0x1 + sc k1,0(k0) // set spin lock owned + beq zero,k1,5b // if eq, store conditional failure + nop +#endif + +// +// Check it DUMP Key or Power SW +// To Checked Interrupt cause SetUp MRCMODE to PowerSW Interrupt mode. +// + +10: + li k0, 0xbf0f0000 //LBCTL addr + lb k0, (k0) + li k1, 0x40 + and k1,k0,k1 + bne zero,k1,10b + nop +// +// Local Device Lock Complete +// +#if 1 //SVP +// +// when EXTNMI happend. which NMI DUMP Key or SVP +// + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCMODE Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x08 //MRCMODE li + sb k1, (k0) + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x18 //Read Command + sb k1, (k0) + + +99: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 99b + nop + + li k0, 0xbf0f0020 //LBDT addr + lb k0, (k0) //Read MRMODE Register Value + + + li k1,0x2 //MRCMODE register DUMP Bit + and k1,k0,k1 + bne zero,k1,Dump // if neq --> dump key + nop + nop + + +// Save CPU Register Context +// +// +#if 0 + li k0,0xb9800310 // get Colombs REVR Local Address + lw k0 ,0x0(k0) // get value + + li k1,0x03000000 // NODE Bit Mask. But low 2 bit only + and k0,k0,k1 // Get NODE Bit Only + srl k0,k0,17 // shift right 17(23 - 6) bit for offset + + la k1,HalpNmiSvp // get performance counter address + addu k0,k0,k1 // compute address of nmi buffer + lw k1,0x0(k0) + addi k1,k1,1 + sw k1,0x0(k0) + nop + nop +//#endif + la k0,HalpSvpAlive // SVP check + lw k1,0x0(k0) + nop + beq k1,zero,5f + nop + la k0,HalpLogLock +3: ll k1,0(k0) // get current lock value + bne zero,k1,3b // if ne, spin lock owned + nop + li k1,0x1 + sc k1,0(k0) // set spin lock owned + beq zero,k1,3b // if eq, store conditional failure + nop + la k0,HalpSvpGlobal //Svp Windows2 lock + lb k1,0x58(k0) + la k0,HalpNmiSvp + sb k1,0x0(k0) + sync + la k0,HalpSvpGlobal + li k1,0xff + sb k1,0x58(k0) + sync + la k0,HalpSvpWindow2 // Nmi para clear + lb k1,0xe6(k1) + sb zero,0xe6(k0) + sync + la k0,HalpNmiSvp // Svp Window2 lock + lb k1,0x0(k0) + la k0,HalpSvpGlobal + sb k1,0x58(k0) + sync + la k0,HalpLogLock // ZERO CLEAR + sw zero,0x0(k0) + nop +#endif + j 25f + nop + + + +Dump: +#endif + la k0,HalpDumpFlag + li k1,0x01 + sw k1,0x0(k0) + + + + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCMODE Addr Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x08 //MRCMODE Addr li + sb k1, (k0) + + li k0, 0xbf0f0020 //LBDT addr + li k1, 0x80 // + sb k1, (k0) // + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x10 //Write Command + sb k1, (k0) + +20: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 20b + nop +25: + +// +// MRCMODE Setuped to MRCINT mode. +// So Check DUMP Key or Power Switch + + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCINT Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x00 //MRCINT li + sb k1, (k0) + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x18 //Read Command + sb k1, (k0) + + +50: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 50b + nop + + + li k0, 0xbf0f0020 //LBDT addr + lb k0, (k0) //Read MRCINT Register Value + + li k1,0x4 //MRCINT register OFFSW Bit + and k1,k0,k1 + beq zero,k1,DumpKey // if eq --> Not Power SW. it is DUMP Key. + nop + nop + + +#if DBG + + + li k0,0xb9800310 // get Colombs REVR Local Address + lw k1 ,0x0(k0) // get value + li k0,0x03000000 // NODE Bit Mask. But low 2 bit only + + and k0,k0,k1 // Get NODE Bit Only + srl k1,k0,22 // shift right 24>> <<2 bit for offset + + la k0,HalpResetCount // get address + addu k0,k0,k1 // compute address of nmihappend buffer + lw k1,0x0(k0) + addi k1,k1,1 + sw k1,0x0(k0) + nop +#endif + + +// +// This Is Power Switch NMI so Power down. +// + +resetloop: + + + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //Power S/W Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x30 //Power S/W li + sb k1, (k0) + + li k0, 0xbf0f0020 //LBDT addr + li k1, 0x01 //Set Power SW OFF + sb k1, (k0) + + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x10 //Write Command + sb k1, (k0) + + +poll6: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, poll6 + nop + + j resetloop + nop + nop + +// +// This Is DUMP KEY NMI +// +DumpKey: + + +// +// Early time I was crashed ? +// + li k0,0xb9800310 // get Colombs REVR Local Address + lw k1 ,0x0(k0) // get value + li k0,0x03000000 // NODE Bit Mask. But low 2 bit only + + and k0,k0,k1 // Get NODE Bit Only + srl k1,k0,22 // shift right 24>> <<2 bit for offset + + la k0,HalpNMIHappend // get address + addu k0,k0,k1 // compute address of nmihappend buffer + lw k1,0x0(k0) + nop + nop + + beq zero,k1,doeif //if eq it was first time dump key. + nop + nop + + // + // Setup DUMP Key And Power Key to NMI + // + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCMODE Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x08 //MRCMODE li + sb k1, (k0) + + li k0, 0xbf0f0020 //LBDT addr + li k1, 0x0 //DUMP KEY Reset. + sb k1, (k0) // + + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x10 //Write Command + sb k1, (k0) + +34: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 34b + nop + + + +#if DBG + + li k0,0xb9800310 // get Colombs REVR Local Address + lw k1 ,0x0(k0) // get value + li k0,0x03000000 // NODE Bit Mask. But low 2 bit only + + and k0,k0,k1 // Get NODE Bit Only + srl k1,k0,22 // shift right 24>> <<2 bit for offset + + la k0,HalpNMISecond // get address + addu k0,k0,k1 // compute address of nmihappend buffer + lw k1,0x0(k0) + addi k1,k1,1 + sw k1,0x0(k0) + +#endif + + +nomakeeif: + // + // UnLock + // + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x80 // + sb k1, (k0) + nop + nop + + // CHIPSet Reset + // This version implement of EXNMI Only. + // + // + + li k0,0xb9800038 // get Colombs NMIRST Local Address + li k1,0xf // Bit Reset + sw k1,(k0) // reset nmi + + + li k0,0xb9800388 // Set Colombs STSR local address + li k1,0x00080000 // Enable NMI + sw k1,0x0(k0) // store value + nop + + // CPU Reset. + // This is a test code. + // We must clear BEV bit of psr register. + // + + mfc0 k1,psr // get psr + li k0,0xffbfffff // clear BEV bit + nop // fill + nop // fill + and k1,k1,k0 // + nop // + nop // + mtc0 k1,psr // set psr + nop // fill + nop // + nop // + nop + eret // return to errorepc + nop + nop + nop + eret // errata + nop + + +// This Is First NMI By DUMP Key. +// Save CPU Context. And Markd. +// And Make EIF!! +// +doeif: + addi k1, k1, 0x1 // mark set. + nop + sw k1, 0x0(k0) // HalpNMIHappend[NODE] = 1 + nop + + // + // MRCMODE Register Set Up For Next NMI (DumpKey and PoeHwerSW) + // +#if 0 + + + // + // MRCINT Clear + // + nop + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCINT Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x00 //MRCINT li + sb k1, (k0) + + li k0, 0xbf0f0020 //LBDT addr + li k1, 0x0 //Reset PowerOff Interrupt + sb k1, (k0) + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x10 //Write Command + sb k1, (k0) + + +250: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 250b + nop + +#endif + + + // + // Reset NMI + // + li k0, 0xbf0f0018 //LBADH addr + li k1, 0x02 //MRCMODE Hi + sb k1, (k0) + + li k0, 0xbf0f0010 //LBADL addr + li k1, 0x08 //MRCMODE li + sb k1, (k0) + + li k0, 0xbf0f0020 //LBDT addr + li k1, 0x0 //DUMP KEY Reset. + sb k1, (k0) // + + + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x10 //Write Command + sb k1, (k0) + +64: + li k0, 0xbf0f0000 //LBCTL addr + lb k1, (k0) //LBCTL read + li k0, 0x10 //CMD Bit + and k1,k0,k1 + bne zero,k1, 64b + nop + + + +#if 0 + + // + // SetUp NMIFlag for rxeif.c + // + la k0,HalpNMIFlag // set NMI flag address + li k1,0xb9800030 // set Colombs NMIR local address + lw k1,(k1) // get NMIR register value + // + // N.B NMIR register high 16 bit is RFU. + // so used s/w flag for Hal. + sw k1,(k0) // store NMIR regiser value to HalpNmiFlag + + + +// +// UnLock Local Device +// + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x80 // + sb k1, (k0) + +#endif + + +// Save CPU Register Context +// +// + li k0,0xb9800310 // get Colombs REVR Local Address + lw k0 ,0x0(k0) // get value + + li k1,0x03000000 // NODE Bit Mask. But low 2 bit only + and k0,k0,k1 // Get NODE Bit Only + srl k0,k0,16 // shift right 16(23 - 5) bit for offset + + la k1,HalpNMIBuf // get performance counter address + addu k0,k0,k1 // compute address of nmi buffer + +// sw at,0x0(k0) // register save.0 + sw v0,0x4(k0) // 1 + sw v1,0x8(k0) // 2 + sw a0,0xc(k0) // 3 + sw a1,0x10(k0) // 4 + sw a2,0x14(k0) // 5 + sw a3,0x18(k0) // 6 + sw t0,0x1c(k0) // 7 + sw t1,0x20(k0) // 8 + sw t2,0x24(k0) // 9 + sw t3,0x28(k0) // 10 + sw t4,0x2c(k0) // 11 + sw t5,0x30(k0) // 12 + sw t6,0x34(k0) // 13 + sw t7,0x38(k0) // 14 + sw t8,0x3c(k0) // 15 + sw t9,0x40(k0) // 16 + sw gp,0x44(k0) // 17 + sw sp,0x48(k0) // 18 + sw s8,0x4c(k0) // 19 + sw ra,0x50(k0) // 20 + + mfc0 k1,psr // 21 + sw k1,0x54(k0) // + mfc0 k1,cause // 22 + sw k1,0x58(k0) // + mfc0 k1,epc // 23 + sw k1,0x5c(k0) // + mfc0 k1,errorepc // 24 + sw k1,0x60(k0) // + + + +#if 1 //ras + + sw s0,0x64(k0) // 25 + sw s1,0x68(k0) // 26 + sw s2,0x6c(k0) // 27 + sw s3,0x70(k0) // 28 + sw s4,0x74(k0) // 29 + sw s5,0x78(k0) // 30 + sw s6,0x7c(k0) // 31 + sw s7,0x80(k0) // 32 + + mfc0 k1,entrylo0 // + sw k1,0x84(k0) // 33 + + mfc0 k1,entrylo1 // + sw k1,0x88(k0) // 34 + + mfc0 k1,badvaddr // + sw k1,0x8c(k0) // 35 + + mfc0 k1,entryhi + sw k1,0x90(k0) // 36 + + + mfc0 k1,pagemask + sw k1,0x94(k0) // 37 + + mfc0 k1,prid + sw k1,0x98(k0) // 38 + + mfc0 k1,config + sw k1,0x9c(k0) // 39 + + mfc0 k1,lladdr + sw k1,0xa0(k0) // 40 + + mfc0 k1,watchlo + sw k1,0xa4(k0) // 41 + + mfc0 k1,watchhi + sw k1,0xa8(k0) // 42 + + mfc0 k1,$20 //xcontext + sw k1,0xac(k0) // 43 + + mfc0 k1,ecc + sw k1,0xb0(k0) // 44 + + mfc0 k1,cacheerr + sw k1,0xb4(k0) // 45 + + mfc0 k1,taglo + sw k1,0xb8(k0) // 46 + + mfc0 k1,taghi + sw k1,0xbc(k0) // 47 + +#endif + +#if 0 +// +// Copy CPU state to NvRAM. +// + + li t0,0xb9800388 // Set Colombs STSR local address + li t1,0x00040000 // Enable write to NvRam + sw t1,0x0(t0) // store value + + li t0,0xb9800310 // get Colombs REVR Local Address + lw t0,0x0(t0) // get value + + li t1,0x03000000 // NODE Bit Mask. But low 2 bit only + and t0,t0,t1 // Get NODE Bit Only + srl t0,t0,16 // shift right 16(23 - 5) bit for offset + + li t1,0xbf09dc00 + addu t0,t0,t1 // compute address of nmi buffer + move t1,k0 // src address + li t2,0x100 // calc end address + addu t2,t2,t0 + +cploop: + lb t3,0(t1) + addiu t1,t1,1 + sb t3,0(t0) + addiu t0,t0,1 + bne t2,t0,cploop + nop + + lw t0,0x1c(k0) // 7 + lw t1,0x20(k0) // 8 + lw t2,0x24(k0) // 9 + lw t3,0x28(k0) // 10 +#endif + +#if 1 + // + // SetUp NMIFlag for rxeif.c + // + la k0,HalpNMIFlag // set NMI flag address + lw k1,(k0) // get HalpNmiFlag + bne zero,k1, nomakeeif + nop + + li k1,0xb9800030 // set Colombs NMIR local address + lw k1,(k1) // get NMIR register value + // + // N.B NMIR register high 16 bit is RFU. + // so used s/w flag for Hal. + sw k1,(k0) // store NMIR regiser value to HalpNmiFlag + +#endif + + // + // UnLock + // + li k0, 0xbf0f0000 //LBCTL addr + li k1, 0x80 // + sb k1, (k0) + + // CHIPSet Reset + // This version implement of EXNMI Only. + // + // + + li k0,0xb9800038 // get Colombs NMIRST Local Address + li k1,0xf // Bit Reset + sw k1,(k0) // reset nmi + + + li k0,0xb9800388 // Set Colombs STSR local address + li k1,0x00080000 // Enable NMI + sw k1,0x0(k0) // store value + nop + + + // CPU Reset. + // This is a test code. + // We must clear BEV bit of psr register. + // + + mfc0 k1,psr // get psr + li k0,0xffbfffff // clear BEV bit + nop // fill + nop // fill + and k1,k1,k0 // + nop // + nop // + mtc0 k1,psr // set psr + nop // fill + nop // + nop // + + // + // Do EIF to Myself. + // + // + + + li k0,0xb9800310 // get Colombs REVR Local Address + lw k0 ,0x0(k0) // get value + + li k1,0x03000000 // NODE Bit Mask. node 4-7 + and k0,k0,k1 // Get NODE Bit Only (lower 3 Bit Only) + srl k0,k0,24 // Convert CPU number + + li k1,0x00080000 // Node 4 set + srl k1,k1,k0 // make Node Bit (NODE 4 >> CpuNumber) + + + li k0,0x82000000 // OP bit And Atlantic code 0x2 = EIF + or k1,k1,k0 // make OP Bit And CODE And NODE + + + li k0,0xb9800580 // get Colombs IntIR Local Address + sw k1,(k0) // + + nop + nop + eret // return to errorepc + nop + nop + nop + eret // errata + nop + nop // for interrupt cache aligned line + nop + nop + nop + nop + .set at + .set reorder + + + .end HalpNmiHandler + + + + + SBTTL("Int 1 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 1 interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt1Dispatch) + + move a0,s8 // trap frame + li a1,0x1 // Interrupt is INT1 + j HalpGeneralDispatch + + .end + + SBTTL("Int 2 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 2 interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt2Dispatch) + + move a0,s8 // trap frame + li a1,0x2 // Interrupt is INT2 + j HalpGeneralDispatch + + .end + + SBTTL("Int 3 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 3 interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt3Dispatch) + + move a0,s8 // trap frame + li a1,0x3 // Interrupt is INT3 + j HalpGeneralDispatch + + .end + + SBTTL("Int 4 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 4 interrupt. +// +// This routine checks for IPI interrupt. The IPI interrupt is +// ip[5] on the R98B and ip[6] on the R98A. So this routine +// reads the cause register to determine correct dispatch function +// +// CAVEAT: This is an R98B specific routine. It is only +// called on an R98B. +// CAVEAT: This routine is only used on NT 4.0 because Nt3.51 does +// not have SYNC IRQL +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + +#if defined(NT_40) + +// +// SYNCH Level must enable IPI on R98B. +// Sync level enable IPI on R98A . +// But on R98B, Sync level disable IPI. +// So, on R98B, we need to change Irql mask table. +// Hal determines IPI or EIF here. +// Because when IPI occured, HAl returns same IRQL value from EIF. +// v-masank@microsoft.com 5/11/96 +// Thanks for samejima's comments +// I change that following function is for R98B only. +// Because R98A does not need following function. +// v-masank@microsoft.com 5/21/96 +// + LEAF_ENTRY(HalpT5Int4Dispatch) + + move a0,s8 // trap frame + READ_CAUSE_REGISTER(t0) // Read Cause register + and t0,t0,0x00004000 // INT4 ? + bne t0,zero,10f // ne INT4 + li a1,0x3 // INT3 + j HalpGeneralDispatch + +10: + li a1,0x4 // Interrupt is INT4 + j HalpGeneralDispatch + .end +#endif + + + +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 4 interrupt. +// +// CAVEAT: This routine used by R98A on NT 3.51 and NT4.0 +// This routine used by R98B on NT 3.51 +// +// CAVEAT: This routine is only used on NT 3.51 because Nt3.51 does +// not have SYNC IRQL +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt4Dispatch) + + move a0,s8 // trap frame + li a1,0x4 // Interrupt is INT4 + j HalpGeneralDispatch + + .end + + SBTTL("Read Cause Register") +//++ +// S005 +// Routine Description: +// +// This routine is get of cause register +// +// Argments: +// +// None. +// +// Return Value: +// +// cause rezister value. +// +//-- + + LEAF_ENTRY(HalpGetCause) + + READ_CAUSE_REGISTER(v0) + + j ra // return + + .end HalpGetCause + + + + SBTTL("Int 0 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 1 interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt0Dispatch) + + move a0,s8 // trap frame + li a1,0x0 // Interrupt is INT0 + j HalpGeneralDispatch + + .end + + + + SBTTL("Int 5 Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an Int 1 interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpInt5Dispatch) + + move a0,s8 // trap frame + li a1,0x5 // Interrupt is INT5 + j HalpGeneralDispatch + + .end + + +//#if 0 +// I use following function for performance. +// v-masank@microsoft.com 5/21/96 +//++ + SBTTL("Read Large Register") +// +// Routine Description: +// +// This routine is read of large register +// +// Argments: +// +// a0 - Virtual address +// +// a1 - pointer to buffer of large register +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpReadLargeRegister) +#if !defined(NT_40) + lw t2,0x0(a0) // get register(upper) + lw t3,0x4(a0) // get register(lower) + + sw t2,0x0(a1) // set upper register value + sw t3,0x4(a1) // set lower register value +#else + ld t2,0x0(a0) // get register + sd t2,0x0(a1) // set register +#endif + + j ra // return + + .end HalpReadLargeRegister + + + + SBTTL("Write Large Register") +//++ +// +// Routine Description: +// +// This routine is write of large register +// +// Argments: +// +// a0 - Virtual address +// +// a1 - pointer to value of large register +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpWriteLargeRegister) + +#if !defined(NT_40) + + lw t2,0x0(a1) // load register value + lw t3,0x4(a1) // + + sw t2,0x0(a0) // set register value + sw t3,0x4(a0) // +#else + ld t2,0x0(a1) + sd t2,0x0(a0) +#endif + + sync // + + j ra // return + + .end HalpWriteLargeRegister + + +//#endif + +// S005 vvv + SBTTL("Read Physical Address") +//++ +// +// Routine Description: +// +// This routine is read of physical address. +// +// Argments: +// +// a0 - Physical address +// +// Return Value: +// +// read data. +// +//-- + + LEAF_ENTRY(HalpReadPhysicalAddr) + + li t1,0x90000000 + + .set noreorder + .set noat + li t6,1 << PSR_CU1 // disable interrupt + ori t6,t6,1 << PSR_KX // use 64bit address mode + mfc0 t7,psr // + mtc0 t6,psr // + nop + nop + .set at + .set reorder + + and t0,zero,zero + dsll t0,t1,32 // shift entry address to upper 32-bits + or t0,t0,a0 // make access address + lw v0,0(t0) + + .set noreorder + .set noat + mtc0 t7,psr // enable interrupt + nop + .set at + .set reorder + + j ra // return + + .end HalpReadPhysicalAddress +// S005 ^^^ +// S006 vvv + SBTTL("Write Physical Address") +//++ +// +// Routine Description: +// +// This routine is Write of physical address. +// +// Argments: +// +// a0 - Physical address +// +// a1 - Write Data +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpWritePhysicalAddr) + + li t1,0x90000000 + + .set noreorder + .set noat + li t6,1 << PSR_CU1 // disable interrupt + ori t6,t6,1 << PSR_KX // use 64bit address mode + mfc0 t7,psr // + mtc0 t6,psr // + nop + nop + .set at + .set reorder + + and t0,zero,zero + dsll t0,t1,32 // shift entry address to upper 32-bits + or t0,t0,a0 // make access address + sw a1,0(t0) + + .set noreorder + .set noat + mtc0 t7,psr // enable interrupt + nop + .set at + .set reorder + + j ra // return + + .end HalpWritePhysicalAddress + + + SBTTL("Read And Write Physical Address") +//++ +// +// Routine Description: +// +// This routine is read and write of physical address. +// +// Argments: +// +// a0 - Physical address +// +// Return Value: +// +// read data. +// +//-- + + LEAF_ENTRY(HalpReadAndWritePhysicalAddr) + + li t1,0x90000000 + + .set noreorder + .set noat + li t6,1 << PSR_CU1 // disable interrupt + ori t6,t6,1 << PSR_KX // use 64bit address mode + mfc0 t7,psr // + mtc0 t6,psr // + nop + nop + .set at + .set reorder + + and t0,zero,zero + dsll t0,t1,32 // shift entry address to upper 32-bits + or t0,t0,a0 // make access address + lw v0,0(t0) + sw v0,0(t0) + + .set noreorder + .set noat + mtc0 t7,psr // enable interrupt + nop + .set at + .set reorder + + j ra // return + + .end HalpReadAndWritePhysicalAddress +// S006 ^^^ + + +#if 0 //koredmo ugoku kedo waikomi disable ha amari yokuarimasenn.... + +//++ +// +// VOID +// READ_REGISTER_ULONGLONG ( +// IN PLARGE_INTEGER RegisterAddress, +// IN PVOID Variable +// ) +// +// Routine Description: +// +// 64-bit 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. +// +//-- + +#if 1 + .struct 0 +sv1f0: .space 4*2 +Length1F0: + NESTED_ENTRY(READ_REGISTER_ULONGLONG, Length1F0, zero) + subu sp,sp,Length1F0 // allocate stack frame + DISABLE_INTERRUPTS(t7) // disable interrupts + sdc1 f0,sv1f0(sp) // f0 save +#else + LEAF_ENTRY(READ_REGISTER_ULONGLONG) +#endif + + ldc1 f0,0(a0) // move 8-byte block + sdc1 f0,0(a1) // +#if 1 + ldc1 f0,sv1f0(sp) // f0 resume + addu sp,sp,Length1F0 // deallocate stack frame + ENABLE_INTERRUPTS(t7) // enable interrupts +#endif + + sync // synchronize read + + j ra // return + + .end READ_REGISTER_ULONGLONG + + +//++ +// +// VOID +// WRITE_REGISTER_ULONGLONG ( +// 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. +// +//-- + +#if 1 + .struct 0 +sv2f0: .space 4*2 +Length2F0: + NESTED_ENTRY(WRITE_REGISTER_ULONGLONG, Length2F0, zero) + subu sp,sp,Length2F0 // allocate stack frame + DISABLE_INTERRUPTS(t7) // disable interrupts + sdc1 f0,sv2f0(sp) // f0 save +#else + LEAF_ENTRY(WRITE_REGISTER_ULONGLONG) +#endif + + ldc1 f0,0(a1) // move 8-byte block + sdc1 f0,0(a0) // +#if 1 + ldc1 f0,sv2f0(sp) // f0 resume + addu sp,sp,Length2F0 // deallocate stack frame + ENABLE_INTERRUPTS(t7) // enable interrupts +#endif + + sync // synchronize write + + j ra // return + + .end WRITE_REGISTER_ULONGLONG + +#else //korede warikomi ha enable no mama syori dekimasu. +// +// +// +// + + .struct 0 +CiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +Rt7: .space 4 +Rt8: .space 4 + +LengthRtN: + + NESTED_ENTRY(READ_REGISTER_ULONGLONG, LengthRtN, zero) +// DISABLE_INTERRUPTS(t9) // disable interrupts + subu sp,sp,LengthRtN // allocate stack frame + + + PROLOGUE_END + sw t7,Rt7(sp) + sw t8,Rt8(sp) + + lw t7,0x0(a0) + lw t8,0x4(a0) + + sw t7,0x0(a1) + sw t8,0x4(a1) + + lw t7,Rt7(sp) + lw t8,Rt8(sp) + + addu sp,sp,LengthRtN // deallocate stack frame +// ENABLE_INTERRUPTS(t9) // enable interrupts + sync // synchronize read + + j ra // return + + .end READ_REGISTER_ULONGLONG + +// +// +// +// + .struct 0 +DiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +Wt7: .space 4 +Wt8: .space 4 + +LengthWtN: + + NESTED_ENTRY(WRITE_REGISTER_ULONGLONG, LengthWtN, zero) +// DISABLE_INTERRUPTS(t9) // disable interrupts + subu sp,sp,LengthWtN // allocate stack frame + + + PROLOGUE_END + + sw t7,Wt7(sp) + sw t8,Wt8(sp) + + lw t7,0x0(a1) + lw t8,0x4(a1) + sw t7,0x0(a0) + sw t8,0x4(a0) + + lw t7,Wt7(sp) + lw t8,Wt8(sp) + + addu sp,sp,LengthWtN // deallocate stack frame +// ENABLE_INTERRUPTS(t9) // enable interrupts + sync // synchronize read + + j ra // return + + .end WRITE_REGISTER_ULONGLONG + +#endif + + + SBTTL("T5 Int 5 Interrupt") +// +// On the R98B (r10k) this hardware interrupt is for the internal timer +// interrupt. This is not used for the PROFILE interrupt on the R98B +// + +// +// InternalTimer interrupt does not use for profile interrupt. +// So,Here is only clear internal interrupt. +// v-masank@microsoft.com + + LEAF_ENTRY(HalpT5Int5Dispatch) + + .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 + nop + nop + .set at + .set reorder + + move a0,s8 // trap frame + li a1,0x5 // Interrupt is INT5 + j HalpGeneralDispatch + + .end HalpT5Int5Dispatch + + diff --git a/private/ntos/nthals/halr98b/mips/rxipiint.s b/private/ntos/nthals/halr98b/mips/rxipiint.s new file mode 100644 index 000000000..c3e99ffd2 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxipiint.s @@ -0,0 +1,79 @@ +// TITLE("Interprocessor Interrupts") +//++ +// +// Copyright (c) 1993 Microsoft Corporation +// +// Module Name: +// +// rxipiint.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interprocessor interrupts on a MIPS R98 system. +// +// Author: +// +// +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + + SBTTL("Interprocessor Interrupt") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interprocessor interrupt. +// Its function is to acknowledge the interrupt and transfer control to +// the standard system routine to process interprocessor requrests. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame at hal first dispatch +// a0 - Supplies a pointer to a trap frame at kernel trap frame +// a1 - intx +// Return Value: +// +// None. +// +//-- +// secondary + + .struct 0 + // +liArgs: .space 4 * 4 // saved arguments +IiS8: .space 4 // +IiRa: .space 4 // +IiFrameLength: // + + NESTED_ENTRY(HalpIpiInterrupt, IiFrameLength, zero) + + subu sp,sp,IiFrameLength // allocate stack frame + sw s8,IiS8(sp) // save s8 + sw ra,IiRa(sp) // save Ra + + PROLOGUE_END + + or s8,a0,zero // set up trapframe to s8 + // KeIpiInterrupt require trapframe at s8 + + lw t1,__imp_KeIpiInterrupt // process interprocessor requests + jal t1 // + + lw ra,IiRa(sp) // restore ra + lw s8,IiS8(sp) // restore s8 + addu sp,sp,IiFrameLength // deallocate stack frame + j ra // return + + .end HalpIpIInterrupt + + diff --git a/private/ntos/nthals/halr98b/mips/rxisabus.c b/private/ntos/nthals/halr98b/mips/rxisabus.c new file mode 100644 index 000000000..abc396c95 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxisabus.c @@ -0,0 +1,729 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixisabus.c + +Abstract: + +Author: + +Environment: + +Revision History: + + +--*/ + +#include "halp.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetEisaInterruptVector) +#pragma alloc_text(PAGE,HalpAdjustEisaResourceList) +#pragma alloc_text(PAGE,HalpGetEisaData) +#endif + + +ULONG +HalpGetEisaInterruptVector( + 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. + +--*/ +{ + UNREFERENCED_PARAMETER( BusInterruptVector ); + + // + // On standard PCs, IRQ 2 is the cascaded interrupt, and it really shows + // up on IRQ 9. + // + if (BusInterruptLevel == 2) { + BusInterruptLevel = 9; + } + + if (BusInterruptLevel > 15) { + return 0; + } + + *Irql = (KIRQL)(INT0_LEVEL+HalpIntLevelofIpr[HalpMachineCpu][EISA_DISPATCH_VECTOR-DEVICE_VECTORS]); + *Affinity = 0x1 <<HalpResetValue[EISA_DISPATCH_VECTOR-DEVICE_VECTORS].Cpu; + + // + // Get parent's translation from here.. + // + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + return(BusInterruptLevel + EISA_VECTORS); + +} + +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 + ); +} + +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; +#if 1 + PHYSICAL_ADDRESS BusAddressTmp; +#endif + // + // Translated normally + // +#if defined(DBG1) + DbgPrint("Hal: Trans ISA IN\n"); +#endif + + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddress, + AddressSpace, + TranslatedAddress + ); + +#if DBG +// DbgPrint("Hal: Trans ISA IN 2 Status = 0x%x\n",Status); +#endif + + + // + // 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) { +#if DBG +// DbgPrint("Hal: Trans ISA IN3\n"); +#endif + + Status = HalTranslateBusAddress ( + Eisa, + BusHandler->BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress + ); + } + // + // Add BackWard Compatibility. + // + // +#if 1 + else + + // + // If it could not be translated, and It's ISA Alias at Eisa Slot + // range then (for compatibility) try translating it on the + // dummy slot io range + // + + if (Status == FALSE && + *AddressSpace == 1 && + BusAddress.HighPart == 0 && + BusAddress.LowPart >= 0x4000 && + BusAddress.LowPart <= 0xFFFF) { + +#if DBG +// DbgPrint("Isa Low ffffffffff= 0x%x\n",BusAddress.LowPart); +// DbgPrint("Isa Hig ffffffffff= 0x%x\n",BusAddress.HighPart); +// DbgPrint("Isa add ffffffffff= 0x%x\n", *AddressSpace); + +#endif + BusAddressTmp.LowPart = BusAddress.LowPart; + BusAddressTmp.LowPart &= 0x0fff; + BusAddressTmp.LowPart |= 0x4000; + BusAddressTmp.HighPart = 0 ; + + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddressTmp, + AddressSpace, + TranslatedAddress + ); +#if DBG +// DbgPrint("EIsa Low = 0x%x\n",TranslatedAddress->LowPart); +// DbgPrint("EIsa Hig = 0x%x\n",TranslatedAddress->HighPart); +// DbgPrint("EIsa add = 0x%x\n", *AddressSpace); +// DbgPrint("Eisa Status = 0x%x\n", Status); +#endif + + } +#endif + + + +#if defined(DBG) +// DbgPrint("Hal: Trans ISA Out\n"); + +// DbgPrint("Isa Low = 0x%x\n",BusAddress.LowPart); +// DbgPrint("Isa Hig = 0x%x\n",BusAddress.HighPart); +// DbgPrint("Isa add = 0x%x\n", *AddressSpace); +// DbgPrint("Isa TLow = 0x%x\n",TranslatedAddress->LowPart); +// DbgPrint("Isa THig = 0x%x\n",TranslatedAddress->HighPart); +// DbgPrint("Isa Status = 0x%x\n", Status); + + +#endif + + + return Status; +} + +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; +#if 1 + PHYSICAL_ADDRESS BusAddressTmp; +#endif + + // + // 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 + ); + } + // + // Add BackWard Compatibility. + // + // +#if 1 + + else + + + // + // If it could not be translated, and It's EISA Slot + // range then (for compatibility) try translating it on the + // dummy slot io range + // + + if (Status == FALSE && + *AddressSpace == 1 && + BusAddress.HighPart == 0 && + BusAddress.LowPart >= 0x4000 && + BusAddress.LowPart <= 0xFFFF) { + +#if DBG +// DbgPrint("EIsa Low ffffffffff= 0x%x\n",BusAddress.LowPart); +// DbgPrint("EIsa Hig ffffffffff= 0x%x\n",BusAddress.HighPart); +// DbgPrint("EIsa add ffffffffff= 0x%x\n", *AddressSpace); +#endif + + BusAddressTmp.LowPart = BusAddress.LowPart; + BusAddressTmp.LowPart &= 0x0fff; + BusAddressTmp.LowPart |= 0x4000; + BusAddressTmp.HighPart = 0 ; + + + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddressTmp, + AddressSpace, + TranslatedAddress + ); +#if DBG +// DbgPrint("EIsa Low = 0x%x\n",TranslatedAddress->LowPart); +// DbgPrint("EIsa Hig = 0x%x\n",TranslatedAddress->HighPart); +// DbgPrint("EIsa add = 0x%x\n", *AddressSpace); +// DbgPrint("Eisa Status = 0x%x\n", Status); +#endif + + } +#endif + + return Status; +} + + +HalpGetEisaData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + 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 (); + +#if DBG //SNES + DbgPrint("Halp Get Eisa DataOh!\n"); +#endif + 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)) { +#if DBG + DbgPrint("HAL: Open Status = %x\n",NtStatus); +#endif + return(0); + } +#if DBG + DbgPrint("Halp Get EisaAdapter Key Open Complete !\n"); +#endif + + + // + // 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)) { +#if DBG + DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus); +#endif + 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; +} diff --git a/private/ntos/nthals/halr98b/mips/rxnvr.h b/private/ntos/nthals/halr98b/mips/rxnvr.h new file mode 100644 index 000000000..71824fe8c --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxnvr.h @@ -0,0 +1,176 @@ + +/*++ + +Module Name: + + rxnvr.h + +Abstract: + + This module contains definitions for the R98B non-volatile ram structures. + +--*/ + + +#ifndef _RXNVR_ +#define _RXNVR_ + + +// +// R98B Nvram Physicall Map +// +// 0x1f08 0000 +-------+ +// | 4K | POST/ITF and NMI Vector +// 0x1f08 1000 +-------+ +// | 2K | +// 0x1f08 1800 +-------+ +// | 2K | Free +// 0x1f08 2000 +-------+ +// | 800B | Configuration Packet +// 0x1f08 2320 +-------+ +// | 516B | Identifier +// 0x1f08 2524 +-------+ +// | 2K | Configuration Data +// 0x1f08 2d24 +-------+ +// | 4B | Checksum1 +// 0x1f08 2d28 +-------+ +// | 1K | Environment +// 0x1f08 3128 +-------+ +// | 4BK | Checksum2 +// 0x1f08 312c +-------+ +// | 3796B | Reserved For ARC FW +// 0x1f08 4000 +-------+ +// | 32K | H/W Logging field +// 0x1f08 c000 +-------+ +// | 4K | Reserved +// 0x1f08 d000 +-------+ +// | 4K | XXXXXX +// 0x1f08 e000 +-------+ +// | 8B | Ethrnet Address +// 0x1f08 e008 +-------+ +// | 2K | UP Area +// 0x1f08 e800 +-------+ +// | 4092B | EISA Configuration +// 0x1f08 f7fc +-------+ +// | 4B | Checksum3 +// 0x1f08 f800 +-------+ +// | 57K | Free +// 0x1f09 dc00 +-------+ +// | 1K | Hal +// 0x1f09 e000 +-------+ +// | 8K | ESM +// 0x1f0a 0000 +-------+ +// + + + +// Define the private configuration packet structure, which contains a +// configuration component as well as pointers to the component's parent, +// peer, child, and configuration data. +// + +typedef struct _CONFIGURATION_PACKET { + CONFIGURATION_COMPONENT Component; + struct _CONFIGURATION_PACKET *Parent; + struct _CONFIGURATION_PACKET *Peer; + struct _CONFIGURATION_PACKET *Child; + PVOID ConfigurationData; +} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET; + +// +// The compressed configuration packet structure used to store configuration +// data in NVRAM. +// + +typedef struct _COMPRESSED_CONFIGURATION_PACKET { + UCHAR Parent; + UCHAR Class; + UCHAR Type; + UCHAR Flags; + ULONG Key; + USHORT Version; + USHORT ConfigurationDataLength; + USHORT Identifier; + USHORT ConfigurationData; +} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET; + +// +// Defines for Identifier index. +// + +#define NO_CONFIGURATION_IDENTIFIER 0xFFFF + +// +// Defines for the volatile and non-volatile configuration tables. +// + +#define NUMBER_OF_ENTRIES 50 +#define LENGTH_OF_IDENTIFIER 516 +#define LENGTH_OF_DATA 2048 +#define LENGTH_OF_ENVIRONMENT 1024 +#define LENGTH_OF_EISA_DATA 4092 + +// +// The volatile configuration table structure. +// + +typedef struct _CONFIGURATION { + CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; + UCHAR Identifier[LENGTH_OF_IDENTIFIER]; + UCHAR Data[LENGTH_OF_DATA]; +} CONFIGURATION, *PCONFIGURATION; + +// +// The non-volatile configuration table structure. +// + + +typedef struct _NV_CONFIGURATION { + + COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; // 800B =16B * 50 Entry + UCHAR Identifier[LENGTH_OF_IDENTIFIER]; // 516B + UCHAR Data[LENGTH_OF_DATA]; // 2048B + + UCHAR Checksum1[4]; + UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // 1024B + UCHAR Checksum2[4]; + UCHAR ArcReserved[3796]; + UCHAR HwLogging[1024 * 32]; + UCHAR Reserved0[1024 * 4]; + UCHAR Reserved1[1224 * 4]; + UCHAR EthernetAddress[8]; + UCHAR UPArea[1024 * 2]; + UCHAR EisaData[LENGTH_OF_EISA_DATA]; // 4092B + UCHAR Checksum3[4]; + UCHAR Reserved2[ 1024 * 57]; + UCHAR Hal[ 1024]; + UCHAR Esm[1024 * 8]; +// UCHAR NmiVector[4]; +} NV_CONFIGURATION, *PNV_CONFIGURATION; + + +// +// Nmi Vecter Address table structure. by kita +// +#define NMIVECTER_PHYSICAL_BASE 0x1F080000 +#define NMIVECTER_BASE (KSEG1_BASE + NMIVECTER_PHYSICAL_BASE) + +typedef struct _NVRAM_NMIVECTER { + UCHAR NotUsed[12]; + UCHAR NmiVector[4]; +} NVRAM_NMIVECTER, *PNVRAM_NMIVECTER; + + + +// +// Non-volatile ram layout. +// + +#if defined(MIPS) + +#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE +#define NVRAM_SYSTEM_ID NVRAM_VIRTUAL_BASE + 0x00002000 + +#endif + +#endif // _RXNVR_ diff --git a/private/ntos/nthals/halr98b/mips/rxpcibrd.c b/private/ntos/nthals/halr98b/mips/rxpcibrd.c new file mode 100644 index 000000000..37aef5f43 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxpcibrd.c @@ -0,0 +1,1157 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + rxpcibrd.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 ULONG StartPciBus, //R98B + 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; + ULONG Ponce; + + + Rescan = 0; + FoundDisabledBridge = FALSE; + // This is Ponce Number; + + // + // 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; + // R98B + // +#if DBG + DbgPrint("HAL PCI StartPCIBusNo =0x%x\n",(ULONG)StartPciBus); + DbgPrint("HAL PCI MaxPciBus =0x%x\n",*MaxPciBus); +#endif + + for (BusNo=StartPciBus; BusNo < *MaxPciBus; BusNo++) { + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; +#if DBG + DbgPrint("HAL PCI BusNo =0x%x\n",(ULONG)BusNo); +// DbgPrint("HAL PCI brg =0x%x\n",(ULONG)CB.BusHandler); +// DbgPrint("HAL PCI busdata =0x%x\n",(ULONG)CB.BusData); +#endif + + 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 DBG + HalpTestPciPrintResult((PULONG)CB.PciData,PCI_COMMON_HDR_LENGTH ); +#if 0 //f/w debug + + CB.PciData->Command = 0x7; + + if(BusNo == 0 && CB.PciData->u.type1.SecondaryBus == 1){ + CB.PciData->u.type1.IOBase = 0x50; + CB.PciData->u.type1.IOLimit = 0x60; + + }else if(BusNo == 0 && CB.PciData->u.type1.SecondaryBus == 2 ){ + CB.PciData->u.type1.IOBase = 0x70; + CB.PciData->u.type1.IOLimit = 0x80; + CB.PciData->u.type1.MemoryBase =0x0620; + CB.PciData->u.type1.MemoryLimit =0x0630; + + } + else if(BusNo == 3 && CB.PciData->u.type1.SecondaryBus == 1 ){ + CB.PciData->u.type1.IOBase = 0x40; + CB.PciData->u.type1.IOLimit = 0x50; + + } + else if(BusNo == 3 && CB.PciData->u.type1.SecondaryBus == 2 ){ + CB.PciData->u.type1.IOBase = 0x60; + CB.PciData->u.type1.IOLimit = 0x70; + + CB.PciData->u.type1.MemoryBase =0x0620; + CB.PciData->u.type1.MemoryLimit =0x0630; + + +// CB.PciData->u.type1.PrefetchBase = 0x0010; +// CB.PciData->u.type1.PrefetchLimit= 0x0010; + + } + + HalpWritePCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); +#if DBG + DbgPrint ("HAL Brdge fix -----------!!!\n"); +#endif +// HalpReadPCIConfig ( +// CB.BusHandler, +// CB.SlotNumber, +// CB.PciData, +// 0, +// PCI_COMMON_HDR_LENGTH +// ); + +// HalpTestPciPrintResult((PULONG)CB.PciData,PCI_COMMON_HDR_LENGTH ); + +#endif +#endif + + if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + + // this PCI bridge is not enabled - skip it for now + DBGMSG ("HAL Bridge is not enable contineu!!!\n"); + FoundDisabledBridge = TRUE; + continue; + + } + + // R98B First PCI Bus of Ponce Must be 0. + // So Convert System(NT) BusNumber to required BusNumber for PONCE. + // + Ponce = HalpPonceNumber(CB.BusHandler->BusNumber); + if ((ULONG) CB.PciData->u.type1.PrimaryBus != + CB.BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce]) { +#if DBG + DbgPrint ("HAL GetPciData: bad BusNumber =0x%x!!!\n",(ULONG) CB.BusHandler->BusNumber); + DbgPrint ("HAL GetPciData: bad primarybus =0x%x!!!\n",(ULONG) CB.PciData->u.type1.PrimaryBus); + // what to do? +#endif + } + + // + // Found a PCI-PCI bridge. Determine it's parent child + // releationships + // +#if DBG + DbgPrint ("HAL Bridge secondrybus =0x%x!!!\n",(ULONG) CB.PciData->u.type1.SecondaryBus); +#endif + + ChildBus = HalpHandlerForBus (PCIBus, + CB.PciData->u.type1.SecondaryBus+HalpStartPciBusNumberPonce[Ponce] + ); + + if (!ChildBus) { + DBGMSG ("HAL GetPciData: found configured pci bridge\n"); + + // up the number of buses + if (CB.PciData->u.type1.SecondaryBus+HalpStartPciBusNumberPonce[Ponce] > Rescan) { + Rescan = CB.PciData->u.type1.SecondaryBus+(UCHAR)HalpStartPciBusNumberPonce[Ponce]+1; + HalpStartPciBusNumberPonce[Ponce+1]++; + } + 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) { +#if DBG + DbgPrint("Hal Bridge VGA Busnum =0x%x\n",ChildBus->BusNumber); +#endif + 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) { +#if DBG + DbgPrint("Hal Bridge 256 limit\n"); +#endif + + // 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, + (ULONG)0, // address space + (LONGLONG)(PCI_CNTL_PHYSICAL_BASE+ // system base + PCI_MAX_CNTL_SIZE * Ponce), + (LONGLONG)i, // bus address + (LONGLONG)(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); + +#if 1 +// +// If F/W setup PrefetchBaseUpper32 == 0 +// This Bus Range add PrefetchMemory area. This Range not support.. +// Under Ponce #0. Memory area start 64MG so never append prefetch memory area. +// But Punder Pnce 1#. Memory area start 0MG So append prefetch memory area by addrange. +// + // On x86 it's ok to clip Prefetch to 32 bits + + if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) { +#if DBG + DbgPrint("Hal Bridge prefetch upper32\n"); +#endif + + 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; + } + } + +#endif + // 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; + +#if DBG + DbgPrint("HAL Fix Range 0\n"); +#endif + + // + // 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; + } + } + +#if DBG + DbgPrint("HAL Fix Range 1\n"); +#endif + + // + // 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; + } + } +#if DBG + DbgPrint("HAL Fix Range 2\n"); +#endif + + // + // Cleanup + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + HalpConsolidateRanges (Bus->BusAddresses); + } +#if DBG + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + DbgPrint("HAL: PCIBus#%d, MemBase=%x.%x, Lmt=%x.%x, SysBase=%x.%x, IoBase=%x.%x, Lmt=%x.%x\n", + i, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->HighPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Base))->LowPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->HighPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->HighPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->HighPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Base))->LowPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->HighPart, + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart + ); + } +#endif +} + + + +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/halr98b/mips/rxpcibus.c b/private/ntos/nthals/halr98b/mips/rxpcibus.c new file mode 100644 index 000000000..6796e1804 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxpcibus.c @@ -0,0 +1,2826 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + rxpcibus.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +#if defined(INTEL_9036) +ULONG intel_9036=FALSE; +#endif + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + +ULONG HalpCirrusDel = FALSE; + +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 + ); + +VOID +HalpInitializePciBus ( + VOID + ); + +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 + ); + +// +// Globals +// + +KSPIN_LOCK HalpPCIConfigLock; + +// R98B Configuration Mechanism #1. +// +PCI_CONFIG_HANDLER PCIConfigHandler = { + HalpPCISynchronizeType1, + HalpPCIReleaseSynchronzationType1, + { + HalpPCIReadUlongType1, // 0 + HalpPCIReadUcharType1, // 1 + HalpPCIReadUshortType1 // 2 + }, + { + HalpPCIWriteUlongType1, // 0 + HalpPCIWriteUcharType1, // 1 + HalpPCIWriteUshortType1 // 2 + } +}; + + +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +extern BOOLEAN HalpDoingCrashDump; + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ); + +#if DBG +#define DBGMSG(a) DbgPrint(a) +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 + +// Number Of PCI Bus. +// +UCHAR HalpNumberOfAllPciBus=0; + +// Start Pci BusNumber of PONCE #0,#1 #n ,,, +// +ULONG HalpStartPciBusNumberPonce[R98B_MAX_PONCE+1]; +// +// Get PONCE Number (0 origin) From System(NT) BusNumber. +// +ULONG +HalpPonceNumber ( + IN ULONG BusNumber + ) +{ + ULONG Ponce; + + if( BusNumber <HalpStartPciBusNumberPonce[1]){ + Ponce = 0; + }else if(BusNumber <HalpStartPciBusNumberPonce[2]){ + Ponce = 1; + }else if(BusNumber <HalpStartPciBusNumberPonce[3]){ + Ponce = 2; + } + + return Ponce; + +} + +#if DBG + +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); + for (i = 0; i < 4; pchar += 4, i++) { + if (pchar >= Length) + break; + DbgPrint("%08x ", *Buffer++); + } + DbgPrint("\n"); + } +} + + +VOID +HalpTestPciNec (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + ULONG MaxDevice; + + if (!flag2) { + return ; + } + + DbgPrint("Nec Test Start --------------------------------------------\n"); + 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 < HalpNumberOfAllPciBus; bus++) { /* R98B Support Only 2 */ +// for (bus = 3; flag && bus < 4; bus++) { //under ponce #1 only + DbgPrint("Config data BusNumber = 0x%x --------------------------------------------\n",bus); + if( (bus == HalpStartPciBusNumberPonce[0]) || (bus == HalpStartPciBusNumberPonce[1]) ) + MaxDevice = 7; + else + MaxDevice = PONCE_PCI_MAX_DEVICES; + + for (i = 0; i < MaxDevice; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < 8; f++) { + SlotNumber.u.bits.FunctionNumber = f; + DbgPrint("===== GetBusData bus(%d) slot(%d) func(%d) ", bus,i, f); + + // + // Read PCI configuration information + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + HalpTestPciPrintResult((PULONG)&PciData, j); + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + DbgPrint("===== SetBusData bus(%d) slot(%d) func(%d) ", bus,i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + HalpTestPciPrintResult((PULONG)&PciData, 1); + DbgPrint("===== GetBusData bus(%d) slot(%d) func(%d) ", bus,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) bus(%d) slot(%d) func(%d) ", bus,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 bus(%d) slot(%d) func(%d) ", bus, 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"); + } + } + } + } + +} + +#endif + +#define KOTEI 0 + +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; + ULONG Ponce; + +#if 1 + PBUS_HANDLER Bus; + PSUPPORTED_RANGES Addresses; +#endif + + +#if KOTEI + + PCI_REGISTRY_INFO tPCIRegInfo; // only for debug + +#endif + ULONG mnum; + + +#if DBG + DbgPrint("HAL PCI init\n"); +#endif + + +#if !KOTEI + // + // 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, + NULL); + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + + if (!NT_SUCCESS(status)) { +#if DBG + DbgPrint("HAL PCI init 0 Status = 0x%x\n",status); +#endif + + return ; + } + + +#if DBG + DbgPrint("HAL PCI init 0\n"); +#endif + + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + +#endif // !KOTEI + + + // Number Of Host Bridge + for(Ponce = 0 ;Ponce < HalpNumberOfPonce;Ponce++){ + +#if !KOTEI // Original mode + +//org for (i=HalpStartPciBusNumberPonce[Ponce]; TRUE; i++) { + for (i=HalpStartPciBusNumberPonce[Ponce]+1; 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; + } + } +#else //SNES BBM Kotei Mode + + + PCIRegInfo = &tPCIRegInfo; + PCIRegInfo->NoBuses = 1; + PCIRegInfo->HardwareMechanism=0x1; + +#endif + +#if DBG + DbgPrint("HAL PCI init 3 NoBuses = 0x%x\n",PCIRegInfo->NoBuses); +#endif + + + // + // Initialize spinlock for synchronizing access to PCI space + // First Time Only. + if(Ponce == 0) + KeInitializeSpinLock (&HalpPCIConfigLock); + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // PCIRegInfo describes the system's PCI support as indicated by the ARC System + // R98B HardwareMechanism is #1 Only. + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + + // R98B + // HalpStartPciBusNumberPonce[Ponce #0] = 0 (allways) + // HalpStartPciBusNumberPonce[Ponce #1] = Number Of PCIbus Ponce#0 = start pci number + // HalpStartPciBusNumberPonce[Ponce #2] = Number Of PCIbus Ponce#0,#1 = start pci number + // HalpStartPciBusNumberPonce[ ] = Number Of PCIbus Ponce#1,#2 = start pci number + // + + + HalpNumberOfAllPciBus += PCIRegInfo->NoBuses; + HalpStartPciBusNumberPonce[Ponce+1]= + HalpStartPciBusNumberPonce[Ponce]+PCIRegInfo->NoBuses; + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + + do { + // R98B + // SNES +// for (i=HalpStartPciBusNumberPonce[Ponce]; i < HalpStartPciBusNumberPonce[Ponce] +PCIRegInfo->NoBuses; i++) { + for (i=HalpStartPciBusNumberPonce[Ponce]; i < HalpNumberOfAllPciBus;i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { +#if DBG + DbgPrint("HAL PCI init 5\n"); +#endif + + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); +#if DBG + DbgPrint("HAL PCI init 6\n"); +#endif + + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // R98B + + } while (HalpGetPciBridgeConfig (HwType,HalpStartPciBusNumberPonce[Ponce] ,&HalpNumberOfAllPciBus)) ; + +// HalpNumberOfAllPciBus += PCIRegInfo->NoBuses; +// HalpStartPciBusNumberPonce[Ponce+1]= +// HalpStartPciBusNumberPonce[Ponce]+PCIRegInfo->NoBuses; + + // + // Search Next Ponce!!. + // + + } +#if DBG + DbgPrint("HAL PCI init 7\n"); + + for(Ponce =0;Ponce < 4;Ponce++) + DbgPrint( "HalpStartPciBusNumberPonce[%x] = 0x%x\n",Ponce,HalpStartPciBusNumberPonce[Ponce]); + + DbgPrint("HalpNumberOfAllPciBus = 0x%x\n",HalpNumberOfAllPciBus); +#endif + + // + // Fixup SUPPORTED_RANGES + // R98B fix NumberOfPcibus + + HalpFixupPciSupportedRanges ( HalpNumberOfAllPciBus ); + +#if 1 //org + // + // If not Display is CIRRUS. deleate range CIRRUS VGA I/O area. + // As interrupt Dummy read register is CIRRUS register. + // So Allways had mapped CIRRUS I/O area. + // + // If did not delete rage of CIRRUS I/O. Another PCI Driver + // May be Configration by I/O manager allocate CIRRUS I/O Area. + // confrict ocurred. + // + // Do Cirrus Memory area disable. So that another device allocate + // memory area. + // + if (!HalpCirrusAlive) { + Bus = HaliHandlerForBus (PCIBus, HalpStartPciBusNumberPonce[1]); + Addresses = Bus->BusAddresses; + HalpRemoveRange(&Addresses->IO,0x3000,0x3fff); + + SlotNumber.u.bits.Reserved = 0; + SlotNumber.u.bits.DeviceNumber = 0x4; + SlotNumber.u.bits.FunctionNumber = 0; + // + // Cconfig command only + // + HalpReadPCIConfig (Bus, SlotNumber, PciData, 0x0, PCI_COMMON_HDR_LENGTH); + + PciData->Command &= ~(PCI_ENABLE_MEMORY_SPACE); + // + // Cirrus Memory Space Disable + // + PciData->Command |= PCI_ENABLE_IO_SPACE | PCI_ENABLE_BUS_MASTER; + + // + // Cconfig command only + // + HalpWritePCIConfig (Bus, SlotNumber, PciData, 0x0, PCI_COMMON_HDR_LENGTH); + // + // after this flag. CIRRUS device can't see Software.(Hal Only) + // + // + HalpCirrusDel = TRUE; + + //for test only snes +// HalpRemoveRange(&Addresses->Memory,0x08000000,0x2fffffff); + } +#endif + + +#if DBG + DbgPrint("HAL PCI init 8\n"); +#endif + + + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + // + // R98B fix NumberOfPcibus + // + for (BusNo=0; BusNo < HalpNumberOfAllPciBus ; 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 + +#if DBG + DbgPrint("HAL PCI init 9\n"); +#endif + +#if DBG + HalpTestPci (0); + HalpTestPciNec(0); +#endif +} + + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ) +{ + PBUS_HANDLER Bus; + PPCIPBUSDATA BusData; + ULONG Ponce; + + Bus = HalpAllocateBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // bus # +#if 0 + Internal, // child of this bus + 0, // and number +#else + InterfaceTypeUndefined, // R98B + 0, +#endif + sizeof (PCIPBUSDATA) // sizeof bus specific buffer + ); + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; + // + // R98B + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetSystemInterruptVector; + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + Bus->BusAddresses->Dma.Limit = 0; + // + // R98B +// Bus->TranslateBusAddress = HalpTranslatePCIBusAddress; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + 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; + // + // R98B + // + BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2SystemLine; + BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCISystemLine2Pin; + + // + // Set defaults + // + + BusData->MaxDevice = PONCE_PCI_MAX_DEVICES; + BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq; + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // R98B + Ponce = HalpPonceNumber(BusNo); + BusData->Config.Type1.Address = (PULONG)&PONCE_CNTL(Ponce)->CONFA; + BusData->Config.Type1.Data = (ULONG)&PONCE_CNTL(Ponce)->CONFD; + break; + + case 2: + // R98B Not Support Configuration Mechanism #2. + 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 > 0xffff) { + // IO port > 64k? + return FALSE; + } + + } else { + if (j > 0xf && j < 0x80000) { + // Mem address < 0x8000h? + 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 (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 defined(DBG7) + DbgPrint("HalpSetPCIData:in\n"); +#endif + + + 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"); + } +#endif + + // + // Set new PCI configuration + // + + 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; + } + } + +#if defined(DBG7) + DbgPrint("HalpSetPCIData:out 1\n"); +#endif + + return Len; +} + +#if DBG + +ULONG HalsavePonce; +#endif + +// On PONCE If device num cause master Abort!!. +// +ULONG +HalpConfigMask( + IN PPCIPBUSDATA BusData + ) +{ + + ULONG PERRM; + ULONG Ponce; + + // PONCE!!. + Ponce = ((ULONG)BusData->Config.Type1.Address & PONCE_ADDR_MASK) >> PONCE_ADDR_SHIFT; + + + // save original mask value + PERRM = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM); + + // Set Mask of PONCE. + // + WRITE_REGISTER_ULONG( + (PULONG)&PONCE_CNTL(Ponce)->PERRM, + PERRM |(PONCE_PXERR_PMABS) + ); + return PERRM; +} + +BOOLEAN +HalpConfigUnMask( + IN PPCIPBUSDATA BusData, + IN ULONG PERRM +#if DBG +, +PCI_SLOT_NUMBER Slot +#endif + ) +{ + + BOOLEAN Error; + ULONG PAERR; + ULONG Ponce; + + + + Error=FALSE; + + // whitch PONCE!!. + Ponce = ((ULONG)BusData->Config.Type1.Address & PONCE_ADDR_MASK) >>PONCE_ADDR_SHIFT; + + // Check Abort was Occured!!. + // + PAERR = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PAERR) + & (PONCE_PXERR_PMABS); + if(PAERR){ +#if DBG + // Abort Occured!!. So Reset + DbgPrint("PCI Master Abort Occured\n "); + DbgPrint("DeviceNumber=0x%x\n ",Slot.u.bits.DeviceNumber); + DbgPrint("FUnction=0x%x\n \n",Slot.u.bits.FunctionNumber); + DbgPrint("ULONG=0x%x\n ",(ULONG)Slot.u.AsULONG); +#endif + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERST,PAERR); + Error=TRUE; + } + + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->PERRM, PERRM ); + + return Error; +} + + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + + + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + return ; + } + + + 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 + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID do nothing + // + return ; + } + + 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; + + ULONG IdValue; + ULONG PERRM; + + + IdValue = 0x0; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + + return FALSE; + } + // R98B Ponce max device is 21 + +#if 0 //kugi 1214 + if (Slot.u.bits.DeviceNumber == 0) { + + return FALSE; + } +#endif + +#if 1 + // Hack Hack + // display is !cirrus. But Driver installed cirrus. + // cirrus configration must do fail to panic. + // "DISPLAY ......." + // + // If Booted display is not CIRRUS. + // PCI Configration can't see CIRRUS. + // + if( !HalpCirrusAlive && HalpCirrusDel && + (BusHandler->BusNumber == HalpStartPciBusNumberPonce[1]) && + (Slot.u.bits.DeviceNumber == 0x4) + ) + return FALSE; +#endif + + + + // R98B Ponce max device is 21 + // 0 <= device number <= 21 (PONCE_PCI_MAX_DEVICES) + // + if ( ( + (BusHandler->BusNumber == HalpStartPciBusNumberPonce[0]) || + (BusHandler->BusNumber == HalpStartPciBusNumberPonce[1]) + ) && + + (Slot.u.bits.DeviceNumber > 6) + ) + { + return FALSE; + }else if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { + return FALSE; + } + + + // Check Actually device is there!!. Do Vendor ID register Read. + // + PERRM=HalpConfigMask(BusData); + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 4, + PCIConfigHandler.ConfigRead); + + +#if DBG + HalpConfigUnMask(BusData,PERRM,Slot); +#else + HalpConfigUnMask(BusData,PERRM); +#endif + +#if DBG + if(Slot.u.bits.FunctionNumber !=Slot.u.bits.FunctionNumber){ + DbgPrint("BAd Function = 0x%x\n",Slot.u.bits.FunctionNumber); + DbgPrint("Bad Function ato= 0x%x\n",Slot.u.bits.FunctionNumber); + } +#endif + + + if ((IdValue & 0x0000ffff) == 0xffff){ +#if defined(DBG9) + DbgPrint("ID Value Function = 0x%x",Slot.u.bits.FunctionNumber); + DbgPrint("ID Value Device = 0x%x",Slot.u.bits.DeviceNumber); + DbgPrint("ID Value BusNum = 0x%x\n",BusHandler->BusNumber); +#endif + + return FALSE; + } + +#if defined(INTEL_9036) +{ + ULONG RevisionID; + + PERRM=HalpConfigMask(BusData); + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) &RevisionID, 0x8, 4, + PCIConfigHandler.ConfigRead); + + if( (IdValue & 0x0000ffff)==0x8086 && + (IdValue & 0xffff0000)==0x12260000 && + (RevisionID & 0xff) <=0x3 + ){ + intel_9036=TRUE; +#if DBG + DbgPrint("EtherExpress tm PRO/PCI Found!!\n"); +#endif + }else{ + intel_9036=FALSE; + } +#if DBG + HalpConfigUnMask(BusData,PERRM,Slot); +#else + HalpConfigUnMask(BusData,PERRM); +#endif +} +#endif + + 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) { +#if defined(DBG9) + DbgPrint("Header bad type = 0x%x\n",HeaderType); +#endif + + + // 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; + 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 + ) +{ + ULONG Ponce; + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = 0; + // + // First PCIBus Number of PONCE must be 0. So Conver System(NT) BusNumber + // H/W required BusNumber. + // + Ponce = HalpPonceNumber(BusHandler->BusNumber); + PciCfg1->u.bits.BusNumber = BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce]; + 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 (HIGH_LEVEL, Irql); + 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; +#if 0 //snes + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG); +#else +// dame READ_PORT_ULONG (BusData->Config.Type1.Data); +// ok demo moxtuto eehouhouga aru KeStallExecutionProcessor(20); +KeStallExecutionProcessor(20); + +#endif + // + // Release spinlock + // + + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + } +} + + +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); +#if defined(INTEL_9036) + if(intel_9036){ + *Buffer = *((PUCHAR)(& READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data))+i); + }else +#endif + *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); +#if defined(INTEL_9036) + { + ULONG data; + + if(intel_9036){ + data = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data); + *((PUCHAR)(&data)+i) = *Buffer; +// WRITE_PORT_ULONG (PUCHAR) (BusData->Config.Type1.Data + i), data); +#if 1 //SNES WORK_AROUND + READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data )); +#endif + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, data); +#if 1 //SNES WORK_AROUND + READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data )); +#endif + return sizeof (UCHAR); + } + } +#endif + + WRITE_PORT_UCHAR ((PUCHAR) BusData->Config.Type1.Data + i, *Buffer); + +#if 1 //SNES WORK_AROUND + READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i)); +#endif + 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)); +#if 1 //SNES WORK_AROUND + READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i)); +#endif + + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ +#if 1 + extern volatile ULONG DUMMYADDRS[]; +#endif + 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)); + +#if 1 + // + // Hack Hack. + // + if(BusData->Config.Type1.Address == (PULONG)&PONCE_CNTL(1)->CONFA && + PciCfg1->u.bits.BusNumber == 0 && + PciCfg1->u.bits.DeviceNumber == 0x04 && + PciCfg1->u.bits.RegisterNumber== (0x14 / 4 ) && + (*((PULONG) Buffer) & 0xffff0000) == 0 + ){ + DUMMYADDRS[1]= DUMMYADDRS[4]= (*((PULONG) Buffer) & 0xfffc) + 0xBc4003c7; +#if DBG + DbgPrint("DUMMYADDRS[1] = 0x%x\n", DUMMYADDRS[1]); +#endif + } +#endif + +#if 1 //SNES WORK_AROUND + READ_PORT_ULONG ((PULONG) (BusData->Config.Type1.Data )); +#endif + + 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_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; +#if 0 + ULONG Ponce; +#endif + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); +#if 1 //org SNES + BusNumber = BusHandler->BusNumber; +#else + Ponce = HalpPonceNumber(BusHandler->BusNumber); + BusNumber = BusHandler->BusNumber - HalpStartPciBusNumberPonce[Ponce]; +#endif + 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) { +#if DBG + DbgPrint ("HalAssign faild return 0\n"); +#endif + 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); +#if DBG + DbgPrint ("HalAssign faild return 1\n"); +#endif + + 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); +#if DBG + DbgPrint ("HalAssign faild return \n"); +#endif + + + 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 (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) { + ASSERT (RomIndex+1 == NoBaseAddress); + EnableRomBase = FALSE; + NoBaseAddress -= 1; + } + + // + // 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); + + // 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 (!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; + } + + // + // 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; + + } 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 (!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; + } + + // + // 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; + } + } + + 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 + // + + status = IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + CompleteList, + pAllocatedResources + ); + + if (!NT_SUCCESS(status)) { +#if DBG + DbgPrint ("HalAssign Io Assgin faild: = 0x%x\n",status); +#endif + + + 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; +#if DBG + DbgPrint ("Vector: = 0x%x\n",PciData->u.type0.InterruptLine); +#endif + 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 + + DbgPrint("HalAssign: Port Address %x\n", *BaseAddress[j]); + DbgPrint("HalAssign: BusNumber %x\n",BusHandler->BusNumber ); +#endif + } else { + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; +#if DBG + DbgPrint("HalAssign: Memory Address %x\n", *BaseAddress[j]); + DbgPrint("HalAssign: BusNumber %x\n",BusHandler->BusNumber ); +#endif + + } + CmDescriptor++; + } + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + + // koko de new ni kakikomunoda.. + // Turn off decodes, then set new addresses + // + + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Read configuration back and verify address settings took + // + + HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH); + + Match = TRUE; +#if 0 //SNE org + if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || +#else + if( +#endif + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + +#if DBG + DbgPrint ("W InterruptLine = 0x%x\n",PciData->u.type0.InterruptLine); + DbgPrint ("W InterruptPinn = 0x%x\n",PciData->u.type0.InterruptPin); + DbgPrint ("W RomBaseAddress= 0x%x\n",PciData->u.type0.ROMBaseAddress); + + DbgPrint ("R InterruptLine = 0x%x\n",PciData2->u.type0.InterruptLine); + DbgPrint ("R InterruptPinn = 0x%x\n",PciData2->u.type0.InterruptPin); + DbgPrint ("R RomBaseAddress= 0x%x\n",PciData2->u.type0.ROMBaseAddress); + +#endif + + + 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; + } + + // + // 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 //intel networktest + if (PciData.u.type0.BaseAddresses[j] == 0x10001) { + DbgPrint (" Express INTEL\n"); + PciData.u.type0.BaseAddresses[j] = 0x5001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + } +#endif + } + } + +#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 (); +} +#endif diff --git a/private/ntos/nthals/halr98b/mips/rxpciint.c b/private/ntos/nthals/halr98b/mips/rxpciint.c new file mode 100644 index 000000000..717d6cf3a --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxpciint.c @@ -0,0 +1,615 @@ +/*++ + + +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: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +ULONG PciIsaIrq; +ULONG HalpEisaELCR; +BOOLEAN HalpDoingCrashDump = FALSE; +BOOLEAN HalpPciLockSettings; + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus) +#pragma alloc_text(PAGE,HalpAdjustPCIResourceList) +#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq) +#endif +// +// PCI Configuration Type #0 Area Offset 0x3D: Interrupt Pin +// +// Interrupt Pin INT +// ----------------+----------------- +// 0 :Non Use Interrupt +// 1 :INT A +// 2 :INT B +// 3 :INT C +// 4 :INT D +// +// Device or Phys Slot # :PONCE # : Device Number: +// ------------------------+--------+------------------------------ +// PCEB/ESC :PONCE0 : 1 :PCI/EISA Bridge +// SLOT #4 :PONCE0 : 2 : +// SLOT #5 :PONCE0 : 3 : +// SLOT #6 :PONCE0 : 4 : +// SLOT #7 :PONCE0 : 5 : +// ------------------------+--------+------------------------------ +// 53C825#0 :PONCE1 : 1 :SCSI(Wide) +// 53C825#1 :PONCE1 : 2 :SCSI(Narrow) +// SLOT #1 DEC21140 :PONCE1 : 3 :Ehternet Card +// GD5430 :PONCE1 : 4 :VGA +// SLOT #2 :PONCE1 : 5 : +// SLOT #3 :PONCE1 : 6 : +// ------------------------+--------+------------------------------ + +// (See 8-15) +// R98B_PCIPinToLineTableForPonceX[] is Convert table for PCI Pin OutPut to Line. +// Line is Same as Columbus IPR Rgister Bit3. +// +// Table Access is [DeviceNumber][Interrupt Pin]. +// +// INTA is Per Device/Slot. +// INTB,INTC,INTD was Shared +// +UCHAR R98B_PCIPinTolineTable[R98B_MAX_PONCE][7][5] = { +#if 0 + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY) + { RFU, 13,RFU,RFU,RFU }, // Device Num #1 is PCEB/ESC + { RFU, 25, 8, 5, 2 }, // Device Num #2 is Slot #7 + { RFU, 24, 8, 5, 2 }, // Device Num #3 is Slot #6 + { RFU, 23, 8, 5, 2 }, // Device Num #4 is Slot #5 + { RFU, 22, 8, 5, 2 }, // Device Num #5 is Slot #4 + { RFU,RFU,RFU,RFU,RFU } // Device Num #6 is none. (DUMMY) + }, + + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY) + { RFU, 31,RFU,RFU,RFU }, // Device Num #1 is 53C825#0 SCSI(Wide) + { RFU, 30,RFU,RFU,RFU }, // Device Num #2 is 53C825#1 SCSI(Narrow) + { RFU, 29, 7, 4, 1 }, // Device Num #3 is Slot #1 DEC21440 Ether + { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 is GD5430 nonused. + { RFU, 21, 7, 4, 1 }, // Device Num #5 is Slot #9 + { RFU, 20, 7, 4, 1 } // Device Num #6 is Slot #8 + }, + + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #1 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #2 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #3 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #5 + { RFU,RFU,RFU,RFU,RFU } // Device Num #6 + } +#endif + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY) + { RFU, 13,RFU,RFU,RFU }, // Device Num #1 is PCEB/ESC + { RFU, 5, 7, 15, 12 }, // Device Num #2 is Slot #7 + { RFU, 4, 7, 15, 12 }, // Device Num #3 is Slot #6 + { RFU, 3, 7, 15, 12 }, // Device Num #4 is Slot #5 + { RFU, 2, 7, 15, 12 }, // Device Num #5 is Slot #4 + { RFU,RFU,RFU,RFU,RFU } // Device Num #6 is none. (DUMMY) + }, + + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 is none. (DUMMY) + { RFU, 31,RFU,RFU,RFU }, // Device Num #1 is 53C825#0 SCSI(Wide) + { RFU, 30,RFU,RFU,RFU }, // Device Num #2 is 53C825#1 SCSI(Narrow) + { RFU, 9, 6, 14, 11 }, // Device Num #3 is Slot #1 DEC21440 Ethe + { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 is GD5430 nonused. + { RFU, 1, 6, 14, 11 }, // Device Num #5 is Slot #9 + { RFU, 10, 6, 14, 11 } // Device Num #6 is Slot #8 + }, + + { // { Interrupt NonUse,INTA,INTB,INTC,INTD} + { RFU,RFU,RFU,RFU,RFU }, // Device Num #0 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #1 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #2 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #3 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #4 + { RFU,RFU,RFU,RFU,RFU }, // Device Num #5 + { RFU,RFU,RFU,RFU,RFU } // Device Num #6 + } +}; +UCHAR HalpPciLogical2PhysicalInt[32]= + {0,21,22,23,24,25, 7, 8, 0,29,20, 1, 2,13, 4, 5, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,30,31}; + +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 +HalpPCIPin2SystemLine ( + 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. + +--*/ +{ + ULONG Ponce; + PPCIBUSDATA BusData; + PBUS_HANDLER tBusHandler, pBusHandler; + PCI_SLOT_NUMBER bSlotNumber; + ULONG ActualSlotNumber; + ULONG PinNo; + + if (!PciData->u.type0.InterruptPin) { + return ; + } + + Ponce = HalpPonceNumber ( BusHandler->BusNumber ); + + tBusHandler = BusHandler; + pBusHandler = BusHandler->ParentHandler; + + // + // My Mother Search!! + // + if(pBusHandler) + for(;TRUE;){ + if (pBusHandler->BusNumber != HalpStartPciBusNumberPonce[Ponce]) { + tBusHandler = pBusHandler; + pBusHandler = pBusHandler->ParentHandler; + } else { + break; + } + } + + BusData = (PPCIBUSDATA)tBusHandler->BusData; + + if(pBusHandler) + bSlotNumber = BusData->ParentSlot; + else + bSlotNumber = SlotNumber; + + ActualSlotNumber = bSlotNumber.u.bits.DeviceNumber; + + if(pBusHandler) + PinNo = (PciData->u.type0.InterruptPin + SlotNumber.u.bits.DeviceNumber) % 4; + else + PinNo = PciData->u.type0.InterruptPin; + + // + // + // + PciData->u.type0.InterruptLine = + (UCHAR) R98B_PCIPinTolineTable[Ponce][ActualSlotNumber][PinNo]; + +} + + + +VOID +HalpPCISystemLine2Pin ( + 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. + +--*/ +{ + ULONG Ponce; + PPCIBUSDATA BusData; + PBUS_HANDLER tBusHandler, pBusHandler; + PCI_SLOT_NUMBER bSlotNumber; + ULONG ActualSlotNumber; + ULONG PinNo; + + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + + + Ponce = HalpPonceNumber ( BusHandler->BusNumber ); + + tBusHandler = BusHandler; + pBusHandler = BusHandler->ParentHandler; + + // + // My Mother Search!! + // + + if(pBusHandler) + for(;TRUE;){ + if (pBusHandler->BusNumber != HalpStartPciBusNumberPonce[Ponce]) { + tBusHandler = pBusHandler; + pBusHandler = pBusHandler->ParentHandler; + } else { + break; + } + } + + BusData = (PPCIBUSDATA)tBusHandler->BusData; + + if(pBusHandler) + bSlotNumber = BusData->ParentSlot; + else + bSlotNumber = SlotNumber; + + ActualSlotNumber = bSlotNumber.u.bits.DeviceNumber; + + if(pBusHandler) + PinNo = (PciOldData->u.type0.InterruptPin + SlotNumber.u.bits.DeviceNumber) % 4; + else + PinNo = PciOldData->u.type0.InterruptPin; + + // + // + // + PciNewData->u.type0.InterruptLine = + (UCHAR) R98B_PCIPinTolineTable[Ponce][ActualSlotNumber][PinNo]; + + +#if DBG + if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine || + PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) { + DbgPrint ("HalpPCISystem2Pin: System does not support changing the PCI device interrupt routing\n"); + +// DbgPrint ("N Line = 0x%x\n",PciNewData->u.type0.InterruptLine); +// DbgPrint ("O Line = 0x%x\n",PciOldData->u.type0.InterruptLine); +// DbgPrint ("N Pin = 0x%x\n",PciNewData->u.type0.InterruptPin); +// DbgPrint ("O Pin = 0x%x\n",PciOldData->u.type0.InterruptPin); +// DbgBreakPoint (); + } +#endif +} + +#if !defined(SUBCLASSPCI) + +VOID +HalpPCIAcquireType2Lock ( + PKSPIN_LOCK SpinLock, + PKIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { + KeRaiseIrql (HIGH_LEVEL, Irql); + KiAcquireSpinLock (SpinLock); + } else { + *Irql = HIGH_LEVEL; + } +} + + +VOID +HalpPCIReleaseType2Lock ( + PKSPIN_LOCK SpinLock, + KIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (SpinLock); + KeLowerIrql (Irql); + } +} + +#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; + PSUPPORTED_RANGE Range; + PSUPPORTED_RANGES SupportedRanges; + PPCI_COMMON_CONFIG PciData, PciOrigData; + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + UCHAR buffer2[PCI_COMMON_HDR_LENGTH]; + BOOLEAN UseBusRanges; + ULONG i, j, RomIndex, length, ebit; + ULONG Base[PCI_TYPE0_ADDRESSES + 1]; + PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1]; + + 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; + } + + SupportedRanges = NULL; + UseBusRanges = TRUE; + Status = STATUS_INSUFFICIENT_RESOURCES; + + if (HalpPciLockSettings) { + + PciData = (PPCI_COMMON_CONFIG) buffer; + PciOrigData = (PPCI_COMMON_CONFIG) buffer2; + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // If this is a device, and it current has its decodes enabled, + // then use the currently programmed ranges only + // + + if (PCI_CONFIG_TYPE(PciData) == 0 && + (PciData->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) { + + // + // Save current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type0.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type0.ROMBaseAddress; + RomIndex = j; + + // + // Write all one-bits to determine lengths for each address + // + + for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) { + Base[j] = *BaseAddress[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); + + // + // restore original settings + // + + 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) + ); + + // + // Build a memory & io range list of just the ranges already + // programmed into the device + // + + UseBusRanges = FALSE; + SupportedRanges = HalpAllocateNewRangeList(); + if (!SupportedRanges) { + goto CleanUp; + } + + *BaseAddress[RomIndex] &= ~PCI_ADDRESS_IO_SPACE; + for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) { + + i = *BaseAddress[j]; + + if (i & PCI_ADDRESS_IO_SPACE) { + length = 1 << 2; + Range = &SupportedRanges->IO; + ebit = PCI_ENABLE_IO_SPACE; + + } else { + length = 1 << 4; + Range = &SupportedRanges->Memory; + ebit = PCI_ENABLE_MEMORY_SPACE; + + if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) { + Range = &SupportedRanges->PrefetchMemory; + } + } + + Base[j] &= ~(length-1); + while (!(i & length) && length) { + length <<= 1; + } + + if (j == RomIndex && + !(PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)) { + + // range not enabled, don't use it + length = 0; + } + + if (length) { + if (!(PciOrigData->Command & ebit)) { + // range not enabled, don't use preprogrammed values + UseBusRanges = TRUE; + } + + if (Range->Limit >= Range->Base) { + Range->Next = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE)); + Range = Range->Next; + if (!Range) { + goto CleanUp; + } + + Range->Next = NULL; + } + + Range->Base = Base[j]; + Range->Limit = Base[j] + length - 1; + } + + if (Is64BitBaseAddress(i)) { + // skip upper half of 64 bit address since this processor + // only supports 32 bits of address space + j++; + } + } + } + } + + // + // Adjust resources + // + + Status = HaliAdjustResourceListRange ( + UseBusRanges ? BusHandler->BusAddresses : SupportedRanges, + Interrupt, + pResourceList + ); + +CleanUp: + if (SupportedRanges) { + HalpFreeRangeList (SupportedRanges); + } + + 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; + PPCIPBUSDATA BusData; + + 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 + + // + // R98B + // + BusData = (PPCIPBUSDATA) BusHandler->BusData; + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); + + (*Interrupt)->Base = PciData->u.type0.InterruptLine; + (*Interrupt)->Limit = PciData->u.type0.InterruptLine; + return STATUS_SUCCESS; +} + + diff --git a/private/ntos/nthals/halr98b/mips/rxsysbus.c b/private/ntos/nthals/halr98b/mips/rxsysbus.c new file mode 100644 index 000000000..c2e592eb0 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/rxsysbus.c @@ -0,0 +1,214 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixsysbus.c + +Abstract: + +Author: + +Environment: + +Revision History: + + +--*/ + +#include "halp.h" + +ULONG HalpDefaultInterruptAffinity; +extern UCHAR HalpPciLogical2PhysicalInt[]; + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#endif + + +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; +#if DBG + PULONG datap; + PULONG datap2; +#endif + + 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; + + +#if 0 + + datap = (PULONG)&(BusAddress.QuadPart); + + DbgPrint("HAL T BusAddress HIGH:LOW = %08lX:%08lX \n", + datap[1], + datap[0] + ); + datap = (PULONG)&(pRange->Base); + datap2 =(PULONG)&(pRange->Limit); + DbgPrint("HAL T RBase-RLimit HIGH:LOW = %08lX:%08lX -- %08lX:%08lX\n", + datap[1], + datap[0], + datap2[1], + datap2[0] + ); + + datap = (PULONG)&(pRange->SystemBase); + DbgPrint("HAL T RSysbase HIGH:LOW = %08lX:%08lX \n", + datap[1], + datap[0] + ); + + DbgPrint("HAL T BusNo = (0x%x) AddrSpace = 0x%x TransAddr HIGH:LOW = %08lX:%08lX \n", + BusHandler->BusNumber, + *AddressSpace, + TranslatedAddress->u.HighPart, + TranslatedAddress->u.LowPart + ); +#endif + + + 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. + +--*/ +{ + ULONG SystemVector; + ULONG NumCpu; + ULONG PhysicalInterrupt; + + UNREFERENCED_PARAMETER( RootHandler ); + + // + // R98B + // + if(BusHandler->InterfaceType == PCIBus){ + PhysicalInterrupt= (ULONG)HalpPciLogical2PhysicalInt[BusInterruptVector]; + SystemVector = PhysicalInterrupt + DEVICE_VECTORS; + }else{ + PhysicalInterrupt= BusInterruptVector; + SystemVector = BusInterruptVector + DEVICE_VECTORS; + } + *Irql = (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][PhysicalInterrupt]); + //For MRCINT + if(PhysicalInterrupt < 43){ + *Affinity = 0x1 <<HalpResetValue[PhysicalInterrupt].Cpu; + }else{ + NumCpu = (**((PULONG *)(&KeNumberProcessors))); + *Affinity = (0x1 <<NumCpu)-1; + } + + return SystemVector; +} + diff --git a/private/ntos/nthals/halr98b/mips/tga.h b/private/ntos/nthals/halr98b/mips/tga.h new file mode 100644 index 000000000..a8db1925a --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/tga.h @@ -0,0 +1,101 @@ +#ident "@(#) NEC tga.h 1.1 94/11/29 14:09:17" +/*++ + +Module Name: + + tga.h + +Abstract: + + This module contains the register definitions for the TGA (DEC21030) + +Author: + + T.Katoh create-data 1994/11/11 + +Revision Histort: + +--*/ + +/* + * D001 1994.11.29 T.Katoh + * + * Del: non-used definitions + * Chg: TGA_DSP_BUF_OFFSET value + * Add: VIDEO_BASE definition + */ + +// TGA Core Space Map offset for 8-bpp Frame Buffers + +#define TGA_REG_SPC_OFFSET 0x00100000 +#define TGA_DSP_BUF_OFFSET 0x00200000 // D001 + +// 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 // D001 +#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/halr98b/mips/x86bios.c b/private/ntos/nthals/halr98b/mips/x86bios.c new file mode 100644 index 000000000..46543c412 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/x86bios.c @@ -0,0 +1,1256 @@ +/*++ + +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: + +--*/ + +/* + * S001 samezima@oa2.kbnes.nec.co.jp + * - marge r94d glint and x86bios source and. + * + */ + + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +//#include "xm86.h" +//#include "x86new.h" + +#if defined(_X86_DBG_) +#define X86DbgPrint(STRING) \ + DbgPrint STRING; +#else +#define X86DbgPrint(STRING) +#endif + +#define VIDEO_MEMORY_BASE 0x40000000 + +#define PCI_0_IO_BASE 0x1c000000 + +#define PONCE_ADDR_REG ((PULONG)(0x1a000008 | KSEG1_BASE)) +#define PONCE_DATA_REG ((PULONG)(0x1a000010 | KSEG1_BASE)) +#define PONCE_PERRM ((PULONG)(0x1a000810 | KSEG1_BASE)) +#define PONCE_PAERR ((PULONG)(0x1a000800 | KSEG1_BASE)) +#define PONCE_PERST ((PULONG)(0x1a000820 | KSEG1_BASE)) + +extern PULONG HalpPonceConfigAddrReg; +extern PULONG HalpPonceConfigDataReg; +extern PULONG HalpPoncePerrm; +extern PULONG HalpPoncePaerr; +extern PULONG HalpPoncePerst; + +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 + ); + +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 + ); + +extern ULONG HalpDisplayControlBase; + +// S001 ^^^ + +// +// Define global data. +// + +ULONG HalpX86BiosInitialized = FALSE; +ULONG HalpEnableInt10Calls = FALSE; +// S001 vvv +PVOID HalpIoMemoryBase = NULL; +PVOID HalpIoControlBase= NULL; +PUCHAR HalpRomBase = NULL; + +ULONG ROM_Length; +#define BUFFER_SIZE (64*1024) +UCHAR ROM_Buffer[BUFFER_SIZE]; + +ULONG X86BoardOnPonce = 0; // S001 + +extern KSPIN_LOCK HalpPCIConfigLock; + +BOOLEAN +HalpInitX86Emulator( + VOID + ) +{ + ULONG ROMsave, ROM_size = 0; + PHYSICAL_ADDRESS PhysAddr; + UCHAR BaseClass, SubClass, ProgIf; + USHORT Cmd,SetCmd, VendorID, DeviceID, Slot; + PUCHAR ROM_Ptr, ROM_Shadow; + ULONG i; + ULONG r; + USHORT PciDataOffset; + PCI_SLOT_NUMBER PciSlot; + UCHAR header; + KIRQL Irql; + ULONG ponceNumber; // S001 + ULONG Index; + ENTRYLO Pte; + PENTRYLO PageFrame; + LARGE_INTEGER HalpX86PhigicalVideo = {0,0}; + + PhysAddr.HighPart = 0x00000000; + +// KeInitializeSpinLock (&HalpPCIConfigLock); + KeRaiseIrql (PROFILE_LEVEL, &Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); + +// Temp Same vvv + ponceNumber = 1; + HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400); + HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400); + HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400); + HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400); + HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400); + + PciSlot.u.bits.FunctionNumber = 0; + PciSlot.u.bits.DeviceNumber = 4; + + // + // Disable on-board cirrus memory space + // + + HalpReadPCIConfigUshortByOffset( + PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command) + ); +// SetCmd = Cmd & 0xfffd; + SetCmd = Cmd; + HalpWritePCIConfigUshortByOffset( + PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command) + ); +// Temp Same ^^^ + + // + // Scan PCI slots for video BIOS ROMs, except 3 PCI "slots" on motherboard + // + + for (ponceNumber = 0; ponceNumber < R98B_MAX_PONCE ; ponceNumber++) { + ULONG startDevNum; + ULONG endDevNum; + ULONG Slot; + + PageFrame = (PENTRYLO)(PTE_BASE | + (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + HalpX86PhigicalVideo.HighPart = 1; + HalpX86PhigicalVideo.LowPart = 0x40000000 * (ponceNumber+1); + + HalpDisplayControlBase = PCI_0_IO_BASE + (ponceNumber * 0x400000); + + Pte.PFN = (HalpX86PhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpX86PhigicalVideo.HighPart << (32 - PAGE_SHIFT); + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + Pte.C = UNCACHED_POLICY; + + // + // Page table entries of the video memory. + // + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT; + + for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) { + *PageFrame-- = Pte; + Pte.PFN -= 1; + } + + HalpPonceConfigAddrReg = PONCE_ADDR_REG + (ponceNumber * 0x400); + HalpPonceConfigDataReg = PONCE_DATA_REG + (ponceNumber * 0x400); + HalpPoncePerrm = PONCE_PERRM + (ponceNumber * 0x400); + HalpPoncePaerr = PONCE_PAERR + (ponceNumber * 0x400); + HalpPoncePerst = PONCE_PERST + (ponceNumber * 0x400); + + switch(ponceNumber){ + case 0: + startDevNum = 2; + endDevNum = 5; + break; + + case 1: + if (HalpNumberOfPonce == 3) + continue; + startDevNum = 3; + endDevNum = 6; + break; + + case 2: + if (HalpNumberOfPonce == 2) + continue; + startDevNum = 1; + endDevNum = 4; + break; + + default: + continue; + } + + for (Slot = startDevNum; Slot <= endDevNum; Slot++) { + + X86DbgPrint(("HAL: PCI SLot Number=%x",Slot)); + + // + // Create a mapping to PCI configuration space + // + PciSlot.u.bits.FunctionNumber = 0; + PciSlot.u.bits.DeviceNumber = Slot; + + // + // Read Vendor ID and check if slot is empty + // + HalpReadPCIConfigUshortByOffset(PciSlot,&VendorID,FIELD_OFFSET (PCI_COMMON_CONFIG, VendorID)); + X86DbgPrint((" Vendor ID=%x",VendorID)); + + if (VendorID == 0xFFFF){ + X86DbgPrint(("\n")); + continue; // Slot is empty; go to next slot + } + + // + // Read Device ID and check if slot is empty + // + HalpReadPCIConfigUshortByOffset(PciSlot,&DeviceID,FIELD_OFFSET (PCI_COMMON_CONFIG, DeviceID)); + + // + // Check for GLINT or DEC-GA board. + // + if ( (VendorID == 0x3d3d && DeviceID == 0x0001) || + (VendorID == 0x1013 && DeviceID == 0x00a0) || // S001 + (VendorID == 0x1011 && DeviceID == 0x0004) ) { + + X86DbgPrint(("\n")); + continue; + } + + // + // Check Base Class Code + // + HalpReadPCIConfigUcharByOffset(PciSlot,&BaseClass,FIELD_OFFSET (PCI_COMMON_CONFIG, BaseClass)); + + // + // Check Sub Class Code + // + HalpReadPCIConfigUcharByOffset(PciSlot,&SubClass,FIELD_OFFSET (PCI_COMMON_CONFIG, SubClass)); + + // + // Check Proglamming Interface + // + HalpReadPCIConfigUcharByOffset(PciSlot,&ProgIf,FIELD_OFFSET (PCI_COMMON_CONFIG, ProgIf)); + X86DbgPrint((" BaseClass =%x, SubClass =%x, ProgIf =%x\n", BaseClass, SubClass, ProgIf)); + + // + // check if video card + // + if ( ( (BaseClass == 0) && (SubClass == 1) && (ProgIf == 0) ) || + ( (BaseClass == 3) && (SubClass == 0) && (ProgIf == 0) ) || + ( (BaseClass == 3) && (SubClass == 1) && (ProgIf == 0) ) || + ( (BaseClass == 3) && (SubClass == 0x80) && (ProgIf == 0) ) ) { + + X86DbgPrint(("HAL: This is Video card \n")); + + } else { + X86DbgPrint(("HAL: This is not Video card \n")); + continue; + } + + // + // Get size of ROM + // + + ROM_size=0xFFFFFFFF; + + HalpReadPCIConfigUlongByOffset(PciSlot,&ROMsave,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + + HalpWritePCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + HalpReadPCIConfigUlongByOffset(PciSlot,&ROM_size,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + + HalpWritePCIConfigUlongByOffset(PciSlot,&ROMsave,FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + + X86DbgPrint(("HAL: ROM_Size = %0x\n",ROM_size)); + + if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) { + + ROM_size = 0xD0000; // Map to end of option ROM space + + // + // Set Expansion ROM Base Address & enable ROM + // + + PhysAddr.LowPart = 0x000C0000 | PCI_ROMADDRESS_ENABLED; + + HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + + // + // Enable Memory & I/O spaces in command register + // + + HalpReadPCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command)); + X86DbgPrint(("HAL: READ CMD=%0x\n",Cmd)); + + SetCmd = Cmd|0x3; + HalpWritePCIConfigUshortByOffset(PciSlot,&SetCmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command)); + + // + // Create a mapping to the PCI memory space + // + HalpIoMemoryBase = (PVOID)0x40000000; + // + // Look for PCI option video ROM signature + // + HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000; + + X86DbgPrint(("HAL: HalpRomBase=%x,\n",HalpRomBase)); + X86DbgPrint(("HAL: RomSignature[0]=%x, RomSignature[1]=%x, RomSize=%x\n", + *(ROM_Ptr+0), *(ROM_Ptr+1), *(ROM_Ptr+2)<<9 )); + + if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) { + // + // Copy ROM to RAM. PCI Spec says you can't execute from ROM. + // Sometimes option ROM and video RAM can't co-exist. + // + ROM_Length = *(ROM_Ptr+2) << 9; + + if (ROM_Length <= BUFFER_SIZE) { + X86DbgPrint(("HAL: ROM Copy:")); + + for (i=0; i<ROM_Length; i++){ + ROM_Buffer[i] = *ROM_Ptr++; + if( !(i % 0x400) ) + X86DbgPrint((".")); + } + + X86DbgPrint(("\n")); + HalpRomBase = (PUCHAR) ROM_Buffer; + + } + X86DbgPrint(("HAL: ROM Short HalpRomBase=%x\n",HalpRomBase)); + + // + // Io Map. + // + HalpIoControlBase= (PVOID)0x403f0000; + + PhysAddr.LowPart = 0x000C0000; + HalpWritePCIConfigUlongByOffset(PciSlot,&(PhysAddr.LowPart),FIELD_OFFSET (PCI_COMMON_CONFIG, u.type0.ROMBaseAddress)); + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + + X86BoardOnPonce = ponceNumber; // S001 + + return TRUE; // Exit slot scan after finding 1st option ROM + } + + // Not Found So Reset!!. + // Delete mapping to PCI memory space + + // Found PCI VIDEO ROM. + // 1.Map ISA Memory Space + // 2. + + X86DbgPrint(("HAL: Found PCI ROM BIOS\n")); + + // 0: rom enable so do PCI + // 1: rom disable so do EISA vga + + HalpWritePCIConfigUshortByOffset(PciSlot,&Cmd,FIELD_OFFSET (PCI_COMMON_CONFIG, Command)); + + } // end of if clause + + X86DbgPrint(("HAL: ROM SIZE invalid\n")); + + } // end of for loop + + } // end of ponce searce loop + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + + X86DbgPrint(("HAL: Search (E)ISA ROM BIOS\n")); + + PageFrame = (PENTRYLO)(PTE_BASE | + (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + HalpX86PhigicalVideo.HighPart = 1; + HalpX86PhigicalVideo.LowPart = 0x40000000; + + HalpDisplayControlBase = PCI_0_IO_BASE; + + Pte.PFN = (HalpX86PhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpX86PhigicalVideo.HighPart << (32 - PAGE_SHIFT); + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + Pte.C = UNCACHED_POLICY; + + // + // Page table entries of the video memory. + // + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + Pte.PFN = ((ULONG)HalpDisplayControlBase + 0xffff) >> PAGE_SHIFT; + + for (Index = 0; Index < (0x10000 / PAGE_SIZE ); Index++) { + *PageFrame-- = Pte; + Pte.PFN -= 1; + } + + // + // No PCI BIOS SO Search ISA BIOS. + // Create a mapping to ISA memory space, unless one already exists + // + + HalpIoMemoryBase = (PULONG)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. + // + X86DbgPrint(("HAL: EISA ROM BIOS Found \n")); + + ROM_Length = *(ROM_Ptr+2) << 9; + if (ROM_Length <= BUFFER_SIZE) { + for (i=0; i<ROM_Length; i++) + ROM_Buffer[i] = *ROM_Ptr++; + } + + HalpRomBase = (PUCHAR) ROM_Buffer; + HalpIoControlBase= (PVOID)0x403f0000; + return TRUE; + } + + // + // No video option ROM was found. Delete mapping to PCI memory space. + // + + X86DbgPrint(("HAL: 55AA BIOS Not \n")); + + return FALSE; +} +// S001 ^^^ + +BOOLEAN +HalCallBios ( + IN ULONG BiosCommand, + IN OUT PULONG Eax, + IN OUT PULONG Ebx, + IN OUT PULONG Ecx, + IN OUT PULONG Edx, + IN OUT PULONG Esi, + IN OUT PULONG Edi, + IN OUT PULONG Ebp + ) + +/*++ + +Routine Description: + + This function provides the platform specific interface between a device + driver and the execution of the x86 ROM bios code for the specified ROM + bios command. + +Arguments: + + BiosCommand - Supplies the ROM bios command to be emulated. + + Eax to Ebp - Supplies the x86 emulation context. + +Return Value: + + A value of TRUE is returned if the specified function is executed. + Otherwise, a value of FALSE is returned. + +--*/ + +{ + XM86_CONTEXT Context; + + // + // If the x86 BIOS Emulator has not been initialized, then return FALSE. + // + + if (HalpX86BiosInitialized == FALSE) { + return FALSE; + } + + // + // If the Video Adapter initialization failed and an Int10 command is + // specified, then return FALSE. + // + + if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) { + return FALSE; + } + + // + // Copy the x86 bios context and emulate the specified command. + // + + Context.Eax = *Eax; + Context.Ebx = *Ebx; + Context.Ecx = *Ecx; + Context.Edx = *Edx; + Context.Esi = *Esi; + Context.Edi = *Edi; + Context.Ebp = *Ebp; + // S001 vvv + if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, + &Context, + HalpIoControlBase, + HalpIoMemoryBase) != XM_SUCCESS) { + return FALSE; + } + // S001 ^^^ + + // + // Copy the x86 bios context and return TRUE. + // + + *Eax = Context.Eax; + *Ebx = Context.Ebx; + *Ecx = Context.Ecx; + *Edx = Context.Edx; + *Esi = Context.Esi; + *Edi = Context.Edi; + *Ebp = Context.Ebp; + return TRUE; +} + +// S001 vvv +BOOLEAN +HalpInitializeX86DisplayAdapter( + VOID + ) +// S001 ^^^ +/*++ + +Routine Description: + + This function initializes a display adapter using the x86 bios emulator. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + // + // If EISA I/O Ports or EISA memory could not be mapped, then don't + // attempt to initialize the display adapter. + // + + // S001 vvv + if (!HalpInitX86Emulator()){ + X86DbgPrint(("HAL: X86 HalpInitX86Emulator() False\n")); // S001 + return FALSE; + } + + if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) { + X86DbgPrint(("HAL: X86 Bios or Mem Base False\n")); // S001 + return FALSE; + } + // S001 ^^^ + + // + // Initialize the x86 bios emulator. + // + + x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase); // S001 + HalpX86BiosInitialized = TRUE; + + // + // Attempt to initialize the display adapter by executing its ROM bios + // code. The standard ROM bios code address for PC video adapters is + // 0xC000:0000 on the ISA bus. + // + + if (x86BiosInitializeAdapter(0xc0000, NULL, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) { // S001 + HalpEnableInt10Calls = FALSE; + return FALSE; // S001 + } + + HalpEnableInt10Calls = TRUE; + + return TRUE; // S001 +} + +VOID +HalpResetX86DisplayAdapter( + VOID + ) + +/*++ + +Routine Description: + + This function resets a display adapter using the x86 bios emulator. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + XM86_CONTEXT Context; + + // + // Initialize the x86 bios context and make the INT 10 call to initialize + // the display adapter to 80x25 color text mode. + // + + Context.Eax = 0x0003; // Function 0, Mode 3 + Context.Ebx = 0; + Context.Ecx = 0; + Context.Edx = 0; + Context.Esi = 0; + Context.Edi = 0; + Context.Ebp = 0; + + HalCallBios(0x10, + &Context.Eax, + &Context.Ebx, + &Context.Ecx, + &Context.Edx, + &Context.Esi, + &Context.Edi, + &Context.Ebp); + + return; +} + +// S001 vvv +// +// This code came from ..\..\x86new\x86bios.c +// +#define LOW_MEMORY_SIZE 0x800 +extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3]; +extern ULONG x86BiosScratchMemory; +extern ULONG x86BiosIoMemory; +extern ULONG x86BiosIoSpace; + + +PVOID +x86BiosTranslateAddress ( + IN USHORT Segment, + IN USHORT Offset + ) + +/*++ + +Routine Description: + + This translates a segment/offset address into a memory address. + +Arguments: + + Segment - Supplies the segment register value. + + Offset - Supplies the offset within segment. + +Return Value: + + The memory address of the translated segment/offset pair is + returned as the function value. + +--*/ + +{ + + ULONG Value; + + // + // Compute the logical memory address and case on high hex digit of + // the resultant address. + // + + Value = Offset + (Segment << 4); + Offset = (USHORT)(Value & 0xffff); + Value &= 0xf0000; + switch ((Value >> 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); + + X86DbgPrint(("HAL: HalpRomBase=%0x\n",HalpRomBase)); + + for (i=0; i<ROM_Length; i++) { + *ROM_Shadow++ = ROM_Buffer[i]; + } + } +} + + +/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/ + +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + x86bios.c + +Abstract: + + This module implements supplies the HAL interface to the 386/486 + real mode emulator for the purpose of emulating BIOS calls.. + +Author: + + David N. Cutler (davec) 13-Nov-1994 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "nthal.h" +#include "hal.h" +#include "xm86.h" +#include "x86new.h" + +// +// Define the size of low memory. +// + +#define LOW_MEMORY_SIZE 0x800 +// +// Define storage for low emulated memory. +// + +UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3]; +ULONG x86BiosScratchMemory; + +// +// Define storage to capture the base address of I/O space and the +// base address of I/O memory space. +// + +ULONG x86BiosIoMemory; +ULONG x86BiosIoSpace; + +// +// Define BIOS initialized state. +// + +BOOLEAN x86BiosInitialized = FALSE; + +ULONG +x86BiosReadIoSpace ( + IN XM_OPERATION_DATATYPE DataType, + IN USHORT PortNumber + ) + +/*++ + +Routine Description: + + This function reads from emulated I/O space. + +Arguments: + + DataType - Supplies the datatype for the read operation. + + PortNumber - Supplies the port number in I/O space to read from. + +Return Value: + + The value read from I/O space is returned as the function value. + + N.B. If an aligned operation is specified, then the individual + bytes are read from the specified port one at a time and + assembled into the specified datatype. + +--*/ + +{ + + ULONG Result; + + union { + PUCHAR Byte; + PUSHORT Word; + PULONG Long; + } u; + + // + // Compute port address and read port. + // + + u.Long = (PULONG)(x86BiosIoSpace + PortNumber); + + if (DataType == BYTE_DATA) { + Result = READ_REGISTER_UCHAR(u.Byte); + + } else if (DataType == LONG_DATA) { + if (((ULONG)u.Long & 0x3) != 0) { + Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | + (READ_REGISTER_UCHAR(u.Byte + 1) << 8) | + (READ_REGISTER_UCHAR(u.Byte + 2) << 16) | + (READ_REGISTER_UCHAR(u.Byte + 3) << 24); + + } else { + Result = READ_REGISTER_ULONG(u.Long); + } + + } else { + if (((ULONG)u.Word & 0x1) != 0) { + Result = (READ_REGISTER_UCHAR(u.Byte + 0)) | + (READ_REGISTER_UCHAR(u.Byte + 1) << 8); + + } else { + Result = READ_REGISTER_USHORT(u.Word); + } + } + return Result; +} + +VOID +x86BiosWriteIoSpace ( + IN XM_OPERATION_DATATYPE DataType, + IN USHORT PortNumber, + IN ULONG Value + ) + +/*++ + +Routine Description: + + This function write to emulated I/O space. + + N.B. If an aligned operation is specified, then the individual + bytes are written to the specified port one at a time. + +Arguments: + + DataType - Supplies the datatype for the write operation. + + PortNumber - Supplies the port number in I/O space to write to. + + Value - Supplies the value to write. + +Return Value: + + None. + +--*/ + +{ + union { + PUCHAR Byte; + PUSHORT Word; + PULONG Long; + } u; + + // + // Compute port address and read port. + // + + u.Long = (PULONG)(x86BiosIoSpace + PortNumber); + + if (DataType == BYTE_DATA) { + WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value); + + } else if (DataType == LONG_DATA) { + if (((ULONG)u.Long & 0x3) != 0) { + WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value)); + WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 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); + + X86DbgPrint(("HAL: EMU INIT \n")); + + 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) { + + X86DbgPrint(("HAL: Interrupt emulation failed, status %lx\n", Status)); + + } + + 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; + + + X86DbgPrint(("HAL: BIOS INIT \n")); + + // + // If BIOS emulation has not been initialized, then return an error. + // + + if (x86BiosInitialized == FALSE) { + X86DbgPrint(("HAL: x86BiosInitializeAdapter() False 1\n")); + 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)) { + X86DbgPrint(("HAL: x86BiosInitializeAdapter() False 2\n")); + 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); + + X86DbgPrint(("HAL: Emcall BIOS start \n")); + + Status = XmEmulateFarCall(Segment, Offset, Context); + + X86DbgPrint(("HAL: Emcall BIOS End \n")); + + if (Status != XM_SUCCESS) { + + X86DbgPrint(("HAL: Adapter initialization falied, status %lx\n", Status)); + + } + + return Status; +} +// S001 ^^^ diff --git a/private/ntos/nthals/halr98b/mips/xxcalstl.c b/private/ntos/nthals/halr98b/mips/xxcalstl.c new file mode 100644 index 000000000..0a8a7197d --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/xxcalstl.c @@ -0,0 +1,260 @@ +/*++ + +Copyright (c) 1991-1994 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 R98 System + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + + +#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. + // + + HalpProfileCountRate = + HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT); + + // + // 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[CLOCK_VECTOR] = HalpClockInterrupt0; + + // + // Write the compare register and clear the count register, and + // connect the profile interrupt. + // + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); + + PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt; + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, PROFILE_VECTOR - DEVICE_VECTORS); + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR2, TIMER_RELOAD_START); + + + 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. + +--*/ + +{ + + // + // 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; + HalpWriteCompareRegisterAndClear(0); + + } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) { + HalpStallEnd = PCR->StallExecutionCount; + HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0); + + } + + return; +} diff --git a/private/ntos/nthals/halr98b/mips/xxclock.c b/private/ntos/nthals/halr98b/mips/xxclock.c new file mode 100644 index 000000000..4f953ab8d --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/xxclock.c @@ -0,0 +1,207 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + xxclock.c + +Abstract: + + + This module implements the function necesssary to change the clock + interrupt rate. + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * K001 95.11.24 M.Kusano + * Add for WDT + */ + + +#include "halp.h" + +// +// Define global data used to communicate new clock rates to the clock +// interrupt service routine. +// + +ULONG HalpCurrentTimeIncrement; +ULONG HalpNextIntervalCount; +ULONG HalpNextTimeIncrement; +ULONG HalpNewTimeIncrement; +//K001 +ULONG HalpStartWDTFlag[R98B_MAX_CPU]; +ULONG HalpStopWDTFlag[R98B_MAX_CPU]; +ULONG HalpSetWDTFlag[R98B_MAX_CPU]; +ULONG HalpSetWDTCount[R98B_MAX_CPU]; + +VOID +HalStartWDT( + IN ULONG Count + ); + +VOID +HalStopWDT( + VOID + ); + +VOID +HalSetWDTCounter( + VOID + ); + +ULONG +HalSetTimeIncrement ( + IN ULONG DesiredIncrement + ) +/*++ + +Routine Description: + + This function is called to set the clock interrupt rate to the frequency + required by the specified time increment value. + + N.B. This function is only executed on the processor that keeps the + system time. + +Arguments: + + DesiredIncrement - Supplies desired number of 100ns units between clock + interrupts. + +Return Value: + + The actual time increment in 100ns units. + +--*/ + +{ + + ULONG NewTimeIncrement; + ULONG NextIntervalCount; + KIRQL OldIrql; + + // + // If the specified time increment value is less that the minimum value + // or greater than the maximum value ,then set the time increment value + // to the minimum or maximum as appropriate. + // + + if (DesiredIncrement < MINIMUM_INCREMENT) { + DesiredIncrement = MINIMUM_INCREMENT; + + } else if (DesiredIncrement > MAXIMUM_INCREMENT) { + DesiredIncrement = MAXIMUM_INCREMENT; + } + + // + // Raise IRQL to the highest level, set the new clock interrupt + // parameters, lower IRQl, and return the new time increment value. + // + + // Adjust clock values to the Columbus clock frequency + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + NextIntervalCount = ((DesiredIncrement * COLUMBUS_CLOCK_FREQUENCY) / 1000) / 10; + NewTimeIncrement = (NextIntervalCount * 1000 * 10) / COLUMBUS_CLOCK_FREQUENCY; + HalpNextIntervalCount = NextIntervalCount; + HalpNewTimeIncrement = NewTimeIncrement; + KeLowerIrql(OldIrql); + return NewTimeIncrement; +} + +//K001 +VOID HalStartWDT( + IN ULONG Count +) +/*++ +Routine Description: + + This function is called to start WDT. + +Arguments: + + Count - Counter value for WDT. + +Return Value: + + NONE +--*/ +{ + ULONG NumCPU,i; + + NumCPU=**((PULONG *)(&KeNumberProcessors)); + NumCPU--; + + for(i=0;i<=NumCPU;i++){ + HalpStartWDTFlag[i]=1; + HalpSetWDTCount[i]=Count; + } +} + +VOID HalStopWDT( +) +/*++ +Routine Description: + + This function is called to stop WDT. + +Arguments: + + NONE + +Return Value: + + NONE +--*/ +{ + ULONG NumCPU,i; + + NumCPU=**((PULONG *)(&KeNumberProcessors)); + NumCPU--; + + for(i=0;i<=NumCPU;i++){ + HalpStopWDTFlag[i]=1; + } +} + +VOID HalSetWDTCounter( +) +/*++ +Routine Description: + + This function is called to stop WDT. + +Arguments: + + NONE + +Return Value: + + NONE +--*/ +{ + ULONG NumCPU,i; + + NumCPU=**((PULONG *)(&KeNumberProcessors)); + NumCPU--; + + for(i=0;i<=NumCPU;i++){ + HalpSetWDTFlag[i]=1; + } +} diff --git a/private/ntos/nthals/halr98b/mips/xxidle.s b/private/ntos/nthals/halr98b/mips/xxidle.s new file mode 100644 index 000000000..e202c795c --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/xxidle.s @@ -0,0 +1,76 @@ +// "@(#) NEC xxidle.s 1.2 94/10/17 11:59:42" +// TITLE("Processor Idle") +//++ +// +// Copyright (c) 1994 Microsoft Corporation +// +// Module Name: +// +// xxidle.s +// +// Abstract: +// +// This module implements system platform dependent power management +// support. +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "halmips.h" + + SBTTL("Processor Idle") +//++ +// +// VOID +// HalProcessorIdle( +// VOID +// ) +// +// Routine Description: +// +// This function is called when the current processor is idle with +// interrupts disabled. There is no thread active and there are no +// DPCs to process. Therefore, power can be switched to a standby +// mode until the the next interrupt occurs on the current processor. +// +// N.B. This routine is entered with IE in PSR clear. This routine +// must do any power management enabling necessary, set the IE +// bit in PSR, then either return or wait for an interrupt. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalProcessorIdle) + +// +// Perform power management enabling. +// + + .set noreorder + .set noat + mfc0 v0,psr // get current PSR + nop // fill + or v0,v0,1 << PSR_IE // set interrupt enable. + mtc0 v0,psr // enable interrupts + .set at + .set reorder + +// +// Wait for an interrupt if supported. +// + + j ra // return + + .end HalProcessorIdle diff --git a/private/ntos/nthals/halr98b/mips/xxinithl.c b/private/ntos/nthals/halr98b/mips/xxinithl.c new file mode 100644 index 000000000..5071b6b61 --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/xxinithl.c @@ -0,0 +1,894 @@ +/*++ + +Copyright (c) 1991-1993 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 R98B system. + +Revision History: + +--*/ + +#include "halp.h" +// For CPU +#define CPU_PHY_INF_OFFSET 0x1d68 +#define CPU_RED_INF_OFFSET 0x1d60 +//For Memory +#define SIMM_PHY_INF_OFFSET 0x1d10 +#define SIMM_RED_INF_OFFSET 0x1d00 +#define SIMM_PHY_CAP_OFFSET 0x1d20 +#define FW_NOT_DETECT 0x0000 +#define FW_16_DETECT 0x0001 +#define FW_32_DETECT 0x0002 +#define FW_64_DETECT 0x0004 +#define FW_128_DETECT 0x0008 + + +ULONG HalpMachineCpu; +ULONG HalpNumberOfPonce; +ULONG HalpPhysicalNode; + + +//For CPU +ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; +ULONG HalpPhysicalAffinity=0; +ULONG HalpFwAffinity=0; +ULONG HalpFwDetectErrorCpu=0; +// For Memory +ULONG HalpFwDetectMemory=0; +ULONG HalpPhysicalMemory=0; +ULONG HalpFwDetectErrorMemory=0; +UCHAR HalpPhysicalSimmSize[64]; +// For INTERRUPT +// v-masank@microsoft.com +// +extern PINT_ENTRY HalpIntEntryPointer; +// +// Define forward referenced prototypes. +// + +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 + ); + +VOID +HalpCopyROMs( + VOID + ); + +extern PVOID HalpIoControlBase; +extern PVOID HalpIoMemoryBase; +extern UCHAR HalpSzPciLock[]; +extern UCHAR HalpSzBreak[]; +extern BOOLEAN HalpPciLockSettings; + +VOID +HalpGetParameters ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +// +// 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, HalpGetParameters) +#pragma alloc_text(INIT, HalInitializeProcessor) +#pragma alloc_text(INIT, HalStartNextProcessor) +#pragma alloc_text(INIT, HalpCpuCheck) + +#endif + +// +// Define global spin locks used to synchronize various HAL operations. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; +KSPIN_LOCK HalpIprInterruptLock; +KSPIN_LOCK HalpDieLock; +KSPIN_LOCK HalpLogLock; +// +// 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; + +extern ULONG HalpX86BiosInitialized; +extern ULONG X86BoardOnPonce; + +KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord; + +UCHAR HalpComponentId[] = "hal.dll"; + + +VOID +HalpGetParameters ( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +/*++ + +Routine Description: + + This gets any parameters from the boot.ini invocation line. + +Arguments: + + None. + +Return Value: + + None + +--*/ +{ + PCHAR Options; + + if (LoaderBlock != NULL && LoaderBlock->LoadOptions != NULL) { + Options = LoaderBlock->LoadOptions; + + // + // Check if PCI settings are locked down + // + + if (strstr(Options, HalpSzPciLock)) { + HalpPciLockSettings = TRUE; + } + + // + // Has the user asked for an initial BreakPoint? + // + + if (strstr(Options, HalpSzBreak)) { + DbgBreakPoint(); + } + + } + + return; +} + +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. + +--*/ + +{ + + PKPRCB Prcb; + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS ZeroAddress; + ULONG AddressSpace; + + ULONG Revr; + ULONG PhysicalNumber; + + ULONG Cnfg; + ULONG TmpAffinity; + PUCHAR FwNvram; + PULONG FwNvram2; + UCHAR FwCpu; + ULONG i,j; + ULONG FwMemory; + ULONG FwNoMemory; + // + // Initialize the HAL components based on the phase of initialization + // and the processor number. + // + + Prcb = PCR->Prcb; + // + // DataBuserr handling + // + PCR->DataBusError = HalpBusError; + // + // Instruction BusError handling + // + PCR->InstructionBusError = HalpBusError; + + if ((Phase == 0) || (Prcb->Number != 0)) { + + // + // 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(); + HalpGetParameters (LoaderBlock); + + Revr=READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->REVR ) ; + PhysicalNumber=((Revr&0x0f000000)>>24)-4; + HalpLogicalCPU2PhysicalCPU[Prcb->Number]=PhysicalNumber; + + // + // If processor 0 is being initialized, then initialize various + // variables, spin locks, and the display adapter. + // + + if (Prcb->Number == 0) { + + // + // Fill in handlers for APIs which this hal supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; +#if !defined(NT_40) + HalRegisterBusHandler = HaliRegisterBusHandler; + HalHandlerForBus = HaliHandlerForBus; + HalHandlerForConfigSpace = HaliHandlerForConfigSpace; + HalQueryBusSlots = HaliQueryBusSlots; + HalSlotControl = HaliSlotControl; + HalCompleteSlotControl = HaliCompleteSlotControl; +#endif + + // + // Set NMI interrupt service routine on NVRAM + // + + HalpSetupNmiHandler(); // DUMP by kita + + // + // Set the number of process id's and TB entries. + // + + **((PULONG *)(&KeNumberProcessIds)) = 256; + + // + // Cpu Type + // + + HalpCpuCheck(); + + // + // Set the interval clock increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNextTimeIncrement = MAXIMUM_INCREMENT; + HalpNextIntervalCount = 0; + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // + // Set DMA I/O coherency attributes. + // + + KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP); + + // + // Initialize all spin locks. + // + + KeInitializeSpinLock(&HalpBeepLock); + KeInitializeSpinLock(&HalpDisplayAdapterLock); + KeInitializeSpinLock(&HalpSystemInterruptLock); + KeInitializeSpinLock(&HalpIprInterruptLock); + KeInitializeSpinLock(&HalpDieLock); + KeInitializeSpinLock(&HalpLogLock); + + // + // Set address of cache error routine. + // + + KeSetCacheErrorRoutine(HalpCacheErrorRoutine); + + // + // Initialize the display adapter. + // + + HalpInitializeDisplay0(LoaderBlock); + + // + // Allocate map register memory. + // + + HalpAllocateMapRegisters(LoaderBlock); + + // + // Initialize and register a bug check callback record. + // + + KeInitializeCallbackRecord(&HalpCallbackRecord); + KeRegisterBugCheckCallback(&HalpCallbackRecord, + HalpBugCheckCallback, + &HalpBugCheckBuffer, + sizeof(HALP_BUGCHECK_BUFFER), + &HalpComponentId[0]); + + // For CPU log(FW Nvram -> OS Nvram) + Cnfg=READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG ) ; + TmpAffinity=((~((Cnfg&0x0f000000)>>24))&0x0000000f); + + for(i=0;i<4;i++){ + HalpPhysicalAffinity = HalpPhysicalAffinity | ((TmpAffinity>>i)&0x1); + if(i==3){ + break; + } + HalpPhysicalAffinity=(HalpPhysicalAffinity)<<1; + } + + (ULONG)FwNvram=0xbf080000; + FwCpu=(*FwNvram); + HalpFwAffinity=(ULONG)FwCpu; + HalpFwDetectErrorCpu=((HalpPhysicalAffinity)&(~HalpFwAffinity)); + HalNvramWrite(CPU_RED_INF_OFFSET,4,&HalpFwDetectErrorCpu); + HalNvramWrite(CPU_PHY_INF_OFFSET,4,&HalpPhysicalAffinity); + + //For memory Log(FW Nvram -> OS NVram) + (ULONG)FwNvram2=0xbf080050; + HalpFwDetectMemory=(*FwNvram2); + FwMemory=0; + FwNoMemory=0; + for(i=0;i<4;i++){ + FwMemory=((FwMemory)|((HalpFwDetectMemory <<(i*8))& 0xff000000)) ; + if(i==3){ + break; + } + FwMemory=((FwMemory)>>8); + } + for(i=0;i<8;i++){ + switch(FwMemory&0xf){ + case FW_NOT_DETECT: + FwNoMemory=(FwNoMemory|(0xf<<(i*4))); + break; + case FW_16_DETECT: + for(j=0;j<4;j++){ + HalpPhysicalSimmSize[i*4+j]=0x04; + } + break; + case FW_32_DETECT: + for(j=0;j<4;j++){ + HalpPhysicalSimmSize[i*4+j]=0x08; + } + break; + case FW_64_DETECT: + for(j=0;j<4;j++){ + HalpPhysicalSimmSize[i*4+j]=0x16; + } + break; + case FW_128_DETECT: + for(j=0;j<4;j++){ + HalpPhysicalSimmSize[i*4+j]=0x32; + } + break; + default: + HalpFwDetectErrorMemory=(HalpFwDetectErrorMemory|(0xf<<(i*4) )); + } + FwMemory=((FwMemory)>>4); + } + HalpPhysicalMemory=~(FwNoMemory); + + HalNvramWrite(SIMM_RED_INF_OFFSET,4,&HalpFwDetectErrorMemory); + HalNvramWrite(SIMM_PHY_INF_OFFSET,4,&HalpPhysicalMemory); + HalNvramWrite(SIMM_PHY_CAP_OFFSET,64,HalpPhysicalSimmSize); + } + + // + // Initialize I/O address + // + + HalpMapIoSpace(); + +#if DBG + DbgPrint("Errnod addr is 0x%x\n",(PULONG)&(COLUMNBS_LCNTL)->ERRNOD ); +#endif + // + // 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 (); + + if (HalpInitializeDisplay1(LoaderBlock) == FALSE) { + return FALSE; + + } else { + + // + // Map I/O space, calibrate the stall execution scale factor, + // and create DMA data structures. + // + + HalpCalibrateStall(); + + HalpCreateDmaStructures(); + + // + // 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); + + // + // reset EISA io/memory base for HalCallBios() use. + // + if( HalpX86BiosInitialized ){ + if(X86BoardOnPonce == 0){ + HalpIoControlBase = HalpEisaControlBase; + HalpIoMemoryBase = HalpEisaMemoryBase; + } else { + HalpIoControlBase = (PVOID)( + KSEG1_BASE + + PCI_CNTL_PHYSICAL_BASE + + (0x40000 * X86BoardOnPonce ) + ); + PhysicalAddress.HighPart = 1; + PhysicalAddress.LowPart = 0x40000000 * (X86BoardOnPonce+1); + HalpIoMemoryBase = MmMapIoSpace(PhysicalAddress, + PAGE_SIZE * 256, + FALSE + ); + } + DbgPrint("HAL: X86 Bus=%d, HalpIoControlBase = 0x%x, HalpIoMemoryBase = 0x%x%x\n", + X86BoardOnPonce, HalpIoControlBase, HalpIoMemoryBase); + } + +#if DBG + DbgPrint("HAL: EisaMemoryBase = 0x%x\n", HalpEisaMemoryBase); +#endif +// HalpInitializeX86DisplayAdapter(); + + return TRUE; + } + } +} + +// +// Check MPU is R4400 or R10000 +// +VOID +HalpCpuCheck( + VOID + ) +{ + // + // For Driver. NVRAM Erea Write Enable Any Time. + // + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR ,STSR_WNVWINH); + // + // Default setup. future implement is daynamic diagnotics. + // + HalpNumberOfPonce = 2; + + // + // Set DUMP Key Only NMI. + // PUSH Power SW coused Interrupt. Not NMI!! + // + HalpMrcModeChange((UCHAR)MRC_OP_DUMP_AND_POWERSW_NMI); + + HalpPhysicalNode = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->CNFG ); + + if( READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->STSR) & STSR_MPU){ + HalpMachineCpu = R98_CPU_R4400; + **((PULONG *)(&KeNumberTbEntries)) = 48; + + }else{ + HalpMachineCpu = R98_CPU_R10000; + **((PULONG *)(&KeNumberTbEntries)) = 64; + +#if defined(NT_40) + // + // Set SyncIrql + // + // Hal must not set SyncIrql + // v-masank@microsoft.com 5/10/96 + // KeSetSynchIrql(5); +#endif + } + //v-masank@microsoft.com for interrupt + // + HalpIntEntryPointer= (&HalpIntEntry[HalpMachineCpu][0][0]); +} + + + +#include "rxnvr.h" + +VOID +HalpSetupNmiHandler( + VOID + ) + +/*++ + +Routine Description: + + This routine set NMI handler to nvRAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + +#if 1 //NMI Vector not imprement yet -> modify by kita + ULONG funcAddr; + KIRQL OldIrql; + ENTRYLO SavedPte[2]; + PNVRAM_NMIVECTER NvramNmiVecter; + + // + // Get address of HalpNmiHandler + // + + funcAddr = (ULONG)HalpNmiHandler; + + + ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) && + ((ULONG)&HalpNmiHandler < KSEG2_BASE) ); + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(&SavedPte[0]); + + NvramNmiVecter = (PNVRAM_NMIVECTER)NMIVECTER_BASE; + + WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[0], + (UCHAR)(funcAddr >> 24)); + + WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[1], + (UCHAR)((funcAddr >> 16) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[2], + (UCHAR)((funcAddr >> 8) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvramNmiVecter->NmiVector[3], + (UCHAR)(funcAddr & 0xFF)); + + // + // Unmap the NVRAM from the address space of the current process. + // + + HalpUnmapNvram(&SavedPte[0], OldIrql); +#endif + return; +} + + + + +// +// no change +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. + +--*/ + +{ + + // + // N.B This version Not Implement. + // Future support!! + // + 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 MagellanAllError0 =0; + ULONG MagellanAllError1 =0; + ULONG ColumbsAllError; + + // + // Only one Eif or Buserr trap + // + + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->MKSR, + 63-(EIF_VECTOR-DEVICE_VECTORS )); + + KiAcquireSpinLock(&HalpDieLock); + HalpBusErrorLog(); + +// KiReleaseSpinLock(&HalpDieLock); + // + // Bus Error case (Instruction Fetch and Data Load or Store) + // -At Memory Read Multi Bit Error. + // -Read to Memory Hole Area + // -Read to reserved area or protection area + // + if(!(HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0 )) + MagellanAllError0 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->AERR ); + if(!(HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1 )) + MagellanAllError1 = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->AERR ); + + ColumbsAllError = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->AERR); + + + KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff, + (ULONG)VirtualAddress, + ColumbsAllError, + MagellanAllError0, + MagellanAllError1 + ); + return FALSE; +} + + +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. + +--*/ + +{ + 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; + } + + if (NextRestartBlock->BootStatus.ProcessorReady != FALSE){ + Number += 1; + } + NextRestartBlock = NextRestartBlock->NextRestartBlock; + } while (NextRestartBlock != NULL); + + return FALSE; +} + +VOID +HalpVerifyPrcbVersion( + VOID + ) + +/*++ + +Routine Description: + + This function ? + +Arguments: + + None. + + +Return Value: + + None. + +--*/ + +{ + + return; +} diff --git a/private/ntos/nthals/halr98b/mips/xxinitnt.c b/private/ntos/nthals/halr98b/mips/xxinitnt.c new file mode 100644 index 000000000..e0f4bae5a --- /dev/null +++ b/private/ntos/nthals/halr98b/mips/xxinitnt.c @@ -0,0 +1,424 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + xxinitnt.c + +Abstract: + + + This module implements the interrupt initialization for a MIPS R98B + system. + +--*/ + + +#include "halp.h" +#include "eisa.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, HalpInitializeInterrupts) + +#endif + +VOID +HalpT5Int5Dispatch( + VOID + ); + + +// +// Define the IRQL mask and level mapping table. +// +// These tables are transfered to the PCR and determine the priority of +// interrupts. +// +// N.B. The two software interrupt levels MUST be the lowest levels. +// + +UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits + 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits + 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits + 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits + +UCHAR HalpIrqlTable[] = {0xff, // IRQL 0 + 0xfe, // IRQL 1 + 0xfc, // IRQL 2 + 0xf8, // IRQL 3 + 0xf0, // IRQL 4 + 0xe0, // IRQL 5 + 0xc0, // IRQL 6 + 0x80, // IRQL 7 + 0x00}; // IRQL 8 + +#if defined(NT_40) +// +// SYNCH Level must enable IPI on R98B. +// Sync level enable IPI on R98A . +// But on R98B, Sync level disable IPI. +// So, on R98B, we need to change Irql mask table. +// v-masank@microsoft.com 5/10/96 +// +// And mask Internal Timer. +// Because Internal Timer does not use for Profile Interrupt. +// v-masank@microsoft.com 5/14/96 +// For R98B INT4 handler. +// v-masank@microsoft.com 5/21/96 +// +UCHAR HalpIrqlMaskForR98b[] = {4, 5, 7, 7, 7, 7, 7, 7, // 0000 - 0111 high 4-bits + 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits + 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits + 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits + + +// On the R98B ip[7] is the internal clock. The internal clock +// is not used for profile interrupt. On the R98B ip[4] used +// for Profile Interrupt AND clock interrupt. The ip[4] has +// two external clock interrupts. + +UCHAR HalpIrqlTableForR98b[] = {0x7f, // IRQL 0 + 0x7e, // IRQL 1 + 0x7c, // IRQL 2 + 0x78, // IRQL 3 + 0x70, // IRQL 4 + 0x60, // IRQL 5 + 0x60, // IRQL 6 + 0x00, // IRQL 7 + 0x00}; // IRQL 8 +VOID +HalpT5Int4Dispatch( + VOID + ); +#endif + +BOOLEAN +HalpInitializeInterrupts ( + VOID + ) + +/*++ + +Routine Description: + + This function initializes interrupts for a Jazz or Duo MIPS system. + + N.B. This function is only called during phase 0 initialization. + +Arguments: + + None. + +Return Value: + + A value of TRUE is returned if the initialization is successfully + completed. Otherwise a value of FALSE is returned. + +--*/ + +{ + + ULONG Value[2]; + + PULONG Vp; + PKPRCB Prcb; + ULONG fcpu; + ULONG IntNo; + ULONG Index; + ULONG TmpValue; + ULONG Ponce; + ULONG DataLong; + ULONG BitCount; + ULONG repeatCounter; + ULONG MagBuffer; + + // + // Get the address of the processor control block for the current + // processor. + // + + Prcb = PCR->Prcb; + + // + // Initialize the IRQL translation tables in the PCR. These tables are + // used by the interrupt dispatcher to determine the new IRQL and the + // mask value that is to be loaded into the PSR. They are also used by + // the routines that raise and lower IRQL to load a new mask value into + // the PSR. + // + +#if defined(NT_40) + // + // SYNCH Level must enable IPI on R98B. + // Sync level enable IPI on R98A . + // But on R98B, Sync level disable IPI. + // So, On R98B, we need to change Irql mask table. + // v-masank@microsoft.com 5/10/96 + // + if( HalpMachineCpu == R98_CPU_R10000 ){ + for (Index = 0; Index < sizeof(HalpIrqlMaskForR98b); Index += 1) { + PCR->IrqlMask[Index] = HalpIrqlMaskForR98b[Index]; + } + for (Index = 0; Index < sizeof(HalpIrqlTableForR98b); Index += 1) { + PCR->IrqlTable[Index] = HalpIrqlTableForR98b[Index]; + } + }else{ + for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) { + PCR->IrqlMask[Index] = HalpIrqlMask[Index]; + } + for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) { + + PCR->IrqlTable[Index] = HalpIrqlTable[Index]; + } + } +#else + for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) { + PCR->IrqlMask[Index] = HalpIrqlMask[Index]; + } + for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) { + + PCR->IrqlTable[Index] = HalpIrqlTable[Index]; + } +#endif + + + // + // All interrupt disables. + // + Value[0] = (ULONG)0xFFFFFFFF; + Value[1] = (ULONG)0xFFFFFFFF; + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + WRITE_REGISTER_ULONG( Vp++, Value[0]); + WRITE_REGISTER_ULONG( Vp, Value[1]); + + if( HalpMachineCpu == R98_CPU_R10000 ){ + + // + // Disable illegal memory access error on Columbus. + // + TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK) | 0x94400000; + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK, TmpValue); + + TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK2) | 0x00000540; + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK2, TmpValue); + + TmpValue = READ_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIM2) | 0x00000540; + WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->NMIM2, TmpValue); + + if( Prcb->Number == 0 ){ + // + // Disable illegal memory access error on Magellan. + // + + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ + + TmpValue = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRM) | 0x000000c0; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRM, TmpValue ); + + } + + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ + + TmpValue = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRM) | 0x000000c0; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRM, TmpValue ); + + } + + // + // Disable illegal memory access error on Ponce. + // + + TmpValue = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRM ) | 0x90400000; + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->ERRM, TmpValue ); + + TmpValue = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->ERRM ) | 0x90400000; + WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->ERRM, TmpValue ); + } + } + + // + // If processor 0 is being initialized, then set all device + // interrupt disables. + // + + if (Prcb->Number == 0) { + + for (Ponce = 0;Ponce <HalpNumberOfPonce;Ponce++){ + repeatCounter = 0; + while( + ((DataLong = READ_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG) & 0x07ff07ff) != 0) && + (++repeatCounter < 60) + ) { + + for( BitCount = 0 ; BitCount <=10 ; BitCount++ ) { + if( (DataLong & ( 1 << BitCount )) != 0) { + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG,0x1 << (BitCount)); + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTRG,0x1 << (BitCount+21)); + } + } + } + + // + // Disable I/O TLB error. + // + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->ERITTG[1], 0x0 ); + WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->ERRST, PONCE_XERR_TUAER | PONCE_XERR_TIVER ); + } + } + + PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch; + PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; + PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch; + PCR->InterruptRoutine[INT3_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt3Dispatch; + + // + // On NT4.0 , INT4 handler is different between R98A and R98B. + // v-masank@microsoft.com 5/21/96 + // + PCR->InterruptRoutine[INT4_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt4Dispatch; + + + if( HalpMachineCpu == R98_CPU_R4400){ + // + // R4400 System (R98A) + // + PCR->InterruptRoutine[INT5_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt5Dispatch; + + }else{ + // + // R10000 System (R98B) + // +#if defined(NT_40) + PCR->InterruptRoutine[INT4_LEVEL] = (PKINTERRUPT_ROUTINE) HalpT5Int4Dispatch; +#endif + PCR->InterruptRoutine[INT5_LEVEL] = (PKINTERRUPT_ROUTINE) HalpT5Int5Dispatch; + + } + + // + // If processor 0 is being initialized, then connect the interval timer + // interrupt to the stall interrupt routine so the stall execution count + // can be computed during phase 1 initialization. Otherwise, connect the + // interval timer interrupt to the appropriate interrupt service routine + // and set stall execution count from the computation made on processor + // 0. + // + + if (Prcb->Number == 0) { + + PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt; + + } else { + + PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1; + + PCR->StallScaleFactor = HalpStallScaleFactor; + } + + // + // Initialize the interval timer to interrupt at the specified interval. + // + + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMSR1, CLOCK_INTERVAL-1); + + // + // Initialize the profile timer to interrupt at the default interval. + // + + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMSR2, + DEFAULT_PROFILETIMER_COUNT); + // + // Enable the interval timer interrupt on the current processor. + // + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, CLOCK_VECTOR - DEVICE_VECTORS); + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR1, TIMER_RELOAD_START); + + // + // If processor 0 is being initialized, then connect the count/compare + // interrupt to the count interrupt routine to handle early count/compare + // interrupts during phase 1 initialization. Otherwise, connect the + // count\comapre interrupt to the appropriate interrupt service routine. + // + + if (Prcb->Number != 0) { + PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt; + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->MKRR, PROFILE_VECTOR - DEVICE_VECTORS); + WRITE_REGISTER_ULONG( (PULONG) &(COLUMNBS_LCNTL)->TMCR2,TIMER_RELOAD_START); + } + + // + // ECC 1Bit Error Vector Set + // + + if (Prcb->Number == 0) { + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ + MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ); + MagBuffer |= ECC_ERROR_DISABLE; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, MagBuffer ); + } + if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ + MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ); + MagBuffer |= ECC_ERROR_DISABLE; + WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, MagBuffer ); + } + } + PCR->InterruptRoutine[ECC_1BIT_VECTOR] = HalpEcc1bitError; + + // + // Connect the interprocessor interrupt service routine and enable + // interprocessor interrupts. + // + for(fcpu = 0;fcpu < R98B_MAX_CPU;fcpu++) + PCR->InterruptRoutine[IPI_VECTOR3+fcpu] = HalpIpiInterrupt; + + + // + // Enable Interrupt at Columnbs + // N.B + // At This Interrupt Mask is not perfact. Because Number Of CPU is unknown. + // So fix at HalAllProcessorsStarted () + // + Value[0] = (ULONG)0xFFFFFFFF; + Value[1] = (ULONG)0xFFFFFFFF; + + // + // Build Mask + // + for(IntNo=0 ; IntNo< 6 ;IntNo++){ + Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][IntNo].Enable); +#if DBG + DbgPrint("Init Interrupt CPU= %x: INT 0x%x Low =0x%x High = 0x%X\n", + PCR->Number,IntNo, Vp[0], Vp[1]); +#endif + Value[0] &= ~Vp[0]; + Value[1] &= ~Vp[1]; + } +#if DBG + DbgPrint("Init Interrupt CPU= %x :MKR Low =0x%x High = 0x%X\n", + PCR->Number,Value[0], Value[1]); +#endif + Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; + WRITE_REGISTER_ULONG(Vp++,Value[0]); + WRITE_REGISTER_ULONG(Vp, Value[1]); + + // + // Reserve the local device interrupt vector for exclusive use by the HAL. + // + PCR->ReservedVectors |= ((1 << INT0_LEVEL) |(1 << INT1_LEVEL)|(1 << INT2_LEVEL)| + (1 << INT4_LEVEL)); + + if( HalpMachineCpu == R98_CPU_R4400){ + PCR->ReservedVectors = (0x1 <<INT5_LEVEL); + } + + return TRUE; +} |