From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halr98mp/mips/allstart.c | 200 ++ private/ntos/nthals/halr98mp/mips/cacherr.s | 196 ++ private/ntos/nthals/halr98mp/mips/cirrus.h | 298 ++ private/ntos/nthals/halr98mp/mips/cmdcnst.h | 105 + private/ntos/nthals/halr98mp/mips/esmnvram.h | 687 ++++ private/ntos/nthals/halr98mp/mips/halp.h | 708 ++++ private/ntos/nthals/halr98mp/mips/j4cache.s | 1056 ++++++ private/ntos/nthals/halr98mp/mips/j4flshbf.s | 58 + private/ntos/nthals/halr98mp/mips/j4flshio.c | 238 ++ private/ntos/nthals/halr98mp/mips/j4prof.c | 362 ++ private/ntos/nthals/halr98mp/mips/jazznvr.h | 164 + private/ntos/nthals/halr98mp/mips/jxbeep.c | 131 + private/ntos/nthals/halr98mp/mips/jxdisp.c | 3132 +++++++++++++++++ private/ntos/nthals/halr98mp/mips/jxebsup.c | 1275 +++++++ private/ntos/nthals/halr98mp/mips/jxenvirv.c | 818 +++++ private/ntos/nthals/halr98mp/mips/jxhalp.h | 99 + private/ntos/nthals/halr98mp/mips/jxmapio.c | 153 + private/ntos/nthals/halr98mp/mips/jxmaptb.c | 84 + private/ntos/nthals/halr98mp/mips/jxport.c | 897 +++++ private/ntos/nthals/halr98mp/mips/jxreturn.c | 189 + private/ntos/nthals/halr98mp/mips/jxsysint.c | 454 +++ private/ntos/nthals/halr98mp/mips/jxtime.c | 313 ++ private/ntos/nthals/halr98mp/mips/jxusage.c | 497 +++ private/ntos/nthals/halr98mp/mips/mipsdat.c | 144 + private/ntos/nthals/halr98mp/mips/mode542x.h | 1302 +++++++ private/ntos/nthals/halr98mp/mips/modeset.h | 86 + private/ntos/nthals/halr98mp/mips/pcibrd.c | 1020 ++++++ private/ntos/nthals/halr98mp/mips/pcip.h | 214 ++ private/ntos/nthals/halr98mp/mips/r98busdt.c | 1181 +++++++ private/ntos/nthals/halr98mp/mips/r98busdt.h | 142 + private/ntos/nthals/halr98mp/mips/r98clock.s | 471 +++ private/ntos/nthals/halr98mp/mips/r98def.h | 471 +++ private/ntos/nthals/halr98mp/mips/r98dspt.c | 704 ++++ private/ntos/nthals/halr98mp/mips/r98eif.c | 801 +++++ private/ntos/nthals/halr98mp/mips/r98esm.c | 1026 ++++++ private/ntos/nthals/halr98mp/mips/r98hal.h | 132 + private/ntos/nthals/halr98mp/mips/r98hwsup.c | 4771 ++++++++++++++++++++++++++ private/ntos/nthals/halr98mp/mips/r98info.c | 99 + private/ntos/nthals/halr98mp/mips/r98int.s | 522 +++ private/ntos/nthals/halr98mp/mips/r98ipint.s | 176 + private/ntos/nthals/halr98mp/mips/r98led.c | 252 ++ private/ntos/nthals/halr98mp/mips/r98pci.c | 289 ++ private/ntos/nthals/halr98mp/mips/r98pcibs.c | 3180 +++++++++++++++++ private/ntos/nthals/halr98mp/mips/r98pcint.c | 384 +++ private/ntos/nthals/halr98mp/mips/r98reg.h | 475 +++ private/ntos/nthals/halr98mp/mips/tga.h | 101 + private/ntos/nthals/halr98mp/mips/x86bios.c | 2 + private/ntos/nthals/halr98mp/mips/xxcalstl.c | 290 ++ private/ntos/nthals/halr98mp/mips/xxclock.c | 131 + private/ntos/nthals/halr98mp/mips/xxidle.s | 76 + private/ntos/nthals/halr98mp/mips/xxinithl.c | 660 ++++ private/ntos/nthals/halr98mp/mips/xxinitnt.c | 556 +++ private/ntos/nthals/halr98mp/mips/xxmemory.c | 184 + 53 files changed, 31956 insertions(+) create mode 100644 private/ntos/nthals/halr98mp/mips/allstart.c create mode 100644 private/ntos/nthals/halr98mp/mips/cacherr.s create mode 100644 private/ntos/nthals/halr98mp/mips/cirrus.h create mode 100644 private/ntos/nthals/halr98mp/mips/cmdcnst.h create mode 100644 private/ntos/nthals/halr98mp/mips/esmnvram.h create mode 100644 private/ntos/nthals/halr98mp/mips/halp.h create mode 100644 private/ntos/nthals/halr98mp/mips/j4cache.s create mode 100644 private/ntos/nthals/halr98mp/mips/j4flshbf.s create mode 100644 private/ntos/nthals/halr98mp/mips/j4flshio.c create mode 100644 private/ntos/nthals/halr98mp/mips/j4prof.c create mode 100644 private/ntos/nthals/halr98mp/mips/jazznvr.h create mode 100644 private/ntos/nthals/halr98mp/mips/jxbeep.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxdisp.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxebsup.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxenvirv.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxhalp.h create mode 100644 private/ntos/nthals/halr98mp/mips/jxmapio.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxmaptb.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxport.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxreturn.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxsysint.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxtime.c create mode 100644 private/ntos/nthals/halr98mp/mips/jxusage.c create mode 100644 private/ntos/nthals/halr98mp/mips/mipsdat.c create mode 100644 private/ntos/nthals/halr98mp/mips/mode542x.h create mode 100644 private/ntos/nthals/halr98mp/mips/modeset.h create mode 100644 private/ntos/nthals/halr98mp/mips/pcibrd.c create mode 100644 private/ntos/nthals/halr98mp/mips/pcip.h create mode 100644 private/ntos/nthals/halr98mp/mips/r98busdt.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98busdt.h create mode 100644 private/ntos/nthals/halr98mp/mips/r98clock.s create mode 100644 private/ntos/nthals/halr98mp/mips/r98def.h create mode 100644 private/ntos/nthals/halr98mp/mips/r98dspt.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98eif.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98esm.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98hal.h create mode 100644 private/ntos/nthals/halr98mp/mips/r98hwsup.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98info.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98int.s create mode 100644 private/ntos/nthals/halr98mp/mips/r98ipint.s create mode 100644 private/ntos/nthals/halr98mp/mips/r98led.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98pci.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98pcibs.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98pcint.c create mode 100644 private/ntos/nthals/halr98mp/mips/r98reg.h create mode 100644 private/ntos/nthals/halr98mp/mips/tga.h create mode 100644 private/ntos/nthals/halr98mp/mips/x86bios.c create mode 100644 private/ntos/nthals/halr98mp/mips/xxcalstl.c create mode 100644 private/ntos/nthals/halr98mp/mips/xxclock.c create mode 100644 private/ntos/nthals/halr98mp/mips/xxidle.s create mode 100644 private/ntos/nthals/halr98mp/mips/xxinithl.c create mode 100644 private/ntos/nthals/halr98mp/mips/xxinitnt.c create mode 100644 private/ntos/nthals/halr98mp/mips/xxmemory.c (limited to 'private/ntos/nthals/halr98mp/mips') diff --git a/private/ntos/nthals/halr98mp/mips/allstart.c b/private/ntos/nthals/halr98mp/mips/allstart.c new file mode 100644 index 000000000..480e6933f --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/allstart.c @@ -0,0 +1,200 @@ +#pragma comment(exestr, "@(#) allstart.c 1.6 94/12/07 23:10:52 nec") +/*++ + +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. + +--*/ + +/* + * Original source: Build Number 1.807 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 '94.10/14 T.Samezima + * Add HalpConnectInt1Interrupt() + * valiable HalpInt1Affinity. + * Call HalpConnectInt1Interrupt() + * Del Call HalpCreateEisaStructures() + * + * S002 '94.10/18 T.Samezima + * Chg Enable interrupt on MKR register only exist device, + * + * S003 '94.10/22 T.Samezima + * Chg Issue restart timer interrupt on CPU#0 to all CPU + * + * S004 '94.12/07 T.Samezima + * Del warning + * + */ + + +#include "halp.h" + +// S001 vvv +// +// Define INT1 interrupt affinity. +// + +KAFFINITY HalpInt1Affinity; + +BOOLEAN // S004 +HalpConnectInt1Interrupt( + VOID + ); +// S001 ^^^ + + +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. + +--*/ + +{ + // S001, S003 vvv + // Restart all timer interrupt. because, generate interrupt for same time + // + + if (PCR->Number == 0) { + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TCIR.Long, + TCIR_ALL_CLOCK_RESTART); // S007 + } + // S001, S003 ^^^ + + // + // If the number of processors in the host configuration is one, + // then connect EISA interrupts to that processor zero. Otherwise, + // connect EISA interrupts to processor one. + // + + if (**((PULONG *)(&KeNumberProcessors)) == 1) { + return HalpConnectInt1Interrupt(); // S001 + + } else if (PCR->Number == 1) { + return HalpConnectInt1Interrupt(); // S001 + + } else { + return TRUE; + } +} + +// S001 vvv +ULONG AII1Mask; +ULONG AII2Mask; + +BOOLEAN // S004 +HalpConnectInt1Interrupt( + VOID + ) + +/*++ + +Routine Description: + + This function connect int1 interrupt on execution processor. + +Arguments: + + None. + +Return Value: + + return TRUE. + +--*/ + +{ + + ULONG number; + ULONG pmcRegisterAddr; + ULONG pmcRegisterUpperPart; + ULONG pmcRegisterLowerPart; + + // + // Get CPU number. + // + + number = PCR->Number; + + // + // Set route for notice of interrupt + // + + AII1Mask = AII_INIT_DATA >> number; + AII2Mask = ( ((AII_INIT_DATA >> number) & 0xffff0000) + | (AII_INIT_DATA & 0x0000ffff) ); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long, + AII1Mask ); + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long, + AII2Mask ); + + // + // Enable INT1 interrupt on PMC + // + + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); + HalpReadLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT1_DEVICE_ENABLE_LOW ); // S002 + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + PCR->ReservedVectors |= (1 << INT1_LEVEL); + + // + // Set Int1 interrupt affinity. + // + + HalpInt1Affinity = PCR->SetMember; + + // + // Initialize the interrupt dispatcher for I/O interrupts. + // + + PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; + + // + // Initialize EISA bus interrupts. + // + + HalpCreateEisaStructures(); + + // + // Initialize PCI bus interrupts. + // + + return HalpCreatePciStructures (); +} +// S001 ^^^ diff --git a/private/ntos/nthals/halr98mp/mips/cacherr.s b/private/ntos/nthals/halr98mp/mips/cacherr.s new file mode 100644 index 000000000..95f59c0cd --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/cacherr.s @@ -0,0 +1,196 @@ +// "@(#) 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" + +// +// 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 + 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) // + +// +// Get the current processor state and cache error register, and check +// if the error can be corrected. +// + + mfc0 v0,psr // get current processor state + mfc0 v1,cacheerr // get cache error state + .set at + .set reorder + +// +// ****** temp ****** +// +// The following code is temporary and will be removed when full cache +// error support is included. +// +// ****** temp ****** +// + + b SoftReset // ****** all error soft rest + +// +// If the EXL bit is set in the processor state, then the error is not +// recoverable because the EXL bit may be erroneously set (errata) and +// it cannot be determined whether is should or should not be set, e.g., +// the exact addresses ranges over which EXL might be correctly set are +// not verifiable. Also, k0 and k1 are destroyed before they are saved +// and are used by the exception handling code (there is no way to save +// a register in noncached memory wihtout the use of a register). +// + + sll a0,v0,31 - PSR_EXL // shift EXL bit in sign + bltz a0,SoftReset // if ltz, error not correctable + +// +// If the error occured on the SysAd bus, then the error is not correctable. +// + + sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign + bltz a0,SoftReset // if ltz, error not correctable + +// +// Determine whether the error is in the instruction or data cache. +// + + sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign + bgez a0,IcacheError // if gez, instruction cache error + +// +// The error occured in the data cache. +// +// If the error is a data error in the primary cache, then the error +// is not correctable since the cache line dirty bit is included in +// the parity calculation and therefore may be wrong. +// + +DcacheError: // + sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign + bgez a0,SoftReset // if gez, error in primary cache + b ExitError // exit error + +// +// The error occured in the instruction cache. +// +// If the error occured in the secondary data cache, then the error is not +// correctable since there is not secondary instruciton cache. +// + +IcacheError: // + sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign + bltz a0,SoftReset // if ltz, error in secondary cache + +// +// The cache error has been corrected - restore register state and continue +// execution. +// + +ExitError: // + + .set noreorder + .set noat + la k0,SavedAt // get address of register save area + li k1,KSEG1_BASE // convert address of KSEG1 address + or k0,k0,k1 // + lw AT,0(k0) // restore registers AT - a3 + lw v0,4(k0) // + lw v1,8(k0) // + lw a0,12(k0) // + lw a1,16(k0) // + lw a2,20(k0) // + eret // + .set at + .set reorder + +// +// Cache error cannot be corrected - transfer control to soft reset vector. +// + +SoftReset: // + la k0,SOFT_RESET_VECTOR // get address of soft reset vector + j k0 // perform a soft reset + + .end HalpCacheErrorRoutine diff --git a/private/ntos/nthals/halr98mp/mips/cirrus.h b/private/ntos/nthals/halr98mp/mips/cirrus.h new file mode 100644 index 000000000..9f9846aaf --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/cmdcnst.h b/private/ntos/nthals/halr98mp/mips/cmdcnst.h new file mode 100644 index 000000000..ea2bba221 --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/esmnvram.h b/private/ntos/nthals/halr98mp/mips/esmnvram.h new file mode 100644 index 000000000..313bec380 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/esmnvram.h @@ -0,0 +1,687 @@ +#ident "@(#) NEC esmnvram.h 1.1 95/02/20 16:50:43" +/**************************************************************** + ******* Copyright (C) 1994 NEC Corporation ******* + ****************************************************************/ + +/******* + + File Name: + + envram.h + + Abstract: + + This module contains the definitions for the extended NVRAM. + + Author: + + Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994 + + Modification History: + + - M000 12/22/94 - + created. + +*******/ + + + +/******************************************************************************* + ******** NVRAM(8Kバイト)の論理フォーマットを以下に記述する。 ******** + ******************************************************************************* + * + * S001 11/22/94 + * レコードの有効/無効フラグ、Check未/済フラグを各レコードの先頭におくか + * まとめてレコードリージョンの先頭におくかで、レコードの処理方法が変わって + * くる。後者はランダムアクセス、前者はシーケンシャルアクセスにむく。 + * 今回は前者を採用。 + * + * 行の先頭にある数字は割り当てるバイト数をあらわす。 + * + * 本仕様にしたがって構造体を作成予定。 + * + * S002 11/26/94 + * 各領域(ECC関連、パニック情報関連、クリティカルエラーログ関連、etc.) + * の先頭のヘッダ部を全てNVRAMの先頭に移す。NVRAMの先頭にあるヘッダ内に + * 各領域のレコードを直接アクセスするためのオフセットをもつようにする。 + * + * NVRAMのアクセス時には256バイト単位でバンク切り換えがおこなわれるため + * 各データ(256バイト長以下のもの)が256バイトバウンダリをまたがらないよう + * に配慮。各領域(ECC関連、パニック情報関連、etc.)の先頭が必ず256バイト + * バウンダリから開始されるようにする。 + * + * ECCエラーログ内のSIMM特定化情報を2バイトから1バイトへ変更。 + * + * ”オフセット ”はすべてNVRAMの先頭からのオフセット。 + * + * S003 12/13/94 + * NWエージェントとメモリエラーエリアを共通化するため先頭512バイトを + * メモリエラーエリアとし、フォーマットをNWエージェントと統一する。 + * + * STEP1ではメモリ縮退を行わないため本エリアは使用しない。 + * 本メモリエラーエリアはNWエージェントとの共通化のために新たに設ける + * ものであり、以前からのECCエラー情報領域はそのまま残る。 + * + * 512バイトのエリアを先頭に設けるため、以前からのその他全ての情報領域は + * 512バイトオフセットが大きくなることになる。 + * + * システム情報エリアへのオフセット2バイトを追加。 + * + * オフセットの再計算。 + * + * S004 12/14/94 + * 構造体作成。 + * + * ’パニック ’を’ストップエラー ’に変更。 + * + * S005 12/23/94 + * 4byte alignmentにそなえてパディングを一部変更。 + * + * ストップエラーのフラグの2ビットに新たに定義追加。 + * + * システム情報エリアをNVRAMヘッダにとりこむ。 + * これにともないシステム情報エリアへのオフセットは不要となるため + * 2バイト分未使用とする。 + * + * システム情報エリアにマジックナンバーを追加。論理フォーマットの有無を + * マジックナンバーとフラグでチェックするようにする。マジックナンバーは + * 0xFF651026とする。 + * + * ’ストップエラー ’を’システムエラー ’に変更。 + * + * S006 12/27/94 + * #pragma pack() を追加 + * + * char reserved[49] を char reserved[49] に修正。本変更はharmlessである + * と信じる... (^_^; + * + * unsigned short offset_ecc2err を offset_2biterrに修正。本変更は + * harmlessであると信じる... (^_^; + * + ****************************************************************************** + + + ################### + # NVRAMヘッダ部 # + ################### + + ###################################################### + # F/W用メモリーエラーエリア (NWエージェントと共通) # + ###################################################### + + 512 メモリエラー情報レコード(2バイト) × 256 + + #################### + # レコードの内容 # + #################### + +   1 ステータス 0:正常 1:異常(2bitエラー有無) + 1 1bitエラーカウント + +   ###################### + # 全体に関するもの # + ###################### + + 1 NVRAMの状態をあらわすフラグ + + ################## + # フラグの内容 # + ################## + +   0 NVRAM全体有効/無効 0:無効 1:有効 +  1 論理フォーマットの有無 0:無 1:有 +   2 READ-ONLY 0:NO 1:YES +   3 LOCK 0:NO 1:YES +   4 [reserved] +   5   ↑ +   6   ↑ +   7   ↑ + 14 NVRAMがフォーマットされたタイムスタンプ + + 3 [ reserved ] + +   ############################### + # ALIVE情報領域に関するもの # + ############################### + + 2 ALIVE情報領域へのオフセット + +   ####################################### + # ECC1bitエラー情報領域に関するもの # + ####################################### + + 2 ECC 1bitエラーログ部の先頭へのオフセット +   2 ECC 1bitエラーログ1レコードサイズ + 2 ECC 1bitエラーログレコード数 + 2 ECC 1bitエラーログを一番最後に登録したレコードへのオフセット + 4 一番最後のECC1bitエラー時のリードデータ +   8 ECC 1bitエラーカウント × メモリグループ数8 + +   ####################################### + # ECC2bitエラー情報領域に関するもの # + ####################################### + + 2 ECC 2bitエラーログ部の先頭へのオフセット +   2 ECC 2bitエラーログ1レコードサイズ + 2 ECC 2bitエラーログレコード数 + 2 ECC 2bitエラーログを一番最後に登録したレコードへのオフセット + 4 一番最後のECC複数bitエラー時のリードデータ + 4 SIMM交換フラグ × メモリグループ数4 + + ################## + # フラグの内容 # + ################## + +   0 グループN内SIMM #0 (N=1〜4) 0:OK 1:NG(要交換) +   1 グループN内SIMM #1 ↑ +   2 グループN内SIMM #2   ↑ +   3 グループN内SIMM #3   ↑ +   4 [reserved] +   5 ↑ +   6 ↑ +   7   ↑ + 4 [reserved] + +   ######################################## +   # システムエラー情報領域に関するもの # +   ######################################## + + 2 システムエラー情報部の先頭へのオフセット +   2 システムエラー情報1レコードサイズ + 2 システムエラー情報レコード数 + 2 システムエラー情報を一番最後に登録したレコードへのオフセット + +   ############################################ +   # クリティカルエラーログ領域に関するもの # + ############################################ + + 2 クリティカルエラーログ部の先頭へのオフセット +   2 クリティカルエラーログ1レコードサイズ + 2 クリティカルエラーログレコード数 + 2 クリティカルエラーログを一番最後に登録したレコードへのオフセット + +   ################################## +   # しきい値情報領域に関するもの # + ################################## + + 2 しきい値情報部の先頭へのオフセット + +   ############################## +   # リザーブ領域に関するもの # + ############################## + + 2 リザーブ領域の先頭へのオフセット + + + ######################## + # システム情報エリア # + ######################## + +     1 システムの状態をあらわすフラグ + + ################## + # フラグの内容 # + ################## + + 0 [reserved] +   1   ↑ +   2   ↑ +   3   ↑ +   4   ↑ +   5   ↑ +   6   ↑ +   7   ↑ + 3 [reserved] + 32 システムの情報(システム名) + 4 マシンシリアルナンバー + 4 マジックナンバー + 4 [reserved] + +----------------------------------------------------------------------------- +TOTAL 640 バイト + + + ####################################### + # ALIVE, ページャーコール情報エリア # + ####################################### + + 1 現在の通報レベル + 16 ALIVE一次通報先 + 16 ALIVE二次通報先 + 47 [reserved for pager call] + +----------------------------------------------------------------------------- +TOTAL 80 バイト + + + ############################################################################## + # ↑ここまで720バイト。次の領域の先頭が256バイトバウンダリから始まるように # + # 48バイトを[reserved]としてパディングする。 # + ############################################################################## + + 48 [reserved] + + + ####################### + # メモリエラーログ部 # + ####################### + + 400 1bitエラー情報レコード(25バイト) × 16 + + #################### + # レコードの内容 # + #################### + + 1  フラグ + +    ################## + # フラグの内容 # + ################## + +   0 有効/無効 0:無効 1:有効 +   1 check済/未 0:未 1:済 +   2 [reserved] +   3   ↑ +   4   ↑ +   5   ↑ +   6   ↑ +   7    ↑ +   4 エラーアドレス + 14 発生タイムスタンプ + 4 シンドローム +   1 メモリグループ + 1 SIMM特定情報 + 100 2bitエラー情報レコード(25バイト) × 4 + + #################### + # レコードの内容 # + #################### + + 1 フラグ + + ################## + # フラグの内容 # + ################## + +   0 有効/無効 0:無効 1:有効 +   1 check済/未 0:未 1:済 +   2 [reserved] +   3   ↑ +   4   ↑ +   5    ↑ +   6   ↑ +   7   ↑ +   4 エラーアドレス + 14 発生タイムスタンプ + 4 シンドローム +   1 メモリグループ + 1 SIMM特定情報 + +----------------------------------------------------------------------------- +TOTAL 500 バイト + + + ############################################################################### + # ↑ここまで1268バイト。次の領域の先頭が256バイトバウンダリから始まるように # + # 12バイトを[reserved]としてパディングする。 # + ############################################################################### + + 12 [reserved] + + + ########################## + # システムエラー情報部 # + ########################## + + 2048 システムエラー情報部 (1レコード512バイト × 4 = 2K) + + #################### + # レコードの内容 # + #################### + + 1 フラグ + + ################## + # フラグの内容 # + ################## + +   0 有効/無効 0:無効 1:有効 +   1 check済/未 0:未 1:済 +   2 Dump/Dump SW 0:D 1:D SW +   3 通報の有無 0:未 1:済 +   4 boot結果 0:正常 1:異常 +   5   ↑ +   6   ↑ +   7   ↑ + 14 発生タイムスタンプ + 496 システムエラー情報 + 1 [reserved] + +----------------------------------------------------------------------------- +TOTAL 2048 バイト + + + ####################################################### + # ↑ここまで3328バイト。ちょうど256バイトバウンダリ # + ####################################################### + + + ############################################################### + # クリティカルエラーログ部 (1レコード128バイト × 32 = 4K) # + ############################################################### + + 4096 クリティカルエラーログ部 (1レコード128バイト × 32 = 4K) + + #################### + # レコードの内容 # + #################### + + 1 フラグ + ################## + # フラグの内容 # + ################## + +   0 有効/無効 0:無効 1:有効 +   1 check済/未 0:未 1:済 +   2 Panic/Shutdown 0:P 1:S +   3 [reserved] +   4   ↑ +   5   ↑ +   6   ↑ +   7   ↑ + 14 発生タイムスタンプ + 20 ソース名 + 80 クリティカルエラー情報 + 13 [reserved] + +----------------------------------------------------------------------------- +TOTAL 4096 バイト + + + ####################################################### + # ↑ここまで7424バイト。ちょうど256バイトバウンダリ # + ####################################################### + + + ############################## + # しきい値判定用データ領域 # + ############################## + +   256 [reserved] + +----------------------------------------------------------------------------- +TOTAL 256 バイト + + + ############################################################### + # ↑ここまで7680(7K+512)バイト。ちょうど256バイトバウンダリ # + ############################################################### + + + ############################## + # リザーブ領域 (512バイト) # + ############################## + + 512 PAiNTS用? + +----------------------------------------------------------------------------- +TOTAL 512 バイト + + + ############################################# + # ↑ここまで8192(8K)バイト。NVRAMのしっぽ # + ############################################# + +******************************************************************************/ + + +#pragma pack(1) + +/******************** + * * + *  構造体定義 * + * * + ********************/ + + +/* + * WAS & PS共通FW用メモリエラー情報領域 + */ +typedef struct _MEM_ERR_REC { + unsigned char mem_status; /* ステータス */ + unsigned char err_count; /* 1bitエラーカウント */ +} MEM_ERR_REC, *pMEM_ERR_REC; + + +/* + * ALIVE情報領域に関するもの + */ +typedef struct _ALIVE_AREA_INFO { + unsigned short offset_alive; + /* ALIVE情報エリアオフセット */ +} ALIVE_AREA_INFO, *pALIVE_AREA_INFO; + + +/* + * ECC1bitエラー情報領域に関するもの + */ +typedef struct _ECC1_ERR_AREA_INFO { + unsigned short offset_1biterr; /* エリアの先頭へのオフセット */ + unsigned short size_rec; /* 1レコードサイズ */ + unsigned short num_rec; /* 総レコード数 */ + unsigned short offset_latest; /* 最新レコードオフセット */ + unsigned long read_data_latest; /* 最新リードエラーデータ */ + unsigned char err_count_group0; /* メモリG#0 エラーカウント */ + unsigned char err_count_group1; /* メモリG#1 エラーカウント */ + unsigned char err_count_group2; /* メモリG#2 エラーカウント */ + unsigned char err_count_group3; /* メモリG#3 エラーカウント */ + unsigned char err_count_group4; /* メモリG#4 エラーカウント */ + unsigned char err_count_group5; /* メモリG#5 エラーカウント */ + unsigned char err_count_group6; /* メモリG#6 エラーカウント */ + unsigned char err_count_group7; /* メモリG#7 エラーカウント */ +} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO; + + +/* + * ECC2bitエラー情報領域に関するもの + */ +typedef struct _ECC2_ERR_AREA_INFO { + unsigned short offset_2biterr; /* エリアの先頭へのオフセット */ + unsigned short size_rec; /* 1レコードサイズ */ + unsigned short num_rec; /* 総レコード数 */ + unsigned short offset_latest; /* 最新レコードオフセット */ + unsigned long read_data_latest; /* 最新リードエラーデータ */ + unsigned char simm_flag_group1; /* メモリG#1内SIMMフラグ */ + unsigned char simm_flag_group2; /* メモリG#2内SIMMフラグ */ + unsigned char simm_flag_group3; /* メモリG#3内SIMMフラグ */ + unsigned char simm_flag_group4; /* メモリG#4内SIMMフラグ */ + char reserved[4]; /* reserved */ +} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO; + + +/* + * システムエラー情報領域に関するもの + */ +typedef struct _SYSTEM_ERR_AREA_INFO { + unsigned short offset_systemerr;/* エリアの先頭へのオフセット */ + unsigned short size_rec; /* 1レコードサイズ */ + unsigned short num_rec; /* 総レコード数 */ + unsigned short offset_latest; /* 最新レコードオフセット */ +} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO; + + +/* + * クリティカルエラー情報領域に関するもの + */ +typedef struct _CRITICAL_ERR_AREA_INFO { + unsigned short offset_critical; /* エリアの先頭へのオフセット */ + unsigned short size_rec; /* 1レコードサイズ */ + unsigned short num_rec; /* 総レコード数 */ + unsigned short offset_latest; /* 最新レコードオフセット */ +} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO; + + +/* + * しきい値等その他の情報領域に関するもの + */ +typedef struct _MISC_AREA_INFO { + unsigned short offset_misc; + /* しきいち等の情報エリア先頭オフセット */ +} MISC_AREA_INFO, *pMISC_AREA_INFO; + + +/* + * リザーブ領域に関するもの + */ +typedef struct _RESERVE_AREA_INFO { + unsigned short offset_reserve; + /* リザーブエリア先頭オフセット */ +} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO; + + +/* + * システム情報エリア + * 49バイト + */ + +typedef struct _SYS_INFO { + unsigned char system_flag; /* システム状態フラグ */ + char reserved1[3]; /* 4byte alignmentにそなえて */ + char sys_description[32]; /* システムの情報 */ + unsigned long serical_num; /* マシンシリアルナンバー */ + unsigned long magic; /* マジックナンバー */ + char reserved2[4]; /* reserved */ +} SYS_INFO, *pSYS_INFO; + + + +/* + * NVRAMヘッダ部 + * 640バイト + */ + +typedef struct _NVRAM_HEADER { + MEM_ERR_REC mem_err_map[256]; /* メモリエラー情報NT&NW共通エリア */ + unsigned char nvram_flag; /* nvramの状態フラグ */ + char when_formatted[14]; /* フォーマットタイムスタンプ */ + char reserved[3]; /* 4byte alignment にそなえて */ + ALIVE_AREA_INFO alive; /* ALIVE情報エリア */ + ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bitエラー情報エリア */ + ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bitエラー情報エリア */ + SYSTEM_ERR_AREA_INFO system_err;/* システムエラー情報エリア */ + CRITICAL_ERR_AREA_INFO critical_err_log; + /* クリティカルエラーログエリア */ + MISC_AREA_INFO misc; /* しきいち情報エリア */ + RESERVE_AREA_INFO reserve; /* リザーブエリアオフセット */ + SYS_INFO system; /* システム情報 */ +} NVRAM_HEADER, *pNVRAM_HEADER; + + + +/* + * ALIVE, ページャーコール情報エリア + * 80バイト + */ + +typedef struct _ALIVE_INFO { + unsigned char alert_level; /* 通報レベルグ */ + char primary_destination[16]; /* 一次通報先電話番号 */ + char secondary_destinaiton[16]; /* 二次通報先電話番号 */ + char reserved[47]; /* reserved for pager call */ +} ALIVE_INFO, *pALIVE_INFO; + + +/* + * ↑ここまで720バイト。次の領域の先頭が256バイトバウンダリから始まるように + * 48バイトを[reserved]としてパディングする。 + */ + +char reserved[48]; + + +typedef struct _ECC1_ERR_REC { + unsigned char record_flag; /* レコードフラグ */ + unsigned long err_address; /* エラーアドレス */ + char when_happened[14]; /* 発生タイムスタンプ */ + unsigned long syndrome; /* シンドローム */ + unsigned char specified_group; /* メモリグループ */ + unsigned char specified_simm; /* SIMM特定情報 */ +} ECC1_ERR_REC, *pECC1_ERR_REC; + + +typedef struct _ECC2_ERR_REC { + unsigned char record_flag; /* レコードフラグ */ + unsigned long err_address; /* エラーアドレス */ + char when_happened[14]; /* 発生タイムスタンプ */ + unsigned long syndrome; /* シンドローム */ + unsigned char specified_group; /* メモリグループ */ + unsigned char specified_simm; /* SIMM特定情報 */ +} ECC2_ERR_REC, *pECC2_ERR_REC; + + +/* + * メモリエラーログ部 + * 500 バイト + */ + +ECC1_ERR_REC ecc1_err_rec_log[16]; + +ECC2_ERR_REC ecc2_err_rec_log[4]; + + +/* + * ↑ここまで1268バイト。次の領域の先頭が256バイトバウンダリから始まるように + * 12バイトを[reserved]としてパディングする。 + */ + +char reserved2[12]; + + +typedef struct _STOP_ERR_REC { + unsigned char record_flag; /* レコードフラグ */ + char when_happened[14]; /* 発生タイムスタンプ */ + char err_description[496]; /* システムエラー情報 */ + char reserved[1]; /* reserved */ +} STOP_ERR_REC, *pSTOP_ERR_REC; + +/* + * スットプエラー情報部 + * 2048 バイト + */ + +STOP_ERR_REC stop_err_rec_log[4]; + + +typedef struct _CRITICAL_ERR_REC { + unsigned char record_flag; /* レコードフラグ */ + char when_happened[14]; /* 発生タイムスタンプ */ + char source[14]; /* ソース名 */ + char err_description[496]; /* クリティカルエラー情報 */ + char reserved[13]; /* reserved */ +} CRITICAL_ERR_REC, *pCRITICAL; + + +/*   + * クリティカルエラーログ部 (1レコード128バイト × 32 = 4K) + * 4096バイト + */ + +CRITICAL_ERR_REC critical_err_rec_log[32]; + + +/* + * しきい値判定用等データ領域. + * 256バイト + */ + +char reserved3[256]; /* reserved */ + + +/* + * リザーブ領域(PAiNTS用?) + * 512バイト + */ + +char reserved4[512]; /* reserved for paints ? */ + +#pragma pack(4) diff --git a/private/ntos/nthals/halr98mp/mips/halp.h b/private/ntos/nthals/halr98mp/mips/halp.h new file mode 100644 index 000000000..f3d80fe71 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/halp.h @@ -0,0 +1,708 @@ +#ident "@(#) NEC halp.h 1.19 95/06/19 10:53:45" +/*++ BUILD Version: 0003 // Increment this if a change has global effects + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + halp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + interfaces. + +--*/ + +/* + * Original source: Build Number 1.531 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 3/25-5/30 T.Samezima + * + * add Spinlock HalpEifInterruptLock + * define function + * define external references + * + * change include file + * + * del '#if defined(_JAZZ_)' with content + * '#if defined(_DUO_)' with content + * + *********************************************************************** + * + * S002 6/10 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S003 7/7 T.Samezima + * + * Del Arbitration point variable name + * + * Add Function define + * + * + *********************************************************************** + * + * S004 8/22 T.Samezima on SNES + * + * Chg Register buffer size from USHORT to ULONG + * + *********************************************************************** + * + * S005 '94.9/27 T.Samezima + * + * Add Define debug Print + * + * K000 94/10/11 N.Kugimoto + * Fix 807 base + * K001 94/10/12 N.Kugimoto + * add halpNmihandler + * K002 94/10/13 N.Kugimoto + * add HalpEifRegisterBuffer + * K003 94/10/13 N.Kugimoto + * add HalpEisaMemoryBase + * chg extern + * + * S006 '94.10/14 T.Samezima + * Add extern valiable + * Chg Change condition of ifdef + * + * A001 ataka@oa2.kb.nec.co.jp + * add ADD001 Resource Usage Information + * + * S007 '94.10/23 T.Samezima + * chg variable size from ULONG to UCHAR + * + * K004 94/12/06 N.Kugimoto + * Add ESM NVRAM Interface Add + * + * S008 94/12/07 N.Kugimoto + * Add HalpDisablePciInterrupt,HalpEnablePciInterrupt + * + * S009 94/12/23 T.Samezima + * Add ESM function and variable. + * + * S00a 94/01/15 T.Samezima + * Add ESM function. + * + * S00b 94/01/16-20 T.Samezima + * Add ESM variable and ESM function. + * + * S00c 94/03/10 T.Samezima + * Add HalpNMIFlag + * + * S00d 94/03/10 T.Samezima + * Add HalpLRErrorInterrupt(), HalpReadAndWritePhysicalAddr() + * + * A002 95/06/13 ataka@oa2.kb.nec.co.jp + * Marge build 1050 + * + */ + + +#ifndef _HALP_ +#define _HALP_ +#if defined(NT_UP) +#undef NT_UP +#endif +#include "nthal.h" +#include "hal.h" // A002 + +#ifndef _HALI_ // A002 +#include "..\inc\hali.h" +#endif + +/* Start S001 */ +#include "r98def.h" +#include "r98reg.h" +#include "r98hal.h" // S002 +/* End S001 */ + + +#if defined(USE_BIOS_EMULATOR) // A002 +#include "xm86.h" +#include "x86new.h" +#endif + +/* Start S002 */ +// #include "jxhalp.h" + + +// A002 +// Define map register translation entry structure. +// +//typedef struct _TRANSLATION_ENTRY { +// PVOID VirtualAddress; +// ULONG PhysicalAddress; +// ULONG Index; +//} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY; + + +extern PVOID HalpEisaControlBase; +extern PVOID HalpRealTimeClockBase; +extern PVOID HalpEisaMemoryBase; //K003 +/* End S002 */ +// +// 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 + ); + +/* Start S002 */ +#if !defined(_R98_) +BOOLEAN +HalpDmaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); +#endif +/* End S002 */ + +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 + ); + +VOID //K000 +HalpInitializeX86DisplayAdapter( + VOID + ); + +VOID //K000 +HalpResetX86DisplayAdapter( + VOID + ); + + +/* Start S001 */ +/* Start S002 */ +VOID +HalpInt0Dispatch( + VOID + ); + +VOID +HalpInt1Dispatch( + VOID + ); + +VOID +HalpInt2Dispatch( + VOID + ); + +VOID +HalpTimerDispatch( + VOID + ); + +VOID +HalpEifDispatch( + VOID + ); +/* End S002 */ + +VOID +HalpOutputSegment( + IN ULONG Number, + IN UCHAR Data + ); + +VOID +HalpDisplaySegment( + IN ULONG Number, + IN UCHAR Data + ); +/* End S001 */ + +/* Start S002 */ +ULONG +HalpAllocPhysicalMemory( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG MaxPhysicalAddress, + IN ULONG NoPages, + IN BOOLEAN bAlignOn64k + ); + +BOOLEAN +HalpGrowMapBuffers( + PADAPTER_OBJECT AdapterObject, + ULONG Amount + ); + +VOID +HalpCopyBufferMap( + IN PMDL Mdl, + IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ); + +BOOLEAN +HalpEisaDispatch( + IN PKINTERRUPT Interrupt, + IN PVOID ServiceContext + ); + +BOOLEAN +HalpCreateEisaStructures ( + VOID + ); + +BOOLEAN +HalpCreatePciStructures ( + VOID + ); + +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 + ); + +// S008 vvv +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ); + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector + ); +// S008 ^^^ + +VOID +HalpReadLargeRegister( + IN ULONG VirtualAddress, + OUT PULONG UpperPart, + OUT PULONG LowerPart + ); + +VOID +HalpWriteLargeRegister( + IN ULONG VirtualAddress, + IN PULONG UpperPart, + IN PULONG LowerPart + ); + +VOID +HalpRegisterNmi( + VOID + ); + +VOID +HalpAllocateMapRegisters( + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +/* Start S003 */ +VOID +HalpHandleEif( + VOID + ); + +ULONG +HalpGetCause( + VOID + ); +/* End S003 */ + +//K001 +VOID +HalpNmiHandler( + VOID + ); + +//K004 Start + +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 +); + +//K004 End +//S009 vvv +ULONG +HalpEccError( + IN ULONG EifrRegister + ); + +VOID +HalpInitDisplayStringIntoNvram( + VOID + ); + +VOID +HalpSetInitDisplayTimeStamp( + VOID + ); + +VOID +HalpSuccessOsStartUp( + VOID + ); + +VOID +HalpChangePanicFlag( + IN ULONG NewPanicFlg, + IN UCHAR NewLogFlg, + IN UCHAR CurrentLogFlgMask + ); + +#if 0 // S00b +VOID +HalpStringIntoNvram( + IN ULONG Column, + IN ULONG Row, + IN PUCHAR String + ); +#endif // S00b +//S009 ^^^ + +// S00a vvv +ULONG +HalpReadPhysicalAddr( + IN ULONG PhysicalAddr + ); +// S00a ^^^ +// S00b vvv +VOID +HalStringIntoBuffer( + IN UCHAR Character + ); + +VOID +HalStringIntoBufferStart( + IN ULONG Column, + IN ULONG Row + ); + +VOID +HalpStringBufferCopyToNvram( + VOID + ); +// S00b ^^^ +// S00d vvv +ULONG +HalpReadAndWritePhysicalAddr( + IN ULONG PhysicalAddr + ); + +BOOLEAN +HalpLRErrorInterrupt( + VOID + ); +// S00d ^^^ + +/* Start S005 */ +#if DBG // S006 +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 +/* End S005 */ + +#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 +/* End S002 */ + +// +// Define external references. +// + +extern KSPIN_LOCK HalpBeepLock; +extern ULONG HalpBuiltinInterruptEnable; // S004 +extern KSPIN_LOCK HalpDisplayAdapterLock; +extern ULONG HalpProfileCountRate; +extern ULONG HalpStallScaleFactor; +extern KSPIN_LOCK HalpSystemInterruptLock; +/* Start S001 */ +extern KSPIN_LOCK HalpEifInterruptLock; +/* Start S003 */ +extern ULONG HalpInt2ArbitrationPoint; +extern ULONG HalpInt1ArbitrationPoint; +extern ULONG HalpInt0ArbitrationPoint; +/* End S003 */ +extern ULONG HalpUnknownInterruptCount[]; +/* Start S002 */ +extern KAFFINITY HalpEisaBusAffinity; //K000 +extern KAFFINITY HalpPCIBusAffinity; //S006 +extern KAFFINITY HalpInt1Affinity; //S006 +extern UCHAR HalpChangeIntervalFlg[]; //S006, S007 +extern ULONG HalpChangeIntervalCount; +extern ULONG HalpNextTimeIncrement; +extern ULONG HalpCurrentTimeIncrement; +extern ULONG HalpNextIntervalCount; +extern ULONG HalpNewTimeIncrement; +/* End S002 */ +/* End S001 */ +extern ULONG HalpEifRegisterBuffer[]; //K002,K003 + +// S009 vvv +extern ULONG HalpNvramValid; +extern USHORT ErrBufferArea; +// S009 ^^^ +// S00b vvv +LONG HalpECC1bitDisableFlag; +LONG HalpECC1bitDisableTime; +ULONG HalpECC1bitScfrBuffer; +// S00b ^^^ +extern volatile ULONG HalpNMIFlag; // R98TEMP + + +// ADD001 +// +// Resource usage information +// + +#if !defined (_R98_) +#pragma pack(1) +#endif +typedef struct { + UCHAR Flags; + KIRQL Irql; + UCHAR BusReleativeVector; +} IDTUsage; + +typedef struct _HalAddressUsage{ + struct _HalAddressUsage *Next; + CM_RESOURCE_TYPE Type; // Port or Memory + UCHAR Flags; // same as IDTUsage.Flags + struct { + ULONG Start; + USHORT Length; + } Element[]; +} ADDRESS_USAGE; +#if !defined (_R98_) +#pragma pack() +#endif + +#define IDTOwned 0x01 // IDT is not available for others +#define InterruptLatched 0x02 // Level or Latched +#define InternalUsage 0x11 // Report usage on internal bus +#define DeviceUsage 0x21 // Report usage on device bus + +extern IDTUsage HalpIDTUsage[]; +extern ADDRESS_USAGE *HalpAddressUsageList; +// CMP001 +extern ADDRESS_USAGE HalpDefaultPcIoSpace; +extern ADDRESS_USAGE HalpEisaIoSpace; +extern ADDRESS_USAGE HalpMapRegisterMemorySpace; + +#define HalpRegisterAddressUsage(a) \ + (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a); + +// CMP001 +#define IRQ_PREFERRED 0x02 +#define IRQ_VALID 0x01 + +// CMP001 +VOID +HalpReportResourceUsage ( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE DeviceInterfaceToUse +); + +// +// Temp definitions to thunk into supporting new bus extension format +// +// A002 +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + +// A002 +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 + ); + +// A002 +#define HalpHandlerForBus HaliHandlerForBus +#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p; + + +#endif // _HALP_ diff --git a/private/ntos/nthals/halr98mp/mips/j4cache.s b/private/ntos/nthals/halr98mp/mips/j4cache.s new file mode 100644 index 000000000..d6e9f2dd6 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/j4cache.s @@ -0,0 +1,1056 @@ +// "@(#) 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 +10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + +#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 +20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index + 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 +10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index + +#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 +10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line + 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 +30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + +#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 +10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line + +#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/halr98mp/mips/j4flshbf.s b/private/ntos/nthals/halr98mp/mips/j4flshbf.s new file mode 100644 index 000000000..b9a1cda9b --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/j4flshio.c b/private/ntos/nthals/halr98mp/mips/j4flshio.c new file mode 100644 index 000000000..d509d6522 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/j4flshio.c @@ -0,0 +1,238 @@ +#pragma comment(exestr, "@(#) j4flshio.c 1.7 95/03/10 19:31:22 nec") +/*++ + +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: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * K001 94/5/31 (Tue) N.Kugimoto + * Add At Dma Nothing to Do.( I/O Cache By R98 H/W) + * K002 94/9/26 N.Kugimoto + * Bug define bug + * K003 94/10/11 N.Kugimoto + * H/W Work around for LR4360 + * K004 94/10/18 N.Kugimoto + * Add Flush LR4360 Read Cache at DMA READ(MemotryToDevice) + * K005 95/03/10 N.Kugimoto + * H/W flush + */ + + +#include "halp.h" + +VOID +HalFlushIoBuffers ( + IN PMDL Mdl, + IN BOOLEAN ReadOperation, + IN BOOLEAN DmaOperation + ) + +/*++ + +Routine Description: + + This function flushes the I/O buffer specified by the memory descriptor + list from the data cache on the current processor. + +Arguments: + + Mdl - Supplies a pointer to a memory descriptor list that describes the + I/O buffer location. + + ReadOperation - Supplies a boolean value that determines whether the I/O + operation is a read into memory. + + DmaOperation - Supplies a boolean value that determines whether the I/O + operation is a DMA operation. + +Return Value: + + None. + +--*/ + +{ + + ULONG CacheSegment; + ULONG Length; + ULONG Offset; + KIRQL OldIrql; + PULONG PageFrame; + ULONG Source; + +#if defined(_R98_) + // K001,K002 + // R98 I/O Cache Supported So Nothing to Do Dma Operation!!. + // + if (DmaOperation == TRUE){ + // LR4360 Bug. IO cache Flush!! + // + // MemoryToDevice + // + if(ReadOperation==FALSE) //K004 + WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K003,K005 + return; + } +#endif + // + // The Jazz R4000 uses a write back data cache and, therefore, must be + // flushed on reads and writes. + // + // If the length of the I/O operation is greater than the size of the + // data cache, then sweep the entire data cache. Otherwise, flush or + // purge individual pages from the data cache as appropriate. + // + + Offset = Mdl->ByteOffset & PCR->DcacheAlignment; + Length = (Mdl->ByteCount + + PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment; + + if ((Length > PCR->FirstLevelDcacheSize) && + (Length > PCR->SecondLevelDcacheSize)) { + + // + // If the I/O operation is a DMA operation, or the I/O operation is + // not a DMA operation and the I/O operation is a page read operation, + // then sweep (index/writeback/invalidate) the entire data cache. + // + + if ((DmaOperation != FALSE) || + ((DmaOperation == FALSE) && + (ReadOperation != FALSE) && + ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) { + HalSweepDcache(); + } + + // + // If the I/O operation is a page read, then sweep (index/invalidate) + // the entire instruction cache. + // + + if ((ReadOperation != FALSE) && + ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) { + HalSweepIcache(); + } + + } else { + + // + // Flush or purge the specified pages from the data cache and + // instruction caches as appropriate. + // + // Compute the number of pages to flush and the starting MDL page + // frame address. + // + + Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment; + PageFrame = (PULONG)(Mdl + 1); + Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset; + + // + // Flush or purge the specified page segments from the data and + // instruction caches as appropriate. + // + + do { + if (Length >= (PAGE_SIZE - Offset)) { + CacheSegment = PAGE_SIZE - Offset; + + } else { + CacheSegment = Length; + } + + if (ReadOperation == FALSE) { + + // + // The I/O operation is a write and the data only needs to + // to be copied back into memory if the operation is also + // a DMA operation. + // + + if (DmaOperation != FALSE) { + HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + + } else { + + // + // If the I/O operation is a DMA operation, then purge the + // data cache. Otherwise, is the I/O operation is a page read + // operation, then flush the data cache. + // + + if (DmaOperation != FALSE) { + HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment); + + } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { + HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + + // + // If the I/O operation is a page read, then the instruction + // cache must be purged. + // + + if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) { + HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment); + } + } + + PageFrame += 1; + Length -= CacheSegment; + Offset = 0; + Source += CacheSegment; + } while(Length != 0); + } + + return; +} + +ULONG +HalGetDmaAlignmentRequirement ( + VOID + ) + +/*++ + +Routine Description: + + This function returns the alignment requirements for DMA transfers on + host system. + +Arguments: + + None. + +Return Value: + + The DMA alignment requirement is returned as the fucntion value. + +--*/ + +{ + + return PCR->DcacheFillSize; +} diff --git a/private/ntos/nthals/halr98mp/mips/j4prof.c b/private/ntos/nthals/halr98mp/mips/j4prof.c new file mode 100644 index 000000000..80ead3885 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/j4prof.c @@ -0,0 +1,362 @@ +#ident "@(#) NEC j4prof.c 1.4 95/06/19 10:54:59" +/*++ + +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 R4000 Jazz system. + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/23-5/25 T.Samezima + * + * change establish interrupt interval setting + * init PROFILE interrupt interval + * range of PROFILE interrupt interval + * + * add restart interrupt + * calculate change of unit from 100ns to 1us + * + * del calculate from interrupt interval to clock number + * + *********************************************************************** + * + * S002 94.07/5 T.Samezima + * + * change Irql level from PROFILE_LEVEL to EIF_LEVEL + * + * A002 1995/6/17 ataka@oa2.kb.nec.co.jp + * - resolve compile wornings. + */ + +// #include "ki.h" +#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]; +/* Start S001 */ +ULONG HalpProfileInterval = DEFAULT_PROFILETIMER_INTERVAL; +/* End S001 */ + +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. + // + + /* Start S002 */ + KeRaiseIrql(EIF_LEVEL, &OldIrql); + /* End S002 */ + 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); + /* Start S001 */ + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, + DEFAULT_PROFILETIMER_COUNT); + /* End S001 */ + + Prcb = KeGetCurrentPrcb(); + HalpPerformanceCounter[Prcb->Number].LowPart = 0; + HalpPerformanceCounter[Prcb->Number].HighPart = 0; + /* Start S001 */ + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3); + /* End S001 */ + + // + // 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. + +--*/ + +{ + +// LARGE_INTEGER TempValue; + + // + // 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. + // + + /* Start S001 */ + if (Interval < MINIMUM_PROFILETIMER_INTERVAL) { + Interval = MINIMUM_PROFILETIMER_INTERVAL; + + } else if (Interval > MAXIMUM_PROFILETIMER_INTERVAL) { + Interval = MAXIMUM_PROFILETIMER_INTERVAL; + } + + HalpProfileInterval = Interval; + /* End S001 */ + + return HalpProfileInterval; +} + +VOID +HalStartProfileInterrupt ( + KPROFILE_SOURCE Reserved // A002 + ) + +/*++ + +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; + /* Start S001 */ + ULONG TempValue; + /* End S001 */ + + // + // Compute the profile count from the current profile interval. + // + + /* Start S001 */ + TempValue = HalpProfileInterval / 10; + + // + // Write the compare register and clear the count register. + // + + PreviousCount = HalpWriteCompareRegisterAndClear(TempValue); + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, TempValue); + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3); + /* End S001 */ + + // + // 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 // A002 + ) + +/*++ + +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. + // + + PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT); + /* Start S001 */ + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, + DEFAULT_PROFILETIMER_COUNT); + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3); + /* End S001 */ + + // + // 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/halr98mp/mips/jazznvr.h b/private/ntos/nthals/halr98mp/mips/jazznvr.h new file mode 100644 index 000000000..79ab847cf --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jazznvr.h @@ -0,0 +1,164 @@ +#ident "@(#) NEC jazznvr.h 1.2 94/10/17 12:10:14" +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jazznvr.h + +Abstract: + + This module contains definitions for the Jazz non-volatile ram structures. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 '94.6/02 T.Samezima + * + * Change NV_CONFIGURATION structure and define + * + *********************************************************************** + * + * S002 '94.8/22 T.Samezima on SNES + * + * Chg NV_CONFIGURATION structure and define + * + * + */ + + +#ifndef _JAZZNVR_ +#define _JAZZNVR_ + +// +// 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. +// + +#if defined(_R98_) + +// Start S002 +#define NUMBER_OF_ENTRIES 50 // REV 05 1994/05/23 +#define LENGTH_OF_IDENTIFIER 516 // REV 05 1994/05/23 +#define LENGTH_OF_DATA 2048 // REV 05 1994/05/23 +#define LENGTH_OF_ENVIRONMENT 1024 // R98 support 1994/01/31(REV 01) +#define LENGTH_OF_EISA_DATA 2044 // R98 support 1994/01/31(REV 01) +#define LENGTH_OF_PCI_DATA 512 // REV 06 1994/06/17 +#define LENGTH_OF_ITF_DATA 128 // R98 support 1994/01/31(REV 01) +#define NUMBER_MEM_ENTRIES 90 // REV 05 1994/05/23 +#define LENGTH_MEM_IDENTIFIER 1024 // REV 05 1994/05/23 +// End S002 + +#else // #if defined(_R98_) + +#define NUMBER_OF_ENTRIES 32 +#define LENGTH_OF_IDENTIFIER 504 +#define LENGTH_OF_DATA 2048 +#define LENGTH_OF_ENVIRONMENT 1024 + +#endif // #if defined(_R98_) + +#define MAXIMUM_ENVIRONMENT_VALUE 128 + +// +// 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 { + +// Start S002 +#if defined(_R98_) + + COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; // R98 support 1994/01/31(REV 01) + UCHAR Identifier[LENGTH_OF_IDENTIFIER]; // R98 support 1994/01/31(REV 01) + UCHAR Data[LENGTH_OF_DATA]; // R98 support 1994/01/31(REV 01) + UCHAR Checksum1[4]; // R98 support 1994/01/31(REV 01) + UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // R98 support 1994/01/31(REV 01) + UCHAR Checksum2[4]; // R98 support 1994/01/31(REV 01) + UCHAR EisaData[LENGTH_OF_EISA_DATA]; // R98 support 1994/01/31(REV 01) + UCHAR Checksum3[4]; // R98 support 1994/01/31(REV 01) + UCHAR EthernetAddress[8]; // R98 support 1994/01/31(REV 01) + UCHAR NmiVector[4]; // R98 support 1994/01/31(REV 01) + UCHAR ItfUseArea[LENGTH_OF_ITF_DATA]; // R98 support 1994/01/31(REV 01) + UCHAR Reserved[1608]; // R98 support 1994/01/31(REV 01) + +#else // #if defined(_R98_) + + COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; + UCHAR Identifier[LENGTH_OF_IDENTIFIER]; + UCHAR Data[LENGTH_OF_DATA]; + UCHAR Checksum1[4]; + UCHAR Environment[LENGTH_OF_ENVIRONMENT]; + UCHAR Checksum2[4]; + +#endif // #if defined(_R98_) +// End S002 + +} NV_CONFIGURATION, *PNV_CONFIGURATION; + +// +// Non-volatile ram layout. +// + +#if defined(MIPS) + +#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE +#define NVRAM_SYSTEM_ID NVRAM_VIRTUAL_BASE + 0x00002000 + +#endif + +#endif // _JAZZNVR_ diff --git a/private/ntos/nthals/halr98mp/mips/jxbeep.c b/private/ntos/nthals/halr98mp/mips/jxbeep.c new file mode 100644 index 000000000..d39405c78 --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/jxdisp.c b/private/ntos/nthals/halr98mp/mips/jxdisp.c new file mode 100644 index 000000000..1882d69ee --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxdisp.c @@ -0,0 +1,3132 @@ +#ident "@(#) NEC jxdisp.c 1.19 95/07/05 16:32:19" +/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.10 93/12/01 12:18:22" ) */ +/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.9 93/11/19 13:48:37" ) */ +/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.7 93/11/18 14:57:07" ) */ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxdisp.c + +Abstract: + + This module implements the HAL display initialization and output routines + for a MIPS R3000 or R4000 Jazz system. + +History: + +--*/ + +/* + * M001 1993.10.28 A. Kuriyama@oa2 + * + * - Modify for R96 MIPS R4400 + * + * Add : Initialize routine for Cirrus CL5428. + * + * Notes : HalpCirrusInterpretCmdStream() based on VgaInterpretCmdStream() + * in Cirrus Miniport Driver. + * + * M002 1993.11.10 M. Kusano + * + * - initialize bug fixed + * + * Add : Color palette initialize sequence. + * + * - scroll bug fixed + * + * Add : 32bit Move Memory routine. + * + * M003 1993.11.18 A. Kuriyama@oa2 + * + * - Exchanged HalpMoveMemory32() + * + * Add : HalpMoveMemory32() + * + * M004 1993.11.18 M. Kusano + * + * - Modefy HalpMoveMemory32() + * + * Bug fix + * + * + * M005 1993.11.30 M.Kusano + * + * - Modefy Display Identifier + * Cirrus GD5428 -> necvdfrb + * + * #if defined(DBCS) && defined(_MIPS_) + * + * M006 1994.10.29 T.Samezima + * + * - Add display mode on vga + * + * #endif // DBCS && _MIPS_ + * + * Revision History in Cirrus Miniport Driver as follows: + * + * L001 1993.10.15 Kuroki + * + * - Modify for R96 MIPS R4400 in Miniport Driver + * + * Delete : Micro channel Bus Initialize. + * VDM & Text, Fullscreen mode support. + * Banking routine. + * CL64xx Chip support. + * 16-color mode. + * + * Add : Liner Addressing. + * + *************************************************************** + * + * S001 1994.06/06 T.Samezima + * + * - Modify for R98 MIPS R4400 + * + * Change : memory and I/O Address + * + *********************************************************************** + * + * S002 1994.6/10 T.Samezima + * + * Del Compile err + * + *************************************************************** + * + * S003 1994.07/12 T.Samezima + * + * Change : I/O Address + * + * + * K000 94/10/11 N.Kugimoto + * fix 807 base + * K001 94/10/13 N.Kugimoto + * Chg resest-->reset + * + * S004 94/10/25 T.Samezima + * Add define _DUO_ + * + * S005 94/11/23 T.Samezima + * Add Marge TGA(DEC21030) initialize rotine (program by T.Katoh 1994.11/15) + * + * S006 94/11/29 T.Katoh + * Bug Fix + * + * S007 94/12/07 T.Samezima + * Chg Color palet change. + * + * S008 94/12/12 T.Samezima + * Add Config read function. + * Chg Change PCI configuration read function from READ_REGISTER_ULONG + * to PciReadConfigUlong. + * + * S009 94/12/24-95/1/9 T.Samezima + * Add ESM logic. + * + * S00a 95/01/14 T.Samezima + * Chg Display string into nvram. + * + * S00b 95/03/14 T.Samezima + * Chg TGA parametor change. + * Add stall execution. + * Del Warning + * S00c 95/04/4 T.Samezima + * Chg TGA parametor change for adjust standard of VESA + * Windows-NT 3.51 + * K1001 '95.7.5 N.Kugimoto + * Chg TGA parametor change for adjust standard of VESA + * + */ + + +#include "halp.h" +#include "jazzvdeo.h" +#include "jzvxl484.h" +#include +/* START M001 */ +#include "cirrus.h" +#include "modeset.h" +#include "mode542x.h" +/* END M001 */ +#include "string.h" +/* START S005 */ +#include +/* END S005 */ + +#define _DUO_ // S004 + +// +// 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 + +// +// Define forward referenced procedure prototypes. +// + +VOID +HalpDisplayCharacter ( + IN UCHAR Character + ); + +VOID +HalpOutputCharacter( + IN PUCHAR Glyph + ); + +VOID +HalpDisplayG300Setup ( + VOID + ); + +VOID +HalpDisplayG364Setup ( + VOID + ); + +VOID +HalpDisplayVxlSetup ( + VOID + ); + +/* START M001 */ +VOID +HalpDisplayCirrusSetup ( + VOID + ); + +BOOLEAN +HalpCirrusInterpretCmdStream ( + PUSHORT pusCmdStream + ); +/* END M001 */ + +/* START M002 */ +VOID +Write_Dbg_Uchar( +PUCHAR, +UCHAR +); +/* END M002 */ + +/* START M003 */ +VOID +HalpMoveMemory32 ( + PUCHAR Destination, + PUCHAR Source, + ULONG Length +); +/* END M003 */ +/* START S005 */ +VOID +HalpDisplayTgaSetup( + VOID + ); +/* END S005 */ + +// +// Define virtual address of the video memory and control registers. +// + +#define VIDEO_MEMORY_BASE 0x40000000 +#define G300_VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)0x403ff000) +#define G364_VIDEO_CONTROL ((PG364_VIDEO_REGISTERS)0x403ff000) +#define G364_VIDEO_RESET ((PVIDEO_REGISTER)0x403fe000) + +// +// Define memory access constants for VXL +// + +#define VXL_VIDEO_MEMORY_BASE 0x40000000 +#define BT484_BASE ((PBT484_REGISTERS)0x403fd000) +#define CLOCK_BASE ((PUCHAR)0x403fe000) +#define JAGUAR_BASE ((PJAGUAR_REGISTERS)0x403ff000) +/* START M001 */ +/* Start S001 */ +#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000) +/* End S001 */ +#define CIRRUS_OFFSET ((PUSHORT)0x3b0) +/* END M001 */ + +/* START S005 */ +#define KSEG1_BASE 0xa0000000 +#define TGA_REGISTER_BASE ((ULONG)0x403ff000) // S006 +#define R98_PCI_SPACE_BASE ((ULONG)0xc0000000) // S006 +#define R98_PCI1_ID ((PULONG)(0x18ca8800 | KSEG1_BASE)) +#define R98_PCI1_MEM_BASE ((PULONG)(0x18ca8810 | KSEG1_BASE)) +#define R98_PCI1_CS_REG ((PULONG)(0x18ca8804 | KSEG1_BASE)) +#define R98_PCI2_ID ((PULONG)(0x18ca9000 | KSEG1_BASE)) +#define R98_PCI2_MEM_BASE ((PULONG)(0x18ca9010 | KSEG1_BASE)) +#define R98_PCI2_CS_REG ((PULONG)(0x18ca9004 | KSEG1_BASE)) +#define R98_PCI3_ID ((PULONG)(0x18ca9800 | KSEG1_BASE)) +#define R98_PCI3_MEM_BASE ((PULONG)(0x18ca9810 | KSEG1_BASE)) +#define R98_PCI3_CS_REG ((PULONG)(0x18ca9804 | KSEG1_BASE)) + +/* END S005 */ + +// +// The three type of g364 boards we support +// + +#define JAZZG364 1 +#define MIPSG364 2 +#define OLIVETTIG364 3 + +// +// Define controller setup routine type. +// + +typedef +VOID +(*PHALP_CONTROLLER_SETUP) ( + VOID + ); + +// +// Define OEM font variables. +// + +ULONG HalpBytesPerRow; +ULONG HalpCharacterHeight; +ULONG HalpCharacterWidth; +ULONG HalpColumn; +ULONG HalpDisplayText; +ULONG HalpDisplayWidth; +POEM_FONT_FILE_HEADER HalpFontHeader; +ULONG HalpRow; +ULONG HalpScrollLength; +ULONG HalpScrollLine; + +// +// Define display variables. +// + +BOOLEAN HalpDisplayOwnedByHal; +ENTRYLO HalpDisplayPte; +ULONG HalpDisplayControlBase = 0; +ULONG HalpDisplayResetRegisterBase = 0; +ULONG HalpDisplayVxlClockRegisterBase = 0; +ULONG HalpDisplayVxlBt484RegisterBase = 0; +ULONG HalpDisplayVxlJaguarRegisterBase = 0; +PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL; +MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData; +BOOLEAN HalpDisplayTypeUnknown = FALSE; +ULONG HalpG364Type = 0; +/* START M001 */ +LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0}; +/* END M001 */ + +// S008 vvv +ULONG +PciReadConfigUlong( + PULONG Addr + ) +{ + ULONG reg; + ULONG regTmp; + ULONG returnValue; + + reg = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN ); + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, (reg & 0xffbfffff)); + + returnValue = READ_PORT_ULONG( Addr ); + + regTmp = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ); + if( regTmp & 0x80000000 ){ + WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS, 0x80000000); + regTmp = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE ); + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE, (regTmp & 0xffbfffff) ); + returnValue = 0xffffffff; + } + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, reg); + return returnValue; +} +// S008 ^^^ + +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; + + // + // 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. + // + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("HalpInitializeDisplay0\n"); +#endif + /* END M002 */ + + MatchKey = 0; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + DisplayController, + &MatchKey); + /* START M002 */ +#if defined (R96DBG) + DbgPrint("ConfigurationEntry Found\n"); +#endif + /* END M002 */ + + if (ConfigurationEntry == NULL) { + /* START S005 */ + MatchKey = 1; + ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot, + ControllerClass, + DisplayController, + &MatchKey); + if (ConfigurationEntry == NULL) { + /* END S005 */ + return FALSE; + /* START S005 */ + } + /* END S005 */ + } + + // + // Determine which video controller is present in the system. + // Copy the display controller and monitor parameters in case they are + // needed later to reinitialize the display to output a message. + // + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "Jazz G300")) { + + HalpDisplayControllerSetup = HalpDisplayG300Setup; + + HalpDisplayControlBase = + ((PJAZZ_G300_CONFIGURATION_DATA) + (ConfigurationEntry->ConfigurationData))->ControlBase; + + } else { + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "Jazz G364")) { + + HalpDisplayControllerSetup = HalpDisplayG364Setup; + HalpG364Type = JAZZG364; + + HalpDisplayControlBase = 0x60080000; + +// HalpDisplayControlBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ControlBase; + + HalpDisplayResetRegisterBase = 0x60180000; + +// HalpDisplayResetRegisterBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ResetRegister; + + } else { + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "Mips G364")) { + + HalpDisplayControllerSetup = HalpDisplayG364Setup; + HalpG364Type = MIPSG364; + + HalpDisplayControlBase = 0x60080000; + +// HalpDisplayControlBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ControlBase; + + HalpDisplayResetRegisterBase = 0x60180000; + +// HalpDisplayResetRegisterBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ResetRegister; + + } else { + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "OLIVETTI_G364")) { + + HalpDisplayControllerSetup = HalpDisplayG364Setup; + HalpG364Type = OLIVETTIG364; + + HalpDisplayControlBase = 0x60080000; + +// HalpDisplayControlBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ControlBase; + + HalpDisplayResetRegisterBase = 0x60180000; + +// HalpDisplayResetRegisterBase = +// ((PJAZZ_G364_CONFIGURATION_DATA) +// (ConfigurationEntry->ConfigurationData))->ResetRegister; + + } else { + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "VXL")) { + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("VXL config found\n"); +#endif + /* END M002 */ + HalpDisplayControllerSetup = HalpDisplayVxlSetup; + HalpDisplayVxlBt484RegisterBase = 0x60100000; + HalpDisplayVxlClockRegisterBase = 0x60200000; + HalpDisplayVxlJaguarRegisterBase = 0x60300000; + + /* START M001 */ + } else { + + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "necvdfrb")) { /* M005 */ + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("necvdfrb Config found\n"); /* M005 */ +#endif + /* END M002 */ + + HalpDisplayControllerSetup = HalpDisplayCirrusSetup; + /* Start S001,S003 */ + HalpDisplayControlBase = 0x18cc0000; + /* End S001,S003 */ + /* END M001 */ + + } else { + + /* START S005 */ + if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier, + "10110004")) { + HalpDisplayControllerSetup = HalpDisplayTgaSetup; + + if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) { // S006 + if ((PciReadConfigUlong(R98_PCI1_CS_REG) & 0x00000002) == 2){ // S006 + HalpDisplayControlBase + = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE // S006 + + TGA_REG_SPC_OFFSET; + } else { + return FALSE; + } + } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) { // S006 + if ((PciReadConfigUlong(R98_PCI2_CS_REG) & 0x00000002) == 2){ // S006 + HalpDisplayControlBase + = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE // S006 + + TGA_REG_SPC_OFFSET; + } else { + return FALSE; + } + } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) { // S006 + if ((PciReadConfigUlong(R98_PCI3_CS_REG) & 0x00000002) == 2){ // S006 + HalpDisplayControlBase + = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE // S006 + + TGA_REG_SPC_OFFSET; + } else { + return FALSE; + } + } + + } else { + /* END S005 */ + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("DisplayTypeUnknown\n"); +#endif + /* END M002 */ + + HalpDisplayTypeUnknown = TRUE; + /* START S005 */ + } + /* END S005 */ + } + /* START M001 */ + } + /* END M001 */ + } + } + } + } + + Child = ConfigurationEntry->Child; + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("parameters read start\n"); +#endif + /* END M002 */ + + RtlMoveMemory((PVOID)&HalpMonitorConfigurationData, + Child->ConfigurationData, + Child->ComponentEntry.ConfigurationDataLength); + + // + // Compute character output display parameters. + // + + HalpDisplayText = + HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight; + + /* START M002 */ + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpScrollLine = + 1024 * HalpCharacterHeight; + }else{ + /* END M002 */ + + HalpScrollLine = + HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight; + + /* START M002 */ + } + /* END M002 */ + + HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1); + + /* START M002 */ + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + HalpDisplayWidth = + 1024 / HalpCharacterWidth; + + }else{ + /* END M002 */ + + HalpDisplayWidth = + HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth; + /* START M002 */ + } + /* END M002 */ + + // + // Scan the memory allocation descriptors and allocate a free page + // to map the video memory and control registers, and initialize the + // PDE entry. + // + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("Mem get \n"); +#endif + /* END M002 */ + + + NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) { + MemoryDescriptor = CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + + if ((MemoryDescriptor->MemoryType == LoaderFree) && + (MemoryDescriptor->PageCount > 1)) { + StartingPfn = MemoryDescriptor->BasePage; + MemoryDescriptor->BasePage += 1; + MemoryDescriptor->PageCount -= 1; + break; + } + + NextEntry = NextEntry->Flink; + } + + ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead); + + Pte.X1 = 0; + Pte.PFN = StartingPfn; + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + + Pte.N = 1; + +#endif + +#if defined(R4000) + + Pte.C = UNCACHED_POLICY; + +#endif + + // + // Save the page table page PTE for use in displaying information and + // map the appropriate PTE in the current page directory page to address + // the display controller page table page. + // + + HalpDisplayPte = Pte; + *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte; + + // + // Initialize the page table page. + // + + PageFrame = (PENTRYLO)(PTE_BASE | + (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + + /* START M001 */ + if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) { + /* Start S001 */ + HalpCirrusPhigicalVideo.HighPart = 0; + HalpCirrusPhigicalVideo.LowPart = MEM_VGA | EISA_MEMORY_PHYSICAL_BASE; + /* End S001 */ + Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) & + (0x7fffffff >> PAGE_SHIFT-1) | + HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT); + } + else { + /* END M001 */ + /* START S005 */ + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { + Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT; + } else { + /* END S005 */ + Pte.PFN = VIDEO_MEMORY_BASE >> PAGE_SHIFT; + /* START S005 */ + } + /* END S005 */ + /* START M001 */ + } + /* END M001 */ + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + + Pte.N = 1; + +#endif + +#if defined(R4000) + + Pte.C = UNCACHED_POLICY; + +#endif + + // + // Page table entries of the video memory. + // + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + if (HalpDisplayControllerSetup == HalpDisplayVxlSetup) { + + // + // If this is VXL then map a page for the + // brooktree base + // Clock base + // jaguar base + // + + Pte.PFN = ((ULONG)HalpDisplayVxlBt484RegisterBase) >> PAGE_SHIFT; + *(PageFrame - 2) = Pte; + + Pte.PFN = ((ULONG)HalpDisplayVxlClockRegisterBase) >> PAGE_SHIFT; + *(PageFrame - 1) = Pte; + + Pte.PFN = ((ULONG)HalpDisplayVxlJaguarRegisterBase) >> PAGE_SHIFT; + *PageFrame = Pte; + + } else { + + // + // If we have a G364, use the page before last to map the reset register. + // + + if (HalpDisplayControllerSetup == HalpDisplayG364Setup) { + Pte.PFN = ((ULONG)HalpDisplayResetRegisterBase) >> PAGE_SHIFT; + *(PageFrame - 1) = Pte; + } + + // + // Page table for the video registers. + // + + Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + *PageFrame = Pte; + } + + // + // Initialize the display controller. + // + + HalpDisplayControllerSetup(); + + HalpInitDisplayStringIntoNvram(); // S009 + + 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(); // S009 + + return TRUE; +} + +VOID +HalAcquireDisplayOwnership ( + IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters //K001 + ) + +/*++ + +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(); // S009 + + // + // Set HAL ownership of the display to false. + // + + HalpDisplayOwnedByHal = FALSE; + return; +} + +VOID +HalpDisplayG300Setup ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the G300B display controller chip. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + ULONG BackPorch; + PULONG Buffer; + ULONG DataLong; + ULONG FrontPorch; + ULONG HalfLineTime; + ULONG HalfSync; + ULONG Index; + ULONG Limit; + ULONG MultiplierValue; + ULONG ScreenUnitRate; + ULONG VerticalBlank; + ULONG ShortDisplay; + ULONG TransferDelay; + + // + // Disable the G300B display controller. + // + + DataLong = 0; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1; + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong); + + // + // Initialize the G300B boot register value. + // + + ScreenUnitRate = + (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) / + (HalpMonitorConfigurationData.HorizontalResolution); + + MultiplierValue = 125000 / (ScreenUnitRate / 4); + DataLong = 0; + ((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue; + ((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1; + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Boot.Long, DataLong); + + // + // Wait for phase locked loop to stablize. + // + + KeStallExecutionProcessor(50); + + // + // Initialize the G300B operational values. + // + + HalfSync = + (HalpMonitorConfigurationData.HorizontalSync * 1000) / ScreenUnitRate / 2; + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->HorizonalSync.Long, HalfSync); + + BackPorch = + (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / ScreenUnitRate; + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BackPorch.Long, BackPorch); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Display.Long, + HalpMonitorConfigurationData.HorizontalResolution / 4); + + HalfLineTime = ((HalpMonitorConfigurationData.HorizontalSync + + HalpMonitorConfigurationData.HorizontalFrontPorch + + HalpMonitorConfigurationData.HorizontalBackPorch + + HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / ScreenUnitRate / 2; + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineTime.Long, HalfLineTime * 2); + FrontPorch = + (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / ScreenUnitRate; + + ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch); + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ShortDisplay.Long, ShortDisplay); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BroadPulse.Long, + HalfLineTime - FrontPorch); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalSync.Long, + HalpMonitorConfigurationData.VerticalSync * 2); + + VerticalBlank = (HalpMonitorConfigurationData.VerticalFrontPorch + + HalpMonitorConfigurationData.VerticalBackPorch - + (HalpMonitorConfigurationData.VerticalSync * 2)) * 2; + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalBlank.Long, + VerticalBlank); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalDisplay.Long, + HalpMonitorConfigurationData.VerticalResolution * 2); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineStart.Long, LINE_START_VALUE); + if (BackPorch < ShortDisplay) { + TransferDelay = BackPorch - 1; + } else { + TransferDelay = ShortDisplay - 1; + } + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->TransferDelay.Long, TransferDelay); + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->DmaDisplay.Long, + 1024 - TransferDelay); + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->PixelMask.Long, G300_PIXEL_MASK_VALUE); + + // + // Initialize the G300B control parameters. + // + + DataLong = 0; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL; + ((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2; + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong); + + // + // Set up the color map for two colors. + // + + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[0], 0xffffff); + WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[1], 0x900000); + + // + // Set the video memory to address color one. + // + + Buffer = (PULONG)VIDEO_MEMORY_BASE; + Limit = (HalpMonitorConfigurationData.HorizontalResolution * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (Index = 0; Index < Limit; Index += 1) { + *Buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; +} + +VOID +HalpDisplayG364Setup( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the G364 display controller chip. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + ULONG videoClock; + ULONG videoPeriod; + ULONG backPorch; + ULONG dataLong; + ULONG frontPorch; + ULONG halfLineTime; + ULONG halfSync; + PULONG buffer; + ULONG index; + ULONG limit; + ULONG multiplierValue; + ULONG screenUnitRate; + ULONG shortDisplay; + ULONG transferDelay; + ULONG verticalBlank; + + // + // Reset the G364 display controller. + // + + WRITE_REGISTER_ULONG(&G364_VIDEO_RESET->Long, + 0); + + // + // Initialize the G364 boot register value. + // + + if (HalpG364Type == MIPSG364) { + + videoClock = 5000000; + + } else { + + videoClock = 8000000; + + } + + videoPeriod = 1000000000 / (videoClock / 1000); + + screenUnitRate = (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) / + (HalpMonitorConfigurationData.HorizontalResolution); + + multiplierValue = videoPeriod / (screenUnitRate / 4); + dataLong = 0; + ((PG364_VIDEO_BOOT)(&dataLong))->Multiplier = multiplierValue; + ((PG364_VIDEO_BOOT)(&dataLong))->ClockSelect = 1; + ((PG364_VIDEO_BOOT)(&dataLong))->MicroPort64Bits = 1; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Boot.Long, + dataLong); + + // + // Wait for phase locked loop to stablize. + // + + KeStallExecutionProcessor(50); + + // + // Initialize the G364 control parameters. + // + + dataLong = 0; + ((PG364_VIDEO_PARAMETERS)(&dataLong))->DelaySync = G364_DELAY_SYNC_CYCLES; + ((PG364_VIDEO_PARAMETERS)(&dataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL; + ((PG364_VIDEO_PARAMETERS)(&dataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT; + ((PG364_VIDEO_PARAMETERS)(&dataLong))->DisableCursor = 1; + + if (HalpG364Type == OLIVETTIG364) { + + // + // Initialize the G364 control parameters for VDR1 with patch for HSync + // problem during the VBlank. The control register is set to 0xB03041 + // according to the hardware specs. @msu, Olivetti, 5/14/92 + // + + ((PG364_VIDEO_PARAMETERS)(&dataLong))->VideoOnly = 1; + + } else { + + // + // Only set tesselated sync in non-olivetti G364 cards when + // vertical frontporch is set to 1 + // + + if (HalpMonitorConfigurationData.VerticalFrontPorch != 1) { + ((PG364_VIDEO_PARAMETERS)(&dataLong))->PlainSync = 1; + } + + } + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long, + dataLong); + + // + // Initialize the G364 operational values. + // + + halfSync = (HalpMonitorConfigurationData.HorizontalSync * 1000) / screenUnitRate / 2; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->HorizontalSync.Long, + halfSync); + + backPorch = (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / screenUnitRate; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BackPorch.Long, + backPorch); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Display.Long, + HalpMonitorConfigurationData.HorizontalResolution / 4); + + halfLineTime = ((HalpMonitorConfigurationData.HorizontalSync + + HalpMonitorConfigurationData.HorizontalFrontPorch + + HalpMonitorConfigurationData.HorizontalBackPorch + + HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / + screenUnitRate / 2; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineTime.Long, + halfLineTime * 2); + + frontPorch = (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / + screenUnitRate; + + shortDisplay = halfLineTime - ((halfSync * 2) + backPorch + frontPorch); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ShortDisplay.Long, + shortDisplay); + + if (HalpG364Type == OLIVETTIG364) { + + // + // Initialize Broad Pulse, Vertical PreEqualize and Vertical + // PostEqualize registers to work with Olivetti monitors. + // @msu, Olivetti, 5/14/92 + // + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long, + 0x30); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long, + 2); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long, + 2); + + } else { + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long, + halfLineTime - frontPorch); + + // NOTE: changed the order to simplify if statement . + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long, + HalpMonitorConfigurationData.VerticalFrontPorch * 2); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long, + 2); + + } + + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalSync.Long, + HalpMonitorConfigurationData.VerticalSync * 2); + + verticalBlank = (HalpMonitorConfigurationData.VerticalBackPorch - 1) * 2; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalBlank.Long, + verticalBlank); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalDisplay.Long, + HalpMonitorConfigurationData.VerticalResolution * 2); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineStart.Long, + LINE_START_VALUE); + + if (HalpG364Type == OLIVETTIG364) { + + // + // Fixes for Olivetti monitors, @msu, Olivetti + // + + transferDelay = 30; // @msu + + } else { + + if (backPorch < shortDisplay) { + transferDelay = backPorch - 1; + } else { + transferDelay = shortDisplay - 4; + } + } + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->TransferDelay.Long, + transferDelay); + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->DmaDisplay.Long, + 1024 - transferDelay); + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->PixelMask.Long, + 0xFFFFFF); + + // + // Enable video + // + + ((PG364_VIDEO_PARAMETERS)(&dataLong))->EnableVideo = 1; + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long, + dataLong); + + // + // Set up the color map for two colors. + // NOTE: this device is not RGB but BGR. + // + + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[0], 0xffffff); + WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[1], 0x000090); + + // + // Set the video memory to address color one. + // + + buffer = (PULONG)VIDEO_MEMORY_BASE; + limit = (HalpMonitorConfigurationData.HorizontalResolution * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (index = 0; index < limit; index += 1) { + *buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; +} + +VOID +HalpDisplayVxlSetup( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the JazzVxl Graphics accelerator. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + + UCHAR DataChar; + UCHAR CmdReg0; + ULONG Status; + PULONG Buffer; + LONG Limit; + LONG Index; + + + // + // Define clock value for the ICS part (pS) + // + + LONG ClockResList[32] = { 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4,42918,40984,38760,36724,33523,31017, + 29197,27548,24882,23491,22482,21468,20509,19920, + 18692,18054,16722,15015,14773,14053,13040, 4}; + + JAGUAR_REG_INIT JagInitData; + + LONG HorDisplayTime; + LONG HorResolutionDiv; + LONG RequestedClockPeriod; + LONG CurrentClockError; + LONG MinErrorValue; + USHORT MinErrorIndex; + LONG ShiftClockPeriod; + + USHORT BoardTypeBt485; + + + + // + // Determine if this is a Bt484 or Bt485 board. To do this write a 1 to command + // register bit 07 then write 01 to the address register 0. This will enable + // read/writes to command register 3 on a Bt485 but not on a Bt484. Clear + // Command register 3 then read it back. On a Bt485 the return value will be 0x00, + // on a Bt484 it will be 0x40. + // + // Get the value in command register 0, then set bit 07 + // + + DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Command0.Byte); + DataChar |= 0x80; + WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,DataChar); + + // + // Write 0x01 to the address register + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01); + + // + // Clear command register 3 + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,0x00); + + // + // Read Command Register 3 back and compare + // + + DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Status.Byte); + + if (DataChar != 0x00) { + + // + // This is a Bt484 + // + + BoardTypeBt485 = 0; + JagInitData.Bt485Multiply = 0; + + } else { + + // + // This is a Bt485 + // + + BoardTypeBt485 = 1; + JagInitData.Bt485Multiply = 0; + } + + // + // Calculate the requested clock frequency then find the closest match in the + // ICS clock frequency table. The requested clock frequency in picoseconds = + // + // Horizontal display time * 1000000 + // --------------------------------- + // horizontal resolution + // + // + + HorDisplayTime = HalpMonitorConfigurationData.HorizontalDisplayTime * 1000; + HorResolutionDiv = HalpMonitorConfigurationData.HorizontalResolution; + RequestedClockPeriod = HorDisplayTime / HorResolutionDiv; + + // + // Check for a Bt485 frequency + // + + if ((BoardTypeBt485 == 1) && (RequestedClockPeriod < ClockResList[30])) { + RequestedClockPeriod = RequestedClockPeriod * 2; + JagInitData.Bt485Multiply = 1; + } + + MinErrorIndex = 0; + + // + // Gaurentee a maximum starting error + // + + MinErrorValue = RequestedClockPeriod + 1; + for (Index = 0; Index < 32; Index++) { + + // + // Calculate the absolute value of clock error and find the + // closest match in the array of clock values + // + + CurrentClockError = RequestedClockPeriod - ClockResList[Index]; + if (CurrentClockError < 0) { + CurrentClockError *= -1; + } + + if (CurrentClockError < MinErrorValue) { + MinErrorValue = CurrentClockError; + MinErrorIndex = (USHORT)Index; + } + } + + // + // We now have a closest match in the clock array, now calculate the + // values for the Bt484/Bt485 register values + // + + JagInitData.ClockFreq = (UCHAR)MinErrorIndex; // S002 + JagInitData.BitBltControl = 1; + JagInitData.TopOfScreen = 0; + JagInitData.XferLength = 0x200; + JagInitData.VerticalInterruptLine = 4; + JagInitData.HorizontalDisplay = HalpMonitorConfigurationData.HorizontalResolution; + + // + // All jaguar timing values are based on the brooktree shift clock value which + // is the clock frequency divided by 4. (period * 4) If this is a Bt485 using + // its internal 2x clock multiplier than is is period * 2; (freq * 2 / 4) + // + + if (JagInitData.Bt485Multiply == 1) { + ShiftClockPeriod = ClockResList[MinErrorIndex] * 2; + } else { + ShiftClockPeriod = ClockResList[MinErrorIndex] * 4; + } + + JagInitData.HorizontalBlank = (USHORT)( ((HalpMonitorConfigurationData.HorizontalBackPorch + + HalpMonitorConfigurationData.HorizontalSync + + HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000) + / ShiftClockPeriod); // S002 + + JagInitData.HorizontalBeginSync = (USHORT)((HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) + / ShiftClockPeriod); // S002 + + JagInitData.HorizontalEndSync = (USHORT)(((HalpMonitorConfigurationData.HorizontalSync + + HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000) + / ShiftClockPeriod); // S002 + + JagInitData.HorizontalLine = JagInitData.HorizontalBlank + + (HalpMonitorConfigurationData.HorizontalResolution / 4); + + JagInitData.VerticalBlank = HalpMonitorConfigurationData.VerticalBackPorch + + HalpMonitorConfigurationData.VerticalSync + + HalpMonitorConfigurationData.VerticalFrontPorch; + + JagInitData.VerticalBeginSync = HalpMonitorConfigurationData.VerticalFrontPorch; + + JagInitData.VerticalEndSync = HalpMonitorConfigurationData.VerticalFrontPorch + + HalpMonitorConfigurationData.VerticalSync; + + JagInitData.VerticalLine = HalpMonitorConfigurationData.VerticalBackPorch + + HalpMonitorConfigurationData.VerticalSync + + HalpMonitorConfigurationData.VerticalFrontPorch + + HalpMonitorConfigurationData.VerticalResolution; + + // + // Start ICS Clock pll and stabilize. + // + + WRITE_REGISTER_UCHAR(CLOCK_BASE,JagInitData.ClockFreq); + + // + // Wait 10 uS for PLL clock to stabilize on the video board + // + + for (Index = 0; Index < 10; Index++) { + READ_REGISTER_UCHAR(CLOCK_BASE); + } + + // + // Initialize Bt484 Command Register 0 to: + // + // 8 Bit DAC Resolution + // + + CmdReg0 = 0; + ((PBT484_COMMAND0)(&CmdReg0))->DacResolution = 1; + ((PBT484_COMMAND0)(&CmdReg0))->GreenSyncEnable = 1; + ((PBT484_COMMAND0)(&CmdReg0))->SetupEnable = 1; + WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0); + + // + // Initialize Command Register 1 to: + // + + DataChar = 0; + ((PBT484_COMMAND1)(&DataChar))->BitsPerPixel = VXL_EIGHT_BITS_PER_PIXEL; + WRITE_REGISTER_UCHAR(&BT484_BASE->Command1.Byte,DataChar); + + // + // Initialize Command Register 2 to: + // + // SCLK Enabled + // TestMode disabled + // PortselMask Non Masked + // PCLK 1 + // NonInterlaced + // + + DataChar = 0; + ((PBT484_COMMAND2)(&DataChar))->SclkDisable = 0; + ((PBT484_COMMAND2)(&DataChar))->TestEnable = 0; + ((PBT484_COMMAND2)(&DataChar))->PortselMask = 1; + ((PBT484_COMMAND2)(&DataChar))->PclkSelect = 1; + ((PBT484_COMMAND2)(&DataChar))->InterlacedDisplay = 0; + ((PBT484_COMMAND2)(&DataChar))->PaletteIndexing = CONTIGUOUS_PALETTE; + ((PBT484_COMMAND2)(&DataChar))->CursorMode = BT_CURSOR_WINDOWS; + WRITE_REGISTER_UCHAR(&BT484_BASE->Command2.Byte,DataChar); + + // + // if JagInitData.ClockFreq bit 8 is set then this is a Bt485 mode that requires + // the internal 2x clock multiplier to be enabled. + // + + if (JagInitData.Bt485Multiply == 1) { + + // + // To access cmd register 3, first set bit CR17 in command register 0 + // + + CmdReg0 |= 0x80; + WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0); + + // + // Write a 0x01 to Address register + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01); + + // + // Write to cmd register 3 in the status register location. Cmd3 is initialized + // to turn on the 2x clock multiplier. + // + + DataChar = 0; + ((PBT484_COMMAND3)(&DataChar))->ClockMultiplier = 1; + WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,DataChar); + + // + // Allow 10 uS for the 2x multiplier to stabilize + // + + for (Index = 0; Index < 10; Index++) { + READ_REGISTER_UCHAR(CLOCK_BASE); + } + } + + // + // Initialize Color Palette. Only init the first 2 entries + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0); + + // + // Entry 0 red + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff); + + // + // Entry 0 green + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff); + + // + // Entry 0 blue + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff); + + // + // Entry 1 red + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00); + + // + // Entry 1 green + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00); + + // + // Entry 1 blue + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x90); + + // + // Initialize Cursor and Overscan color. + // + // Set address pointer base. + // Zero 4 entries. + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColorWrAddress.Byte,0); + for (Index = 0; Index < 4*3; Index++) { + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColor.Byte,0); + } + + // + // Initialize cursor RAM + // + // Set address pointer to base of ram. + // Clear both planes + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0); + for (Index = 0; Index < 256; Index++) { + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorRam.Byte,0); + } + + // + // Initialize cursor position registers--cursor off. + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXLow.Byte,0); + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXHigh.Byte,0); + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYLow.Byte,0); + WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYHigh.Byte,0); + + // + // Initialize pixel mask. + // + + WRITE_REGISTER_UCHAR(&BT484_BASE->PixelMask.Byte,0xFF); + + // + // Init Jaguar Registers + // + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->TopOfScreen.Short, + JagInitData.TopOfScreen); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBlank.Short, + JagInitData.HorizontalBlank); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBeginSync.Short, + JagInitData.HorizontalBeginSync); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalEndSync.Short, + JagInitData.HorizontalEndSync); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalLine.Short, + JagInitData.HorizontalLine); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBlank.Short, + JagInitData.VerticalBlank); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBeginSync.Short, + JagInitData.VerticalBeginSync); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalEndSync.Short, + JagInitData.VerticalEndSync); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalLine.Short, + JagInitData.VerticalLine); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->XferLength.Short, + JagInitData.XferLength); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalInterruptLine.Short, + JagInitData.VerticalInterruptLine); + + WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalDisplay.Short, + JagInitData.HorizontalDisplay); + + WRITE_REGISTER_UCHAR(&JAGUAR_BASE->BitBltControl.Byte, + JagInitData.BitBltControl); + + // + // Enable timing. + // + + WRITE_REGISTER_UCHAR(&JAGUAR_BASE->MonitorControl,MONITOR_TIMING_ENABLE); + + // + // Set the video memory to address color one. + // + + Buffer = (PULONG)VXL_VIDEO_MEMORY_BASE; + Limit = (HalpMonitorConfigurationData.HorizontalResolution * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (Index = 0; Index < Limit; Index += 1) { + *Buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; +} + +/* START M001 */ +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; + +#if defined(DBCS) && defined(_MIPS_) + // M006 vvv + 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 ) { +#if defined (R96DBG) + DbgPrint("HAL: 640x480 60Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { +#if defined (R96DBG) + DbgPrint("HAL: 640x480 72Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_640x480_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 800: + if( verticalFrequency < 58 ) { +#if defined (R96DBG) + DbgPrint("HAL: 800x600 56Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_800x600_256_56); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 66 ) { +#if defined (R96DBG) + DbgPrint("HAL: 800x600 60Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_800x600_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { +#if defined (R96DBG) + DbgPrint("HAL: 800x600 72Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_800x600_256_72); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + + case 1024: + // S005 vvv + if( verticalFrequency < 52 ) { +#if defined (R96DBG) + DbgPrint("HAL: 1024x768 87Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else + // S005 ^^^ + if( verticalFrequency < 65 ) { +#if defined (R96DBG) + DbgPrint("HAL: 1024x768 60Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else if( verticalFrequency < 78 ) { +#if defined (R96DBG) + DbgPrint("HAL: 1024x768 70Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } else { +#if defined (R96DBG) + DbgPrint("HAL: 1024x768 87Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + } + break; + default: + // S005 vvv +#if defined (R96DBG) + DbgPrint("HAL: 640x480 60Hz setup\n"); +#endif + HalpCirrusInterpretCmdStream(CL542x_640x480_256_60); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); +// return; + // S005 ^^^ + } + // M006 ^^^ +#else // defined(DBCS) && defined(_MIPS_) + + switch (HalpMonitorConfigurationData.HorizontalResolution) { + case 640: + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("640x480 setup\n"); +#endif + /* END M002 */ + + HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + case 800: + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("800x600 setup\n"); +#endif + /* END M002 */ + + HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + case 1024: + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("1024x768 setup\n"); +#endif + /* END M002 */ + + HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256); + HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE); + break; + default: + return; + } +#endif // defined(DBCS) && defined(_MIPS_) + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("color set\n"); +#endif + + dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT; + dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT; + + + + Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0); + + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f); + + Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00); + Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2)); + /* END M002 */ + + // + // Set the video memory to address color one. + // + Buffer = (PULONG)VIDEO_MEMORY_BASE; +// Limit = (HalpMonitorConfigurationData.HorizontalResolution * +// HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + /* START M002 */ + Limit = (1024 * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + /* END M002 */ + + 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++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), + jValue); + /* END M002 */ + + + } else { + + // + // Single word out + // + + ulPort = *pusCmdStream++; + usValue = *pusCmdStream++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff)); + /* END M002 */ + + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8)); + /* END M002 */ + + + } + + } 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++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulPort, + jValue); + /* END M002 */ + + + } + + } else { + + // + // String word outs + // + + ulPort = *pusCmdStream++; + culCount = *pusCmdStream++; +// +// Buffering out is not use on the Miniport Driver for R96 machine. +// + + /* START L001 */ + + while(culCount--) + { + usValue = *pusCmdStream++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR) + (ulBase + ulPort), (UCHAR) (usValue & 0x00ff)); + Write_Dbg_Uchar((PUCHAR) + (ulBase + ulPort+1), (UCHAR) (usValue >> 8)); + /* END M002 */ + + } + + /* END L001 */ + } + } + + } 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)); + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff)); + /* END M002 */ + + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8)); + /* END M002 */ + + + ulIndex++; + + } + + break; + + // + // Masked out (read, AND, XOR, write) + // + + case MASKOUT: + + ulPort = *pusCmdStream++; + jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort); + jValue &= *pusCmdStream++; + jValue ^= *pusCmdStream++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulBase + ulPort, + jValue); + /* END M002 */ + + break; + + // + // Attribute Controller out + // + + case ATCOUT: + + ulPort = ulBase + *pusCmdStream++; + culCount = *pusCmdStream++; + ulIndex = *pusCmdStream++; + + while (culCount--) { + + // Write Attribute Controller index + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulPort, + (UCHAR)ulIndex); + /* END M002 */ + + + // Write Attribute Controller data + jValue = (UCHAR) *pusCmdStream++; + + /* START M002 */ + Write_Dbg_Uchar((PUCHAR)ulPort, jValue); + /* END M002 */ + + + 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() +/* END M001 */ + +/* START S005 */ +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; + + // Start S006 + // ULONG NowDisplayControlBase; + // PENTRYLO PageFrame; + // ENTRYLO Pte; + // End S006 + + // S00b vvv + 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 }; // S00c + const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 }; + const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 }; + // S00b ^^^ + + const UCHAR Vga_Ini_ColorTable[48] = + { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // S006, S007 + VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B, // S006 + 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, // S006 + 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, // S006 + VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // S006, S007 + VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B, // S006 + 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, // S006 + 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 // S006 + }; + + // Start S006 + //// + //// Check Phisical Address and reinitialize PTE + //// + // + //if (READ_REGISTER_ULONG(R98_PCI1_ID) == 0x10110004) { + // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI1_MEM_BASE) & 0xfffffff0) + // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET; + //} else if (READ_REGISTER_ULONG(R98_PCI2_ID) == 0x10110004) { + // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI2_MEM_BASE) & 0xfffffff0) + // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET; + //} else if (READ_REGISTER_ULONG(R98_PCI3_ID) == 0x10110004) { + // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI3_MEM_BASE) & 0xfffffff0) + // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET; + //} + // + //if (HalpDisplayControlBase != NowDisplayControlBase){ + // // Called by OS, so reinitialize PTE + // HalpDisplayControlBase = NowDisplayControlBase; + // + // Pte.G = 0; + // Pte.V = 1; + // Pte.D = 1; + // + //#if defined(R3000) + // Pte.N = 1; + //#endif + //#if defined(R4000) + // Pte.C = UNCACHED_POLICY; + //#endif + // PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + // Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT; + // + // for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + // *PageFrame++ = Pte; + // Pte.PFN += 1; + // } + // + // Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + // *PageFrame = Pte; + //} + // End S006 + + // + // 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; // S00b + } else { + PLLbits = (PVOID)PLLbits640x480_60; // S00b + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 800 + && HalpMonitorConfigurationData.VerticalResolution == 600 ){ + if( VerticalFrequency > 66 ){ + PLLbits = (PVOID)PLLbits800x600_72; // S00b + } else { + PLLbits = (PVOID)PLLbits800x600_60; // S00b + } + } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024 + && HalpMonitorConfigurationData.VerticalResolution == 768 ){ + PLLbits = (PVOID)PLLbits1024x768_60; // S00b + } else { + PLLbits = (PVOID)PLLbits640x480_60; // S00b + } + + // Set PLL Data + for( i = 0; i <= 6; i++ ){ + for( j = 0; j <= 7; j++ ){ + PLLdata = (PLLbits[i] >> (7-j)) & 1; + if( i == 6 && j == 7 ) + PLLdata |= 2; // Set ~HOLD bit on last write + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata); + } + } + + // Verify 21030 is idle ( check busy bit on Command Status Register ) + while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ // S006 + } + + // 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 ){ // S006 + } + + // Start S006 + // Set to Video Base Address Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 ); + // End S006 + + // 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 ); + + KeStallExecutionProcessor(10000L); // S00b + + // 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++ ){ // S006 + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 ); + } + + // Set to Video Valid Register + WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 ); + + // + // Set Video Memory to address color one. + // + + Buffer = (PULONG)VIDEO_MEMORY_BASE; + Limit = (HalpMonitorConfigurationData.HorizontalResolution * + HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG); + + for (Index = 0; Index < Limit; Index += 1) { + *Buffer++ = 0x01010101; + } + + // + // Initialize the current display column, row, and ownership values. + // + + HalpColumn = 0; + HalpRow = 0; + HalpDisplayOwnedByHal = TRUE; + return; + +} + +/* END S005 */ + +VOID +HalDisplayString ( + PUCHAR String + ) + +/*++ + +Routine Description: + + This routine displays a character string on the display screen. + +Arguments: + + String - Supplies a pointer to the characters that are to be displayed. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + ENTRYLO SavedPte; + // Start S006 + ULONG NowDisplayControlBase; + PENTRYLO PageFrame; + ENTRYLO Pte; + LONG Index; + // End S006 + + // + // 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. + // + + /* START M002 */ +#if defined (R96DBG) + DbgPrint("HalDisplayString\n"); +#endif + /* END M002 */ + + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + +#if defined(_DUO_) + + KiAcquireSpinLock(&HalpDisplayAdapterLock); + +#endif + + SavedPte = *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))); + + KeFlushCurrentTb(); + *((PENTRYLO)(PDE_BASE | + ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte; + + // Start S006 + if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) { + if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) { + NowDisplayControlBase = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE + + TGA_REG_SPC_OFFSET; + } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) { + NowDisplayControlBase = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE + + TGA_REG_SPC_OFFSET; + } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) { + NowDisplayControlBase = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0) + | R98_PCI_SPACE_BASE + + TGA_REG_SPC_OFFSET; + } + + if (HalpDisplayControlBase != NowDisplayControlBase){ + HalpDisplayControlBase = NowDisplayControlBase; + + Pte.G = 0; + Pte.V = 1; + Pte.D = 1; + +#if defined(R3000) + Pte.N = 1; +#endif +#if defined(R4000) + Pte.C = UNCACHED_POLICY; +#endif + PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT))); + Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT; + + for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) { + *PageFrame++ = Pte; + Pte.PFN += 1; + } + + Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT; + *PageFrame = Pte; + } + } + // End S006 + + // + // 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) { + HalpDisplayControllerSetup(); + HalpInitDisplayStringIntoNvram(); // S009 + HalpResetX86DisplayAdapter(); //K000 + } + +// HalpStringIntoNvram(HalpColumn, HalpRow, String); // S009, S00a + HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a + + // + // Display characters until a null byte is encountered. + // + + while (*String != 0) { + HalpDisplayCharacter(*String++); + } + + HalpStringBufferCopyToNvram(); // S00a + + // + // Restore the previous mapping for the current process, flush the TB, + // release the display adapter spin lock, and lower IRQL to its previous + // level. + // + + KeFlushCurrentTb(); + *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte; + +#if defined(_DUO_) + + KiReleaseSpinLock(&HalpDisplayAdapterLock); + +#endif + + KeLowerIrql(OldIrql); + return; +} + +VOID +HalpDisplayCharacter ( + 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; + 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 { + /* START M002 */ + HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE, + (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine), + HalpScrollLength); + /* END M002 */ + + Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength; + for (Index = 0; Index < HalpScrollLine; Index += 1) { + *Destination++ = 1; + } + } + + HalpStringBufferCopyToNvram(); // S00a + HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a + + } else if (Character == '\r') { + HalpColumn = 0; + + HalpStringBufferCopyToNvram(); // S00a + HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a + + } else { + HalStringIntoBuffer( Character ); // S00a + + if ((Character < HalpFontHeader->FirstCharacter) || + (Character > HalpFontHeader->LastCharacter)) { + Character = HalpFontHeader->DefaultCharacter; + } + + Character -= HalpFontHeader->FirstCharacter; + HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset); + } + + return; +} + +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 +HalpOutputCharacter( + 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; + 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. + // + + Destination = (PUCHAR)(VIDEO_MEMORY_BASE + + (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth)); + + for (I = 0; I < HalpCharacterHeight; I += 1) { + FontValue = 0; + for (J = 0; J < HalpBytesPerRow; J += 1) { + FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8)); + } + + Glyph += 1; + for (J = 0; J < HalpCharacterWidth ; J += 1) { + *Destination++ = (UCHAR)((FontValue >> 31) ^ 1); // S002 + FontValue <<= 1; + } + + if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){ + Destination += + (1024 - HalpCharacterWidth); + }else{ + Destination += + (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth); + } + } + HalpColumn += 1; + return; +} + +/* START M002 */ +VOID +Write_Dbg_Uchar( + PUCHAR Ioadress, +UCHAR Moji +) + +{ +#if defined (R96DBG) + DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji); +#endif + WRITE_PORT_UCHAR(Ioadress,Moji); +} +/* END M002 */ + +/* START M003 */ + +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; /* M004 */ + PUCHAR Srcend; /* M004 */ + + if ( (Source == Destination) || (Length == 0) ) { /* M004 */ + return; + } + + if ((Source < Destination)&((Source + Length) > Destination)) { /* M004 vvv */ + if((Destination - Source) > 4){ + Remainder = (UCHAR)(Length &0x03); // S002 + 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); // S002 + 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++; /* M004 ^^^*/ + } + } +} + +/* END M003 */ diff --git a/private/ntos/nthals/halr98mp/mips/jxebsup.c b/private/ntos/nthals/halr98mp/mips/jxebsup.c new file mode 100644 index 000000000..464a35673 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxebsup.c @@ -0,0 +1,1275 @@ +#ident "@(#) NEC jxebsup.c 1.13 95/06/19 11:10:34" +/*++ + +Copyright (c) 1990-1994 Microsoft Corporation + +Module Name: + + jxebsup.c + +Abstract: + + The module provides the EISA bus support for JAZZ systems. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/25 T.Samezima + * + * HalpCreateEisaStructure + * + * Del #ifdef of Duo + * Disable NMI Interrupt + * + * Change Parameter of initialize interrupt + * Irql Level + * + *********************************************************************** + * + * S002 94.04/19 T.Samezima + * + * HalpEisaDispatch + * + * Del #ifdef of Duo + * K001 94/5/31 (Tue) N.Kugimoto + * Add SpinLock HalpEisaMapTransfer() + * + *********************************************************************** + * + * S003 94.06/01 T.Samezima + * + * HalHandleNMI + * + * Del display interrupt information + * + *********************************************************************** + * + * S004 94.6/13 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S005 94.7/5 T.Samezima + * + * Chg base i/o address to kseg1_base + * + * + *********************************************************************** + * + * S006 94.8/22 T.Samezima on SNES + * + * Add Move EISA NMI enable logic from HalpInitializeInterrupts() + * + *********************************************************************** + * + * S007 94.8/23 T.Samezima + * + * Chg Register read size from long to short + * + * + * K001 94/9/13 N.Kugimoto + * Add For a spurious interrupt PIC IR7 + * K002 94/9/13 N.Kugimoto + * Chg Interrupt Ack reg non USHORT.must UCHAR!!. + * + * S008 94.10/13 T.Samezima + * Fix Version Up at build807 + * S009 94.11/21 T.Samezima + * Chg Disable EISA NMI + * Disable ASSERT(). because. senseless ASSERT on r98 + * + * K003 95/04/24 N.Kugimoto + * Add DUMMDMA + * LR4360 workaround. can't TLB flush while dma. + * So ESC DMAC channel2 use. + * A002 1995/6/17 ataka@oa2.kb.nec.co.jp + * - resolve compile wornings. + */ + +#include "halp.h" +#include "eisa.h" +#include "bugcodes.h" + +// +// Define the context structure for use by the interrupt routine. +// + +// Start S008 +typedef +BOOLEAN +(*PSECONDARY_DISPATCH)( + PKINTERRUPT Interrupt + ); + +// End S008 +// 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; + +// Start S008 +// Define EISA bus interrupt affinity. +// + +KAFFINITY HalpEisaBusAffinity; +// End S008 + +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; // S006 + + /* Start S001, S008 */ + // + // Directly connect the EISA interrupt dispatcher to the level for + // EISA bus interrupt. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization. + // + + PCR->InterruptRoutine[EISA_DEVICE_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch; // A002 + /* End S001, S008 */ + + // + // Raise the IRQL while the EISA interrupt controller is initalized. + // + + /* Start S001 */ + KeRaiseIrql(INT1_LEVEL, &oldIrql); + /* End S001 */ + + // + // 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); // S004 + + 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; + + // Start S008 + // Set EISA bus interrupt affinity. + // + + HalpEisaBusAffinity = PCR->SetMember; + // End S008 + + // + // Restore IRQL level. + // + + KeLowerIrql(oldIrql); + + /* Start S001, S008 */ + // + // Enable eisa interrupt on LR4360 + // + KiAcquireSpinLock(&HalpSystemInterruptLock); + + HalpBuiltinInterruptEnable |= iREN_ENABLE_EISA_INTERRUPT; + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + + KiReleaseSpinLock(&HalpSystemInterruptLock); + + /* End S008 */ + // + // 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 + ); + /* End S001 */ + + // Start S006 + charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus ); +// charBuffer = (charBuffer & 0x03); // S009 + charBuffer = ((charBuffer & 0x03) | 0X0C); // S009 + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus, + charBuffer + ); + /* Start S001 in xxinitnt.c */ + charBuffer = READ_REGISTER_UCHAR( + &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl + ); + /* End S001 in xxinitnt.c */ +// charBuffer = ( (charBuffer & 0x01) | 0x0e ); // S009 + charBuffer = (charBuffer & 0x01); // S009 + WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl, + charBuffer ); // S007 + // End S006 + + 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; // K001 + + BytePtr = (PUCHAR) &Offset; + +// ASSERT(Offset >= 0x100000); // S009 + + adapterMode = AdapterObject->AdapterMode; + + // + // Check to see if this request is for a master I/O card. + // + + if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) { + + // + // Set the mode, Disable the request and return. + // + + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } else { + + // + // This request is for DMA controller 1 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + + // + // Unmask the DMA channel. + // + + WRITE_REGISTER_UCHAR( + &dmaControl->SingleMask, + (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber) + ); + + } + + return; + } + + + // + // Determine the mode based on the transfer direction. + // + + ((PDMA_EISA_MODE) &adapterMode)->TransferType = WriteToDevice ? + WRITE_TRANSFER : READ_TRANSFER; + + // K001 + // grab the spinlock for the system DMA controller + // +#if !defined(DUMMYDMA) + KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql ); +#endif + // + // 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) + ); + } +#if !defined(DUMMYDMA) + KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql); +#endif +} + + +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 + ); + } +} + +// Start S008 +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_UCHAR( (PVOID)(LR_PHYSICAL_PCI_INT_ACK_BASE | KSEG1_BASE)); + + // + // 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; +} +// End S008 + +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/halr98mp/mips/jxenvirv.c b/private/ntos/nthals/halr98mp/mips/jxenvirv.c new file mode 100644 index 000000000..5e9446d73 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxenvirv.c @@ -0,0 +1,818 @@ +#pragma comment(exestr, "@(#) jxenvirv.c 1.8 94/12/06 15:07:37 nec") +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxenvirv.c + +Abstract: + + This module implements the HAL get and set environment variable routines + for a MIPS system. + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * K001 94.5/31 (Tue) N.Kugimoto + * Del No Map TLB. & nvram base define -->def.h + * Add Nvram write enable + * K002 94/6/10 (Fri) N.Kugimoto + * Chg Compile err del. + * K003 94/8/29 (Mon) N.Kugimoto + * -1 BUG HalpUnmapNvram() stsr register write value bug. + * -2 Chg HalpMapNvram() stsr register write value is absolute. + * K004 94/10/11 N.Kugimoto + * H/W Work Around. NVRAM can't write protect!!. + * K005 94/12/06 N.Kugimoto + * Add ESM Interface + * -2 Miss ;; -->, + */ + +#include "halp.h" +#include "arccodes.h" +#include "jazznvr.h" +#include "string.h" + +// +// Define base address at which to map NVRAM. +// +#if !defined(_R98_) // K001 +#define NVRAM_MEMORY_BASE PTE_BASE +#endif +// +// 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; +#if defined(_R98_) // K001 + // + // Nvram Write enable + // K002 + WRITE_REGISTER_ULONG( + &( PMC_CONTROL1 )->STSR.Long, + STSR_NVWINH_ENABLE //K003-2 + ); + +#else // K001 + ENTRYLO NvramPte; + PENTRYLO PtePointer; + + // + // Construct a PTE to map NVRAM into the address space of the current + // process. + // + + NvramPte.X1 = 0; + NvramPte.PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT; + NvramPte.G = 0; + NvramPte.V = 1; + NvramPte.D = 1; + +#if defined(R3000) + + NvramPte.N = 1; + +#endif + +#if defined(R4000) + + NvramPte.C = UNCACHED_POLICY; + +#endif + + // + // Raise IRQL to the highest level, flush the TB, map the NVRAM into + // the address space of the current process, and return the previous + // IRQL. + // + + PtePointer = (PENTRYLO)PDE_BASE; +#endif // _R98_ + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); +#if !defined(_R98_) + SavedPte[0] = PtePointer[0]; + SavedPte[1] = PtePointer[1]; + KeFlushCurrentTb(); + PtePointer[0] = NvramPte; + NvramPte.PFN += 1; + PtePointer[1] = NvramPte; +#endif //_R98_ + 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 defined(_R98_) // K001 +#if 0 //K004 vvvvv + // + // Nvram write disable + // K002 + WRITE_REGISTER_ULONG( + &( PMC_CONTROL1 )->STSR.Long, + STSR_NVWINH_DISABLE //K003-1 + ); + +#endif //K004 ^^^^^ +#else + PENTRYLO PtePointer; + // + // Restore the previous mapping for the current process, flush the TB, + // and lower IRQL to its previous level. + // + + PtePointer = (PENTRYLO)PDE_BASE; + KeFlushCurrentTb(); + PtePointer[0] = SavedPte[0]; + PtePointer[1] = SavedPte[1]; +#endif //_R98_ + 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; + + // + // 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); + 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; + + // + // 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); + return Status; +} + + + +#if defined(_R98_) //K005 Start VVVVV + +BOOLEAN +HalNvramWrite( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Write Byte Count + PVOID Buffer // Pointer Of Buffer Write to NVRAM +){ + // Write into NVRAM + return HalpNvramReadWrite(Offset,Count,Buffer,1); +} + +BOOLEAN +HalNvramRead( + ULONG Offset, // Offset Of ESM NVRAM + ULONG Count, // Read Byte Count + PVOID Buffer // Pointer Of Buffer Read From NVRAM +){ + // Read From NVRAM + return HalpNvramReadWrite(Offset,Count,Buffer,0); +} + +BOOLEAN +HalpNvramReadWrite( + ULONG Offset, // Read/Write offset of ESM NVRAM + ULONG Count, // Read/Write Byte Count + PVOID Buffer, // read/Write Pointer + ULONG Write // Operation +){ + + 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;iReceiveBuffer); + + // + // 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; +#if !defined(_R98_) + ULONG KdPortEntry; +#endif //!defined(_R98_) K002 + 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; + } +#if !defined(_R98_) // K001 + // + // Map the serial port into the system virtual address space by loading + // a TB entry. + // + + HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT; + HalpPte[0].G = 1; + HalpPte[0].V = 1; + HalpPte[0].D = 1; + +#if defined(R3000) + + // + // Set the TB entry and set the noncached bit in the PTE that will + // map the serial controller. + // + + KdPortEntry = KDPORT_ENTRY; + HalpPte[0].N = 1; + +#endif + +#if defined(R4000) + + // + // Allocate a TB entry, set the uncached policy in the PTE that will + // map the serial controller, and initialize the second PTE. + // + + KdPortEntry = HalpAllocateTbEntry(); + HalpPte[0].C = UNCACHED_POLICY; + + HalpPte[1].PFN = 0; + HalpPte[1].G = 1; + HalpPte[1].V = 0; + HalpPte[1].D = 0; + HalpPte[1].C = 0; + +#endif +#endif // _R98_ + + KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE; + +#if !defined(_R98_) // K001 + // + // Map the serial controller through a fixed TB entry. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], + (PVOID)SP_VIRTUAL_BASE, + KdPortEntry); +#endif // _R98_ + // + // 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. + // +#if !defined(_R98_) // K002 +#if defined(R4000) + + HalpFreeTbEntry(); + +#endif +#endif + 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. + // +#if !defined(_R98_) // K001 +#if defined(R4000) + + HalpFreeTbEntry(); + +#endif +#endif // _R98_ + 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. + +--*/ + +{ +#if !defined(_R98_) // K001 + ULONG KdPortEntry; + +#if defined(R3000) + + // + // Set the TB entry that will be used to map the serial controller. + // + + KdPortEntry = KDPORT_ENTRY; + +#endif + +#if defined(R4000) + + // + // Allocate the TB entry that will be used to map the serial controller. + // + + KdPortEntry = HalpAllocateTbEntry(); + +#endif + + // + // Map the serial controller through a allocated TB entry. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0], + (PVOID)SP_VIRTUAL_BASE, + KdPortEntry); +#endif // _R98_ + 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/halr98mp/mips/jxreturn.c b/private/ntos/nthals/halr98mp/mips/jxreturn.c new file mode 100644 index 000000000..0afe8eed8 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxreturn.c @@ -0,0 +1,189 @@ +#pragma comment(exestr, "@(#) jxreturn.c 1.5 94/10/17 11:47:45 nec") +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + jxreturn.c + +Abstract: + + This module implements the HAL return to firmware function. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * K001 95/5/31 (Tue) N.Kugimoto + * Del TLB mapping del. + * + * S002 94/6/13 (Mon) T.Samezima + * Chg Compile err del + * + * K002 94/10/11 (Tue) N.Kugimoto + * Fix 807 Base + */ + +#include "halp.h" +#define HEADER_FILE +#include "kxmips.h" + +// +// Define keyboard registers structure. +// + +typedef struct _KBD_REGISTERS { + union { + UCHAR Output; + UCHAR Input; + } Data; + + union { + UCHAR Status; + UCHAR Command; + } Control; +} KBD_REGISTERS; + +#define KBD_IBF_MASK 2 // input buffer full mask + +#define KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status)) +#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte) +#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte) +#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output)) + +VOID +HalReturnToFirmware( + IN FIRMWARE_REENTRY Routine + ) + +/*++ + +Routine Description: + + This function returns control to the specified firmware routine. + In most cases it generates a soft reset by asserting the reset line + trough the keyboard controller. + The Keyboard controller is mapped using the same virtual address + and the same fixed entry as the DMA. + +Arguments: + + Routine - Supplies a value indicating which firmware routine to invoke. + +Return Value: + + Does not return. + +--*/ + +{ + + KIRQL OldIrql; +#if defined(_R98_) // K001 + // S001 + volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)(KEYBOARD_PHYSICAL_BASE|KSEG1_BASE); +#else + ENTRYLO Pte[2]; + volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE; + +#endif // _R98_ + // + // Disable Interrupts. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + + // + // Case on the type of return. + // + + switch (Routine) { + case HalHaltRoutine: + + // + // Hang looping. + // + + for (;;) { + } + + case HalPowerDownRoutine: + case HalRestartRoutine: + case HalRebootRoutine: + case HalInteractiveModeRoutine: + + // K002 + // Reset ISA Display Adapter to 80x25 color text mode. + // + + HalpResetX86DisplayAdapter(); + +#if !defined(_R98_) // K001 + // + // Map the keyboard controller + // + + Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT; + Pte[0].G = 1; + Pte[0].V = 1; + Pte[0].D = 1; + + #if defined(R3000) + + Pte[0].N = 1; + + #endif + + #if defined(R4000) + + // + // set second page to global and not valid. + // + + Pte[0].C = UNCACHED_POLICY; + Pte[1].G = 1; + Pte[1].V = 0; + + #endif + + // + // Map keyboard controller using virtual address of DMA controller. + // + + KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0], + (PVOID)DMA_VIRTUAL_BASE, + DMA_ENTRY); +#endif // K001 + + + // + // 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/halr98mp/mips/jxsysint.c b/private/ntos/nthals/halr98mp/mips/jxsysint.c new file mode 100644 index 000000000..5b3f855c3 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxsysint.c @@ -0,0 +1,454 @@ +#ident "@(#) NEC jxsysint.c 1.13 94/11/08 16:20:09" +/*++ + +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 R98 + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * M001 94.03/25-5/31 T.Samezima + * + * Change Interrupt control + * Irql level + * + * Add Correspond to PCIBus + * Exchange mask data + * define table of ipi interrupt request + * + * Del #ifdef DUO + * + *********************************************************************** + * + * S002 94.06/02 T.Samezima + * + * Add HalGetInterruptVector + * + *********************************************************************** + * + * S003 94,6/10 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S004 94,7/5 T.Samezima + * + * Chg Mask value + * Maximun EISA vecter + * + *********************************************************************** + * + * S005 94,7/8 T.Samezima + * + * Chg Maximun EISA vecter + * + *********************************************************************** + * + * S006 94,7/21 T.Samezima + * + * Chg Fixd to PCI + * + * + *********************************************************************** + * + * S007 94,8/22 T.Samezima on SNES + * + * Chg Designate member + * + *********************************************************************** + * + * K001 94/09/26 N.Kugimoto + * Mov Move Source code to r98busdat.c + *********************************************************************** + * + * S008 94/09/30 T.Samezima + * + * Bug Miss define of PCI Interrupt vector. + * + * S009 94/11/08 T.Samezima + * Bug Miss define of IpiRequestMask. + * + * + */ + +#include "halp.h" + +/* Start M001 */ +// +// Define Ipi Interrupt Reqest value table. +// +/* Start S003 */ +ULONG HalpIpiIntRequestMask[] = { + IntIR_REQUEST_IPI | (0x00 << IntIR_CPU3_BIT) , // 0000 -> 0000 + IntIR_REQUEST_IPI | (0x08 << IntIR_CPU3_BIT) , // 0001 -> 1000 + IntIR_REQUEST_IPI | (0x04 << IntIR_CPU3_BIT) , // 0010 -> 0100 + IntIR_REQUEST_IPI | (0x0c << IntIR_CPU3_BIT) , // 0011 -> 1100 + IntIR_REQUEST_IPI | (0x02 << IntIR_CPU3_BIT) , // 0100 -> 0010 + IntIR_REQUEST_IPI | (0x0a << IntIR_CPU3_BIT) , // 0101 -> 1010 + IntIR_REQUEST_IPI | (0x06 << IntIR_CPU3_BIT) , // 0110 -> 0110 + IntIR_REQUEST_IPI | (0x0e << IntIR_CPU3_BIT) , // 0111 -> 1110 + IntIR_REQUEST_IPI | (0x01 << IntIR_CPU3_BIT) , // 1000 -> 0001 + IntIR_REQUEST_IPI | (0x09 << IntIR_CPU3_BIT) , // 1001 -> 1001 + IntIR_REQUEST_IPI | (0x05 << IntIR_CPU3_BIT) , // 1010 -> 0101 + IntIR_REQUEST_IPI | (0x0d << IntIR_CPU3_BIT) , // 1011 -> 1101 + IntIR_REQUEST_IPI | (0x03 << IntIR_CPU3_BIT) , // 1100 -> 0011 // S009 + IntIR_REQUEST_IPI | (0x0b << IntIR_CPU3_BIT) , // 1101 -> 1011 + IntIR_REQUEST_IPI | (0x07 << IntIR_CPU3_BIT) , // 1110 -> 0111 + IntIR_REQUEST_IPI | (0x0f << IntIR_CPU3_BIT) // 1111 -> 1111 + }; +/* End S003 */ +/* End M001 */ + + +VOID +HalDisableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql + ) + +/*++ + +Routine Description: + + This routine disables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is disabled. + + Irql - Supplies the IRQL of the interrupting source. + +Return Value: + + None. + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + // + // If the vector number is within the range of builtin devices, then + // disable the builtin device interrupt. + // + + if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) { + HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1)); + /* Start M001 */ + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + /* End M001 */ + } + + // + // If the vector number is within the range of the EISA interrupts, then + // disable the EISA interrrupt. + // + + /* Start M001 */ + /* Start S003 */ + if (Vector >= EISA_VECTORS && + Vector <= MAXIMUM_EISA_VECTORS && // S004 + Irql == INT1_LEVEL) { + HalpDisableEisaInterrupt(Vector); + } + /* End S003 */ + + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + /* Start S006 */ + if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) { + HalpDisablePciInterrupt(Vector); + } + /* End S006 */ + /* End M001 */ + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return; +} + +BOOLEAN +HalEnableSystemInterrupt ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +/*++ + +Routine Description: + + This routine enables the specified system interrupt. + +Arguments: + + Vector - Supplies the vector of the system interrupt that is enabled. + + Irql - Supplies the IRQL of the interrupting source. + + InterruptMode - Supplies the mode of the interrupt; LevelSensitive or + Latched. + +Return Value: + + TRUE if the system interrupt was enabled + +--*/ + +{ + + KIRQL OldIrql; + + // + // Raise IRQL to the highest level and acquire device enable spinlock. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + + // + // If the vector number is within the range of builtin devices, then + // enable the builtin device interrupt. + // + + if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) { + HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1)); + /* Start M001 */ + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + /* End M001 */ + } + + // + // If the vector number is within the range of the EISA interrupts, then + // enable the EISA interrrupt and set the Level/Edge register. + // + + /* Start M001 */ + /* Start S003 */ + if (Vector >= EISA_VECTORS && + Vector <= MAXIMUM_EISA_VECTORS && // S005 + Irql == INT1_LEVEL) { + HalpEnableEisaInterrupt( Vector, InterruptMode); + } + /* End S003 */ + + // + // If the vector number is within the range of the PCI interrupts, then + // disable the PCI interrrupt. + // + + /* Start S006 */ + if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) { + HalpEnablePciInterrupt(Vector); + } + /* End S006 */ + /* End M001 */ + + // + // Release the device enable spin loc and lower IRQL to the previous level. + // + + KiReleaseSpinLock(&HalpSystemInterruptLock); + KeLowerIrql(OldIrql); + return TRUE; +} + +VOID +HalRequestIpi ( + IN ULONG Mask + ) + +/*++ + +Routine Description: + + This routine requests an interprocessor interrupt on a set of processors. + + N.B. This routine must ensure that the interrupt is posted at the target + processor(s) before returning. + +Arguments: + + Mask - Supplies the set of processors that are sent an interprocessor + interrupt. + +Return Value: + + None. + +--*/ + +{ + /* Start M001 */ + ULONG buffer; + /* End M001 */ + + // + // Request an interprocessor interrupt on each of the specified target + // processors. + // + + /* Start M001 */ + buffer = HalpIpiIntRequestMask[(Mask & 0xf)] | // S004 + ( (((PCR->Prcb)->Number) & 0x3) << IntIR_CODE_BIT ); + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->IntIR.Long, buffer); // S007 + /* End M001 */ + + return; +} + +#if 0 //K001 +ULONG +HalGetInterruptVector( + IN INTERFACE_TYPE InterfaceType, + IN ULONG BusNumber, + 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: + + InterfaceType - Supplies the type of bus which the vector is for. + + BusNumber - Supplies the bus number for the device. + + BusInterruptLevel - Supplies the bus specific interrupt level. + + BusInterruptVector - Supplies the bus specific interrupt vector. + + Irql - Returns the system request priority. + + Affinity - Returns the affinity for the requested vector. + +Return Value: + + Returns the system interrupt vector corresponding to the specified device. + +--*/ + +{ + + // + // N.B. On Jazz systems which are single processor systems, all interrupts + // go to processor 0. On Duo systems both processors could handle + // interrupts, but the hardware does not arbitrate and distribute + // interrupts, and therefore, both processors would get all interrupts. + // + + *Affinity = 1; + + // + // If this is for the internal bus then just return the passed parameter. + // + + if (InterfaceType == Internal) { + + // + // Return the passed parameters. + // + + *Irql = (KIRQL)BusInterruptLevel; + /* Start S002 */ + return(BusInterruptVector + DEVICE_VECTORS); + /* End S002 */ + } + + /* Start S002 */ + // + // If this is for the pci bus then just return the passed parameter. + // + + if (InterfaceType == PCIBus) { + + // + // Return the passed parameters. + // + + *Irql = INT1_LEVEL; + return(PCI_DEVICE_VECTOR); // S008 + } + /* End S002 */ + + if (InterfaceType != Isa && InterfaceType != Eisa) { + + // + // Not on this system return nothing. + // + + *Affinity = 0; + *Irql = 0; + return(0); + + } + + // + // Jazz and Duo only have one I/O bus which is an EISA, so the bus + // number and the bus interrupt vector are unused. + // + // The IRQL level is always equal to the EISA level. + // + + /* Start S001 */ + *Irql = INT1_LEVEL; + /* End S001 */ + + // + // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa + // hardware. + // + + if (BusInterruptLevel == 2) { + BusInterruptLevel = 9; + } + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + return(BusInterruptLevel + EISA_VECTORS); +} + +#endif diff --git a/private/ntos/nthals/halr98mp/mips/jxtime.c b/private/ntos/nthals/halr98mp/mips/jxtime.c new file mode 100644 index 000000000..b9d543f1b --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxtime.c @@ -0,0 +1,313 @@ +#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. + // + + /* Start S001 */ + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + /* End S001 */ + 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. + // + + /* Start S001 */ + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + /* End S001 */ + 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/halr98mp/mips/jxusage.c b/private/ntos/nthals/halr98mp/mips/jxusage.c new file mode 100644 index 000000000..dd480366e --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/jxusage.c @@ -0,0 +1,497 @@ +#ident "@(#) NEC jxusage.c 1.3 94/10/19 22:05:01" +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ixusage.c + +Abstract: + +Author: + + Ken Reneris (kenr) + +Environment: + + Kernel mode only. + +Revision History: + + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994 + - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS + CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994 + - delete HalpEnableInterruptHandler, HalpRegisterVector + - change IDT vector LOOP, R98 report up to DEVICE_VECTORS + - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994 + - resolve compile error + +--*/ + +#include "halp.h" + + +// +// Array to remember hal's IDT usage +// + +#if !defined(_R98_) // CMP001 +extern ADDRESS_USAGE *HalpAddressUsageList; +extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif // _R98 + +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 (_R98_) // CHG001 +VOID +HalpEnableInterruptHandler ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql, + IN VOID (*HalInterruptServiceRoutine)(VOID), + IN KINTERRUPT_MODE InterruptMode + ) +/*++ + +Routine Description: + + This function connects & registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql); + + + // + // Connect the IDT and enable the vector now + // + + KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine); + HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode); +} + + + +VOID +HalpRegisterVector ( + IN UCHAR ReportFlags, + IN ULONG BusInterruptVector, + IN ULONG SystemInterruptVector, + IN KIRQL SystemIrql + ) +/*++ + +Routine Description: + + This registers an IDT vectors usage by the HAL. + +Arguments: + +Return Value: + +--*/ +{ +#if DBG + // There are only 0ff IDT entries... + ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR && + BusInterruptVector <= MAXIMUM_IDTVECTOR); +#endif + + // + // Remember which vector the hal is connecting so it can be reported + // later on + // + + HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags; + HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql; + HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector; +} +#endif // _R98_ + + +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(_R98_) // CHG001 + for(i=0; i < DEVICE_VECTORS; i++) { // ADD001 + HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched; + HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; + } +#else + for(i=0; i < PRIMARY_VECTOR_BASE; i++) { + if (!(HalpIDTUsage[i].Flags & IDTOwned)) { + HalpIDTUsage[i].Flags = InternalUsage; + HalpIDTUsage[i].BusReleativeVector = (UCHAR) i; + } + } +#endif + + for(pass=0; pass < 2; pass++) { + if (pass == 0) { + // + // First pass - build resource lists for resources reported + // reported against device usage. + // + + reporton = DeviceUsage & ~IDTOwned; + interfacetype = DeviceInterfaceToUse; + } else { + + // + // Second pass = build reousce lists for resources reported + // as internal usage. + // + + reporton = InternalUsage & ~IDTOwned; + interfacetype = Internal; + } + + CurrentIDT = 0; + CurrentElement = 0; + CurrentAddress = HalpAddressUsageList; + + for (; ;) { + if (CurrentIDT <= MAXIMUM_VECTOR) { // CHG001 + // + // Check to see if CurrentIDT needs to be reported + // + + if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) { + // Don't report on this one + CurrentIDT++; + continue; + } + + // + // Report CurrentIDT resource + // + + RPartialDesc.Type = CmResourceTypeInterrupt; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + RPartialDesc.Flags = + HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ? + CM_RESOURCE_INTERRUPT_LATCHED : + CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector; + RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors; + + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + TPartialDesc.u.Interrupt.Vector = CurrentIDT; + TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql; + + CurrentIDT++; + + } else { + // + // Check to see if CurrentAddress needs to be reported + // + + if (!CurrentAddress) { + break; // No addresses left + } + + if (!(CurrentAddress->Flags & reporton)) { + // Don't report on this list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + if (!CurrentAddress->Element[CurrentElement].Length) { + // End of current list, go to next list + CurrentElement = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + // + // Report CurrentAddress + // + + RPartialDesc.Type = (UCHAR) CurrentAddress->Type; + RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive; + + if (RPartialDesc.Type == CmResourceTypePort) { + i = 1; // address space port + RPartialDesc.Flags = CM_RESOURCE_PORT_IO; + } else { + i = 0; // address space memory + RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE; + } + + // Notice: assuming u.Memory and u.Port have the same layout + RPartialDesc.u.Memory.Start.HighPart = 0; + RPartialDesc.u.Memory.Start.LowPart = + CurrentAddress->Element[CurrentElement].Start; + + RPartialDesc.u.Memory.Length = + CurrentAddress->Element[CurrentElement].Length; + + // translated address = Raw address + RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc); + HalTranslateBusAddress ( + interfacetype, // device bus or internal + 0, // bus number + RPartialDesc.u.Memory.Start, // source address + &i, // address space + &TPartialDesc.u.Memory.Start ); // translated address + + if (RPartialDesc.Type == CmResourceTypePort && i == 0) { + TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY; + } + + CurrentElement++; + } + + // + // Include the current resource in the HALs list + // + + if (pRFullDesc->InterfaceType != interfacetype) { + // + // Interface type changed, add another full section + // + + RawResourceList->Count++; + TranslatedResourceList->Count++; + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + + pRFullDesc->InterfaceType = interfacetype; + pTFullDesc->InterfaceType = interfacetype; + + pRPartList = &pRFullDesc->PartialResourceList; + pTPartList = &pTFullDesc->PartialResourceList; + + // + // Bump current location pointers up + // + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + } + + + pRPartList->Count++; + pTPartList->Count++; + RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc); + RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc); + + pRCurLoc++; + pTCurLoc++; + } + } + + ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) ); + + // + // The HAL's resource usage structures have been built + // Sort the partial lists based on the Raw resource values + // + + pRFullDesc = RawResourceList->List; + pTFullDesc = TranslatedResourceList->List; + + for (i=0; i < RawResourceList->Count; i++) { + + pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors; + pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors; + Count = pRFullDesc->PartialResourceList.Count; + + for (j=0; j < Count; j++) { + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + + pRSortLoc = pRCurLoc; + pTSortLoc = pTCurLoc; + + for (k=j; k < Count; k++) { + HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue); + + if (sortscale < curscale || + (sortscale == curscale && + RtlLargeIntegerLessThan (sortvalue, curvalue)) ) { + + // + // Swap the elements.. + // + + RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc); + RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc); + RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc); + + // swap translated descriptor as well + RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc); + RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc); + RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc); + + // get new curscale & curvalue + HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue); + } + + pRSortLoc++; + pTSortLoc++; + } + + pRCurLoc++; + pTCurLoc++; + } + + pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc; + pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc; + } + + + // + // Inform the IO system of our resources.. + // + + IoReportHalResourceUsage ( + HalName, + RawResourceList, + TranslatedResourceList, + ListSize + ); + + ExFreePool (RawResourceList); + ExFreePool (TranslatedResourceList); +} diff --git a/private/ntos/nthals/halr98mp/mips/mipsdat.c b/private/ntos/nthals/halr98mp/mips/mipsdat.c new file mode 100644 index 000000000..23a92be23 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/mipsdat.c @@ -0,0 +1,144 @@ +#ident "@(#) NEC mipsdat.c 1.2 95/06/19 11:11:45" +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ixdat.c + +Abstract: + + Declares various data which is initialize data, or pagable data. + +Author: + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +/*++ + +Revision History: + + ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994 + - add HalpMapRegisterMemorySpace + BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994 + - change HalpMapRegisterMemorySpace Size + CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994 + - change HalpIDTUsage size to MAXIMUM_VECTOR + CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994 + - resolve compile error + A002 ataka@oa2.kb.nec.co.jp 1995/6/17 + - marge 1050 +--*/ + + + + +#include "halp.h" + +#ifdef ALLOC_DATA_PRAGMA +#pragma data_seg("INIT") +#endif + +// +// The following data is only valid during system initialiation +// and the memory will be re-claimed by the system afterwards +// + +ADDRESS_USAGE HalpDefaultPcIoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA + EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA + EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA + + EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC + EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC + + EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word + EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe + + EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B) + EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A + + EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable + EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports + 0,0 + } +}; + +ADDRESS_USAGE HalpEisaIoSpace = { + NULL, CmResourceTypePort, InternalUsage, + { + EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA + EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA + + EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI + EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted + + EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers + + EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable + 0, 0 + } +}; + +#define R98_MAPREGISTER_BASE 100 // CMP001 + +// BUG001 +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 usage.c +// + +ADDRESS_USAGE *HalpAddressUsageList; + +// +// Misc hal stuff in the registry +// + +WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer"; + + +// +// From ixpcibus.c +// + +WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter"; +WCHAR rgzConfigurationData[] = L"Configuration Data"; +WCHAR rgzIdentifier[] = L"Identifier"; +WCHAR rgzPCIIndetifier[] = L"PCI"; +WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002 + + +#ifdef ALLOC_DATA_PRAGMA +#pragma data_seg() +#endif + +// +// IDT vector usage info +// +// CNG001 +#if defined(MIPS) +IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[] +#else // CMP001 +IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +#endif + diff --git a/private/ntos/nthals/halr98mp/mips/mode542x.h b/private/ntos/nthals/halr98mp/mips/mode542x.h new file mode 100644 index 000000000..00445a6d9 --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/modeset.h b/private/ntos/nthals/halr98mp/mips/modeset.h new file mode 100644 index 000000000..b699eacc7 --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/pcibrd.c b/private/ntos/nthals/halr98mp/mips/pcibrd.c new file mode 100644 index 000000000..c4ea03464 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/pcibrd.c @@ -0,0 +1,1020 @@ +#ident "@(#) NEC pcibrd.c 1.2 95/06/19 11:12:35" +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpcibrd.c + +Abstract: + + Get PCI-PCI bridge information + +Author: + + Ken Reneris (kenr) 14-June-1994 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "stdio.h" + +// debugging only... +// #define INIT_PCI_BRIDGE 1 + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzReservedResources[]; + + +#if DBG +#define DBGMSG(a) DbgPrint(a) +#else +#define DBGMSG(a) +#endif + + + +#define IsPciBridge(a) \ + (a->VendorID != PCI_INVALID_VENDORID && \ + PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \ + a->SubClass == 4 && a->BaseClass == 6) + + +typedef struct { + ULONG BusNo; + PBUS_HANDLER BusHandler; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + ULONG IO, Memory, PFMemory; + UCHAR Buffer[PCI_COMMON_HDR_LENGTH]; +} CONFIGBRIDGE, *PCONFIGBRIDGE; + +// +// Internal prototypes +// + + +#ifdef INIT_PCI_BRIDGE +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ); +#endif + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG Base, + IN ULONG Limit + ); + + +ULONG +HalpGetBridgedPCIInterrupt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetBridgedPCIISAInt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +NTSTATUS +HalpGetBridgedPCIIrqTable ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PUCHAR IrqTable + ); + + + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpGetPciBridgeConfig) +#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk) +#pragma alloc_text(INIT,HalpFixupPciSupportedRanges) + +#ifdef INIT_PCI_BRIDGE +#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt) +//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable) +#pragma alloc_text(INIT,HalpGetPciBridgeNeeds) +#endif +#endif + + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN PUCHAR MaxPciBus + ) +/*++ + +Routine Description: + + Scan the devices on all known pci buses trying to locate any + pci to pci bridges. Record the hierarchy for the buses, and + which buses have what addressing limits. + +Arguments: + + HwType - Configuration type. + MaxPciBus - # of PCI buses reported by the bios + +--*/ +{ + PBUS_HANDLER ChildBus; + PPCIPBUSDATA ChildBusData; + ULONG d, f, i, j, BusNo; + UCHAR Rescan; + BOOLEAN FoundDisabledBridge; + CONFIGBRIDGE CB; + + Rescan = 0; + FoundDisabledBridge = FALSE; + + // + // Find each bus on a bridge and initialize it's base and limit information + // + + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + // next device + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge, next function + continue; + } + + if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is not enabled - skip it for now + FoundDisabledBridge = TRUE; + continue; + } + + if ((ULONG) CB.PciData->u.type1.PrimaryBus != + CB.BusHandler->BusNumber) { + + DBGMSG ("HAL GetPciData: bad primarybus!!!\n"); + // what to do? + } + + // + // Found a PCI-PCI bridge. Determine it's parent child + // releationships + // + + ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus); + if (!ChildBus) { + DBGMSG ("HAL GetPciData: found configured pci bridge\n"); + + // up the number of buses + if (CB.PciData->u.type1.SecondaryBus > Rescan) { + Rescan = CB.PciData->u.type1.SecondaryBus; + } + continue; + } + + ChildBusData = (PPCIPBUSDATA) ChildBus->BusData; + if (ChildBusData->BridgeConfigRead) { + // this child buses releationships already processed + continue; + } + + // + // Remember the limits which are programmed into this bridge + // + + ChildBusData->BridgeConfigRead = TRUE; + HalpSetBusHandlerParent (ChildBus, CB.BusHandler); + ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber; + ChildBusData->CommonData.ParentSlot = CB.SlotNumber; + + ChildBus->BusAddresses->IO.Base = + PciBridgeIO2Base( + CB.PciData->u.type1.IOBase, + CB.PciData->u.type1.IOBaseUpper16 + ); + + ChildBus->BusAddresses->IO.Limit = + PciBridgeIO2Limit( + CB.PciData->u.type1.IOLimit, + CB.PciData->u.type1.IOLimitUpper16 + ); + + // + // Special VGA address remapping occuring on this bridge? + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + HalpSetPciBridgedVgaCronk ( + ChildBus->BusNumber, + (ULONG) ChildBus->BusAddresses->IO.Base, + (ULONG) ChildBus->BusAddresses->IO.Limit + ); + } + + // + // If supported I/O ranges on this bus are limitied to + // 256bytes on every 1K aligned boundry within the + // range, then redo supported IO BusAddresses to match + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + // assume Base is 1K aligned + i = (ULONG) ChildBus->BusAddresses->IO.Base; + j = (ULONG) ChildBus->BusAddresses->IO.Limit; + + // convert head entry + ChildBus->BusAddresses->IO.Limit = i + 256; + i += 1024; + + // add remaining ranges + while (i < j) { + HalpAddRange ( + &ChildBus->BusAddresses->IO, + 1, // address space + 0, // system base + i, // bus address + i + 256 // bus limit + ); + + // next range + i += 1024; + } + } + + ChildBus->BusAddresses->Memory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase); + + ChildBus->BusAddresses->Memory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit); + + // On x86 it's ok to clip Prefetch to 32 bits + + if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) { + ChildBus->BusAddresses->PrefetchMemory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase); + + + ChildBus->BusAddresses->PrefetchMemory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit); + + if (CB.PciData->u.type1.PrefetchLimitUpper32) { + ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff; + } + } + + // should call HalpAssignPCISlotResources to assign + // baseaddresses, etc... + } + } + } + + if (Rescan) { + *MaxPciBus = Rescan; + return TRUE; + } + + if (!FoundDisabledBridge) { + return FALSE; + } + + DBGMSG ("HAL GetPciData: found disabled pci bridge\n"); + +#ifdef INIT_PCI_BRIDGE + // + // We've calculated all the parent's buses known bases & limits. + // While doing this a pci-pci bus was found that the bios didn't + // configure. This is not expected, and we'll make some guesses + // at a configuration here and enable it. + // + // (this code is primarily for testing the above code since + // currently no system bioses actually configure the child buses) + // + + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge + continue; + } + + if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is enabled + continue; + } + + // + // We have a disabled bus - assign it a number, then + // determine all the requirements of all devices + // on the other side of this bridge + // + + CB.BusNo = BusNo; + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + } + } + } + // preform Rescan + return TRUE; + +#else + + return FALSE; + +#endif + +} + +VOID +HalpFixupPciSupportedRanges ( + IN ULONG MaxBuses + ) +/*++ + +Routine Description: + + PCI-PCI bridged buses only see addresses which their parent + bueses support. So adjust any PCI SUPPORT_RANGES to be + a complete subset of all of it's parent buses. + + PCI-PCI briges use postive address decode to forward addresses. + So, remove any addresses from any PCI bus which are bridged to + a child PCI bus. + +--*/ +{ + ULONG i; + PBUS_HANDLER Bus, ParentBus; + PSUPPORTED_RANGES HRanges; + + // + // Pass 1 - shrink all PCI supported ranges to be a subset of + // all of it's parent buses + // + + for (i = 0; i < MaxBuses; i++) { + + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + HRanges = Bus->BusAddresses; + Bus->BusAddresses = HalpMergeRanges ( + ParentBus->BusAddresses, + HRanges + ); + + HalpFreeRangeList (HRanges); + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Pass 2 - remove all child PCI bus ranges from parent PCI buses + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + if (ParentBus->InterfaceType == PCIBus) { + HalpRemoveRanges ( + ParentBus->BusAddresses, + Bus->BusAddresses + ); + } + + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Cleanup + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + HalpConsolidateRanges (Bus->BusAddresses); + } +} + + + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG BaseAddress, + IN ULONG LimitAddress + ) +/*++ + +Routine Description: . + + The 'vga compatible addresses' bit is set in the bridge control regiter. + This causes the bridge to pass any I/O address in the range of: 10bit + decode 3b0-3bb & 3c0-3df, as TEN bit addresses. + + As far as I can tell this "feature" is an attempt to solve some problem + which the folks solving it did not fully understand, so instead of doing + it right we have this fine mess. + + The solution is to take the least of all evils which is to remove any + I/O port ranges which are getting remapped from any IoAssignResource + request. (ie, IoAssignResources will never contimplate giving any + I/O port out in the suspected ranges). + + note: memory allocation error here is fatal so don't bother with the + return codes. + +Arguments: + + Base - Base of IO address range in question + Limit - Limit of IO address range in question + +--*/ +{ + UNICODE_STRING unicodeString; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE handle; + ULONG Length; + PCM_RESOURCE_LIST ResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + ULONG AddressMSBs; + WCHAR ValueName[80]; + NTSTATUS status; + + // + // Open reserved resource settings + // + + RtlInitUnicodeString (&unicodeString, rgzReservedResources); + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) { + return; + } + + // + // Build resource list of reseved ranges + // + + Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 * + sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) + + sizeof (CM_RESOURCE_LIST); + + ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length); + memset (ResourceList, 0, Length); + + ResourceList->Count = 1; + ResourceList->List[0].InterfaceType = PCIBus; + ResourceList->List[0].BusNumber = BusNumber; + Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; + + while (BaseAddress < LimitAddress) { + AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr + + // + // Add xx3b0 through xx3bb + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0; + Descriptor->u.Port.Length = 0xb; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Add xx3c0 through xx3df + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0; + Descriptor->u.Port.Length = 0x1f; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Next range + // + + BaseAddress += 1024; + } + + // + // Add the reserved ranges to avoid during IoAssignResource + // + + swprintf (ValueName, L"HAL_PCI_%d", BusNumber); + RtlInitUnicodeString (&unicodeString, ValueName); + + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_RESOURCE_LIST, + ResourceList, + (ULONG) Descriptor - (ULONG) ResourceList + ); + + + ExFreePool (ResourceList); + ZwClose (handle); +} + + + +#ifdef INIT_PCI_BRIDGE + +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ) +{ + ACCESS_MASK DesiredAccess; + UNICODE_STRING unicodeString; + PUCHAR buffer; + HANDLE handle; + OBJECT_ATTRIBUTES objectAttributes; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCONFIGURATION_COMPONENT Component; + CONFIGBRIDGE CB; + ULONG mnum, d, f, i; + NTSTATUS status; + + buffer = ExAllocatePool (PagedPool, 1024); + + // init + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + Current->IO = Current->Memory = Current->PFMemory = 0; + + // + // Assign this bridge an ID, and turn on configuration space + // + + Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo; + Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus; + Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF; + Current->PciData->u.type1.SecondaryStatus = 0xffff; + Current->PciData->Status = 0xffff; + Current->PciData->Command = 0; + + Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + KeStallExecutionProcessor (100); + + Current->PciData->u.type1.BridgeControl = 0; + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + KeStallExecutionProcessor (100); + + // + // Allocate new handler for bus + // + + CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + CB.BusNo = *MaxPciBus; + *MaxPciBus += 1; + + // + // Add another PCI bus in the registry + // + + mnum = 0; + for (; ;) { + // + // Find next available MultiFunctionAdapter key + // + + DesiredAccess = KEY_READ | KEY_WRITE; + swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum); + RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer); + + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes); + if (!NT_SUCCESS(status)) { + break; + } + + // already exists, next + ZwClose (handle); + mnum += 1; + } + + ZwCreateKey (&handle, + DesiredAccess, + &objectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &d + ); + + // + // Add needed registry values for this MultifucntionAdapter entry + // + + RtlInitUnicodeString (&unicodeString, rgzIdentifier); + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_SZ, + L"PCI", + sizeof (L"PCI") + ); + + RtlInitUnicodeString (&unicodeString, rgzConfigurationData); + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer; + Descriptor->InterfaceType = PCIBus; + Descriptor->BusNumber = CB.BusNo; + Descriptor->PartialResourceList.Version = 0; + Descriptor->PartialResourceList.Revision = 0; + Descriptor->PartialResourceList.Count = 0; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_FULL_RESOURCE_DESCRIPTOR, + Descriptor, + sizeof (*Descriptor) + ); + + + RtlInitUnicodeString (&unicodeString, L"Component Information"); + Component = (PCONFIGURATION_COMPONENT) buffer; + RtlZeroMemory (Component, sizeof (*Component)); + Component->AffinityMask = 0xffffffff; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_BINARY, + Component, + FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength) + ); + + ZwClose (handle); + + + // + // Since the BIOS didn't configure this bridge we'll assume that + // the PCI interrupts are bridged. (for BIOS configured buses we + // assume that the BIOS put the ISA bus IRQ in the InterruptLine value) + // + + CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line; + CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin; + //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable; + + if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) { + + // + // The parent bus'es interrupt pin to vector mappings is not + // a static function, and is determined by the boot firmware. + // + + //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt; + + // read each device on parent bus + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + Current->BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (CB.PciData->u.type0.InterruptPin && + (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE || + PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) { + + // get bios supplied int mapping + i = CB.PciData->u.type0.InterruptPin + d % 4; + CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine; + } + } + } + + } else { + _asm int 3; + } + + // + // Look at each device on the bus and determine it's resource needs + // + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (IsPciBridge (CB.PciData)) { + // oh look - another bridge ... + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + continue; + } + + if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) { + continue; + } + + // found a device - figure out the resources it needs + } + } + + // + // Found all sub-buses set SubordinateBus accordingly + // + + Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + // + // Set the bridges IO, Memory, and Prefetch Memory windows + // + + // For now just pick some numbers & set everyone the same + // IO 0x6000 - 0xFFFF + // MEM 0x40000000 - 0x4FFFFFFF + // PFMEM 0x50000000 - 0x5FFFFFFF + + Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4; + Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4; + Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4; + Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4; + Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4; + Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4; + + Current->PciData->u.type1.PrefetchBaseUpper32 = 0; + Current->PciData->u.type1.PrefetchLimitUpper32 = 0; + Current->PciData->u.type1.IOBaseUpper16 = 0; + Current->PciData->u.type1.IOLimitUpper16 = 0; + Current->PciData->u.type1.BridgeControl = + PCI_ENABLE_BRIDGE_ISA; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + HalpReadPCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + // enable memory & io decodes + + Current->PciData->Command = + PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + &Current->PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (Current->PciData->Command) + ); + + ExFreePool (buffer); +} + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + + This function maps the device's InterruptPin to an InterruptLine + value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Convert slot Pin into Bus INTA-D. + // + + i = (PciData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + i = (PciNewData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + +#endif diff --git a/private/ntos/nthals/halr98mp/mips/pcip.h b/private/ntos/nthals/halr98mp/mips/pcip.h new file mode 100644 index 000000000..b757a07a7 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/pcip.h @@ -0,0 +1,214 @@ +#ident "@(#) NEC pcip.h 1.4 95/06/19 11:13:40" +/* + + Revision History + + A002 1995/6/17 ataka@oa2.kb.nec.co.jp + - Marge 807-halr98mp-pcip.h to 1050-halx86-pcip.h +*/ + +// +// Hal specific PCI bus structures +// + +typedef NTSTATUS +(*PciIrqRange) ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ); + +typedef struct tagPCIPBUSDATA { + + // + // Defined PCI data + // + + PCIBUSDATA CommonData; + + // + // Implementation specific data + // + + union { + struct { + PULONG Address; + ULONG Data; + } Type1; + struct { + PUCHAR CSE; + PUCHAR Forward; + ULONG Base; + } Type2; + } Config; + + ULONG MaxDevice; + PciIrqRange GetIrqRange; + + BOOLEAN BridgeConfigRead; + UCHAR ParentBus; + UCHAR reserved[2]; + UCHAR SwizzleIn[4]; + + RTL_BITMAP DeviceConfigured; + ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32]; +} PCIPBUSDATA, *PPCIPBUSDATA; + +#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev); + +#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION) + +#define Is64BitBaseAddress(a) \ + (((a & PCI_ADDRESS_IO_SPACE) == 0) && \ + ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)) + + +#if DBG +#define IRQXOR 0x2B +#else +#define IRQXOR 0 +#endif + +#if defined(_R98_) // A002 + +typedef struct _PCI_TYPER98_CFG_BITS { + union { + struct { + ULONG Reserved1:2; + ULONG RegisterNumber:6; + ULONG FunctionNumber:3; + ULONG SlotNumber:2; + ULONG BaseAddress:19; + } bits; + + ULONG AsULONG; + } u; +} PCI_TYPER98_CFG_BITS, *PPCI_TYPER98_CFG_BITS; + +#define PCI_CONFIG_BASE_ADDRESS 0xb8ca8000 /* N001 */ + +#endif + +// +// Prototypes for functions in ixpcibus.c +// + +VOID +HalpInitializePciBus ( + VOID + ); + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ); + + +// +// Prototypes for functions in ixpciint.c +// + +ULONG +HalpGetPCIIntOnISABus ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpPCIAcquireType2Lock ( + PKSPIN_LOCK SpinLock, + PKIRQL Irql + ); + +VOID +HalpPCIReleaseType2Lock ( + PKSPIN_LOCK SpinLock, + KIRQL Irql + ); + +NTSTATUS +HalpAdjustPCIResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +VOID +HalpPCIPin2ISALine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + +VOID +HalpPCIISALine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +NTSTATUS +HalpGetISAFixedPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ); + +// +// Prototypes for functions in ixpcibrd.c +// + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN PUCHAR MaxPciBus + ); + +VOID +HalpFixupPciSupportedRanges ( + IN ULONG MaxBuses + ); + +// +// +// + +#ifdef SUBCLASSPCI + +VOID +HalpSubclassPCISupport ( + IN PBUS_HANDLER BusHandler, + IN ULONG HwType + ); + +#endif diff --git a/private/ntos/nthals/halr98mp/mips/r98busdt.c b/private/ntos/nthals/halr98mp/mips/r98busdt.c new file mode 100644 index 000000000..a14d3cf4c --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98busdt.c @@ -0,0 +1,1181 @@ +#ident "@(#) NEC r98busdt.c 1.16 95/06/19 11:30:31" +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixhwsup.c + +Abstract: + + This module contains the IoXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would reside in the iosubs.c module. + +Author: + + Darryl E. Havens (darrylh) 11-Apr-1990 + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +/*++ + + Modification History + + N- NEW + D- Only For Debug + B- Bug Fix + +B001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:40:10 JST 1994 + - add DbgPrints + +B002 samezima@oa2.kb.nec.co.jp MON Nov 21 + - chg Mask translate address + +N005 samezima@oa2.kb.nec.co.jp MON Mar 13 + - change PIO interrupt vector from internal to eisa. +A002 ataka@oa2.kb.nec.co.jp 1995/6/17 + - Marge 1050 halx86 many sources to 807 r98busdat.c + and named r98busdt.c + +--*/ + +#include "halp.h" +#include "string.h" // CMP001 + + +UCHAR HalName[] = "NEC MIPS HAL"; // N003 + +VOID HalpInitializePciBus (VOID); // CMP001 +VOID HalpInitOtherBuses (VOID); + + +// +// Prototype for system bus handlers +// + +ULONG +HalpNoBusData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +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 PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +BOOLEAN +HalpTranslatePCIBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +BOOLEAN +HalpTranslateIsaBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + + +BOOLEAN +HalpTranslateEisaBusAddress ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + + +HalpGetEisaData ( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpAdjustEisaResourceList ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +#if DBG // A002 +VOID +HalpDisplayAllBusRanges ( + VOID + ); +VOID +HalpDisplayAddressRange ( + PSUPPORTED_RANGE Address, + PUCHAR String +); +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpAllocateBusHandler) +#pragma alloc_text(PAGE,HalGetInterruptVector) +/* B001 */ +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(PAGE,HalpGetEisaInterruptVector) +#pragma alloc_text(PAGE,HalpAdjustEisaResourceList) +#pragma alloc_text(PAGE,HalpGetEisaData) +#pragma alloc_text(PAGE,HalpGetSystemInterruptVector) +#endif + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers) +#pragma alloc_text(INIT,HalpAllocateBusHandler) +#endif + + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ) +{ + PBUS_HANDLER Bus; + + if (KeGetCurrentPrcb()->Number) { + // only need to do this once + return ; + } + + // + // Initalize BusHandler data before registering any handlers + // + + HalpInitBusHandler (); + + // + // Build internal-bus 0, or system level bus + // + + Bus = HalpAllocateBusHandler ( + Internal, + ConfigurationSpaceUndefined, + 0, // Internal BusNumber 0 + InterfaceTypeUndefined, // no parent bus + 0, + 0 // no bus specfic data + ); + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build internal-bus 0, or system level bus + // + // B003 kugi Internal Bus was called with bus-no. 2, We have no idea. + + Bus = HalpAllocateBusHandler ( + Internal, + ConfigurationSpaceUndefined, + 1, // Internal BusNumber 1 + InterfaceTypeUndefined, // no parent bus + 0, + 0 // no bus specfic data + ); + + Bus->GetInterruptVector = HalpGetSystemInterruptVector; + Bus->TranslateBusAddress = HalpTranslateSystemBusAddress; + + // + // Build Isa/Eisa bus #0 + // + + Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0); + Bus->GetBusData = HalpGetEisaData; + Bus->GetInterruptVector = HalpGetEisaInterruptVector; + Bus->AdjustResourceList = HalpAdjustEisaResourceList; +#if defined(_R98_) // A001 + Bus->TranslateBusAddress = HalpTranslateEisaBusAddress; +#endif // _R98_ + Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0); + Bus->GetBusData = HalpNoBusData; + Bus->BusAddresses->Memory.Limit = 0xFFFFFF; + Bus->TranslateBusAddress = HalpTranslateIsaBusAddress; + + HalpInitOtherBuses (); +#if DBG // A002 + HalpDisplayAllBusRanges (); +#endif +} + + +PBUS_HANDLER +HalpAllocateBusHandler ( + IN INTERFACE_TYPE InterfaceType, + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN INTERFACE_TYPE ParentBusInterfaceType, + IN ULONG ParentBusNumber, + IN ULONG BusSpecificData + ) +/*++ + +Routine Description: + + Stub function to map old style code into new HalRegisterBusHandler code. + + Note we can add our specific bus handler functions after this bus + handler structure has been added since this is being done during + hal initialization. + +--*/ +{ + PBUS_HANDLER Bus; + + + // + // Create bus handler - new style + // + + HaliRegisterBusHandler ( + InterfaceType, + BusDataType, + BusNumber, + ParentBusInterfaceType, + ParentBusNumber, + BusSpecificData, + NULL, + &Bus + ); + + // A001 + if (InterfaceType != InterfaceTypeUndefined) { + Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES)); + RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES)); + Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION; + Bus->BusAddresses->Dma.Limit = 7; + Bus->BusAddresses->IO.Base = 0; + Bus->BusAddresses->IO.SystemAddressSpace = 0; + Bus->BusAddresses->PrefetchMemory.Base = 1; + + switch(InterfaceType) { + case Internal: + Bus->BusAddresses->Memory.Base + = 0x00000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart + = 0xFFFFFFFF; + Bus->BusAddresses->Memory.SystemBase + = 0x00000000; + Bus->BusAddresses->IO.Base + = 0x00000000; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart + = 0xFFFFFFFF; + Bus->BusAddresses->IO.SystemBase + = 0x00000000; + break; + case Eisa: + Bus->BusAddresses->Memory.Base + = 0x00000000; +// = 0x01000000; + Bus->BusAddresses->Memory.Limit + = 0x03FFFFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = EISA_MEMORY_PHYSICAL_BASE; + Bus->BusAddresses->IO.Base + = 0x00000000; + Bus->BusAddresses->IO.Limit + = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = EISA_CONTROL_PHYSICAL_BASE; + break; + case Isa: + Bus->BusAddresses->Memory.Base + = 0x00000000; + Bus->BusAddresses->Memory.Limit + = 0x00FFFFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = EISA_MEMORY_PHYSICAL_BASE; + Bus->BusAddresses->IO.Base + = 0x00000000; + Bus->BusAddresses->IO.Limit + = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = EISA_CONTROL_PHYSICAL_BASE; + break; + case PCIBus: + Bus->BusAddresses->Memory.Base + = 0x04000000; // from 64MB + Bus->BusAddresses->Memory.Limit + = 0x0FFFFFFF; // up to 256MB + ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart + = PCI_MEMORY_PHYSICAL_BASE; + Bus->BusAddresses->IO.Base + = 0x00000000; + Bus->BusAddresses->IO.Limit + = 0x0000FFFF; + ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart + = PCI_CONTROL_SLOT1_PHYSICAL_BASE; + break; + } + } + + return Bus; +} + +// N003 +VOID +HalReportResourceUsage ( + VOID + ) +{ + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + + // N004 +#if 0 // support next version + HalpRegisterAddressUsage (&HalpDefaultPcIoSpace); + HalpRegisterAddressUsage (&HalpEisaIoSpace); + HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace); +#endif + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + HalpReportResourceUsage ( + &UHalName, // descriptive name + Internal // device space interface type + ); + + RtlFreeUnicodeString (&UHalName); + + // + // Registry is now intialized, see if there are any PCI buses + // + + HalpInitializePciBus (); +} + +VOID +HalpInitOtherBuses ( + VOID + ) +{ + // no other internal buses supported +} + + + + +ULONG +HalpGetEisaInterruptVector( + IN 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. + +--*/ +{ + // + // Jazz and Duo only have one I/O bus which is an EISA, so the bus + // number and the bus interrupt vector are unused. + // + // The IRQL level is always equal to the EISA level. + // + + *Affinity = HalpEisaBusAffinity; // N003 + + *Irql = INT1_LEVEL; + + // + // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa + // hardware. + // + + if (BusInterruptLevel == 2) { + BusInterruptLevel = 9; + } + + // + // The vector is equal to the specified bus level plus the EISA_VECTOR. + // + + return(BusInterruptLevel + EISA_VECTORS); +} + +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 (); // A001 + + + RtlInitUnicodeString( + &RootName, + EisaPath + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &RootName, + OBJ_CASE_INSENSITIVE, + (HANDLE)NULL, + NULL + ); + + // + // Open the EISA root + // + + NtStatus = ZwOpenKey( + &EisaHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + DbgPrint("HAL: Open Status = %x\n",NtStatus); + return(0); + } + + // + // Init bus number path + // + + BusNumber = BusHandler->BusNumber; + if (BusNumber > 99) { + return (0); + } + + if (BusNumber > 9) { + BusString[0] += (UCHAR) (BusNumber/10); + BusString[1] += (UCHAR) (BusNumber % 10); + } else { + BusString[0] += (UCHAR) BusNumber; + BusString[1] = '\0'; + } + + RtlInitAnsiString( + &TmpString, + BusString + ); + + RtlAnsiStringToUnicodeString( + &BusName, + &TmpString, + TRUE + ); + + + InitializeObjectAttributes( + &BusObjectAttributes, + &BusName, + OBJ_CASE_INSENSITIVE, + (HANDLE)EisaHandle, + NULL + ); + + // + // Open the EISA root + Bus Number + // + + NtStatus = ZwOpenKey( + &BusHandle, + KEY_READ, + &BusObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus); + return(0); + } + + // + // opening the configuration data. This first call tells us how + // much memory we need to allocate + // + + RtlInitUnicodeString( + &ConfigDataName, + ConfigData + ); + + // + // This should fail. We need to make this call so we can + // get the actual size of the buffer to allocate. + // + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i; + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + 0, + &BytesNeeded + ); + + KeyValueBuffer = ExAllocatePool( + NonPagedPool, + BytesNeeded + ); + + if (KeyValueBuffer == NULL) { +#if DBG + DbgPrint("HAL: Cannot allocate Key Value Buffer\n"); +#endif + ZwClose(BusHandle); + return(0); + } + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer; + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + BytesNeeded, + &BytesWritten + ); + + + ZwClose(BusHandle); + + if (!NT_SUCCESS(NtStatus)) { +#if DBG + DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus); +#endif + ExFreePool(KeyValueBuffer); + return(0); + } + + + // + // We get back a Full Resource Descriptor List + // + + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation + + ValueInformation->DataOffset); + + PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) + &(Descriptor->PartialResourceList.PartialDescriptors); + PartialCount = Descriptor->PartialResourceList.Count; + + for (i = 0; i < PartialCount; i++) { + + // + // Do each partial Resource + // + + switch (PartialResource->Type) { + case CmResourceTypeNull: + case CmResourceTypePort: + case CmResourceTypeInterrupt: + case CmResourceTypeMemory: + case CmResourceTypeDma: + + // + // We dont care about these. + // + + PartialResource++; + + break; + + case CmResourceTypeDeviceSpecific: + + // + // Bingo! + // + + TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)PartialResource + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + + while (((LONG)TotalDataSize) > 0) { + + if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION); + + } else { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) + + SlotInformation->NumberFunctions * + sizeof(CM_EISA_FUNCTION_INFORMATION); + } + + if (SlotDataSize > TotalDataSize) { + + // + // Something is wrong again + // + + ExFreePool(KeyValueBuffer); + return(0); + + } + + if (SlotNumber != 0) { + + SlotNumber--; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)SlotInformation + SlotDataSize); + + TotalDataSize -= SlotDataSize; + + continue; + + } + + // + // This is our slot + // + + Found = TRUE; + break; + + } + + // + // End loop + // + + i = PartialCount; + + break; + + default: + +#if DBG + DbgPrint("Bad Data in registry!\n"); +#endif + + ExFreePool(KeyValueBuffer); + return(0); + + } + + } + + if (Found) { + i = Length + Offset; + if (i > SlotDataSize) { + i = SlotDataSize; + } + + DataLength = i - Offset; + RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength); + } + + ExFreePool(KeyValueBuffer); + return DataLength; +} + + + +// N001 +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. + +--*/ +{ + /* N003 vvv */ + ULONG vector; + + *Irql = (KIRQL)BusInterruptLevel; + vector = BusInterruptVector + DEVICE_VECTORS; + + switch(vector) { + case SCSI1_VECTOR: + case SCSI0_VECTOR: + case ETHER_VECTOR: + *Affinity = HalpInt1Affinity; + break; + + // N005 vvv + case PIO_VECTOR: + return HalpGetEisaInterruptVector( (PBUS_HANDLER)NULL, + (PBUS_HANDLER)NULL, + 1, + 1, + Irql, + Affinity + ); + // N005 ^^^ + + default: + *Affinity = 1; + } + + return vector; + /* N003 ^^^ */ +} + + +// A001 +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 + ); +} + +// A001 +BOOLEAN +HalpTranslateSystemBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + PSUPPORTED_RANGE pRange; + + pRange = NULL; + switch (*AddressSpace) { + case 0: + // verify memory address is within buses memory limits +#if DBG +// DbgPrint("\nHalpTranslateSystemBusAddress-searching(Mem)...."); +#endif + for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) { +#if DBG +// HalpDisplayAddressRange (pRange, "\n PrefetchMemory:"); +#endif // DBG + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + + if (!pRange) { + for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) { +#if DBG +// HalpDisplayAddressRange (pRange, "\n Memory:"); +#endif // DBG + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + } + + break; + + case 1: + // verify IO address is within buses IO limits +#if DBG +// DbgPrint("HalpTranslateSystemBusAddress-searching(Io)....\n"); +#endif + for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) { +#if DBG +// HalpDisplayAddressRange (pRange, "\n Io:"); +#endif // DBG + if (BusAddress.QuadPart >= pRange->Base && + BusAddress.QuadPart <= pRange->Limit) { + break; + } + } + break; + } + + if (pRange) { + TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase; +#if DBG +// DbgPrint("\n Translated=0x%08x:%08x\nEnd of Translating Success!\n", TranslatedAddress->HighPart, +// TranslatedAddress->LowPart); +#endif // DBG + *AddressSpace = pRange->SystemAddressSpace; + return TRUE; + } +#if DBG +// DbgPrint("\nEnd of Translating. False!\n"); +#endif + + return FALSE; +} + +// A001 +BOOLEAN +HalpTranslateIsaBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + BOOLEAN Status; + + // + // Translated normally + // + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddress, + AddressSpace, + TranslatedAddress + ); + + + // + // If it could not be translated, and it's memory space + // then we allow the translation as it would occur on it's + // corrisponding EISA bus. We're allowing this because + // many VLBus drivers are claiming to be ISA devices. + // (yes, they should claim to be VLBus devices, but VLBus is + // run by video cards and like everything else about video + // there's no hope of fixing it. (At least according to + // Andre)) + // + + if (Status == FALSE && *AddressSpace == 0) { + Status = HalTranslateBusAddress ( + Eisa, + BusHandler->BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress + ); + } + + return Status; +} + +// A001 +BOOLEAN +HalpTranslateEisaBusAddress( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function translates a bus-relative address space and address into + a system physical address. + +Arguments: + + BusAddress - Supplies the bus-relative address + + AddressSpace - Supplies the address space number. + Returns the host address space number. + + AddressSpace == 0 => memory space + AddressSpace == 1 => I/O space + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + BOOLEAN Status; + + // + // Translated normally + // + + Status = HalpTranslateSystemBusAddress ( + BusHandler, + RootHandler, + BusAddress, + AddressSpace, + TranslatedAddress + ); + + + // + // If it could not be translated, and it's in the 640k - 1m + // range then (for compatibility) try translating it on the + // Internal bus for + // + + if (Status == FALSE && + *AddressSpace == 0 && + BusAddress.HighPart == 0 && + BusAddress.LowPart >= 0xA0000 && + BusAddress.LowPart < 0xFFFFF) { + + Status = HalTranslateBusAddress ( + Internal, + 0, + BusAddress, + AddressSpace, + TranslatedAddress + ); + } + + return Status; +} + +#if DBG +VOID +HalpDisplayAddressRange ( + PSUPPORTED_RANGE Address, + PUCHAR String + ) +/*++ + +Routine Description: + + Debugging code. Used only by HalpDisplayAllBusRanges + +--*/ +{ + ULONG i; + + i = 0; + while (Address) { + if (i == 0) { + DbgPrint (String); + i = 3; + } + + i -= 1; + DbgPrint (" %x:%08x - %x:%08x + %x:%08x", + (ULONG) (Address->Base >> 32), + (ULONG) (Address->Base), + (ULONG) (Address->Limit >> 32), + (ULONG) (Address->Limit), + (ULONG) (Address->SystemBase >> 32), + (ULONG) (Address->SystemBase) + ); + + Address = Address->Next; + } +} +#endif // DBG diff --git a/private/ntos/nthals/halr98mp/mips/r98busdt.h b/private/ntos/nthals/halr98mp/mips/r98busdt.h new file mode 100644 index 000000000..0517105f5 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98busdt.h @@ -0,0 +1,142 @@ +#ident "@(#) NEC r98busdat.h 1.2 94/10/19 22:15:10" +/*++ + +Module Name: + + ixhwsup.c + +Abstract: + + This module contains the IoXxx routines for the NT I/O system that + are hardware dependent. Were these routines not hardware dependent, + they would reside in the iosubs.c module. + +Author: + + +Environment: + + Kernel mode + +--*/ +/*++ + + Modification History + + N- NEW + D- Only For Debug + B- Bug Fix + + N001 ataka@oa2.kb.nec.co.jp Tue Oct 4 21:29:32 JST 1994 + - (from r98busdat.h && halx86/i386/halp.h) + +--*/ + +// +// Bus handlers +// + +typedef ULONG +(*PGETSETBUSDATA)( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +typedef ULONG +(*PGETINTERRUPTVECTOR)( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +typedef BOOLEAN +(*PTRANSLATEBUSADDRESS)( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +typedef NTSTATUS +(*PADJUSTRESOURCELIST)( + IN PVOID BusHandler, + IN PVOID RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ); + +typedef NTSTATUS +(*PASSIGNSLOTRESOURCES)( + IN PVOID BusHandler, + IN PVOID 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 + ); + +typedef struct tagBUSHANDLER { + struct tagBUSHANDLER *Next; + + // this entry is for: + INTERFACE_TYPE InterfaceType; + BUS_DATA_TYPE ConfigurationType; + ULONG BusNumber; + + // bus specific data: + struct tagBUSHANDLER *ParentHandler; + PVOID BusData; + + // handlers for bus functions + PGETSETBUSDATA GetBusData; + PGETSETBUSDATA SetBusData; + PADJUSTRESOURCELIST AdjustResourceList; + PASSIGNSLOTRESOURCES AssignSlotResources; + PGETINTERRUPTVECTOR GetInterruptVector; + PTRANSLATEBUSADDRESS TranslateBusAddress; +} BUSHANDLER, *PBUSHANDLER; + +#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p; + +PBUSHANDLER HalpAllocateBusHandler ( + IN INTERFACE_TYPE InterfaceType, + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN BUS_DATA_TYPE ParentBusDataType, + IN ULONG ParentBusNumber, + IN ULONG BusSpecificData + ); +#define HalpAllocateConfigSpace HalpAllocateBusHandler + +PBUSHANDLER HalpHandlerForBus ( + IN INTERFACE_TYPE InterfaceType, + IN ULONG BusNumber + ); + + +NTSTATUS +HalpAdjustResourceListLimits ( + IN PBUSHANDLER BusHandler, + IN PBUSHANDLER RootHandler, + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList, + IN ULONG MinimumMemoryAddress, + IN ULONG MaximumMemoryAddress, + IN ULONG MinimumPrefetchMemoryAddress, + IN ULONG MaximumPrefetchMemoryAddress, + IN BOOLEAN LimitedIOSupport, + IN ULONG MinimumPortAddress, + IN ULONG MaximumPortAddress, + IN PUCHAR IrqTable, + IN ULONG IrqTableLength, + IN ULONG MinimumDmaChannel, + IN ULONG MaximumDmaChannel + ); diff --git a/private/ntos/nthals/halr98mp/mips/r98clock.s b/private/ntos/nthals/halr98mp/mips/r98clock.s new file mode 100644 index 000000000..73f629f57 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98clock.s @@ -0,0 +1,471 @@ +// "@(#) NEC r98clock.s 1.10 95/02/20 17:04:37" +// 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. +// +//-- + +// +// Original source: Build Number 1.612 +// +// Modify for R98(MIPS/R4400) +// +//*********************************************************************** +// +// M001 94.03/16-5/31 T.Samezima +// +// change header file from duo to r98 +// change value of use to update of parformance counter +// initial value of count register +// +// del clear interrupt +// +//*********************************************************************** +// +// S002 94.6/13 T.Samezima +// +// Del Compile err +// +// +//*********************************************************************** +// +// S003 94.7/19 T.Samezima +// +// Chg Function interface change +// +//*********************************************************************** +// +// S004 94.7/19 T.Samezima +// +// Bug PMC register address is not change of KSEG1_BASE +// +//*********************************************************************** +// +// S005 94.10/12 T.Samezima +// +// Fix Version Up at build807 +// +// S006 '94.10/14 T.Samezima +// Chg Logic of set interval count +// +// S007 '94.01/11 T.Samezima +// Del delete 'if NT_UP'. +// +// S008 '94.01/16 T.Samezima +// Add Check ECC 1bit err flag and enable ECC 1bit err. +// +// + +#include "halmips.h" +// Start M001 +#if defined(_R98_) + +#include "r98def.h" +// #include "r98reg.h" // S002 + +#else // if defined(_R98_) + +#if defined(_DUO_) + +#include "duodef.h" + +#endif + +#if defined(_JAZZ_) + +#include "jazzdef.h" + +#endif +#endif // #if !defined(_R98_) +// End M001 + +#define ECC_ERROR_COUNT_LIMIT 1 // S008 + + + 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. // S003 +// +// 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 + +// Start M001 +#if !defined(_R98_) + .set noreorder + +#if defined(_DUO_) + + lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt + +#endif + +#if defined(_JAZZ_) + + lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt + +#endif + + .set reorder +#endif // #if !defined(_R98_) +// End M001 + +// S003 +// move a0,s8 // set address of trap frame + lw a1,HalpCurrentTimeIncrement // set current time increment + lw t0,__imp_KeUpdateSystemTime // update system time // S005 + jal t0 // // S005 + +// +// 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. +// + +// Start M001 +#if !defined(_R98_) +#if defined(_JAZZ_) + + .set noreorder + .set noat + mfc0 t0,cause // read the cause register + lw t1,HalpEisaControlBase // get EISA control base address + sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit + bgez t0,10f // if gez, no clock interrupt pending + li t2,0x2 // get NMI port enable bit + lb t3,0x70(t1) // save EISA NMI interrupt disable + lb t4,0x461(t1) // save EISA extended NMI status + sb zero,0x70(t1) // clear EISA NMI interrupt disable + sb t2,0x461(t1) // set EISA NMI port enable + sb zero,0x462(t1) // generate EISA NMI interrupt + sb zero,0x461(t1) // clear EISA extended NMI status + sb t2,0x461(t1) // + lb zero,0x461(t1) // synchronize clear operatin + sb t3,0x70(t1) // restore EISA NMI interupt disable + sb t4,0x461(t1) // restore EISA exteneed NMI status + lb zero,0x461(t1) // synchronize restore operation + .set at + .set reorder + +10: // + +#endif +#endif // #if !defined(_R98_) +// End M001 + +// S008 vvv +// +// 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+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET0_OFFSET + sw zero,0x0(t1) // enable ECC 1bit error + lw t0,HalpECC1bitScfrBuffer // check connect to SIC1 + andi t0,SCFR_SIC_SET1_CONNECT // + bne t0,zero,10f // + la t1,KSEG1_BASE+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET1_OFFSET + sw zero,0x0(t1) // enable ECC 1bit error +// S008 ^^^ + +// +// 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 // S008 + 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 + +// Start M001 + .set noreorder + +#if !defined(_R98_) +#if defined(_DUO_) + + sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count + +#endif + +#if defined(_JAZZ_) + + sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count + +#endif +# else // #if !defined(_R98_) + + sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004 + +#endif // #if !defined(_R98_) + + .set reorder +// End M001 + + sw t3,HalpNextTimeIncrement // set next time increment value +30: beq zero,t0,40f // if eq, debugger not enabled + jal KdPollBreakIn // check if breakin is requested + beq zero,v0,40f // if eq, no breakin requested + li a0,DBG_STATUS_CONTROL_C // break in and send + jal DbgBreakPointWithStatus // status to debugger +40: lw ra,CiRa(sp) // restore return address + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return + + .end HalpClockInterrupt0 + + SBTTL("System Clock Interrupt - Processor N") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt +// and transfer control to the standard system routine to update the +// execution time of the current thread and process. +// +// Arguments: +// +// a0 - Supplies a pointer to a trap frame. // S003 +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpClockInterrupt1) + +#if !defined(_R98_) +#if defined(_DUO_) + + lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt + move a0,s8 // set address of trap frame + j KeUpdateRunTime // update system time + +#endif +#else // #if !defined(_R98_) + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + +// S006 vvv + 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 +// S006 ^^^ + + lw t1,HalpChangeIntervalCount // get next interval count + sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004 + +// Start S003, S005 +//10: move a0,s8 // set address of trap frame +10: lw t1,__imp_KeUpdateRunTime // update system runtime + j t1 // +// End S003, S005 + +#endif // #if !defined(_R98_) + + .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. // S003 +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpProfileInterrupt) + + .set noreorder + .set noat +// Start M001 + mfc0 t0,count // get current count value + addu t1,zero,3 // set initial count value + mtc0 t1,count // set new count register value +// End M001 + .set at + .set reorder + +#if 0 // S007 +//#if defined(NT_UP) + + la t1,HalpPerformanceCounter // get performance counter address + +//#else +#endif + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + la t2,HalpPerformanceCounter // get performance counter address + lbu t1,PbNumber(t1) // get processor number + sll t1,t1,3 // compute address of performance count + addu t1,t1,t2 // + +// #endif // S007 + + lw t2,LiLowPart(t1) // get low part of performance count + lw t3,LiHighPart(t1) // get high part of performance count + addu t2,t2,t0 // update low part of performance count + sw t2,LiLowPart(t1) // store low part of performance count + sltu t4,t2,t0 // generate carry into high part + addu t3,t3,t4 // update high part of performance count + sw t3,LiHighPart(t1) // store high part of performance count + +// move a0,s8 // set address of trap frame // S003 + lw t4,__imp_KeProfileInterrupt // process profile interrupt // S005 + j t4 // // S005 + + .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/halr98mp/mips/r98def.h b/private/ntos/nthals/halr98mp/mips/r98def.h new file mode 100644 index 000000000..62e2aabaf --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98def.h @@ -0,0 +1,471 @@ +#ident "@(#) NEC r98def.h 1.25 95/03/17 11:54:20" +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + r98def.h + +Abstract: + + This module is the header file that describes hardware addresses + for the r98. + +Author: + + +Revision History: + +--*/ + +/* + *********************************************************************** + * + * S001 6/10 T.Samezima + * + * Del Compile err + * + * + *********************************************************************** + * + * S002 7/5 T.Samezima + * + * Chg define miss + * + *********************************************************************** + * + * S003 7/5 T.Samezima + * + * Add define unknown counter buffer length + * + *********************************************************************** + * + * S004 7/5 T.Samezima + * + * Add define err pci and dma in iRSF + * define dummy single read addr + * + *********************************************************************** + * + * S005 7/12 T.Samezima + * + * Chg define miss and define change + * + *********************************************************************** + * + * S006 7/19 T.Samezima + * + * Add define PCI err interrupt vector + * + *********************************************************************** + * + * S007 7/22 T.Samezima + * + * Add define PMC Dummy single read address. + * + *********************************************************************** + * + * S008 7/23 T.Samezima + * + * Add define SIC set0/1 offset + * define value of enable EIF interrupt of SIC CKE0/1 register + * + *********************************************************************** + * + * S009 8/22 T.Samezima on SNES + * + * Chg RTC physical base + * + *********************************************************************** + * + * S00a 8/22 T.Samezima on SNES + * + * Chg PIO, FDC interrupt pending bit on iRSF + * + * S00B 8/29 N.Kugimoto + * + * Bug NVRAM disable logic. + * + * K00C 9/5 N.Kugimoto + * add PCI slot 0 addr + * + * K00D 94/9/22 N.Kugimoto + * -1 chg No Used! + * + * S00E 94/10/13 T.Samezima + * Add define EISA interrupt enable bit + * define all clock interrupt restart command on TCIR in PMC + * + * S00F 94/10/18 T.Samezima + * Add define interrupt enable bit for device only + * + * S010 94/11/21 T.Samezima + * Add correspond SIC3 H/W Bug on R98 + * Chg Dummy read address change. because old address is + * break scsi script. + * + * S011 '94.12/06 T.Samezima + * Add define CKE0 disable mask. (Disable Single bit error mask on SIC) + * Chg CKE0 enable mask change. (Disable Single bit error mask on SIC) + * ERRMK enable mask change. (bit 17,22 is must be zero. ) + * + * K00E 94/12/06 N.Kugimoto + * Add ESM NVRAM Area + * + * S012 94/12/08 T.Samezima + * Add Disable NMI + * + * S013 '95.01/08 T.Samezima + * Add Enable ECC 1bit error. + * + * S014 '95.01/13 T.Samezima + * Add Define Disable ECC 1bit error. + * + * S015 '95.03/13 T.Samezima + * Add Define LR4360 error. + * + */ + +#ifndef _R98DEF_ +#define _R98DEF_ + +// +// define address map +// +#define PMC_PHYSICAL_BASE1 0x19900000 // Physical base of PMC registers1 +#define PMC_PHYSICAL_BASE2 0x19800000 // Physical base of PMC registers2 +#define PMC_LOCAL_OFFSET 0x80000 + +#define IOB_PHYSICAL_BASE 0x18000000 // Physical base of IOB + +#define SIC_PHYSICAL_BASE 0x19000000 // Physical base of SIC registers +#define SIC_ERR_OFFSET 0x2000 // Error registers offset of SIC +#define SIC_DATA_OFFSET 0x3000 // Data registers offset of SIC +#define SIC_SET0_OFFSET 0x0 // Offset SET0 of SIC // S008 +#define SIC_SET1_OFFSET 0x20000 // Offset SET1 of SIC // S008 +#define SIC_NO0_OFFSET 0x4000 // Offset No.0 of SIC +#define SIC_NO1_OFFSET 0x8000 // Offset No.1 of SIC +// Start S005,S008 +#define SIC_NO2_OFFSET (SIC_SET1_OFFSET+SIC_NO0_OFFSET) // Offset No.2 of SIC +#define SIC_NO3_OFFSET (SIC_SET1_OFFSET+SIC_NO1_OFFSET) // Offset No.3 of SIC +// End S005,S008 + +#define LR_PHYSICAL_CMNBASE1 0x18c08000 // Physical base of LR4360 registers1 // S005 +#define LR_PHYSICAL_CMNBASE2 0x18c0a000 // Physical base of LR4360 registers2 +#define LR_PHYSICAL_PCI_INT_ACK_BASE 0x18caa000 // Physical base of LR4360 pci interrupt acknowledge +#define LR_PHYSICAL_PCI_DEV_REG_BASE 0x18cbb000 // Physical base of LR4360 pci device registers + +// Bbus DMA +#define LR_CHANNEL_BASE 0x18c08000 // LR4360 - Device Channel Register Base + // 0x18Cn0000 : n:channel number +#define LR_CHANNEL_SHIFT 0x10 // LR4360 - channel shift bit + +#define SERIAL0_PHYSICAL_BASE 0x18c103f8 // physical base of serial port 0 +#define KEYBOARD_PHYSICAL_BASE 0x18c20060 // physical base of keyboard control +#define RTCLOCK_PHYSICAL_BASE 0x18cc0071 // physical base of realtime clock // S005, S009 + +#define NVRAM_PHYSICAL_BASE 0x18c70000 // physical base of nonvolatile RAM +#define NVRAM_MEMORY_BASE (KSEG1_BASE + NVRAM_PHYSICAL_BASE) +#define NVRAM_NMI_BASE (NVRAM_MEMORY_BASE + 0x1934) + +#define NVRAM_ESM_BASE NVRAM_MEMORY_BASE+1024*8 //Start of ESM Area K00E +#define NVRAM_ESM_END NVRAM_MEMORY_BASE+1024*16-1 //End of ESM Area K00E + +#define MRC_PHYSICAL_BASE 0x18c80000 // physical base of MRC + +#define EISA_MEMORY_PHYSICAL_BASE 0xc0000000 // physical base of EISA memory +#define EISA_CONTROL_PHYSICAL_BASE 0x18cc0000 // physical base of EISA control +#define EISA_CONFIG_REGISTERS_MEMREGN 0x18ca8060 // MEMREG[] register + +#define PCI_MEMORY_PHYSICAL_BASE EISA_MEMORY_PHYSICAL_BASE // physical base of PCI memory + +#define PCI_MEMORY_SLOT1_PHYSICAL_BASE 0xc4000000 // PCI slot1 memory space +#define PCI_MEMORY_SLOT2_PHYSICAL_BASE 0xc8000000 // PCI slot2 memory space +#define PCI_MEMORY_SLOT3_PHYSICAL_BASE 0xcc000000 // PCI slot3 memory space + +#define PCI_CONTROL_SLOT1_PHYSICAL_BASE 0x18cd0000 // PCI slot1 I/O space +#define PCI_CONTROL_SLOT2_PHYSICAL_BASE 0x18ce0000 // PCI slot2 I/O space +#define PCI_CONTROL_SLOT3_PHYSICAL_BASE 0x18cf0000 // PCI slot2 I/O space +#define PCI_LOGICAL_START_ADDRESS 0x00000000 // S001,K00D-1 + +// +// define IDT vector +// + +#define INT0_LEVEL 3 // Define I/O interrupt Low level +#define INT1_LEVEL 4 // Define I/O interrupt High level +#define INT2_LEVEL 5 // Define I/O interrupt level +#define TIMER_LEVEL 6 // Define Timer interrupt level +#define IPI_LEVEL 7 // Define Ipi interrupt level +#define EIF_LEVEL 8 // Define Eif interrupt level +#define CLOCK_VECTOR 14 // Define Clock interrupt vector +#define PROFILE_VECTOR 15 // Define Profile interrupt vector + +#define DEVICE_VECTORS 16 // Define starting builtin device and bus vectors +#define EISA_DEVICE_VECTOR (2 + DEVICE_VECTORS) // Define Eisa interrupt vector +#define KBMS_VECTOR (3 + DEVICE_VECTORS) +#define SIO_VECTOR (4 + DEVICE_VECTORS) +#define PIO_VECTOR (5 + DEVICE_VECTORS) // S005, S00a +#define FDC_VECTOR (6 + DEVICE_VECTORS) // S005, S00a +#define SCSI1_VECTOR (7 + DEVICE_VECTORS) +#define SCSI0_VECTOR (8 + DEVICE_VECTORS) +#define ETHER_VECTOR (9 + DEVICE_VECTORS) +#define PCI_DEVICE_VECTOR (10+ DEVICE_VECTORS) // Define PCI interrupt vector +#define LR_ERR_VECTOR (13+ DEVICE_VECTORS) // Define LR4360 err vector // S015 +#define PCI_ERR_VECTOR (14+ DEVICE_VECTORS) // Define PCI err vector // S006 +#define DMA_VECTOR (15+ DEVICE_VECTORS) // Define Dma interrupt vector + +#define EISA_VECTORS 32 // Define EISA Device interrupt vectors +#define PCI_VECTORS 48 // Define Pci Device interrupt vectors + +#define MAXIMUM_BUILTIN_VECTOR ETHER_VECTOR // maximum builtin vector +#define MAXIMUM_EISA_VECTORS (15 + EISA_VECTORS) // maximum EISA vector +#define MAXIMUM_PCI_VECTORS (3 + PCI_VECTORS) // maximum PCI vector // S005 + +// +// define etc +// + +#define MAXIMUM_CPU_NUMBER 3 // maximum cpu number +// S003 +#define UNKNOWN_COUNT_BUF_LEN 64 // unknown interrupt counter buffer size + +/* Start S001 */ +// +// define PMC registers value +// + +#define PMC_CPU_SHIFT 0xc // S002 + +#define MKR_DISABLE_ALL_INTERRUPT_HIGH 0x0 +#define MKR_DISABLE_ALL_INTERRUPT_LOW 0x0 + +#define MKR_INT0_ENABLE_HIGH 0x0 +// S001 +#define MKR_INT0_ENABLE_LOW 0x00000fff +#define MKR_INT1_ENABLE_HIGH 0x0 +#define MKR_INT1_ENABLE_LOW 0x00fff000 +#define MKR_INT2_ENABLE_HIGH 0x0 +#define MKR_INT2_ENABLE_LOW 0xff000000 +#define MKR_INT3_ENABLE_HIGH 0x00030000 +#define MKR_INT3_ENABLE_LOW 0x0 +#define MKR_INT4_ENABLE_HIGH 0x0000ffff +#define MKR_INT4_ENABLE_LOW 0x0 +#define MKR_INT5_ENABLE_HIGH 0xff000000 +#define MKR_INT5_ENABLE_LOW 0x0 + +// S00F vvv +#define MKR_INT0_DEVICE_ENABLE_HIGH 0x0 +#define MKR_INT0_DEVICE_ENABLE_LOW 0x0 +#define MKR_INT1_DEVICE_ENABLE_HIGH 0x0 +#define MKR_INT1_DEVICE_ENABLE_LOW 0x00a88000 +#define MKR_INT2_DEVICE_ENABLE_HIGH 0x0 +#define MKR_INT2_DEVICE_ENABLE_LOW 0xaa000000 +// S00F ^^^ + +#define IPR_EIF_BIT_NO 61 +#define IPR_EIF_BIT_HIGH 0x20000000 +#define IPR_EIF_BIT_LOW 0x0 +#define IPR_CLOCK_BIT_NO 49 +#define IPR_CLOCK_BIT_HIGH 0x00020000 +#define IPR_CLOCK_BIT_LOW 0x0 +#define IPR_PROFILE_BIT_NO 48 +#define IPR_PROFILE_BIT_HIGH 0x00010000 +#define IPR_PROFILE_BIT_LOW 0x0 +#define IPR_IPI0_BIT_NO 47 +#define IPR_IPI0_BIT_HIGH 0x00008000 +#define IPR_IPI0_BIT_LOW 0x0 +#define IPR_IPI1_BIT_NO 46 +#define IPR_IPI1_BIT_HIGH 0x00004000 +#define IPR_IPI1_BIT_LOW 0x0 +#define IPR_IPI2_BIT_NO 45 +#define IPR_IPI2_BIT_HIGH 0x00002000 +#define IPR_IPI2_BIT_LOW 0x0 +#define IPR_IPI3_BIT_NO 44 +#define IPR_IPI3_BIT_HIGH 0x00001000 +#define IPR_IPI3_BIT_LOW 0x0 +#define IPR_SIO_BIT_NO 31 +#define IPR_SIO_BIT_HIGH 0x0 +#define IPR_SIO_BIT_LOW 0x80000000 +#define IPR_FDC_PIO_BIT_NO 29 +#define IPR_FDC_PIO_BIT_HIGH 0x0 +#define IPR_FDC_PIO_BIT_LOW 0x20000000 +#define IPR_DMA_BIT_NO 27 +#define IPR_DMA_BIT_HIGH 0x0 +#define IPR_DMA_BIT_LOW 0x08000000 +#define IPR_KB_MS_BIT_NO 25 +#define IPR_KB_MS_BIT_HIGH 0x0 +#define IPR_KB_MS_BIT_LOW 0x02000000 +#define IPR_ETHER_BIT_NO 23 +#define IPR_ETHER_BIT_HIGH 0x0 +#define IPR_ETHER_BIT_LOW 0x00800000 +#define IPR_SCSI_BIT_NO 21 +#define IPR_SCSI_BIT_HIGH 0x0 +#define IPR_SCSI_BIT_LOW 0x00200000 +#define IPR_PCI_BIT_NO 19 +#define IPR_PCI_BIT_HIGH 0x0 +#define IPR_PCI_BIT_LOW 0x00080000 +#define IPR_EISA_BIT_NO 15 +#define IPR_EISA_BIT_HIGH 0x0 +#define IPR_EISA_BIT_LOW 0x00008000 + +#define IntIR_REQUEST_IPI 0x00900000 +#define IntIR_CPU3_BIT 12 +#define IntIR_CODE_BIT 16 + +#define TCIR_ALL_CLOCK_RESTART 0x000cf000 // S00E + +// S002 +#if defined(DISABLE_NMI) +#define STSR_NMI_DISABLE 0x08080000 // S008 +#endif +#define STSR_EIF_ENABLE 0x40400000 +#define STSR_NVWINH_ENABLE 0x04040000 // S005 +#define STSR_NVWINH_DISABLE 0x00040000 // S00B +#define ERRMK_EIF_ENABLE 0xffbdfffe // S011 + +// +// Define the minimum and maximum system time increment values in 100ns units. +// +// original ntos/inc/duodef.h +#define MAXIMUM_INCREMENT (10 * 1000 * 10) +#define MINIMUM_INCREMENT (1 * 1000 * 10) + +// +// Time increment in 1us units +// +#define CLOCK_INTERVAL (MAXIMUM_INCREMENT / 10) + +// original ntos/inc/mips.h +#define DEFAULT_PROFILETIMER_COUNT 65000 // = 65 ms +#define DEFAULT_PROFILETIMER_INTERVAL (500 * 10) // = 500 us (100ns units) +#define MAXIMUM_PROFILETIMER_INTERVAL (65000 * 10) // = 65 ms (100ns units) +#define MINIMUM_PROFILETIMER_INTERVAL (40 * 10) // = 40 us (100ns units) + +// +// define IOB registers value +// + +#define EIMR_DISABLE_ALL_EIF 0x0 +#define EIMR_ENABLE_ALL_EIF 0xffe00000 // S002 +#define IEMR_ENABLE_ALL_EIF 0xfffffe00 // S002 + +#define SCFR_CPU0_CONNECT 0x8000 +#define SCFR_CPU1_CONNECT 0x4000 +#define SCFR_CPU2_CONNECT 0x2000 +#define SCFR_CPU3_CONNECT 0x1000 +#define SCFR_SIC_SET0_CONNECT 0x0800 +#define SCFR_SIC_SET1_CONNECT 0x0400 + +#define AII_INIT_DATA 0x80008000 + +// Start S008, S010 +// +// define IOB registers value +// +#define CKE0_DISABLE_SBE 0xffffffff // S011, S013 +#define DPCM_ENABLE_MASK 0x1fffffff // S013 +#define DPCM_ECC1BIT_BIT 0x40000000 // S013, S014 + +#define SECT_REWRITE_ENABLE 0x0000000f // S013 + +#if defined(WORKAROUND_SIC3) +//#define CKE0_DISABLE_SBE 0xf7ffffff // S011 +//#define CKE0_ENABLE_ALL_EIF 0xf040ff00 // S011 //R98TEMP SIC3 H/W Bug +#define CKE0_ENABLE_ALL_EIF 0xf840ff00 // S011, S013 +#define CKE1_ENABLE_ALL_EIF 0xff700000 //R98TEMP SIC3 H/W Bug +#else +//#define CKE0_DISABLE_SBE 0xf7ffffff // S011 +#define CKE0_ENABLE_ALL_EIF 0xf8c0ff00 // S011, S013 +#define CKE1_ENABLE_ALL_EIF 0xfff00000 +#endif +// End S008, S010 + +// +// Define NABus code +// + +#define NACODE_SIO ((0x1f-IPR_SIO_BIT_NO) << 0x2) +#define NACODE_FDC_PIO ((0x1f-IPR_FDC_PIO_BIT_NO) << 0x2) +#define NACODE_DMA ((0x1f-IPR_DMA_BIT_NO) << 0x2) +#define NACODE_KB_MS ((0x1f-IPR_KB_MS_BIT_NO) << 0x2) +#define NACODE_ETHER ((0x1f-IPR_ETHER_BIT_NO) << 0x2) +#define NACODE_SCSI ((0x1f-IPR_SCSI_BIT_NO) << 0x2) +#define NACODE_PCI ((0x1f-IPR_PCI_BIT_NO) << 0x2) +#define NACODE_EISA ((0x1f-IPR_EISA_BIT_NO) << 0x2) + +// +// define LR4360 registers value +// +#define ERRS_ERROR_BIT 0x00008000 // S005 +#define iREN_DISABLE_ALL_INTERRUPT 0x0 +#define iREN_ENABLE_DMA_INTERRUPT 0x00020000 +#define iREN_ENABLE_LR_ERR_INTERRUPT 0x00010000 // S015 +#define iREN_ENABLE_PCI_INTERRUPT 0x00000200 // S006 +#define iREN_ENABLE_PCI_ERR_INTERRUPT 0x00400000 // S006 +#define iREN_ENABLE_EISA_INTERRUPT 0x00000002 // S00E +#define iRRE_MASK 0x004203fe +#define iRSF_CLEAR_INTERRUPT 0x000003fe // S005 +// Start S004 +#define iRSF_ERRPCI_BIT 0x00400000 +#define iRSF_DMA_BIT 0x00020000 +#define iRSF_LR_ERR_BIT 0x00010000 // S015 +// End S004 +#define iRSF_PCI_BIT 0x00000200 +#define iRSF_ETHER_BIT 0x00000100 +#define iRSF_SCSI0_BIT 0x00000080 +#define iRSF_SCSI1_BIT 0x00000040 +#define iRSF_FDC_BIT 0x00000020 // S005, S00a +#define iRSF_PIO_BIT 0x00000010 // S005, S00a +#define iRSF_SIO_BIT 0x0000008 +#define iRSF_KBMS_BIT 0x00000004 +#define iRSF_EISA_BIT 0x00000002 +#define LR_iRSF_REG_iNSF_SHIFT 0x11 +#define LR4360PTSZ4K 0x1 +#define LR4360PTSZ8K 0x2 +#define LR4360PTSZ16K 0x4 +#define LR4360PTSZ32K 0x8 +#define LR4360PTSZSHIFT 0xc +#define LR_DMA_MODE_NORMAL 0x00 + +// +// Define dummy single read address +// + +#define SIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1 +#define PIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1 +#define FDC_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1 +#define DMA_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 +#define KBMS_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1 +#define ETHER_DUMMY_READ_ADDR KSEG1_BASE+0x018600000 +#define SCSI0_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010 +#define SCSI1_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010 +#define PCI_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 +#define EISA_DUMMY_READ_ADDR KSEG1_BASE+0x018cc0023 +#define EIF_DUMMY_READ_ADDR KSEG1_BASE+0x018000218 // S005 + +#define PMC_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S007 + +// +// Define cause register bit offset +// + +#define CAUSE_INT_PEND_BIT 0x8 + +// +// Define cause register read macro +// + +#define READ_CAUSE_REGISTER(reg) \ + .set noreorder; \ + .set noat; \ + mfc0 reg,cause; \ + nop; \ + nop; \ + .set at; \ + .set reorder; + +/* End S001 */ + +#endif _R98DEF_ diff --git a/private/ntos/nthals/halr98mp/mips/r98dspt.c b/private/ntos/nthals/halr98mp/mips/r98dspt.c new file mode 100644 index 000000000..3c89949ec --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98dspt.c @@ -0,0 +1,704 @@ +#ident "@(#) NEC r98dspt.c 1.14 95/03/17 11:55:28" +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + r98dspt.c + +Abstract: + + This module implements the interrupt dispatch routines for R98 + +Author: + + + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +/* + *********************************************************************** + * + * S001 7/7 T.Samezima + * + * Chg all alteration Int0-2 dispach routine + * + * Del move some define in r98def.h + * + *********************************************************************** + * + * S002 8/22 T.Samezima on SNES + * + * Add Buffer for register save when unknown interrupt + * Count up at loop counter + * + * Chg Modify loop logic + * + *********************************************************************** + * + * S003 9/30 T.Samezima + * + * Bug define miss on Int1 dispatch table. + * + * S004 '94.10/14 T.Samezima + * Chg Display IPR and iRSF register on bugcheck + * + * S005 '94.11/8 T.Samezima + * Del Delete call of KeBugCheck. because of wrong interrupt ocure + * of LR4360 bug + * + * S006 '94.11/21 T.Samezima + * Chg Change size of dummy read + * + * S007 '94.12/28 T.Samezima + * Add interrupt clear Broadcast in Unknown interrupt + * + * S009 '95.01/11 T.Samezima + * Add Dummy single read on EIF interrupt. + * + * S00a '95.03/13 T.Samezima + * Del PIO interrupt check. + * Add LR4360 error check. + * check dummy single read + * + */ + +#include "halp.h" +//#include "halmips.h" +#include "bugcodes.h" + +/* Start S001 */ +// +// Define table in use interrupt dispatch routine +// +#define INT2_DATA_TABLE_SIZE 5 +#define INT1_DATA_TABLE_SIZE 6 + +enum _INT_DISP_TABLE { + iRSF_BIT=0, + IPR_BIT, + IDT_VECTOR, + DUMMY_READ_ADDR, + DUMMY_READ_SIZE, + NA_CODE + }; + +typedef struct _DISPATCH_DATA_TABLE { + ULONG IrsfMask; + ULONG IprMask; + ULONG IdtVector; + ULONG DummyReadAddr; + ULONG DummyReadSize; + ULONG NaCode; +} DISPATCH_DATA_TABLE, *PDISPATCH_DATA_TABLE; + +DISPATCH_DATA_TABLE HalpInt2DispatchDataTable[] = { + {iRSF_KBMS_BIT, IPR_KB_MS_BIT_LOW, KBMS_VECTOR, + KBMS_DUMMY_READ_ADDR, 1, NACODE_KB_MS}, +// {iRSF_PIO_BIT, IPR_FDC_PIO_BIT_LOW, PIO_VECTOR, +// PIO_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a + {iRSF_LR_ERR_BIT,IPR_DMA_BIT_LOW, LR_ERR_VECTOR, + DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}, // S00a + {iRSF_FDC_BIT, IPR_FDC_PIO_BIT_LOW, FDC_VECTOR, + FDC_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a + {iRSF_SIO_BIT, IPR_SIO_BIT_LOW, SIO_VECTOR, + SIO_DUMMY_READ_ADDR, 1, NACODE_SIO}, + {iRSF_DMA_BIT, IPR_DMA_BIT_LOW, DMA_VECTOR, + DMA_DUMMY_READ_ADDR, 4, NACODE_DMA} +}; + +DISPATCH_DATA_TABLE HalpInt1DispatchDataTable[] = { + {iRSF_EISA_BIT, IPR_EISA_BIT_LOW, EISA_DEVICE_VECTOR, + EISA_DUMMY_READ_ADDR, 1, NACODE_EISA}, + {iRSF_SCSI1_BIT, IPR_SCSI_BIT_LOW, SCSI1_VECTOR, + SCSI1_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006 + {iRSF_ETHER_BIT, IPR_ETHER_BIT_LOW, ETHER_VECTOR, + ETHER_DUMMY_READ_ADDR, 2, NACODE_ETHER}, + {iRSF_PCI_BIT, IPR_PCI_BIT_LOW, PCI_DEVICE_VECTOR, + PCI_DUMMY_READ_ADDR, 4, NACODE_PCI}, // S003 + {iRSF_SCSI0_BIT, IPR_SCSI_BIT_LOW, SCSI0_VECTOR, + SCSI0_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006, S00a + {iRSF_ERRPCI_BIT,IPR_PCI_BIT_LOW, PCI_ERR_VECTOR, + PCI_DUMMY_READ_ADDR, 4, NACODE_PCI} // S003 +}; + +// DISPATCH_DATA_TABLE HalpInt0DispatchDataTable[]; + +enum _INT_TABLE_DATA{ + TABLE_SIZE=0, + MKR_MASK, + INT_LEVEL + }; + +ULONG HalpIntData[3][3] = { + {0, MKR_INT0_ENABLE_LOW, INT0_LEVEL}, + {INT1_DATA_TABLE_SIZE, MKR_INT1_ENABLE_LOW, INT1_LEVEL}, + {INT2_DATA_TABLE_SIZE, MKR_INT2_ENABLE_LOW, INT2_LEVEL} +}; + +// +// Define pointer of interrupt arbitration +// +ULONG HalpInt2ArbitrationPoint = 0; +ULONG HalpInt1ArbitrationPoint = 0; +ULONG HalpInt0ArbitrationPoint = 0; +/* End S001 */ + +#if DBG +// +// Register buffer +// + +ULONG HalpUnknownCause = 0; // S002 +ULONG HalpUnknownIPRUpper = 0; +ULONG HalpUnknownIPRLower = 0; +ULONG HalpUnknownMKRUpper = 0; +ULONG HalpUnknownMKRLower = 0; +ULONG HalpUnknowniRRE = 0; // S002 +ULONG HalpUnknowniREN = 0; // S002 +ULONG HalpUnknowniRSF = 0; // S002 +ULONG HalpUnknownIprUpperBuf = 0; // S002 +ULONG HalpUnknownIprLowerBuf = 0; // S002 +ULONG HalpIoIntLoopCounter; // S002 + +#endif + +// +// Define the context structure for use by the interrupt routine. +// + +typedef BOOLEAN (*PSECONDARY_DISPATCH)( + PVOID InterruptRoutine + ); + +typedef BOOLEAN (*PTIMER_DISPATCH)( + ULONG TrapFrame + ); + + +VOID +HalpUnknownInterrupt( + IN ULONG IprUpper, + IN ULONG IprLower + ) +/*++ + +Routine Description: + + This function is reset of unknown interrupt. + +Argments: + + IprUpper (a0) - Supplies upper 32bit of result of "IPR & MKR" in present INT level. + + IprLower (a1) - Supplies lower 32bit of result of "IPR & MKR" in present INT level. + + +Return Value: + + None. + +--*/ +{ + ULONG i; + +// Start S002 +#if DBG + HalpUnknownCause = HalpGetCause(); + + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &HalpUnknownIPRUpper, + &HalpUnknownIPRLower + ); + + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ), + &HalpUnknownMKRUpper, + &HalpUnknownMKRLower + ); + + HalpUnknownIprUpperBuf = IprUpper; + HalpUnknownIprLowerBuf = IprLower; + + HalpUnknowniRRE = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE ); + HalpUnknowniREN = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN ); + HalpUnknowniRSF = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF ); + +#if 0 // S005 vvv + KeBugCheckEx(INTERRUPT_EXCEPTION_NOT_HANDLED, + IprUpper, + IprLower, + HalpUnknowniRSF, + HalpUnknowniRRE + ); // S004 +#endif // S005 ^^^ + +#endif +// End S002 + + // + // clear interrupt pending bit + // + + HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ), + &IprUpper, + &IprLower + ); + // S007 vvv + // + // issue broadcast of unknown interrupt clear + // + + if( IprLower != 0 ) { + PDISPATCH_DATA_TABLE dataTable; + ULONG tableSize; + + if( IprLower & MKR_INT2_ENABLE_LOW ) { + dataTable = HalpInt2DispatchDataTable; + tableSize = INT2_DATA_TABLE_SIZE; + } else if( IprLower & MKR_INT1_ENABLE_LOW ) { + dataTable = HalpInt1DispatchDataTable; + tableSize = INT1_DATA_TABLE_SIZE; + } + + for( i=0; iAIMR ), + dataTable[i].NaCode ); + } + } + } + // S007 ^^^ + + // + // count up unknown interrupt + // + + for ( i=0 ; i < 32 ; i++ ) { + HalpUnknownInterruptCount[i] += (IprUpper >> i) & 1; + HalpUnknownInterruptCount[i+32] += (IprLower >> i) & 1; + } +} + +VOID +HalpEifDispatch( + VOID + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an eif interrupt. + +Argments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG pmcRegisterUpperPart; + ULONG pmcRegisterLowerPart; + ULONG pmcIPRRegisterUpperPart; + ULONG pmcIPRRegisterLowerPart; + ULONG zero=0; + ULONG buffer; + + // + // Get interrpt pending bit + // + + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); +Loop: + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ), + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + pmcRegisterUpperPart &= pmcIPRRegisterUpperPart; + + // + // Check eif interrupt + // + + buffer=pmcRegisterUpperPart & IPR_EIF_BIT_HIGH; + + if( buffer ){ + // + // issue dummy single read + // + + READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long ); + READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long ); + + HalpHandleEif(); + + HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ), + &buffer, + &zero ); + } else { + HalpUnknownInterrupt( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH, + 0 ); + } + + // + // Check new interrupt + // + + do { + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); + + if( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH ){ + goto Loop; + } + } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + EIF_LEVEL - 1)) ); + + return; +} + + +VOID +HalpTimerScDispatch( + IN ULONG TrapFrame + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an timer interrupt. + +Argments: + + TrapFrame - Supplies a pointer to a trap frame. + +Return Value: + + None. + +--*/ +{ + ULONG pmcRegisterUpperPart; + ULONG pmcRegisterLowerPart; + ULONG pmcIPRRegisterUpperPart; + ULONG pmcIPRRegisterLowerPart; + ULONG zero=0; + ULONG buffer; + + // + // read IPR register + // + + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); + + // + // read MKR register + // + +Loop: + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ), + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + pmcRegisterUpperPart &= pmcIPRRegisterUpperPart; + + // + // check profile and clock interrupt + // + + buffer=pmcRegisterUpperPart & IPR_PROFILE_BIT_HIGH; + + if( buffer ){ + HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ), + &buffer, + &zero ); + WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT2.Long), 0x0 ); // S002 + + ((PTIMER_DISPATCH) PCR->InterruptRoutine[PROFILE_VECTOR])(TrapFrame); + } else { + buffer=pmcRegisterUpperPart & IPR_CLOCK_BIT_HIGH; + + HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ), + &buffer, + &zero ); + WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT1.Long), 0x0 ); // S002 + + ((PTIMER_DISPATCH) PCR->InterruptRoutine[CLOCK_VECTOR])(TrapFrame); + } + + // + // Check new interrupt + // + + do { + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); + + if( pmcIPRRegisterUpperPart & MKR_INT3_ENABLE_HIGH ){ + goto Loop; + } + } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + TIMER_LEVEL - 1)) ); + + return; +} + + +/* Start S001 */ +VOID +HalpIoIntDispatch( + IN PDISPATCH_DATA_TABLE DataTable, + IN OUT PULONG ArbitrationPoint, + IN ULONG IntNo + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an int0, int1, and int2 interrupt. + +Argments: + + DataTable - Supplies a table useing judge interrupt factor. + + ArbitrationPoint - Supplies a start point of checking interrupt. + + IntNo - Supplies interrupt level. + +Return Value: + + None. + +--*/ +{ + ULONG pmcRegisterUpperPart; + ULONG pmcRegisterLowerPart; + ULONG pmcIPRRegisterUpperPart; + ULONG pmcIPRRegisterLowerPart; + ULONG buffer; + ULONG counter; + ULONG position; + ULONG zero=0; + ULONG flag; + + // Start S002 +#if DBG + HalpIoIntLoopCounter = 0; +#endif + // End S002 + + // + // Get interrpt pending bit + // + + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); +//Loop: // S002 + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ), + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + pmcRegisterLowerPart &= pmcIPRRegisterLowerPart; + +Loop: // S002 + buffer = READ_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF) ); + + (*ArbitrationPoint)++; + + flag = FALSE; + + for(counter = 0; counter < HalpIntData[IntNo][TABLE_SIZE] ; counter++){ + + position = ( (*ArbitrationPoint + counter) % HalpIntData[IntNo][TABLE_SIZE]); + + // + // check interrupt + // + + if( ((buffer & DataTable[position].IrsfMask) == 0) || + ((pmcRegisterLowerPart & DataTable[position].IprMask) == 0) ) { + continue; + } + + flag = TRUE; + + HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ), + &zero, + &(DataTable[position].IprMask) + ); + ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[DataTable[position].IdtVector])( + PCR->InterruptRoutine[DataTable[position].IdtVector] + ); + + // Start S002 + // + // Clear Interrupt pending bit in iRSF register + // + + WRITE_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF), + DataTable[position].IrsfMask ); + // End S002 + + // + // issue dummy single read + // + + switch(DataTable[position].DummyReadSize){ + case 1: + READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr ); + READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr ); + break; + case 2: + READ_REGISTER_USHORT( DataTable[position].DummyReadAddr ); + READ_REGISTER_USHORT( DataTable[position].DummyReadAddr ); + break; + case 4: + READ_REGISTER_ULONG( DataTable[position].DummyReadAddr ); + READ_REGISTER_ULONG( DataTable[position].DummyReadAddr ); + break; + } + + // + // issue broadcast of interrupt clear + // + + WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ), + DataTable[position].NaCode ); + + break; // S006 + } + + if (flag == FALSE){ + HalpUnknownInterrupt( 0, + pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK] + ); + } + + // + // check new interrupt + // + + do { + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ), + &pmcIPRRegisterUpperPart, + &pmcIPRRegisterLowerPart ); + + // Start S002 + HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ), + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + pmcRegisterLowerPart &= pmcIPRRegisterLowerPart; + // end S002 + + if( pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK] ){ + // Start S002 +#if DBG + HalpIoIntLoopCounter++; +#endif + // End S002 + goto Loop; + } + } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+HalpIntData[IntNo][INT_LEVEL]-1)); + + return; +} + + +VOID +HalpInt2Dispatch( + VOID + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an int2 interrupt. + +Argments: + + None. + +Return Value: + + None. + +--*/ +{ + HalpIoIntDispatch( HalpInt2DispatchDataTable, + &HalpInt2ArbitrationPoint, + 2 + ); +} + + +VOID +HalpInt1Dispatch( + VOID + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an int1 interrupt. + +Argments: + + None. + +Return Value: + + None. + +--*/ +{ + HalpIoIntDispatch( HalpInt1DispatchDataTable, + &HalpInt1ArbitrationPoint, + 1 + ); +} + + +VOID +HalpInt0Dispatch( + VOID + ) +/*++ + +Routine Description: + + This routine is enterd as the result of an int0 interrupt. + +Argments: + + None. + +Return Value: + + None. + +--*/ +{ + HalpIoIntDispatch( (PDISPATCH_DATA_TABLE)NULL, + &HalpInt0ArbitrationPoint, + 0 + ); +} +/* End S001 */ diff --git a/private/ntos/nthals/halr98mp/mips/r98eif.c b/private/ntos/nthals/halr98mp/mips/r98eif.c new file mode 100644 index 000000000..98aefd3d1 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98eif.c @@ -0,0 +1,801 @@ +#ident "@(#) NEC r98eif.c 1.16 95/03/17 11:56:21" +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + r98eif.c + +Abstract: + + This module implements the Eif interrupt service routine for R98 + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +/* + *********************************************************************** + * + * S001 6/10 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S002 7/5 T.Samezima + * + * Chg CPU No set miss + * + *********************************************************************** + * + * S003 7/22 T.Samezima + * + * Add give the dummy read after IOB and SIC register read + * for PMC3 bug + * + *********************************************************************** + * + * S004 8/23 T.Samezima + * + * Chg Condition change + * + *********************************************************************** + * + * S005 8/24 T.Samezima + * + * Chg Change a form of display on eif status + * Define buffer name + * + *********************************************************************** + * + * S006 9/22 T.Samezima + * + * Add Execution owner flag + * Lower the Irql level to TIMER_LEVEL. Because KdPrint + * use to inter processor interrupt. + * + * Chg buffer size + * + *********************************************************************** + * + * S007 9/27 T.Samezima + * + * Chg Arg miss + * + *********************************************************************** + * + * S008 9/27 T.Samezima + * + * Chg Init value + * + * S009 10/25 T.Samezima + * Add Variable of KeBugCheckEx() + * + * S00a 11/29 T.Samezima + * Add Enable _R98DBG_ + * + * S00b 12/07 T.Samezima + * Chg print format. + * + * S00c 12/24 T.Samezima + * Add ESM logic. + * Del move EIFR_REGISTER define to r98reg.h + * + * S00d '95.01/11 T.Samezima + * Add Disable EIF interrupt in wait loop. + * + * S00e '95.01/13 T.Samezima + * Add Wait for all processers in wait loop. + * + * S00f '95.01/16-25 T.Samezima + * Add Check ECC 1bit flag. + * + * S010 '95.03/10 T.Samezima + * Add NMI switch check. + * + * S011 '95.03/14 T.Samezima + * Add HalpLRErrorInterrupt() + * + */ + +#include "halp.h" +/* Start S001 */ +#include "bugcodes.h" +#include "eisa.h" +#include "stdio.h" +/* End S001 */ + +#define _R98DBG_ 1 // S00a + +// Start S005 + +// +// define buffer name +// + +enum _EIF_BUFFER { + PMC0_ERR=0, // 0 + PMC0_AERR, + PMC1_ERR, + PMC1_AERR, + PMC2_ERR, + PMC2_AERR, // 5 + PMC3_ERR, + PMC3_AERR, + PMC_EADRH, + PMC_EADRL, + IOB_IERR, // 10 + IOB_AMAH, + IOB_AMAL, + IOB_ANAH, + IOB_ANAL, + IOB_MPER, // 15 + IOB_EIFR, + SIC_N0_EIF0, + SIC_N1_EIF0, + SIC_N0_EIF1, + SIC_N1_EIF1, // 20 + SIC_N0_STS1, + SIC_N1_STS1, + SIC_N0_STS2, + SIC_N1_STS2, + SIC_N0_DSRG, // 25 + SIC_N1_DSRG, + SIC_N2_EIF0, + SIC_N3_EIF0, + SIC_N2_EIF1, + SIC_N3_EIF1, // 30 + SIC_N2_STS1, + SIC_N3_STS1, + SIC_N2_STS2, + SIC_N3_STS2, + SIC_N2_DSRG, // 35 + SIC_N3_DSRG, + LR_ERRS, + LR_PEAR, + LR_AEAR, + EISA_NMI, // 40 + MAXMUM_EIF_BUFFER +}; + +#if 0 // S00c +typedef struct _EIFR_REGISTER { + ULONG Reserved : 21; + ULONG MPDISCN : 1; + ULONG IOBERR : 1; + ULONG Reserved2 : 1; + ULONG EISANMI : 1; + ULONG LRERR : 1; + ULONG SIC1ERR : 1; + ULONG SIC0ERR : 1; + ULONG PMC3ERR : 1; + ULONG PMC2ERR : 1; + ULONG PMC1ERR : 1; + ULONG PMC0ERR : 1; +} EIFR_REGISTER, *PEIFR_REGISTER; +#endif + +// End S005 + +// +// define buffer size +// + +#define REG_BUFFER_SIZE MAXMUM_EIF_BUFFER // S005 + +// +// buffer +// + +ULONG HalpEifRegisterBuffer[REG_BUFFER_SIZE]; + +// Start S006 +// +// Owner flag +// + +volatile ULONG EifOwnFlg=0; +// End S006 + +volatile ULONG CpuCount=0; // S00e +volatile ULONG EccOccurFlag[4]={0,0,0,0}; // S00f + +// S010 vvv +#define NMI_BUFFER_SIZE 32 + +volatile ULONG HalpNMIFlag=0; +ULONG HalpNMIBuf[NMI_BUFFER_SIZE*4]; +// S010 ^^^ + +// S011 vvv +ULONG HalpLRErrorFlag=0; + +BOOLEAN +HalpLRErrorInterrupt( + VOID + ) +{ + // + // LR4360 error flag set. + // + HalpLRErrorFlag=1; + + // + // Issue EIF interrupt. + // + WRITE_REGISTER_ULONG( 0xb9980100, 0x0082f000 ); + + return TRUE; +} +// S011 ^^^ + + +VOID +HalpHandleEif( + VOID + ) + +/*++ + +Routine Description: + + This routine manage the eif interrupt + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UCHAR charBuffer; // S001 + ULONG buffer; + ULONG errsBuffer; + UCHAR messageBuffer[REG_BUFFER_SIZE*12+16]; // S006 + ULONG counter; + UCHAR EisaPort; + ULONG port; + + ULONG cpuNo; // S006 + ULONG EifFlg=0; // S006, S007 + KIRQL oldIrql; // S006 + ULONG i; // S00f + + // Start S005 +#if defined(_R98DBG_) + PEIFR_REGISTER eifrbuf; +#endif + // End S005 + + // + // Acquire eif interrupt spin lock. + // + + KiAcquireSpinLock(&HalpEifInterruptLock); + + // Start S006 + // + // Get CPU Number. + // + + cpuNo=(PCR->Prcb)->Number; + + if(EifOwnFlg == 0) { +// CpuCount=**((PULONG *)(&KeNumberProcessors)); // S00e, S00f + EifOwnFlg = 1; + EifFlg = 1; + } + +// CpuCount--; // S00e, S00f + + KiReleaseSpinLock(&HalpEifInterruptLock); + + if(EifFlg == 0) { +//#ifdef DBG + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long, + 63-IPR_EIF_BIT_NO ); // S00d + KeRaiseIrql(TIMER_LEVEL, &oldIrql); + while( EifOwnFlg == 1 ); + KeLowerIrql(oldIrql); + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, + 63-IPR_EIF_BIT_NO ); // S00d +//#else +// while( EifOwnFlg == 1 ); +//#endif + EccOccurFlag[cpuNo]=0; // S00f + return; + } + + // S00c vvv + buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long ); + + if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) && // S010, S011 + ((((PEIFR_REGISTER)&buffer)->SIC0ERR == 1) || + (((PEIFR_REGISTER)&buffer)->SIC1ERR == 1)) ){ + buffer = HalpEccError(buffer); + if(buffer == 1){ +// while( CpuCount != 0 ); // S00e + // S00f vvv + for( i=0; i<4; i++) { + EccOccurFlag[i]=1; + } + EccOccurFlag[cpuNo]=0; + // S00f ^^^ + EifOwnFlg = 0; + return; + } + } + // S00c ^^^ + // S00f vvv + else if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) && + ((buffer & 0xff600000) == 0) && (EccOccurFlag[cpuNo] == 1) ){ // S010, S011 + EccOccurFlag[cpuNo]=0; + EifOwnFlg = 0; + return; + } + // S00f ^^^ + + // S010 vvv + if( HalpNMIFlag == 0 ) { + HalDisplayString("\nEIF interrupt status: "); // S005 +#ifdef DBG + sprintf( (char *)messageBuffer, "Exe CPU=No.%1d\n", cpuNo ); // S007 +#else + sprintf( (char *)messageBuffer, "\n" ); // S007 +#endif + HalDisplayString( (char *)messageBuffer ); + } else { + HalDisplayString("\nNMI occur: \n"); + } + // S010 ^^^ + // End S006 + + // + // Check LR4360 status. + // + + errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ); + + if( (errsBuffer & ERRS_ERROR_BIT) != 0 ) { + WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS, + ERRS_ERROR_BIT ); + } + + buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long ); + IOB_DUMMY_READ; // S003 + + // + // get register value on ERR, AERR, EADRH and EADRL registers of PMC + // + + for(counter=0 ; counterERR.Long + ); + HalpEifRegisterBuffer[PMC0_AERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 0<AERR.Long + ); + /* End S001 */ + } + + if( (buffer & SCFR_CPU1_CONNECT) == 0 ) { // S004 + /* Start S001,S002 */ + HalpEifRegisterBuffer[PMC1_ERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 1<ERR.Long + ); + HalpEifRegisterBuffer[PMC1_AERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 1<AERR.Long + ); + /* End S001,S002 */ + } + + if( (buffer & SCFR_CPU2_CONNECT) == 0 ) { // S004 + /* Start S001,S002 */ + HalpEifRegisterBuffer[PMC2_ERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 2<ERR.Long + ); + HalpEifRegisterBuffer[PMC2_AERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 2<AERR.Long + ); + /* End S001,S002 */ + } + + if( (buffer & SCFR_CPU3_CONNECT) == 0 ) { // S004 + /* Start S001,S002 */ + HalpEifRegisterBuffer[PMC3_ERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 3<ERR.Long + ); + HalpEifRegisterBuffer[PMC3_AERR] = READ_REGISTER_ULONG( // S005 + &( PMC_GLOBAL_CONTROL1_OR( 3<AERR.Long + ); + /* End S001,S002 */ + } + + /* Start S001 */ + HalpEifRegisterBuffer[PMC_EADRH] = READ_REGISTER_ULONG( // S005 + &( PMC_CONTROL2 )->EADRH.Long + ); + HalpEifRegisterBuffer[PMC_EADRL] = READ_REGISTER_ULONG( // S005 + &( PMC_CONTROL2 )->EADRL.Long + ); + /* End S001 */ + + // + // get register value on IERR, AMAH, AMAL, ANAH, ANAL,MPER and EIFR + // registers of IOB. + // + + HalpEifRegisterBuffer[IOB_IERR] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->IERR.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_AMAH] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->AMAH.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_AMAL] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->AMAL.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_ANAH] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->ANAH.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_ANAL] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->ANAL.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_MPER] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->MPER.Long, + ); + IOB_DUMMY_READ; // S003 + HalpEifRegisterBuffer[IOB_EIFR] = READ_REGISTER_ULONG( // S005 + &( IOB_CONTROL )->EIFR.Long, + ); + IOB_DUMMY_READ; // S003 + + // + // get register value on EIF0, EIF1, STS1, STS2 and DSRG registers of SIC. + // + + if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S004 + /* Start S001 */ + HalpEifRegisterBuffer[SIC_N0_EIF0] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N1_EIF0] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF0.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N0_EIF1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N1_EIF1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N0_STS1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N1_STS1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N0_STS2] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS2.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N1_STS2] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS2.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N0_DSRG] = READ_REGISTER_ULONG( // S005 + &( SIC_DATA_CONTROL_OR( SIC_NO0_OFFSET ) )->DSRG.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N1_DSRG] = READ_REGISTER_ULONG( // S005 + &( SIC_DATA_CONTROL_OR( SIC_NO1_OFFSET ) )->DSRG.Long, + ); + SIC_DUMMY_READ; // S003 + /* End S001 */ + } + + if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S004 + /* Start S001 */ + HalpEifRegisterBuffer[SIC_N2_EIF0] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N3_EIF0] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF0.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N2_EIF1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N3_EIF1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N2_STS1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N3_STS1] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS1.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N2_STS2] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS2.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N3_STS2] = READ_REGISTER_ULONG( // S005 + &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS2.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N2_DSRG] = READ_REGISTER_ULONG( // S005 + &( SIC_DATA_CONTROL_OR( SIC_NO2_OFFSET ) )->DSRG.Long, + ); + SIC_DUMMY_READ; // S003 + HalpEifRegisterBuffer[SIC_N3_DSRG] = READ_REGISTER_ULONG( // S005 + &( SIC_DATA_CONTROL_OR( SIC_NO3_OFFSET ) )->DSRG.Long, + ); + SIC_DUMMY_READ; // S003 + /* End S001 */ + } + + // + // get register value on ERRS, PEAR and AEAR registers of LR4360. + // + + HalpEifRegisterBuffer[LR_ERRS] = errsBuffer; // S005 + HalpEifRegisterBuffer[LR_PEAR] = READ_REGISTER_ULONG( // S005 + &( LR_PCI_DEV_REG_CONTROL )->PEAR, + ); + HalpEifRegisterBuffer[LR_AEAR] = READ_REGISTER_ULONG( // S005 + &( LR_PCI_DEV_REG_CONTROL )->AEAR, + ); + + // + // Display EISA Nmi status. + // + + charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus); + HalpEifRegisterBuffer[EISA_NMI] = charBuffer << 24; // S001, S005 + + charBuffer = READ_REGISTER_UCHAR( + &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl + ); + HalpEifRegisterBuffer[EISA_NMI] |= charBuffer << 16; // S001, S005 + + // + // 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) { + HalpEifRegisterBuffer[EISA_NMI] |= EisaPort; // S005 + } + } + } + +#ifdef DBG // R98TEMP + KdPrint(("HAL: EIF Interrupt\n")); +#endif // R98TEMP + + // Start S005 + for( counter=0 ; counterPMC0ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from PMC0: ERR=0x%08lX, AERR=0x%08lX\n" + " EADRH=0x%08lX, EADRL=0x%08lX\n", + HalpEifRegisterBuffer[PMC0_ERR], + HalpEifRegisterBuffer[PMC0_AERR], + HalpEifRegisterBuffer[PMC_EADRH], + HalpEifRegisterBuffer[PMC_EADRL] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->PMC1ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from PMC1: ERR=0x%08lX, AERR=0x%08lX\n" + " EADRH=0x%08lX, EADRL=0x%08lX\n", + HalpEifRegisterBuffer[PMC1_ERR], + HalpEifRegisterBuffer[PMC1_AERR], + HalpEifRegisterBuffer[PMC_EADRH], + HalpEifRegisterBuffer[PMC_EADRL] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->PMC2ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from PMC2: ERR=0x%08lX, AERR=0x%08lX\n" + " EADRH=0x%08lX, EADRL=0x%08lX\n", + HalpEifRegisterBuffer[PMC2_ERR], + HalpEifRegisterBuffer[PMC2_AERR], + HalpEifRegisterBuffer[PMC_EADRH], + HalpEifRegisterBuffer[PMC_EADRL] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->PMC3ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from PMC3: ERR=0x%08lX, AERR=0x%08lX\n" + " EADRH=0x%08lX, EADRL=0x%08lX\n", + HalpEifRegisterBuffer[PMC3_ERR], + HalpEifRegisterBuffer[PMC3_AERR], + HalpEifRegisterBuffer[PMC_EADRH], + HalpEifRegisterBuffer[PMC_EADRL] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->SIC0ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from SIC SET0\n" + " No0 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n" + " STS1=0x%08lX, STS2=0x%08lX\n" + " No1 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n" + " STS1=0x%08lX, STS2=0x%08lX\n", + HalpEifRegisterBuffer[SIC_N0_EIF0], + HalpEifRegisterBuffer[SIC_N0_EIF1], + HalpEifRegisterBuffer[SIC_N0_DSRG], + HalpEifRegisterBuffer[SIC_N0_STS1], + HalpEifRegisterBuffer[SIC_N0_STS2], + HalpEifRegisterBuffer[SIC_N1_EIF0], + HalpEifRegisterBuffer[SIC_N1_EIF1], + HalpEifRegisterBuffer[SIC_N1_DSRG], + HalpEifRegisterBuffer[SIC_N1_STS1], + HalpEifRegisterBuffer[SIC_N1_STS2] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->SIC1ERR == 1){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from SIC SET1\n" + " No2 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n" + " STS1=0x%08lX, STS2=0x%08lX\n" + " No3 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n" + " STS1=0x%08lX, STS2=0x%08lX\n", + HalpEifRegisterBuffer[SIC_N2_EIF0], + HalpEifRegisterBuffer[SIC_N2_EIF1], + HalpEifRegisterBuffer[SIC_N2_DSRG], + HalpEifRegisterBuffer[SIC_N2_STS1], + HalpEifRegisterBuffer[SIC_N2_STS2], + HalpEifRegisterBuffer[SIC_N3_EIF0], + HalpEifRegisterBuffer[SIC_N3_EIF1], + HalpEifRegisterBuffer[SIC_N3_DSRG], + HalpEifRegisterBuffer[SIC_N3_STS1], + HalpEifRegisterBuffer[SIC_N3_STS2] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( HalpLRErrorFlag == 1 ){ // S011 + sprintf( (char *)messageBuffer, + "LR4360 Error Acknowledge Interrupt:\n" // S011 + " ERRS=0x%08lX, PEAR=0x%08lX, AEAR=0x%08lX\n", // S011 + HalpEifRegisterBuffer[LR_ERRS], + HalpEifRegisterBuffer[LR_PEAR], + HalpEifRegisterBuffer[LR_AEAR] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( (eifrbuf->IOBERR == 1) || (eifrbuf->MPDISCN == 1) ){ + sprintf( (char *)messageBuffer, + "EIF Interrupt from IOB: IERR=0x%08lX, AMAH=0x%08lX, AMAL=0x%08lX\n" + " ANAH=0x%08lX, ANAL=0x%08lX, EIFR=0x%08lX, MPER=0x%08lX\n", + HalpEifRegisterBuffer[IOB_IERR], + HalpEifRegisterBuffer[IOB_AMAH], + HalpEifRegisterBuffer[IOB_AMAL], + HalpEifRegisterBuffer[IOB_ANAH], + HalpEifRegisterBuffer[IOB_ANAL], + HalpEifRegisterBuffer[IOB_EIFR], + HalpEifRegisterBuffer[IOB_MPER] + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if( eifrbuf->EISANMI == 1){ + + sprintf( (char *)messageBuffer, + "EIF Interrupt from EISA NMI: NmiStatus=0x%02lX\n" + " ExtendedNmiResetControl=0x%02lX, Port=%d\n", + ((HalpEifRegisterBuffer[EISA_NMI] >> 24) & 0xff), + ((HalpEifRegisterBuffer[EISA_NMI] >> 16) & 0xff), + (HalpEifRegisterBuffer[EISA_NMI] & 0xff) + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + // S010 vvv + if( (HalpNMIFlag & 0x0000008) != 0 ) { + sprintf( (char *)messageBuffer, + "NMI from MRC\n" + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + // S010 ^^^ +#endif + // End S005 + + EifOwnFlg == 0; + + KeBugCheckEx(NMI_HARDWARE_FAILURE, + HalpEifRegisterBuffer[IOB_EIFR], + HalpNMIFlag, // S010 + HalpLRErrorFlag ? HalpEifRegisterBuffer[LR_ERRS] : 0, // S011 + 0 + ); // S009 +} diff --git a/private/ntos/nthals/halr98mp/mips/r98esm.c b/private/ntos/nthals/halr98mp/mips/r98esm.c new file mode 100644 index 000000000..bf98bf092 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98esm.c @@ -0,0 +1,1026 @@ +#ident "@(#) NEC r98esm.c 1.1 95/02/20 17:21:21" +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + r98esm.c + +Abstract: + + This module implements the ESM service routine for R98 + +Author: + + +Environment: + + Kernel mode + +Revision History: + +--*/ + +/* + * + * S001 '95.01/13 T.Samezima + * Add disable ECC 1bit error for a few second. + * Chg ECC 1bit error interrupt clear logic. + * + * S002 '95.01/14 T.Samezima + * Chg Entirely change logic to display String into nvram + * Entirely change logic to ECC error log into nvram + * + * S003 '95.01/15-24 T.Samezima + * Add wait from ECC 1bit error disable to enable. + * disable ECC 1bit error with SIC set 1 and SIC set 2. + * rewrite data on ECC 1bit error. + * + * S004 '95.01/26 T.Samezima + * Add wait to clear of register. + * + */ + +#include "halp.h" +#include "esmnvram.h" +#include "bugcodes.h" +#include "stdio.h" + +// +// define offset. +// +#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag) +#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic) +#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr) +#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest) +#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr) +#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest) +#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr) +#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest) + + +#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description) +#define TIME_STAMP_SIZE 14 + +// +// define value +// +#define NVRAM_VALID 3 +#define NVRAM_MAGIC 0xff651026 +#define ECC_LOG_VALID_FLG 1 + +#define SIC_ECC_1BIT_ERROR 1 +#define SIC_ECC_2BIT_ERROR 2 +#define SIC_OTHER_ERROR 0 + +#define SDCR_SET0_ADDR 0xb9100030 +#define SDCR_SET1_ADDR 0xb9120030 + +#define STRING_BUFFER_SIZE 512 + +#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10 + +// +// 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; + +LONG HalpECC1bitDisableFlag=1; // S001 +LONG HalpECC1bitDisableTime=0; // S003 +ULONG HalpECC1bitScfrBuffer=0; // S003 + +UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002 + +// +// Define macro +// + +#define GET_PADDR(addr,sts2,SicSet) { \ + (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \ + + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \ + + ( (SicSet) << 30 ) ); \ +} + +#define GET_TIME(Buffer) { \ + TIME_FIELDS timeBuffer; \ + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long, \ + 63-IPR_EIF_BIT_NO ); \ + HalQueryRealTimeClock( &timeBuffer ); \ + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, \ + 63-IPR_EIF_BIT_NO ); \ + sprintf( (Buffer), \ + "%04d%02d%02d%02d%02d%02d", \ + timeBuffer.Year, \ + timeBuffer.Month, \ + timeBuffer.Day, \ + timeBuffer.Hour, \ + timeBuffer.Minute, \ + timeBuffer.Second \ + ); \ +} + +// S002, S003 vvv +#define NOTIFY_ECC1BIT(Scfr) { \ + ULONG buffer; \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer &= DPCM_ENABLE_MASK; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \ + if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer &= DPCM_ENABLE_MASK; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \ + buffer); \ + } \ +} + +#define DONT_NOTIFY_ECC1BIT(Scfr) { \ + ULONG buffer; \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer |= DPCM_ECC1BIT_BIT; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \ + buffer); \ + if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \ + buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \ + SIC_DUMMY_READ; \ + buffer |= DPCM_ECC1BIT_BIT; \ + WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \ + buffer); \ + } \ +} +// S002, S003 ^^^ + + +ULONG +HalpEccError( + IN ULONG EifrRegister + ) + +/*++ + +Routine Description: + + This routine check ecc error and error log put in NVRAM. + +Arguments: + + EifrRegister - EIFR register value in IOB. + +Return Value: + + return value is the following error occured. + 1: ecc 1bit error. + 2: ecc 2bit error. + 0: other error. + +--*/ + +{ + ULONG returnValue; + ULONG sicSet; + ULONG sicOffset; + USHORT infoOffset; + USHORT writeOffset; + ULONG eif0Buffer; + ULONG sts2Buffer; + ULONG sdlmBuffer; + ULONG buffer; // S001 + ULONG i; // S002 + ULONG errAddr; // S002 + UCHAR dataBuf[36]; + UCHAR infoBuf[24]; + UCHAR tempBuf[24]; + + HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long ); + IOB_DUMMY_READ; + + // + // check interrupt from where. + // + + if ( ((PEIFR_REGISTER)&EifrRegister)->SIC1ERR == 1){ + sicSet = 1; + eif0Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long ); + SIC_DUMMY_READ; + if(eif0Buffer & 0x000000c0){ + sicOffset = SIC_NO2_OFFSET; + } else { + sicOffset = SIC_NO3_OFFSET; + } + }else{ + sicSet = 0; + eif0Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long ); + SIC_DUMMY_READ; + if(eif0Buffer & 0x000000c0){ + sicOffset = SIC_NO0_OFFSET; + } else { + sicOffset = SIC_NO1_OFFSET; + } + } + + // + // read diagnosis registers. + // + + eif0Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long ); + SIC_DUMMY_READ; + sts2Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->STS2.Long ); + SIC_DUMMY_READ; + sdlmBuffer = READ_REGISTER_ULONG( + &( SIC_DATA_CONTROL_OR( sicOffset ) )->SDLM.Long ); + SIC_DUMMY_READ; + + // + // Check ECC 1bit or 2bit err + // + + if( (eif0Buffer & 0x08000000) && + ((eif0Buffer & 0xf0000000) == 0) && + ((EifrRegister & 0xf3600000) == 0) ){ + returnValue= SIC_ECC_1BIT_ERROR; + infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET; + } else if (eif0Buffer & 0x00000040){ + returnValue= SIC_ECC_2BIT_ERROR; + infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET; + } else { + return(SIC_OTHER_ERROR); + } + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf ); + + // S002 vvv + switch(returnValue) { + + case SIC_ECC_2BIT_ERROR: + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG; + + GET_PADDR( (((pECC2_ERR_REC)dataBuf)->err_address), sts2Buffer, sicSet); + + GET_TIME(tempBuf); + RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ), + (PVOID)tempBuf, + TIME_STAMP_SIZE + ); + + ((pECC2_ERR_REC)dataBuf)->syndrome = sdlmBuffer; + + ((pECC2_ERR_REC)dataBuf)->specified_group = + (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4); + + ((pECC2_ERR_REC)dataBuf)->specified_simm = + (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN ); + + 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); + } + break; + + + case SIC_ECC_1BIT_ERROR: + + if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){ + + HalNvramRead( (ULONG)infoOffset, 20, infoBuf); + + // + // Disable and clear ECC 1bit error. + // + + DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003 + + if(sicSet == 0){ + WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 ); + } else { + WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 ); + } + + do { + buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long ); + SIC_DUMMY_READ; + } while ( (buffer & 0x08000000) != 0 ); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long, + EifrRegister & 0x0c000000 ); + + // + // Check New error or Old error. + // + + GET_PADDR( errAddr, sts2Buffer, sicSet); + HalpReadAndWritePhysicalAddr( errAddr ); // S003 + + 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) ) { + break; + } + } + + if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) { + break; + } + + // + // wait 20 us. + // + + KeStallExecutionProcessor(20); + + // + // Enable ECC 1bit error. + // + + NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003 + + // + // Check ECC 1bit error. + // + + HalpReadPhysicalAddr( errAddr ); + + buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long ); + SIC_DUMMY_READ; + + if( (buffer & 0x08000000) == 0 ) { + break; + } + + // + // 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)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4); + + ((pECC1_ERR_REC)dataBuf)->specified_simm = + (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN ); + + 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); + } + + break; + } + + if(returnValue == SIC_ECC_1BIT_ERROR) { + + DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003 + + if(sicSet == 0){ + WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 ); + } else { + WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 ); + } + + do { + eif0Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long ); + SIC_DUMMY_READ; + } while ( (eif0Buffer & 0x08000000) != 0 ); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long, + EifrRegister & 0x0c000000 ); + // S004 vvv + do { + eif0Buffer = READ_REGISTER_ULONG( + &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long ); + SIC_DUMMY_READ; + buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long ); + IOB_DUMMY_READ; + } while ( ((buffer & 0x0c000000) != 0) && ((eif0Buffer & 0xf8000000) == 0) ); + // S004 ^^^ + + if(HalpECC1bitDisableFlag > 0) { + HalpECC1bitDisableFlag--; + if(HalpECC1bitDisableFlag > 0) { + NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003 + } + // S003 vvv + else { + HalpECC1bitDisableTime = ECC_1BIT_ERROR_DISABLE_TIME; + HalpECC1bitDisableFlag = 0; + } + // S003 ^^^ + } + } + // S002 ^^^ + + return(returnValue); +} + + +VOID +HalpInitDisplayStringIntoNvram( + VOID + ) + +/*++ + +Routine Description: + + This routine is initialize variable of use when write display data in + HalDisplayString into NVRAM. + + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + SYSTEM_ERR_AREA_INFO infoBuf; + UCHAR recordFlg; + UCHAR buf[8]; + UCHAR buf2[8]; + + CallCountOfInitDisplay++; + if(CallCountOfInitDisplay == 1){ + + // + // Check NVRAM status + // + + HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf ); + HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 ); + + if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){ + HalpNvramValid=FALSE; + return; + } + + HalpNvramValid=TRUE; + + // + // Get log area infomation. + // + + HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET, + sizeof(SYSTEM_ERR_AREA_INFO), + &infoBuf); + + ErrBufferLatest = infoBuf.offset_latest; + + HalNvramRead( infoBuf.offset_latest, 1, &recordFlg); + + // + // Check current record flg. + // + + if( (recordFlg & 0x01) == 1 ) { + infoBuf.offset_latest += infoBuf.size_rec; + if( infoBuf.offset_latest >= + infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){ + infoBuf.offset_latest = infoBuf.offset_systemerr; + } + HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, + 2, + &infoBuf.offset_latest); + } + + // + // initialize variable. this value use log area access. + // + + ErrBufferArea = infoBuf.offset_latest; + ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE; + ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1; + ErrBufferCurrent = ErrBufferStart; + + // + // status flg set. + // + + HalpPanicFlg = 0; + + recordFlg = 0x11; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + + // + // buffer initialize. + // + + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + + } else { + + // + // start Panic log. + // + + HalpChangePanicFlag( 1, 1, 0); + } +} + +VOID +HalpSetInitDisplayTimeStamp( + VOID + ) +{ + UCHAR buf[24]; + + // + // Set time stamp on initialize display. + // + + if(HalpNvramValid == TRUE) { + GET_TIME(buf); + HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf ); + } +} + + +VOID +HalpSuccessOsStartUp( + VOID + ) +{ + UCHAR recordFlg; + + if(HalpNvramValid == TRUE) { + recordFlg = 0; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest ); + } +} + + +VOID +HalpChangePanicFlag( + IN ULONG NewPanicFlg, + IN UCHAR NewLogFlg, + IN UCHAR CurrentLogFlgMask + ) +{ + UCHAR recordFlg; + UCHAR buf[24]; + + if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) { + return; + } + + HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, + 2, + &ErrBufferArea); + + // + // initialize currernt buffer address + // + + ErrBufferCurrent = ErrBufferStart; + + // + // set panic flag + // + + HalNvramRead( ErrBufferArea, 1, &recordFlg ); + recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg; + HalNvramWrite( ErrBufferArea, 1, &recordFlg ); + + GET_TIME(buf); + HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf ); + + // + // set new flag of panic level + // + + HalpPanicFlg = NewPanicFlg; + + // + // initialize log buffer. + // + + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); +} + + +// S002 vvv +VOID +HalStringIntoBuffer( + IN UCHAR Character + ) +{ + if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) { + HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character; + } +} + + +VOID +HalStringIntoBufferStart( + IN ULONG Column, + IN ULONG Row + ) +{ + ULONG i; + + // + // Initialize buffer + // + + for(i=0; i ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) { + return; + } else { + if( HalpPanicFlg == 0 ) { + ErrBufferCurrent = ErrBufferStart; + goto loop; + } else if(ErrBufferCurrent >= ErrBufferEnd){ + return; + } + + for(count=0;;count++) { + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count ); + } + ErrBufferCurrent++; + if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) { + break; + } + } + + buf[0]=0xff; + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + } +} + +#if 0 +VOID +HalpStringIntoNvram( + IN ULONG Column, + IN ULONG Row, + IN PUCHAR String + ) +{ + UCHAR buf[4]; + USHORT count; + + // + // check nvram status. + // + + if(HalpNvramValid == FALSE) { + return; + } + + // + // check panic message + // + + for(count=0; 1; count++) { + if( KernelPanicMessage[count] == '\0' ){ + HalpChangePanicFlag( 8, 0x01, 0x10); + break; + } + if( KernelPanicMessage[count] != String[count] ){ + break; + } + } + + // + // check message length + // + + for(count=0;;count++) { + if(String[count]=='\0'){ + count++; + break; + } + } + +loop: + if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) { + buf[0]=(UCHAR)Column; + buf[1]=(UCHAR)Row; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + ErrBufferCurrent += 2; + HalNvramWrite( ErrBufferCurrent, count, String ); + ErrBufferCurrent += count; + buf[0]=0xff; + buf[1]=0xff; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + + } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) { + return; + } else { + if( HalpPanicFlg == 0 ) { + ErrBufferCurrent = ErrBufferStart; + goto loop; + } else if(ErrBufferCurrent >= ErrBufferEnd){ + return; + } + + buf[0]=(UCHAR)Column; + buf[1]=(UCHAR)Row; + HalNvramWrite( ErrBufferCurrent, 2, buf ); + ErrBufferCurrent += 2; + + for(count=0;;count++) { + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent, 1, String+count ); + } + ErrBufferCurrent++; + if(String[count]=='\0') { + break; + } + } + + buf[0]=0xff; + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + if(ErrBufferCurrent < ErrBufferEnd) { + HalNvramWrite( ErrBufferCurrent++, 1, buf ); + } + } +} +#endif +// S002 ^^^ + + +// +// test code +// + +int +printNvramData(void) +{ + UCHAR buf[256]; + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf ); + DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf ); + buf[14]=0; + DbgPrint("Nvram TimeStamp: %s\n", buf); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err), + sizeof(ECC1_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err), + sizeof(ECC2_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err), + sizeof(SYSTEM_ERR_AREA_INFO), + buf ); + DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf ); + DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) ); + DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) ); + DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) ); + + return(0); +} + + +int +TmpInitNvram(void) +{ + UCHAR buf[256]; + ULONG i; + + buf[0]=0xff; + for(i=0; i<8*1024; i++) + HalNvramWrite( i, 1, buf); + + // + // Make nvram flg + // + + buf[0]=0x03; + HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf); + + i = NVRAM_MAGIC; + HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 1, (PUCHAR)&i); + + // + // Make 1bit err log info + // + + ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768; + ((pECC1_ERR_AREA_INFO)buf)->size_rec=25; + ((pECC1_ERR_AREA_INFO)buf)->num_rec=16; + ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768; + + ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0; + + ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0; + ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0; + + HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET, + sizeof(ECC1_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=768; i<768+25*16; i++) + HalNvramWrite( i, 1, buf); + + // + // Make 2bit err log info + // + + ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400; + ((pECC2_ERR_AREA_INFO)buf)->size_rec=25; + ((pECC2_ERR_AREA_INFO)buf)->num_rec=4; + ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400; + + ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0; + + HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET, + sizeof(ECC2_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=768+400; i<768+400+25*4; i++) + HalNvramWrite( i, 1, buf); + + // + // Make system err log info + // + + ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280; + ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512; + ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4; + ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280; + + HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET, + sizeof(ECC2_ERR_AREA_INFO), + buf); + + buf[0]=0; + for(i=1280; i<1280+512*4; i++) + HalNvramWrite( i, 1, buf); + + return(0); +} diff --git a/private/ntos/nthals/halr98mp/mips/r98hal.h b/private/ntos/nthals/halr98mp/mips/r98hal.h new file mode 100644 index 000000000..63bfa51df --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98hal.h @@ -0,0 +1,132 @@ +#ident "@(#) NEC r98hal.h 1.4 94/09/22 16:56:52" +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + r98hal.h + + +Abstract: + + This module is the header that dma structure and etc. + +Author: + + +Revision History: + +--*/ + +/* + *********************************************************************** + * + * S001 7/12 T.Samezima + * + * Chg define chenge + * + * K001 94/09/22 N.Kugimoto + * Chg DMA logcal addres sapce 4M--->16M + */ + +#ifndef _R98HAL_ +#define _R98HAL_ + +// Start S001 +// +// Map buffer prameters. These are initialized in HalInitSystem +// + +extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress; +extern ULONG HalpMapBufferSize; +// End S001 + +// +// define structure of adapter object +// +typedef struct _ADAPTER_OBJECT { // (= ntos/hal/i386/ixisa.h) + CSHORT Type; + CSHORT Size; + struct _ADAPTER_OBJECT *MasterAdapter; + ULONG MapRegistersPerChannel; + PVOID AdapterBaseVa; + PVOID MapRegisterBase; + ULONG NumberOfMapRegisters; + ULONG CommittedMapRegisters; // new add + struct _WAIT_CONTEXT_BLOCK *CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + KSPIN_LOCK SpinLock; + PRTL_BITMAP MapRegisters; + PUCHAR PagePort; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + UCHAR AdapterMode; +} ADAPTER_OBJECT; // del duo's SingleMaskPort + +// +// Define map register translation entry structure For Internal. +// + +typedef struct _INTERNAL_TRANSLATION_ENTRY { + PVOID VirtualAddress; + ULONG PhysicalAddress; + ULONG Index; +} INTERNAL_TRANSLATION_ENTRY, *PINTERNAL_TRANSLATION_ENTRY; + +// Start S001 +typedef struct _TRANSLATION_ENTRY { + ULONG PageFrame; +} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY; +// End S001 + +// +// define dma +// + +#define MACHINE_TYPE_ISA 0 +#define MACHINE_TYPE_EISA 1 + +#define MAXIMUM_MAP_BUFFER_SIZE 0x40000 // 64 page + +#define INITIAL_MAP_BUFFER_SMALL_SIZE MAXIMUM_MAP_BUFFER_SIZE +#define INITIAL_MAP_BUFFER_LARGE_SIZE MAXIMUM_MAP_BUFFER_SIZE + +#define INCREMENT_MAP_BUFFER_SIZE 0x10000 // 16 page +#define MAXIMUM_ISA_MAP_REGISTER (MAXIMUM_MAP_BUFFER_SIZE/(PAGE_SIZE*2)) + // 32 page + +#define MAXIMUM_PHYSICAL_ADDRESS 0x60000000 // max : 16MB // S001 + +#define COPY_BUFFER 0xFFFFFFFF +#define NO_SCATTER_GATHER 0x00000001 +#define DMA_TRANSLATION_LIMIT 0x4000 // TLB alloc size K001 + +// +// Define pointer to DMA control registers. +// +// Start S001 +#define DMA_CONTROL(x) ((volatile PDMA_CHANNEL)((ULONG)(KSEG1_BASE | LR_CHANNEL_BASE |(x)))) +// End S001 + +// +// Define MRC register structure. +// +typedef struct _MRC_REGISTERS { // offset(H) + UCHAR Reserved1[48]; // 0-2f + UCHAR SwReset; // 30 + UCHAR Reserved2[19]; // 31-43 + UCHAR LedData0; // 44 + UCHAR LedData1; // 45 + UCHAR LedData2; // 46 + UCHAR LedData3; // 47 +} MRC_REGISTERS, *PMRC_REGISTERS; + +// +// Define pointer to MRC registers. +// +#define MRC_CONTROL ((volatile PMRC_REGISTERS)(KSEG1_BASE | MRC_PHYSICAL_BASE)) + +#endif _R98HAL_ diff --git a/private/ntos/nthals/halr98mp/mips/r98hwsup.c b/private/ntos/nthals/halr98mp/mips/r98hwsup.c new file mode 100644 index 000000000..4cee934f9 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98hwsup.c @@ -0,0 +1,4771 @@ +#ident "@(#) NEC r98hwsup.c 1.41 95/06/19 11:31:38" +/*++ + +Copyright (c) 1990-1994 Microsoft Corporation + +Module Name: + + r98hwsup.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. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * HalpCreateDmaStructures() + * + * L001 94.03/24 T.Samezima + * + * Change Interrupt service routine + * + * Add Call initialize of PCI interrupt + * Interrupt enable + * + * K001 '94.5/30 (Mon) N.Kugimoto + * -1 Add HalAllocateAdapterChannel(): + * -2 Add HalAllocateCommonBuffer(): + * -3 Non HalFlushCommonBuffer() + * -4 Add HalFreeCommonBuffer(): For Internal Device + * -5 Chg HalGetAdapter(): New!! + * -6 Mix HalpAllocateAdapter(): mix halfxs,halx86 + * -7 Add IoFreeMapRegisters(): For Internal Device + * -8 Add IoFreeAdapterChannel(): For Internal Device + * -9 FRM HalpAllocateMapRegisters() From halx86 + * -A Mix IoMapTransfer() mix halfxs,halx86 + * -B Mix IoFlushAdapterBuffers() mix halfxs,halx86 + * -C FRM HalpAllocationRoutine () From halfxs + * -D FRM HalReadDmaCounter() From halfxs + * -E Del HalpDmaInterrupt() allways retrun 1 + * -F FRM HalpGrowMapBuffers() halx86 + * -G FRM HalpCopyBufferMap() from halx86 and Argument chg. + * + * K002 Add MasterAdapterObjectForInternal + * K003 Chg HalpInternalAdapters[5]: LR4360 DMA have 5 channel + * K004 Add HalpDmaInterrupt() + * K005 fix spell miss + * K006 FRM global value define!! From halx86 + * K007 Chg if def chg + * K008 94/5/31 N.Kugimoto + * Chg HalTranslateBusAddress() + * N.B. Pci trans addr is per slot ??. + * K009 94/5/31 N.Kugimoto + * BUG AddressSpace!! + * K00A 94/6/2 (Thu) N.Kugimoto + * Chg HalAllocateCrashDumpRegisters() + * N.B. check is OK?? + * + * S002 94.03/24 T.Samezima + * + * Add HalpNmiHandler() + * HalpRegisterNmi() ??? + * + * K00B 94/6/3 (Fri) N.Kugimoto + * Del + * K00C 94/6/6 (Mon) N.Kugimoto + * Chg K007 enable + * K00D 94/6/9 (Thu) N.kugimoto + * Chg Compile err del. + * K00E 94/7/1 (Fri) N.Kugimoto + * -1 Chg IoFlushAdapterBuffers() + * -2 Add IoFlushAdapterBuffers() Reserved Bit set 0. + * -3 Del HalAllocateCrashDumpRegisters() limit check del. + * -4 Bug IoMapTransfer() transferLength is Bad!!. + * -5 Bug MasterAdapterObject ==> AdapterObject. + * -6 Bug at this line. LR4360 dma + * -7 Bug enable #if 0 and eisadma is del. + * -8 Del This code is never use. so del. + * K00F 94/7/6 (Wed) N.Kugimoto + * Mov HalGetAdapter() CnDC->FiFoF Flush LR4360 DMA FiFo Move IoMapTransfer() + * Per DMA Translation. + * K010 94/7/8 (Fri) N.Kugimoto + * -1 Chg enable check logic. + * -2 Add comment add. LR4360 DMA Byte Count Register 64M. Bit25-Bit0. + * -3 Add Comment add. This value use only as flag. Not Port Addr. + * K011 94/8/22 (Mon) N.Kugimoto + * -1 Bug if {} else not match!!. Debug On SNES. + * -2 Bug HalpDmaInterrupt() enable Because First run rather than + * IoFlushAdapterBuffers().Debug On SNES. + * K012 94/9/22 N.Kugimoto + * -1 Bug MasterAdapterObject->NumberOfMapRegiser is Non Initialize. + * K013 94/9/22 N.Kugimoto + * -1 Chg Externl logical addr first allocation 1M align. + * second allocaton is start offset 0. + * -2 Bug MasterAdapter can't use this line. + * K014 94/9/22 N.Kugimoto + * compile err + * K015 94/09/26 N.Kugimoto + * Mov move code to r98busdat.c + * K016 94/09/29 N.Kugimoto + * -1 Chg allocate memory is less than 512M. To see from KSEG1_BASE. + * -2 Add cast ULONG . + * K017 94/10/05 N.Kugimoto + * -1 Bug must be () . + * K018 94/10/07 N.Kugimoto + * -1 Bug align 1m Logic Bug. + * K019 94/10/06 N.Kugimoto + * -1 Bug LR4360 PTBARn Register must be PFN. Not KSEG1_BASE value. + * K020 94/10/11 N.Kugimoto + * -1 Fix Version Up At 807 Base. + * K021 94/10/11 N.Kugimoto + * -1 Add page table clear + * -2 Add tlb flush + * K022 94/10/11 N.Kugimoto + * Add NMI Logic + * K023 94/10/12 N.Kugimoto + * K024 94/10/13 N.Kugimoto + * Chg Compile err + * S025 94/10/14 T.Samezima + * Del Move logic on connect int1 interrupt to allstart.c + * K025 94/10/17 N.Kugimoto + * Bug K020-1 miss + * K026 94/10/18 N.Kugimoto + * -1 Bug LR4360 Page Table is KSEG0_BASE + * -2 Chg Page table Entry Invalidate. + * -3 Chg tlb flush timing chg + * K027 94/11/11 N.Kugimoto + * -1 Chg cache enable + * -2 Chg Som Logical addr range not Used. + * + * K028 95/2/22 N.Kugimoto + * Chg PCEB Prefetch sycle caused LR4360 page fault + * K029 95/2/22 N.Kugimoto + * Add LR4360 TLB RoundUp. + * K030 95/2/22 N.Kugimoto + * Chg LR4360 TLB No Flush. Because At DMA .... + * K031 95/2/22 N.Kugimoto + * Add LR4360 I/O Read Cache Flush + * K032 95/3/13 N.Kugimoto + * Chg #if #else fix Miss. + * + * S003 95/3/14 T.Samezima + * Add Add HalpLRErrorInterrupt() at dispatch table. + * K034 95/04/12 N.Kugimoto + * Del NOTLBFLUSH + * Add DUMMYDMA This is Work around. + * LR4360 can't TLB flush while dma. So ESC DMAC channel 2 use + * Dummy dma 1byte. It't cause TLB flush . + * S004 95/5/15 T.Samezima + * Chg vaild page table on LR4360 + * A002 1995/6/17 ataka@oa2.kb.nec.co.jp + * - resolve compile error. + * ------------------------------------------------------------------- + * K035 95/6/16 N.Kugimoto + * Up version Up 3.51 + */ + +#include "halp.h" +#include "bugcodes.h" +#include "eisa.h" + +#include "jazznvr.h" //K00D + +// +// 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) +#pragma alloc_text(PAGE,HalpGrowMapBuffers) //K035 + +#endif + +extern POBJECT_TYPE IoAdapterObjectType; + +// +// 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; +// +// K002 +// +PADAPTER_OBJECT MasterAdapterObjectForInternal; + + +// K006 +// Map buffer prameters. These are initialized in HalInitSystem +// + +PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress; +ULONG HalpMapBufferSize; + +// +// Pointer to phyiscal memory for map registers. +// + +ULONG HalpMapRegisterPhysicalBase; + + +// PCEB Prefetch sycle cause LR4360 Page Fault +// So reserved DummyPhysicalPage +ULONG HalpNec0DummyPhysicalBase; // K028 +ULONG HalpNec1DummyPhysicalBase; // K028 + +ULONG HalpLogicalAddrArbPoint=0; +KSPIN_LOCK HalpIoMapSpinLock; + +// K004 +// The following function is called when a DMA channel interrupt occurs. +// + +BOOLEAN +HalpDmaInterrupt( + VOID //K00D + ); + + +// +// The following is an array of adapter object structures for the internal DMA +// channels. +// K003 +// N.B: Internal Device without Scatter/Gather not use this array. +// + +PADAPTER_OBJECT HalpInternalAdapters[5]; + + +IO_ALLOCATION_ACTION +HalpAllocationRoutine ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID MapRegisterBase, + IN PVOID Context + ); + +// A002 +PVOID +RtlFillMemoryUlong ( + IN PVOID Destination, + IN ULONG Length, + IN ULONG Pattern + ); +// A002 +VOID +HalpDummyTlbFlush( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG Offset, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ); + +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. + +--*/ + +{ + /* Start L001 */ + ULONG buffer; + + // + // Initialize the interrupt dispatcher for I/O interrupts. + // + // N.B. This vector is reserved for exclusive use by the HAL (see + // interrupt initialization). + // + + PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch; +// PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; // S025 + + PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch; + + // + // Directly connect the local device interrupt dispatcher to the local + // device interrupt vector. + // + + PCR->InterruptRoutine[DMA_VECTOR] = (PKINTERRUPT_ROUTINE) HalpDmaInterrupt; + + // S003 + PCR->InterruptRoutine[LR_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpLRErrorInterrupt; + + // + // + // + + KiAcquireSpinLock(&HalpSystemInterruptLock); + + HalpBuiltinInterruptEnable |= + (iREN_ENABLE_DMA_INTERRUPT | iREN_ENABLE_LR_ERR_INTERRUPT ); // S003 + + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + + KiReleaseSpinLock(&HalpSystemInterruptLock); + +#if 0 // Start S025 + // + // Initialize EISA bus interrupts. + // + + HalpCreateEisaStructures(); + + // + // Initialize PCI bus interrupts. + // + + return HalpCreatePciStructures (); +#else + return TRUE; +#endif // End S025 + /* End L001 */ +} + +// K001: +// +// +NTSTATUS +HalAllocateAdapterChannel( + IN PADAPTER_OBJECT AdapterObject, + IN PWAIT_CONTEXT_BLOCK Wcb, + IN ULONG NumberOfMapRegisters, + IN PDRIVER_CONTROL ExecutionRoutine + ) +/*++ + +Routine Description: + + This routine allocates the adapter channel specified by the adapter object. + This is accomplished by placing the device object of the driver that wants + to allocate the adapter on the adapter's queue. If the queue is already + "busy", then the adapter has already been allocated, so the device object + is simply placed onto the queue and waits until the adapter becomes free. + + Once the adapter becomes free (or if it already is), then the driver's + execution routine is invoked. + + Also, a number of map registers may be allocated to the driver by specifying + a non-zero value for NumberOfMapRegisters. Then the map register must be + allocated from the master adapter. Once there are a sufficient number of + map registers available, then the execution routine is called and the + base address of the allocated map registers in the adapter is also passed + to the driver's execution routine. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + + Wcb - Supplies a wait context block for saving the allocation parameters. + The DeviceObject, CurrentIrp and DeviceContext should be initalized. + + NumberOfMapRegisters - The number of map registers that are to be allocated + from the channel, if any. + + ExecutionRoutine - The address of the driver's execution routine that is + invoked once the adapter channel (and possibly map registers) have been + allocated. + +Return Value: + + Returns STATUS_SUCESS unless too many map registers are requested. + +Notes: + + Note that this routine MUST be invoked at DISPATCH_LEVEL or above. + +--*/ + +{ + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + LONG MapRegisterNumber; + KIRQL Irql; + ULONG srachPoint; + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // dicide MasterAdapter whitch Intrenal Scatter/gathero or PCI,EISA,ISA + // + + 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 && AdapterObject->MasterAdapter != NULL) { + + if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ //K011-1 + // + // At Internal check adapterobject itself. + // + if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + }else{ + // + // At PCI,EISA,ISA check with Masteradapter + // + if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + } //K011-1 + // + // 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)) { + + if(MasterAdapter == MasterAdapterObject){ + srachPoint = HalpLogicalAddrArbPoint; + HalpLogicalAddrArbPoint = (HalpLogicalAddrArbPoint+256) % + (DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)); + } else { + srachPoint = 0; + } + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + MasterAdapter == + MasterAdapterObject ? NumberOfMapRegisters+1 : NumberOfMapRegisters, //K028 + srachPoint + + ); + + } + 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 { + + if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ + AdapterObject->MapRegisterBase = + (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + + MapRegisterNumber); + // + // Set the no scatter/gather flag if scatter/gather not + // supported on Internal Device. + // ~~~~~~~ + // + + AdapterObject->MapRegisterBase = + (PVOID)((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + }else{ + AdapterObject->MapRegisterBase = + (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + + MapRegisterNumber ); //add1 non + + } + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + }else { + AdapterObject->MapRegisterBase = NULL; + + } + + // + // 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); +} + +// K001-2 +// +// +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; + + + PHYSICAL_ADDRESS physicalAddress; + + CacheEnabled =TRUE; //K027-1 + // Is it Internal Device ?. + // + + + if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal || + (AdapterObject->MasterAdapter==NULL ) // K00B + ){ + // + // Internal Device Not use LR4360 TLB. + // LowPart is Any. + // + physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1; + physicalAddress.HighPart = 0; + virtualAddress = MmAllocateContiguousMemory( + Length, + physicalAddress + ); + + if (virtualAddress == NULL) { + return(NULL); + } + + *LogicalAddress = MmGetPhysicalAddress(virtualAddress); + + return(virtualAddress); + } + + // + // PCI,EISA,ISA Device use LR4360 TLB. + // + numberOfMapRegisters = BYTES_TO_PAGES(Length); + + // + // Allocate the actual buffer. + // + if (CacheEnabled != FALSE) { //K020-1 + + 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) { //K020-1 + 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) { //K020-1 + 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. + // + // mapRegisterBase was set up at HalAllocateAdapterChannel()-->ExecutionRoutine()--> + // HalpAllocationRoutine() (value same MapRegisterBase) + // + // + mappedLength = Length; + *LogicalAddress = IoMapTransfer( + NULL, + mdl, + mapRegisterBase, + virtualAddress, + &mappedLength, + TRUE + ); + + //DbgPrint("\n Common Logical = 0x %x \n",*LogicalAddress); + IoFreeMdl(mdl); + + if (mappedLength < Length) { + + // + // Cleanup and indicate that the allocation failed. + // + + HalFreeCommonBuffer( + AdapterObject, + Length, + *LogicalAddress, + virtualAddress, + CacheEnabled //K020-1 + ); + + return(NULL); + } + + // + // The allocation completed successfully. + // + + return(virtualAddress); + +} + +// K00A +// +PVOID +HalAllocateCrashDumpRegisters( + IN PADAPTER_OBJECT AdapterObject, + IN PULONG NumberOfMapRegisters //K020-1 + ) +/*++ + +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; +//K020-1 ULONG NumberOfMapRegisters; + ULONG MapRegisterNumber; +#if !defined(_R98_) + ULONG Hint; +#endif + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + if (AdapterObject->MasterAdapter) { + MasterAdapter = AdapterObject->MasterAdapter; + } else { +#if defined(_R98_) + // MasterAdapter==NULL This is Internal Device with Scatter/Gather. + // So Nothing to Do. Never Use Mapregisters for contigus memory. + // N.B. MasterAdapterObject[ForInternal] does not come here!!. + // So No check !!. + AdapterObject->MapRegisterBase = NULL; + AdapterObject->NumberOfMapRegisters = 0; + return AdapterObject->MapRegisterBase; +#else + MasterAdapter = AdapterObject; +#endif + + + } + + // + // Set the number of map registers required. + // + +//K020-1 *NumberOfMapRegisters = 16; + + + // + // Ensure that this adapter has enough total map registers to satisfy + // the request. + // +#if 1 // K010-1 + // K00E-3 + // + if(MasterAdapter == MasterAdapterObjectForInternal){ + if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { //K020-1 + AdapterObject->NumberOfMapRegisters = 0; + return NULL; + } + }else{ + // PCI,EISA,ISA device's limit is MasterAdapter. + // + if (*NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { //K020-1 + AdapterObject->NumberOfMapRegisters = 0; + return NULL; + } + + } +#endif + // + // Attempt to allocate the required number of map registers w/o + // affecting those registers that were allocated when the system + // crashed. Note that once again the map registers to be allocated + // must be above the 1MB range if this is an EISA bus device. + // + + MapRegisterNumber = (ULONG)-1; +#if !defined(_R98_) + Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; +#endif + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + MasterAdapter == MasterAdapterObject ? *NumberOfMapRegisters+1 : *NumberOfMapRegisters, //K028 +#if defined(_R98_) + 0 +#else + Hint +#endif + ); + +#if !defined(_R98_) + // + // Ensure that any allocated map registers are valid for this adapter. + // + + if ((ULONG) MapRegisterNumber < Hint) { + + // + // Make it appear as if there are no map registers. + // + + RtlClearBits( + MasterAdapter->MapRegisters, + MapRegisterNumber, + *NumberOfMapRegisters //K020-1 + ); + + MapRegisterNumber = (ULONG) -1; + } +#endif + 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, +#if defined(_R98_) + 0, // 0M was reserved +#else + Hint, +#endif // K00D + *NumberOfMapRegisters+1 + ); +#if defined(_R98_) + MapRegisterNumber = 0x0; +#else + MapRegisterNumber = Hint; +#endif + } + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // +#if defined(_R98_) + if(MasterAdapter == MasterAdapterObjectForInternal){ + AdapterObject->MapRegisterBase = ((PINTERNAL_TRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + // + // Set the no scatter/gather flag . + // in there R98 Internal Device is Not always Scatter/Gather supported. + // + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + }else +#endif + AdapterObject->MapRegisterBase = + (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); + + return AdapterObject->MapRegisterBase; +} + + + +// K001-3 +// +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. + +--*/ + +{ + UNREFERENCED_PARAMETER( AdapterObject ); + UNREFERENCED_PARAMETER( Length ); + UNREFERENCED_PARAMETER( LogicalAddress ); + UNREFERENCED_PARAMETER( VirtualAddress ); + + return(TRUE); + +} + +// K001-4 +// +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; + CacheEnabled = TRUE; //K027-1 + + if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal|| + (AdapterObject->MasterAdapter==NULL ) // K00B + ){ + // + // Internal Device + // + MmFreeContiguousMemory (VirtualAddress); + }else{ + + // + // PCI,EISA,ISA. + // + + // + // Calculate the number of map registers, the map register number and + // the map register base. + // + + numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); + // + // For PCI,EISA,ISA Logical address started at PCI_LOGICAL_START_ADDRESS + // See. IoMapTransfer!!. + // + mapRegisterNumber = (LogicalAddress.LowPart - PCI_LOGICAL_START_ADDRESS) >> 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) { //K020-1 + ExFreePool(VirtualAddress); + + } else { + MmFreeNonCachedMemory(VirtualAddress, Length); + } + + + } + + return; +} + +// K001-5 +// As PCI,EISA,ISA Device is used TLB of LR4360. +// Scatter/Gather is supported By Hal. +// +// Internal Device Never use TLB of LR4360. +// So Device without Scatter/Gather is use continuguas memory. +// +// Internal Device at Bbus Device is used LR4360 DMA. +// LR4360's DMA have Scatter/Gather .But Not use this version hal. +// So use continuguas memory. +// +// +// +// +// Source Base 612 halfxs/mips/jxhwsup.c,halx86/i386/ixisasup.c +// +// +// +// +// +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 maximumLength; + ULONG numberOfMapRegisters; + ULONG value; //K00D + // + // Make sure this is the correct version. + // + if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) //K020-1,K025 + return(NULL); + + // + // Return number of map registers requested based on the maximum + // transfer length. + // + + *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1; +#if 0 + // + // 612 halfx code not use. Because Number of R98 PCI,EISA device is 8 and + // Limit By MasterAdapterObject->MapRegisterPerChannel / 8 + // + if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) { + *NumberOfMapRegisters = DMA_REQUEST_LIMIT; + } +#endif + + // + // Get AdapterObject + // At 1 st call HalpAllocateAdapter() Allocateted MasterAdapterObject or + // MasterAdapterObjectForInternal. + + switch(DeviceDescription->InterfaceType){ + case Internal: + // + // Return the adapter pointer for internal adapters. + // such as SCSI,SONIC,Floppy LR4360 + // K00D + + if(DeviceDescription->Master){ // Bus Master Device + if(DeviceDescription->ScatterGather){ // Device is Scatter/Gather support!! + numberOfMapRegisters=0; // then no use Mapregister. + }else{ + numberOfMapRegisters=1; // else use 1 Mapregister. + } + +#if defined(NONARB) + if (((HalpInternalAdapters[3] == NULL) && DeviceDescription->ScatterGather) || + ( (HalpInternalAdapters[4] == NULL) && (DeviceDescription->ScatterGather==0)) ) { + +#endif + + adapterObject= + HalpAllocateAdapter( + numberOfMapRegisters, + NULL, + (PVOID)-1 // K00D + ); +#if defined(NONARB) + if(DeviceDescription->ScatterGather ){ + HalpInternalAdapters[3] = adapterObject; //SCSI0,SCSI1 + adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + return(adapterObject); // K005 + + + }else{ + HalpInternalAdapters[4] = adapterObject; //SONIC + + } + }else{ + if(DeviceDescription->ScatterGather){ + return(HalpInternalAdapters[3]); + }else{ + adapterObject=HalpInternalAdapters[4]; + } + + } + +#endif + + // K00D K00E-6 + }else if (HalpInternalAdapters[DeviceDescription->DmaChannel] != NULL ) { + // + // If necessary allocate an adapter; otherwise, + // just return the adapter for the requested channel. + // + // LR4360 DMA channel 1 is floppy. + // + // K00D + adapterObject = HalpInternalAdapters[DeviceDescription->DmaChannel]; + // + // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K + // + *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? + MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters; + + + }else{ + // + // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K + // + + *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? + MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters; + + adapterObject= + HalpAllocateAdapter( + 1, + // KSEG1_BASE K00D + // K010-3 This value use only as flag. + &(DMA_CONTROL ( DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))->CnDC, // K00D + (PVOID)-1 // K00D + ); + + // + // Driver of use LR4360 DMA + // HalpInternalAdapters[] + // + HalpInternalAdapters[DeviceDescription->DmaChannel] = adapterObject; + + adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + } +#if !defined(NONARB) + // + // Bus Master of Internal Device with Scatter/gather then Nothing to Do. + // K00D + if(DeviceDescription->Master && DeviceDescription->ScatterGather){ + // + // No Limit Because MapRegisters were not used. + // + adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + return(adapterObject); // K005 + + } +#endif + // + // new request > primiry request + // + if (*NumberOfMapRegisters > adapterObject->MapRegistersPerChannel) { + adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; + } + // K00D + if(DeviceDescription->Master){ + // + // Internal device Master without Scatter/Gather. + // + // + // Master I/O devices use several sets of map registers double + // their commitment. + // + + MasterAdapterObjectForInternal->CommittedMapRegisters += + (*NumberOfMapRegisters) * 2; + + }else{ + // + // Internal device with LR4360 DMA. etc floppy + // + + MasterAdapterObjectForInternal->CommittedMapRegisters += + (*NumberOfMapRegisters); + } + // + // See MasterAdapterObjectForInternal and + // Grow--!!. && Link To MapRegister. + // + if (MasterAdapterObjectForInternal->CommittedMapRegisters > + MasterAdapterObjectForInternal->NumberOfMapRegisters && + MasterAdapterObjectForInternal->CommittedMapRegisters - + MasterAdapterObjectForInternal->NumberOfMapRegisters > + MAXIMUM_ISA_MAP_REGISTER) + { + // + // increment INCREMENT_MAP_BUFFER_SIZE=64K + // Number of Mapregister is 64K*4 /4K + // + HalpGrowMapBuffers( + MasterAdapterObjectForInternal, + INCREMENT_MAP_BUFFER_SIZE + ); + } + // + // check LR4360 DMA Channel + // K00D + if(!DeviceDescription->Master){ + adapterObject->ChannelNumber =(UCHAR)DeviceDescription->DmaChannel; //K00D + // + // LR4360 DMA have Scatter/Gather But not support this version. + // Set Up DMA default value. + // + // 1.DMA mode :Normal mode + // + // K00D ULONG value; + + value=READ_REGISTER_ULONG( + &(DMA_CONTROL( + (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT)) + )->CnDF + ); + + ((PLR_DMA_CONFIG)&value)->Reserved1=0; + ((PLR_DMA_CONFIG)&value)->Reserved2=0; + + ((PLR_DMA_CONFIG)&value)->TMODE=LR_DMA_MODE_NORMAL; + ((PLR_DMA_CONFIG)&value)->iNEDi=1; //K00D + ((PLR_DMA_CONFIG)&value)->iNEDE=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT)) + )->CnDF, + value + ); + + + // K00F Under Code Move IoMapTransfer() + + } + return(adapterObject); // K005 K00D + + case Isa: + case Eisa: + // + // Create an adapter object For Pci Device + // + + adapterObject = HalpAllocateEisaAdapter( DeviceDescription ); + //DbgPrint("\nEISA: = 0x%x\n",adapterObject); + + break; + + case PCIBus: + // + // Create an adapter object For Pci Device. + // + + adapterObject = HalpAllocateAdapter( 0,NULL,NULL ); + break; + + default: + // Another Bus Not Suport !! + return(NULL); + } +#if defined(DUMMYDMA) // K034 vvv + // Max is 1M-2: 0xffe000 + // + // + if (*NumberOfMapRegisters > 0x100 -2) + *NumberOfMapRegisters = 0x100-2; + +#else + // + // PCI,EISA,ISA Device use LR4360 TLB.(PCI<-->ASOBus) + // Max Limit Of MapRegister Per Channel For PCI,EISA,ISA Device Set beyond MasterRegisterPerChannel + // + if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 8) + *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 8; +#endif // K034 ^^^ + // Check By HalAllocateAdapterChannel for MasterAdapter. + // adapterObject->NeedsMapRegisters = TRUE; + // + return(adapterObject); +} + +#if 0 //K015 +BOOLEAN +HalTranslateBusAddress( + IN INTERFACE_TYPE InterfaceType, + IN ULONG BusNumber, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ) + +/*++ + +Routine Description: + + This function returns the system physical address for a specified I/O bus + address. The return value is suitable for use in a subsequent call to + MmMapIoSpace. + +Arguments: + + InterfaceType - Supplies the type of bus which the address is for. + + BusNumber - Supplies the bus number for the device. + + BusAddress - Supplies the bus relative address. + + AddressSpace - Supplies the address space number for the device: 0 for + memory and 1 for I/O space. Returns the address space on this system. + + TranslatedAddress - Supplies a pointer to return the translated address + +Return Value: + + A return value of TRUE indicates that a system physical address + corresponding to the supplied bus relative address and bus address + number has been returned in TranslatedAddress. + + A return value of FALSE occurs if the translation for the address was + not possible + +--*/ + +{ + // + // R98 HighPart never carry!! + // + TranslatedAddress->HighPart = 0; + + // + // If this is for the internal bus then just return the passed parameter. + // + + if (InterfaceType == Internal) { + + // + // Return the passed parameters. + // + + TranslatedAddress->LowPart = BusAddress.LowPart; + return(TRUE); + } + +#if defined(_R98_) // K008 + + switch(InterfaceType){ + + case PCIBus: + if(*AddressSpace){ // I/O + // N.B. Pci trans addr is per slot ??. + // So How get slot number!!. + // + TranslatedAddress->LowPart = BusAddress.LowPart+PCI_CONTROL_SLOT1_PHYSICAL_BASE; + + }else{ // Memory + TranslatedAddress->LowPart = BusAddress.LowPart+PCI_MEMORY_PHYSICAL_BASE; + + } + break; + case Eisa: + case Isa: + if(*AddressSpace){ // I/O + TranslatedAddress->LowPart = BusAddress.LowPart+EISA_CONTROL_PHYSICAL_BASE; + + }else{ // Memory + TranslatedAddress->LowPart = BusAddress.LowPart+EISA_MEMORY_PHYSICAL_BASE; + + } + break; + + default: // UnKnow K00D + TranslatedAddress->LowPart = 0; + return(FALSE); + } + *AddressSpace = 0; // K009 + return(TRUE); + +#else // _R98_ + if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != Pci) { + + // + // Not on this system return nothing. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = 0; + return(FALSE); + } + + // + // There is only one I/O bus which is an EISA, so the bus number is unused. + // + // Determine the address based on whether the bus address is in I/O space + // or bus memory space. + // + + if (*AddressSpace) { + + // + // The address is in I/O space. + // + + *AddressSpace = 0; + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE; + if (TranslatedAddress->LowPart < BusAddress.LowPart) { + + // + // A carry occurred. + // + + TranslatedAddress->HighPart = 1; + } + return(TRUE); + + } else { + + // + // The address is in memory space. + // + + *AddressSpace = 0; + +#if !defined(_DUO_) + + if (DMA_CONTROL->RevisionLevel.Long < 2) { + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE; + } else { + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; + TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; + + } +#else + + TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; + TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; + +#endif + + if (TranslatedAddress->LowPart < BusAddress.LowPart) { + + // + // A carry occurred. + // + + TranslatedAddress->HighPart = 1; + } + return(TRUE); + + } + +#endif // _R98_ +} +#endif //K015 + + +// K00-6 +// MapRegistersPerChannel,AdapterBaseVa,MapRegisterBase +//--------------------+-----------------------+-------------+---------------+ +// Internal with S/G 0 0 -1 +// Internal no S/G 1 0 -1 +// Internal DMA 1 XX -1 +// Internal MasterAdp 1 -1 -1 +// EISA 0 XX 0 +// PCI 0 0 0 +// MasterAdp 0 -1 -1 +// + +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 - If (PVOID) -1 then Not MasterAdapter allocate. + +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 i; //K021-2 + // + // Internal without Scatter/Gather or LR4360 DMA + // then allocate MasterAdapterObjectForInternal + // + + if (MasterAdapterObjectForInternal == NULL && AdapterBaseVa !=(PVOID)-1 + && MapRegistersPerChannel + ){ + + MasterAdapterObjectForInternal + = HalpAllocateAdapter( + 1, + (PVOID) -1, + (PVOID) -1 + ); + + // + // If we could not allocate the master adapter For Internal then give up. + // + + if (MasterAdapterObjectForInternal == NULL) + return(NULL); + + }else if (MasterAdapterObject == NULL && MapRegisterBase !=(PVOID)-1) { + + MasterAdapterObject = HalpAllocateAdapter( + 0, + (PVOID)-1, + (PVOID)-1 + ); + // + // 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 == (PVOID)-1 && MapRegistersPerChannel) { + // + // MasterAdapterForInternal + // + BitmapSize = (((sizeof( RTL_BITMAP ) + + (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3); + Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; + + }else if(AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel==0) { + // + // MasterAdapter + // + BitmapSize = (((sizeof( RTL_BITMAP ) + + ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3)) + + 3) & ~3); + Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; + + } else + // + // Not Master Adapter.(Have not Bit Map) + // + Size = sizeof( ADAPTER_OBJECT ); + + + // + // Now create the adapter object. + // + + Status = ObCreateObject( + KernelMode, + *((POBJECT_TYPE *)IoAdapterObjectType), + &ObjectAttributes, + KernelMode, + (PVOID) NULL, + Size, + 0, + 0, + (PVOID *)&AdapterObject + ); + // This code is 612 base. + // 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 )) { + + RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT)); //K035 + + 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->AdapterBaseVa = AdapterBaseVa; + AdapterObject->PagePort = NULL; + // + // Set ->MasterAdapter + // + + if(AdapterBaseVa == (PVOID)-1) + // I am + // Masteradpter or MasterAdapterForInternal. + // + AdapterObject->MasterAdapter = NULL; + else if(MapRegistersPerChannel) + // I am + // Bbus (LR4360 DMA)or ASOBus with No Scatter/Gather. + // + AdapterObject->MasterAdapter = MasterAdapterObjectForInternal; + else if(MapRegisterBase ==NULL){ + // + // I am PCI or EISA or ISA. + // + AdapterObject->MasterAdapter = MasterAdapterObject; + + // Limit was Set End of HalGetAdapter(). + //AdapterObject->MapRegistersPerChannel = + // DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY); + // + }else + // I am + // Internal Device With Scatter/Gather. + // + AdapterObject->MasterAdapter = 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 == (PVOID)-1){ + // + // MasterAdapterObject and MasterAdapterObjectForInternal. + // + + KeInitializeSpinLock( &AdapterObject->SpinLock ); + + InitializeListHead( &AdapterObject->AdapterQueue ); + + AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1); + AdapterObject->NumberOfMapRegisters = 0; //K012 + if(MapRegistersPerChannel) { + // + // MasterAdapterObjectForInternal. + // (For Bbus LR4360 DMA and Internal Device without Scatter/Gather + // may be continuguas memory) + // + AdapterObject->MapRegistersPerChannel =1; + + RtlInitializeBitMap( AdapterObject->MapRegisters, + (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + + sizeof( RTL_BITMAP )), + ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + ); + // + // Set all the bits in the memory to indicate that memory + // has not been allocated for the map buffers + // + + RtlSetAllBits( AdapterObject->MapRegisters ); + + // K012 AdapterObject->NumberOfMapRegisters = 0; + AdapterObject->CommittedMapRegisters = 0; + + // + // ALlocate the memory map registers. + // + + AdapterObject->MapRegisterBase = + ExAllocatePool( + NonPagedPool, + (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) * + sizeof(INTERNAL_TRANSLATION_ENTRY) + ); + if (AdapterObject->MapRegisterBase == NULL) { + + ObDereferenceObject( AdapterObject ); + AdapterObject = NULL; + return(NULL); + + } + // + // Zero the map registers. + // + + RtlZeroMemory( + AdapterObject->MapRegisterBase, + (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) * + sizeof(INTERNAL_TRANSLATION_ENTRY) + ); + + if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE)) + { + + // + // If no map registers could be allocated then free the + // object. + // + + ObDereferenceObject( AdapterObject ); + AdapterObject = NULL; + return(NULL); + + } + + + }else{ + // Not use R98 + //ULONG MapRegisterSize; + // + PULONG Map; + // + // Limit is This code. + // The Number of MapRegisters For PCI,EISA,ISA use LR4360 TLB. + // + AdapterObject->MapRegistersPerChannel = + DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY); + + RtlInitializeBitMap( AdapterObject->MapRegisters, + (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + + sizeof( RTL_BITMAP )), + DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY) + ); + RtlClearAllBits( AdapterObject->MapRegisters ); + + // + // The memory for the map registers was allocated by + // HalpAllocateMapRegisters during phase 0 initialization. + // + // On PCI,EISA,ISA Set Up LR4360TLB Mapping and + // PECB EISA->PCI Mapping. + // + // + + // Not use R98 + //MapRegisterSize = DMA_TRANSLATION_LIMIT; + //MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize); + + // + // Convert the physical address to a non-cached virtual address. + // + // HalpMapRegisterPhysicalBase is Set up HalpAllocateMapRegisters(). + // area of KSEG1_BASE is 512M. So get less than Physical addr 512M + // by HalpAllocateMapRegisters(). + + AdapterObject->MapRegisterBase = (PVOID) + (HalpMapRegisterPhysicalBase | KSEG0_BASE); //K026-1 + + // dummy page data is "CEN CEN CEN". for What happend!!. K028 + RtlFillMemoryUlong( (PULONG)((HalpNec0DummyPhysicalBase) |KSEG0_BASE), + PAGE_SIZE,0x4E454320); // A002 + + RtlFillMemoryUlong( (PULONG)((HalpNec1DummyPhysicalBase) |KSEG0_BASE), + PAGE_SIZE,0x4E454e20); // A002 + // LR4360 Page table Set DumyPhysicalBase. + // LR4360 Page Table Size is DMA_TRANSLATION_LIMIT. K028 + // Set to InValid. + RtlFillMemoryUlong( AdapterObject->MapRegisterBase, +#if defined(PTEINVALID) // S004 vvv + DMA_TRANSLATION_LIMIT,(HalpNec0DummyPhysicalBase | 0x1)); +#else + DMA_TRANSLATION_LIMIT,HalpNec0DummyPhysicalBase ); +#endif // S004 ^^^ + +#if defined(DUMMYDMA) // K034 vvv + // 256 is Number of page teble entry per 1 TLB + // 1M Align Logical Last Page is DUMYY page for TLB FLush!!. + // + Map =AdapterObject->MapRegisterBase; + for(i=0;i<(DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) / 256;i++){ + + RtlSetBits ( + AdapterObject->MapRegisters, + 0xff+0x100*i,//1M*i-1 page. Start + 0x1 //1 page DUMMY + ); + Map[i* 0x100+0xff] =HalpNec1DummyPhysicalBase; + + } +#else + // Reserved For PCEB PreFetch cycle Cause LR4360 TLB miss. + RtlSetBits ( + AdapterObject->MapRegisters, + 0xfff, //0xFFFFFF + 0x1 + ); + +#endif // K034 ^^^ + // 1M Low del + RtlSetBits ( + AdapterObject->MapRegisters, + 0x0, //0x0 + 0xff + ); + + // eisa vram del + RtlSetBits ( + AdapterObject->MapRegisters, + 0xE00, //0xe00000 + 0xff + ); + + // 16M Low del + RtlSetBits ( + AdapterObject->MapRegisters, + 0xf00, //0xf00000 + 0xff + + ); + + // + // LR4360 TLB Set Up + // LR4360:PTBAR0 + // ( Use 0M-4M-1 Logical address) K013 + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PTBAR0, + (ULONG)HalpMapRegisterPhysicalBase + );//K013-2,K016-2,K019-1 + + // + // LR4360:PTBAR1 ( Use 4M-8M-1 Logical address) + // + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PTBAR1, + // K013 + (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE //K019-1 + ); + + // + // LR4360:PTBAR2 ( Use 8M-12M-1 Logical address) + // K013 + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PTBAR2, + (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*2 //K019-1 + ); + // + // LR4360:PTBAR3 ( Use 12M-12M-1 Logical address) + // K013 + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PTBAR3, + (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*3 //K019-1 + ); + + // + // LR4360:PTSZR (Set Page Table Size is 4K) + // K00D + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PTSZR, + LR4360PTSZ4K << LR4360PTSZSHIFT + ); + + // + // LR4360:PABAR Logical addr start 0x00000000(0M) + // Logical addr end 0x00ffffff(16M-1) + // + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->PABAR,0x0); + + + //K021-2 Flush TLB all ,K0026-3 + for (i = 0;i < 16; i++) { //K024 + + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->TFLR,i); + } + + +#if 0 //snes 302 + + // K007, K00C, K013 + // EISA-->PCI map 0M-16M + // PCEB MEMREGN[4:1] + // + WRITE_REGISTER_ULONG( + &((volatile PULONG ) + (KSEG1_BASE|EISA_CONFIG_REGISTERS_MEMREGN))[0], + 0xff0000|0x00 + ); +#endif + WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); + +#if defined(DUMMYDMA) // K034 vvv + { + UCHAR adapterMode; + DMA_EXTENDED_MODE extendedMode; + PVOID adapterBaseVa; + PDMA1_CONTROL dmaControl; + // + // SetUp Ext Mode reg. + adapterBaseVa = + &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort; + + *((PUCHAR) &extendedMode) = 0; + extendedMode.ChannelNumber = 2; //2 is floppy + extendedMode.TimingMode = COMPATIBLITY_TIMING; //ISA compati + extendedMode.TransferSize = BY_BYTE_8_BITS; //8bit DMA + WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode)); + + // + // SetUp Mode reg + dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; + adapterMode=0; + ((PDMA_EISA_MODE) &adapterMode)->Channel = 2; + ((PDMA_EISA_MODE) &adapterMode)->RequestMode = BLOCK_REQUEST_MODE; + ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 0; + // + // Determine the mode based on the transfer direction. + // Read From The Device. it is little first. + +// ((PDMA_EISA_MODE) &adapterMode)->TransferType = READ_TRANSFER; + // it is safety. + ((PDMA_EISA_MODE) &adapterMode)->TransferType = WRITE_TRANSFER; + + // + // This request is for DMA controller 1 + // + WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); + KeInitializeSpinLock (&HalpIoMapSpinLock); + + } + +#endif // K034 ^^^ + + } // MasterAdapterObject (For PCI,EISA,ISA) + + + } // MasterAdapterObject and MasterAdapterObjectForInternal. + + } 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; + // K00E-8 + // return (PADAPTER_OBJECT) NULL; +} + +// K001-7 +// +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; + PWAIT_CONTEXT_BLOCK Wcb; + PLIST_ENTRY Packet; + IO_ALLOCATION_ACTION Action; + KIRQL Irql; +#if defined(DUMMYDMA) + ULONG i; + PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase; +#endif + // + // Begin by getting the address of the master adapter. + // + + if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) { + + MasterAdapter = AdapterObject->MasterAdapter; + + } else { + + // + // There are no map registers to return. + // + // + // Internal Master Device with Scatter/Gather. + // Mapregister Not Used. + // + return; + } + + if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ + // + // Internal Device without Scatter/Gather. + // Strip no scatter/gather flag. + // + MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + MapRegisterNumber = (PINTERNAL_TRANSLATION_ENTRY) MapRegisterBase - + (PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase; + }else{ + 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. + // + +#if defined(DUMMYDMA) + + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + MasterAdapter == MasterAdapterObject ? + NumberOfMapRegisters+1 :NumberOfMapRegisters //K028 + ); + // + // LR4360 PTE InValid. + if(MasterAdapter==MasterAdapterObject){ + for (i = 0; i < NumberOfMapRegisters+1; i++) { +#if defined(PTEINVALID) // S004 vvv + (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1); +#else + (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; +#endif // S004 ^^^ + DmaMapRegister++; + } + } + +#else + RtlClearBits( MasterAdapter->MapRegisters, + MapRegisterNumber, + MasterAdapter == MasterAdapterObject ? + NumberOfMapRegisters+1 :NumberOfMapRegisters //K028 + ); +#endif + // + // 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. + // + + MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, + AdapterObject->MasterAdapter == MasterAdapterObject ? + AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters, //K028 + MasterAdapter->NumberOfMapRegisters + ); + + 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 ); + + if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ + + AdapterObject->MapRegisterBase = + (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + // + // Set the no scatter/gather flag. + // if there device Not Sactter/Gather + // + AdapterObject->MapRegisterBase = + (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + }else{ + // DbgPrint("\nIoFreeMapRegisters = 0x%x\n",MapRegisterNumber+1); + AdapterObject->MapRegisterBase = + (PVOID) ((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber );//add1 non + + } + + // + // 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->MasterAdapter == MasterAdapterObject ? + AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters //K028 + ); +#if defined(DUMMYDMA) + + if(MasterAdapter == MasterAdapterObject){ + DmaMapRegister= (PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber; + for (i = 0; i < AdapterObject->NumberOfMapRegisters+1; i++) { +#if defined(PTEINVALID) // S004 vvv + (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1); +#else + (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; +#endif // S004 ^^^ + DmaMapRegister++; + } + } + +#endif + + + AdapterObject->NumberOfMapRegisters = 0; + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + } + + IoFreeAdapterChannel( AdapterObject ); + } + + KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); + + } + + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); +} + + +// K001-8 +// +VOID +IoFreeAdapterChannel( + IN PADAPTER_OBJECT AdapterObject + ) + +/*++ + +Routine Description: + + This routine is invoked to deallocate the specified adapter object. + Any map registers that were allocated are also automatically deallocated. + No checks are made to ensure that the adapter is really allocated to + a device object. However, if it is not, then kernel will bugcheck. + + If another device is waiting in the queue to allocate the adapter object + it will be pulled from the queue and its execution routine will be + invoked. + +Arguments: + + AdapterObject - Pointer to the adapter object to be deallocated. + +Return Value: + + None. + +--*/ + +{ + PKDEVICE_QUEUE_ENTRY Packet; + PADAPTER_OBJECT MasterAdapter; + BOOLEAN Busy = FALSE; + IO_ALLOCATION_ACTION Action; + PWAIT_CONTEXT_BLOCK Wcb; + KIRQL Irql; + LONG MapRegisterNumber; + ULONG Hint; + + // + // 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. + // + // + // CASE: + // Internal Master Device without Scatter/Gather. + // Internal Device with LR4360 DMA(Always without Scatter/Gather) + // PCI,EISA,ISA Device with LR4360 TLB. + // + if (Wcb->NumberOfMapRegisters != 0 && + AdapterObject->MasterAdapter!=NULL) + { + // K00D + // MasterAdapterObject?? + // + if ( MasterAdapter== MasterAdapterObject) + // + // PCI,EISA,ISA Device with LR4360 TLB. + // + 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, + MasterAdapter == MasterAdapterObject ? + Wcb->NumberOfMapRegisters+1:Wcb->NumberOfMapRegisters, //K028 + 0 + ); + } + + 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 { + if (MasterAdapter == MasterAdapterObjectForInternal){ + // + // Internal Device without Sactter/Gather. + // + AdapterObject->MapRegisterBase = + (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + }else{ + + // + // PCI,EISA,ISA with LR4360 TLB + // + AdapterObject->MapRegisterBase = + (PVOID) ((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + } + + } + KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + }else{ + // + // Only Internal Master Device with Scatter/Gather. + // Always AdapterObject->MasterAdapter ==NULL. + // + AdapterObject->MapRegisterBase = NULL; + AdapterObject->NumberOfMapRegisters = 0; + } + // + // 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; + } + } +} + +// K001-9 +// +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 = PAGE_SIZE*2+DMA_TRANSLATION_LIMIT; //K028 + MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize); + + // + // The address must be in KSEG 0. + // + + //MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ; + // less than 512M. + MaxPageAddress = (0x20000000 >> PAGE_SHIFT) - 1 ; //K016 + // + // 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); + + } + + //K028 + // + // Save the map register base. + // + + HalpNec0DummyPhysicalBase =PhysicalAddress; + HalpNec1DummyPhysicalBase =HalpNec0DummyPhysicalBase+PAGE_SIZE; + HalpMapRegisterPhysicalBase=HalpNec0DummyPhysicalBase+PAGE_SIZE*2; + +} + +#if defined(DUMMYDMA) // K034 vvv +VOID +HalpDummyTlbFlush( + 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. DUMMY DUMMY DUMMY DUMMY + + Offset - Supplies the logical address to use for the transfer. + + Length - Supplies the length of the transfer in bytes. DUMMY DUMMY DUMMY DUMMY + + WriteToDevice - Indicates the direction of the transfer. DUMMY DUMMY DUMMY DUMMY + +Return Value: + + None. + +--*/ + +{ + volatile UCHAR Status; +// volatile UCHAR Mask; + UCHAR adapterMode; + PUCHAR PagePort; + PUCHAR BytePtr; + volatile PUCHAR BytePtr2; + volatile ULONG Count; + PDMA1_CONTROL dmaControl; +// PDMA2_CONTROL dmaControl2; + BytePtr2 = (PUCHAR) &Count; + BytePtr = (PUCHAR) &Offset; + PagePort = &((PDMA_PAGE) 0)->Channel2; + dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; +// dmaControl2 = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort; + +// Mask=READ_REGISTER_UCHAR( &dmaControl2->AllMask ); +// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, (UCHAR) (0xf) ); + + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[0] ); + WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[1] ); + + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + + (ULONG)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)PagePort, + 0 + ); + + // + // Notify DMA chip of the length to transfer. + // transfer Count is 1 Byte . So Set 1-1=0 + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0x1); + WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0); + WRITE_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]), + (UCHAR) 0 + ); + + + //Flush LR4360 Read Cache. + WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031 + // + // SoftWare DMA Request, channel 2 + // + WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x4 | 0x2) ); + // + // check dma transfer was finished!!. + // + do{ + Count=0; + WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); + BytePtr2[0]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount); + BytePtr2[1]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount); + BytePtr2[2]= + READ_REGISTER_UCHAR( + ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]) + ); + if((Count & 0xffffff)== 0xffffff) + break; + }while(1); + +// WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x0 | 0x2) ); +// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, 0x0 ); + +} + +#endif // K034 ^^^ + + +// K001-A +// +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. + +--*/ + +{ +#if defined(DUMMYDMA) // K034 vvv + KIRQL Irql; +#endif // K034 ^^^ + ULONG value; + // + // May be check Bus Master: AdapterObject==NULL!!. + // Internal Device: + // ASOBus with Scatter/Gather:MapRegisterBase ==NULL + // without Scatter/Gather always allocate MapRegister + // So check As if use MapRegister. + // + // ASOBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1 + // BBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1 + // + // + PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase; + PULONG PageFrameNumber; + ULONG NumberOfPages; + ULONG Offset; + ULONG i; + ULONG logicalAddress; + ULONG transferLength; + PINTERNAL_TRANSLATION_ENTRY translationEntry; + ULONG index; //K00D + + //K00E-4 + transferLength=PAGE_SIZE - BYTE_OFFSET((PUCHAR) CurrentVa ); + Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa ); + PageFrameNumber = (PULONG) (Mdl + 1); + PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT); + logicalAddress = (*PageFrameNumber << PAGE_SHIFT) + Offset; + //K00D + if((MapRegisterBase== NULL) || ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) ){ + + // BusMaster with Scatter/gather || witout Scatter/Gather + // + + while(transferLength < *Length ){ + + if (*PageFrameNumber + 1 != *(PageFrameNumber + 1)) { + break; + } + + transferLength += PAGE_SIZE; + PageFrameNumber++; + } + + // + // Limit the transferLength to the requested Length. + // + + transferLength = transferLength > *Length ? *Length : transferLength; + + // + // ASOBus Master without Scatter/Gather && contigous < request + // or + // Bbus Device Floppy use LR4360 DMA(it's not use Scatter/Gater) && contigous < request + // + // + if ( (ULONG)MapRegisterBase & NO_SCATTER_GATHER + && transferLength < *Length ){ + + translationEntry = (PINTERNAL_TRANSLATION_ENTRY) + ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + logicalAddress = translationEntry->PhysicalAddress + Offset; + // + // It's means I have not Scatter/Gather && contigous < request then I use buffer + // At IoFlushAdapterBuffers() Do ?Hal Buffer-->user mem + // + translationEntry->Index = COPY_BUFFER; + index = 0; + // Do Copy So avaleable transfer is request size + transferLength = *Length; + + // When Memory --> Device, Copy From memory to conigous buffer + // + if ( WriteToDevice) + HalpCopyBufferMap( + Mdl, + translationEntry + index, + CurrentVa, + *Length, + WriteToDevice + ); + } + + *Length=transferLength; + // + // ASOBus Master without Scatter/Gather. || + // ASOBus Master with Scatter/Gather + // + // (Thus ASObus Master Don't use LR4360 DMA.) + // + if ( AdapterObject == NULL || MapRegisterBase ==NULL) + return(RtlConvertUlongToLargeInteger(logicalAddress)); + + // + // Bbus DMA used Device etc..Floppy + // Then Set Up LR4360 DMA Controlor + // + + //K00F From HalGetAdapter() + // Flush LR4360 FiFo. + // Note: LR4360 DMA Set up Do Drain. So At this time + // FiFo have Never Data..... + + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + ((PLR_DMA_CONTROL)&value)->Reserved1=0; + ((PLR_DMA_CONTROL)&value)->FiFoF=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + + // + // Sleep till CnDC->iNED =1 ?? + // + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + + //K00D + if(((PLR_DMA_CONTROL)&value)->iNEDS){ + // + // what sec to wait !! + // K00D N.B microsecond + KeStallExecutionProcessor(100); + + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + // + // the die ..... + // K00D + if(((PLR_DMA_CONTROL)&value)->iNEDS) + KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS ); + } + // + // transfer count set + //K010-2 + // N.B *Length must be below 0x03ffffff.(64M) + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnBC, + *Length + ); + // + // transfer addr set + // + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnMA, + // K00D RtlConvertUlongToLargeInteger(logicalAddress) + logicalAddress + ); + // + // direction set + // + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + //K00D + ((PLR_DMA_CONTROL)&value)->Reserved1=0; + ((PLR_DMA_CONTROL)&value)->MEMWE=1; + + if ( WriteToDevice) { + ((PLR_DMA_CONTROL)&value)->MEMWT=0; + // + // For End of DMA function .see HalpDmaInterrupt() + // + // + // Memory --> Device + // + // + // AdapterObject->TransferType = WRITE_TRANSFER; + // + + }else{ + ((PLR_DMA_CONTROL)&value)->MEMWT=1; + // + // Device --> Memory + // + // AdapterObject->TransferType = READ_TRANSFER; + // + } + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + // + // Enable Input BREQ line + // + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + + ((PLR_DMA_CONTROL)&value)->Reserved1=0; //K00D + + ((PLR_DMA_CONTROL)&value)->REQWE=1; //K00D + ((PLR_DMA_CONTROL)&value)->REQiE=1; //K00D + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + // + // End of LR4360 DMA Set Up. + // + return(RtlConvertUlongToLargeInteger(logicalAddress)); + }else{ +#if defined(DUMMYDMA) // K034 vvv + KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql); +#endif + + // + // Determine the maximum number of pages required to satisfy this request. + // + NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT; + + // + // Set up phys addr in LR4360 Page table entry. + // + for (i = 0; i < NumberOfPages; i++) { + (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT; + } + + // + // PCI,EISA,ISA is used TLB of LR4360. + // So There is Inside Logical address Pci. + // K00D offset -->Offset + Offset += ( + (PTRANSLATION_ENTRY) MapRegisterBase - + (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase + ) << PAGE_SHIFT; + + // Not use LR4360 PTBA0 Register ( 0-4M) + // + // use only 4M-8M. !!!! + // + Offset += PCI_LOGICAL_START_ADDRESS; + +#if defined(DUMMYDMA) // K034 + // If PTE is InValid. Set to DummyPage for PCEB Prefetch. + // else It was seted by another IoMapTransfer. +#if defined(PTEINVALID) // S004 vvv + if((DmaMapRegister)->PageFrame & 0x1) + (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; +#endif // S004 ^^^ + + + HalpDummyTlbFlush((PADAPTER_OBJECT)NULL,(Offset & 0x00f00000) | 0x000ff800,(ULONG)NULL,(BOOLEAN)NULL); // A002 + +#else + // + // Flush Translation Look a Side Buffer. + // ( 1 Entry is 1M ) + for (i = Offset >>20 ; i <= ((Offset+NumberOfPages*PAGE_SIZE)>>20); i++) { + + WRITE_REGISTER_ULONG( + &LR_PCI_DEV_REG_CONTROL->TFLR,i); + } + +#endif // K034 ^^^ + if ( AdapterObject != NULL) //K00D + // + // Set Up ESC DMA of EISA,ISA. + // + HalpEisaMapTransfer( + AdapterObject, + Offset, + *Length, + WriteToDevice + ); + // + // BUS Master + // else PCI(always Master) or EISA,ISA Busmaster. + // + } +#if defined(DUMMYDMA) // K034 vvv + KeReleaseSpinLock( &HalpIoMapSpinLock, Irql ); +#endif + return(RtlConvertUlongToLargeInteger(Offset)); +} + +// +// K001-B +// +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. + +--*/ + +{ + // case: Not use Mapregister. + // 1. Internal Master with Scatter/Gather. Never use Mapregiter. + // 2. Internal Master without Scatter/Gather But Not use Mapregister. + // When contigus buffer > request + // 3. Internal Slave with LR4360 DMA (Floppy)But Not use Mapregister. + // When contigus buffer > request + // + // Internal or external device and use Mapregister. + // Case: + // 4. Internal Master without Scatter/Gather use Mapregister. + // When contigus buffer PagePort) { + + WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031 + + + // + // case 7. + // + // + // 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); + } + + // + // At case 2,3,4,5 + // ~ ~ + + + if(AdapterObject != NULL){ + // Master Device is allways NULL + // + // case 3,5 use LR4360 DMA + // + // this line it's may be HalpDmaInterrupt(). but it is not good that + // two End of DMA function (this func,and HalpDmaInterrupt()). + // Because Work at Interrupt from LR4360DMA is Not first (100%) + // + + // + // Read CnDC register. + // + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + // K00E-2 + // Do Write then Reserved Bit must be 0. + // + ((PLR_DMA_CONTROL)&value)->Reserved1=0; + ((PLR_DMA_CONTROL)&value)->Reserved2=0; + // + // At Memory-->Device Do drain So Not FiFo flush !!. + // + // + // Device --> Memory + // K00D + if(!WriteToDevice){ + if( ((PLR_DMA_CONTROL)&value)->FiFoV){ + // + // FiFo have valid Data So Flush!! + // K00D + ((PLR_DMA_CONTROL)&value)->FiFoD=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + + } + } + // + // iNEDS is clear by set 1 write + // K00D + ((PLR_DMA_CONTROL)&value)->iNEDS=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + + } + + // + // Determine if the data needs to be copied to the orginal buffer. + // This only occurs if the data tranfer is from the device, the + // MapReisterBase is not NULL and the transfer spans a page. + + // + // Device --> Memory. + // + if (!WriteToDevice) { + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PINTERNAL_TRANSLATION_ENTRY) + ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // If this is not a master device, then just transfer the buffer. + // + + if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) { + // + // case: 2,3,4,5 + // + if (translationEntry->Index == COPY_BUFFER) { + // + // case: 4,5 + // + if(AdapterObject != NULL) + // + // case: 5 used DMA + // + // Copy only the bytes that have actually been transfered. + // + Length -= HalReadDmaCounter(AdapterObject); + + // + // case: 4,5 + // + // + // The adapter does not support scatter/gather copy the buffer. + // + HalpCopyBufferMap( + Mdl, + translationEntry, + CurrentVa, + Length, + WriteToDevice + ); + } + //else + // + // case: 2,3 + // Not Used Copy Buffer then Nothing to Do. through !!. + // + // + // Strip no scatter/gather flag. + // K00D + } + + } + translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + // + // Clear index in map register. + // + translationEntry->Index = 0; + return( TRUE ); +} + + + +// K001-C +// + +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); +} + +// K001-D +// +// +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. + +--*/ + +{ +#if defined(DUMMYDMA) + KIRQL Irql; +#endif + ULONG i; + ULONG saveEnable; + ULONG count; + ULONG high; + + if (AdapterObject->PagePort) { + // + // PCI,EISA,ISA + // + // + // + // Determine the controller number based on the Adapter number. + // +#if defined(DUMMYDMA) + KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql); +#endif + if (AdapterObject->AdapterNumber == 1) { + + // + // This request is for DMA controller 1 + // + + PDMA1_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } else { + + // + // This request is for DMA controller 2 + // + + PDMA2_CONTROL dmaControl; + + dmaControl = AdapterObject->AdapterBaseVa; + + // + // Initialize count to a value which will not match. + // + + count = 0xFFFF00; + + // + // Loop until the same high byte is read twice. + // + + do { + + high = count; + + WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); + + // + // Read the current DMA count. + // + + count = READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ); + + count |= READ_PORT_UCHAR( + &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] + .DmaBaseCount + ) << 8; + + } while ((count & 0xFFFF00) != (high & 0xFFFF00)); + + } + + // + // The DMA counter has a bias of one and can only be 16 bit long. + // + + count = (count + 1) & 0xFFFF; +#if defined(DUMMYDMA) + KeReleaseSpinLock( &HalpIoMapSpinLock, Irql ); +#endif + } else { + // + // Internal Device With LR4360 DMA. + // + // + // read CnBC register. + // + count=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnBC + ); + + } + + return(count); +} + + +// +// K001-E +// always return 1: See IoFlushAdapterBuffers() +// +BOOLEAN +HalpDmaInterrupt( + VOID + ) +/*++ + +Routine Description: + + This routine is called when a DMA channel interrupt occurs. + LR4360 DMA +Arguments: + +Return Value: + + Returns TRUE. + +--*/ +{ +#if 0 //K011-2 + return(TRUE); +#else + PADAPTER_OBJECT AdapterObject; + ULONG DataWord; + ULONG Channel; + ULONG value; + // + // Read the Inerrupt Service Factor Register. + // + + DataWord = READ_REGISTER_ULONG(&(LR_CONTROL2)->iRSF); + + for (Channel = 0; Channel < 5; Channel++) { + + // + // Determine which channel is interrupting. + // + + if (!(DataWord & ( 1 << (Channel+LR_iRSF_REG_iNSF_SHIFT)))) { + continue; + } + + // + // DMA Channel LR4360 is 1 origin. + // + if((AdapterObject=HalpInternalAdapters[Channel+1])==NULL){ +#if 0 + DmaChannelMsg[18] = (CHAR) Channel+ '1'; + HalDisplayString(DmaChannelMsg); +#endif + // + // + // + KeBugCheck(NMI_HARDWARE_FAILURE); + } + // + // read CnDC register. + // + value=READ_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC + ); + // + // At Memory-->Device drain So Don't FiFo flush. + // + // + // Device --> Memory + // + if( ((PLR_DMA_CONTROL)&value)->MEMWT==0){ + if( ((PLR_DMA_CONTROL)&value)->FiFoV){ + + ((PLR_DMA_CONTROL)&value)->Reserved1=0; + ((PLR_DMA_CONTROL)&value)->Reserved2=0; + // + // FiFo Data is valid So Flush. + // + ((PLR_DMA_CONTROL)&value)->FiFoD=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + + } + } + // + // iNEDS is clear by 1 write + // K00D + ((PLR_DMA_CONTROL)&value)->iNEDS=1; + WRITE_REGISTER_ULONG( + &(DMA_CONTROL ( + (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) + )->CnDC, + value + ); + return(TRUE); + } +#endif +} + +// K001-F +// +// +BOOLEAN +HalpGrowMapBuffers( + PADAPTER_OBJECT AdapterObject, + ULONG Amount + ) +/*++ + +Routine Description: + + This function attempts to allocate additional map buffers for use by I/O + devices. The map register table is updated to indicate the additional + buffers. + +Arguments: + + AdapterObject - Supplies the adapter object for which the buffers are to be + allocated. + + Amount - Indicates the size of the map buffers which should be allocated. + +Return Value: + + TRUE is returned if the memory could be allocated. + + FALSE is returned if the memory could not be allocated. + +--*/ +{ + ULONG MapBufferPhysicalAddress; + PVOID MapBufferVirtualAddress; + PINTERNAL_TRANSLATION_ENTRY TranslationEntry ; + LONG NumberOfPages; + LONG i; + + KIRQL Irql; + PHYSICAL_ADDRESS physicalAddress; + PVOID CodeLockHandle; //K035 + + NumberOfPages = BYTES_TO_PAGES(Amount); + + + // + // Make sure there is room for the addition pages. The maximum number of + // slots needed is equal to NumberOfPages + Amount / 64K + 1. + // + + i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages + + (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 + + AdapterObject->NumberOfMapRegisters); + + if (i < 0) { + + // + // Reduce the allocatation amount to so it will fit. + // + + NumberOfPages += i; + } + + if (NumberOfPages <= 0) { + // + // No more memory can be allocated. + // + return(FALSE); + + } + + + if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) { + + NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize); + + // + // Since this is the initial allocation, use the buffer allocated by + // HalInitSystem rather than allocationg a new one. + // + + MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart; + + // + // Map the buffer for access. + // + + MapBufferVirtualAddress = MmMapIoSpace( + HalpMapBufferPhysicalAddress, + HalpMapBufferSize, + TRUE // Cache enable. + ); + + if (MapBufferVirtualAddress == NULL) { + + // + // The buffer could not be mapped. + // + + HalpMapBufferSize = 0; + return(FALSE); + } + + } else { + + // + // Allocate the map buffers. + // + physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1; + physicalAddress.HighPart = 0; + MapBufferVirtualAddress = MmAllocateContiguousMemory( + NumberOfPages * PAGE_SIZE, + physicalAddress + ); + + if (MapBufferVirtualAddress == NULL) { + + return(FALSE); + } + + // + // Get the physical address of the map base. + // + + MapBufferPhysicalAddress = MmGetPhysicalAddress( + MapBufferVirtualAddress + ).LowPart; + + } + + // + // Initailize the map registers where memory has been allocated. + // + CodeLockHandle = MmLockPagableCodeSection (&HalpGrowMapBuffers); + KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql ); //K025 + + TranslationEntry = ((PINTERNAL_TRANSLATION_ENTRY) AdapterObject->MapRegisterBase) + + AdapterObject->NumberOfMapRegisters; + + for (i = 0; (LONG)i < NumberOfPages; i++) { //K00D K035 + +#if 1 // Enable K00E-7 + // + // Use at R98: LR4360 DMA Not boundry 64K. But per Grow size is 64K incremnet!!. + // + // + // Make sure the perivous entry is physically contiguous with the next + // entry and that a 64K physical bountry is not crossed unless this + // is an Eisa system. + // + + if (TranslationEntry != AdapterObject->MapRegisterBase && + (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) != + MapBufferPhysicalAddress )) { + + // + // An entry needs to be skipped in the table. This entry will + // remain marked as allocated so that no allocation of map + // registers will cross this bountry. + // + + TranslationEntry++; + AdapterObject->NumberOfMapRegisters++; + } +#endif + // + // Clear the bits where the memory has been allocated. + // + + RtlClearBits( + AdapterObject->MapRegisters, + TranslationEntry - (PINTERNAL_TRANSLATION_ENTRY) + AdapterObject->MapRegisterBase, + 1 + ); + + TranslationEntry->VirtualAddress = MapBufferVirtualAddress; + TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress; + TranslationEntry++; + (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE; + MapBufferPhysicalAddress += PAGE_SIZE; + + } + + // + // Remember the number of pages that where allocated. + // + + AdapterObject->NumberOfMapRegisters += NumberOfPages; + + KeReleaseSpinLock( &AdapterObject->SpinLock, Irql ); + MmUnlockPagableImageSection (CodeLockHandle); //K035 + return(TRUE); +} + +// K001-G +// +// +VOID +HalpCopyBufferMap( + IN PMDL Mdl, + IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ) + +/*++ + +Routine Description: + + This routine copies the speicific data between the user's buffer and the + map register buffer. First a the user buffer is mapped if necessary, then + the data is copied. Finally the user buffer will be unmapped if + neccessary. + +Arguments: + + Mdl - Pointer to the MDL that describes the pages of memory that are + being read or written. + + TranslationEntry - 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 - The length of the transfer. This determines the number of map + registers that need to be written to map the transfer. + + WriteToDevice - Boolean value that indicates whether this is a write + to the device from memory (TRUE), or vice versa. + +Return Value: + + None. + +--*/ +{ + PCCHAR bufferAddress; + PCCHAR mapAddress; + + // + // Get the system address of the MDL. + // + + bufferAddress = MmGetSystemAddressForMdl(Mdl); + + // + // Calculate the actual start of the buffer based on the system VA and + // the current VA. + // + + bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl); + + mapAddress = (PCCHAR) TranslationEntry->VirtualAddress + + BYTE_OFFSET(CurrentVa); + + // + // Copy the data between the user buffer and map buffer + // + + if (WriteToDevice) { + + RtlMoveMemory( mapAddress, bufferAddress, Length); + + } else { + + RtlMoveMemory(bufferAddress, mapAddress, Length); + + } + +} +#if 0 //K023 move to r98int.s +/* Start S002 */ +VOID +HalpNmiHandler( + VOID + ) + +/*++ + +Routine Description: + + This routine is call from ROM at NMI + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + // K022 + // NMI was not happend!!. + // + HalpResetNmi(); + // + // Cause EIF !! + // + WRITE_REGISTER_UCHAR(0xB9980100,0x00828000); + return; +} +#endif + +VOID +HalpRegisterNmi( + VOID + ) + +/*++ + +Routine Description: + + This routine set NMI handler to nvRAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +// VOID (*funcAddr)(); + ULONG funcAddr; // K00D + KIRQL OldIrql; + ENTRYLO SavedPte[2]; + PNV_CONFIGURATION NvConfiguration; + + // + // Get address of HalpNmiHandler + // + + funcAddr = (ULONG)HalpNmiHandler; // K00D +// funcAddr += (KSEG1_BASE - KSEG0_BASE); //K023 + + ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) && + ((ULONG)&HalpNmiHandler < KSEG2_BASE) ); + + // + // Map the NVRAM into the address space of the current process. + // + + OldIrql = HalpMapNvram(&SavedPte[0]); + + NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE; + + WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[0], + (UCHAR)(funcAddr >> 24)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[1], + (UCHAR)((funcAddr >> 16) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[2], + (UCHAR)((funcAddr >> 8) & 0xFF)); + + WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[3], + (UCHAR)(funcAddr & 0xFF)); + + // + // Unmap the NVRAM from the address space of the current process. + // + + HalpUnmapNvram(&SavedPte[0], OldIrql); + return; +} +/* End S002 */ + +#if 0 //K015 +// +// K00D form halfxs/mips/jxhwsup.c +// +// +ULONG +HalpReadEisaData ( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Eisa bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + OBJECT_ATTRIBUTES ObjectAttributes; + OBJECT_ATTRIBUTES BusObjectAttributes; + PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter"; + PWSTR ConfigData = L"Configuration Data"; + ANSI_STRING TmpString; + UCHAR BusString[] = "00"; + UNICODE_STRING RootName, BusName; + UNICODE_STRING ConfigDataName; + NTSTATUS NtStatus; + PKEY_VALUE_FULL_INFORMATION ValueInformation; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource; + PCM_EISA_SLOT_INFORMATION SlotInformation; + ULONG PartialCount; + ULONG TotalDataSize, SlotDataSize; + HANDLE EisaHandle, BusHandle; + ULONG BytesWritten, BytesNeeded; + PUCHAR KeyValueBuffer; + ULONG i; + ULONG DataLength = 0; + PUCHAR DataBuffer = Buffer; + BOOLEAN Found = FALSE; + + + RtlInitUnicodeString( + &RootName, + EisaPath + ); + + InitializeObjectAttributes( + &ObjectAttributes, + &RootName, + OBJ_CASE_INSENSITIVE, + (HANDLE)NULL, + NULL + ); + + // + // Open the EISA root + // + + NtStatus = ZwOpenKey( + &EisaHandle, + KEY_READ, + &ObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + KdPrint(("HAL: Open Status = %x\n",NtStatus)); + return(0); + } + + // + // Init bus number path + // + + if (BusNumber > 99) { + return (0); + } + + if (BusNumber > 9) { + BusString[0] += (UCHAR) (BusNumber/10); + BusString[1] += (UCHAR) (BusNumber % 10); + } else { + BusString[0] += (UCHAR) BusNumber; + BusString[1] = '\0'; + } + + RtlInitAnsiString( + &TmpString, + BusString + ); + + RtlAnsiStringToUnicodeString( + &BusName, + &TmpString, + TRUE + ); + + + InitializeObjectAttributes( + &BusObjectAttributes, + &BusName, + OBJ_CASE_INSENSITIVE, + (HANDLE)EisaHandle, + NULL + ); + + // + // Open the EISA root + Bus Number + // + + NtStatus = ZwOpenKey( + &BusHandle, + KEY_READ, + &BusObjectAttributes + ); + + if (!NT_SUCCESS(NtStatus)) { + KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus)); + return(0); + } + + // + // opening the configuration data. This first call tells us how + // much memory we need to allocate + // + + RtlInitUnicodeString( + &ConfigDataName, + ConfigData + ); + + // + // This should fail. We need to make this call so we can + // get the actual size of the buffer to allocate. + // + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + 0, + &BytesNeeded + ); + + KeyValueBuffer = ExAllocatePool( + NonPagedPool, + BytesNeeded + ); + + if (KeyValueBuffer == NULL) { + KdPrint(("HAL: Cannot allocate Key Value Buffer\n")); + ZwClose(BusHandle); + return(0); + } + + ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer; + + NtStatus = ZwQueryValueKey( + BusHandle, + &ConfigDataName, + KeyValueFullInformation, + ValueInformation, + BytesNeeded, + &BytesWritten + ); + + + ZwClose(BusHandle); + + if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) { + KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus)); + ExFreePool(KeyValueBuffer); + return(0); + } + + + // + // We get back a Full Resource Descriptor List + // + + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation + + ValueInformation->DataOffset); + + PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) + &(Descriptor->PartialResourceList.PartialDescriptors); + PartialCount = Descriptor->PartialResourceList.Count; + + for (i = 0; i < PartialCount; i++) { + + // + // Do each partial Resource + // + + switch (PartialResource->Type) { + case CmResourceTypeNull: + case CmResourceTypePort: + case CmResourceTypeInterrupt: + case CmResourceTypeMemory: + case CmResourceTypeDma: + + // + // We dont care about these. + // + + PartialResource++; + + break; + + case CmResourceTypeDeviceSpecific: + + // + // Bingo! + // + + TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)PartialResource + + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + + while (((LONG)TotalDataSize) > 0) { + + if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION); + + } else { + + SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) + + SlotInformation->NumberFunctions * + sizeof(CM_EISA_FUNCTION_INFORMATION); + } + + if (SlotDataSize > TotalDataSize) { + + // + // Something is wrong again + // + + ExFreePool(KeyValueBuffer); + return(0); + + } + + if (SlotNumber != 0) { + + SlotNumber--; + + SlotInformation = (PCM_EISA_SLOT_INFORMATION) + ((PUCHAR)SlotInformation + SlotDataSize); + + TotalDataSize -= SlotDataSize; + + continue; + + } + + // + // This is our slot + // + + Found = TRUE; + break; + + } + + // + // End loop + // + + i = PartialCount; + + break; + + default: + KdPrint(("Bad Data in registry!\n")); + ExFreePool(KeyValueBuffer); + return(0); + } + } + + if (Found) { + + i = Length + Offset; + if (i > SlotDataSize) { + i = SlotDataSize; + } + + DataLength = i - Offset; + RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength); + + } + + ExFreePool(KeyValueBuffer); + return DataLength; +} + +ULONG +HalGetBusDataByOffset( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Offset - Offset in the BusData buffer + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + + ULONG DataLength = 0; + + switch (BusDataType) { + case EisaConfiguration: + DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length); + break; + } + + return(DataLength); + +} +ULONG +HalGetBusData( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ) +/*++ + +Routine Description: + + Subset of HalGetBusDataByOffset, just pass the request along. + +--*/ +{ + return HalGetBusDataByOffset ( + BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length + ); +} + +ULONG +HalSetBusDataByOffset( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function sets the bus data for a slot or address. + +Arguments: + + BusDataType - Supplies the type of bus. + + BusNumber - Indicates which bus. + + Buffer - Supplies the space to store the data. + + Offset - Offset in the BusData buffer + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ + +{ + + ULONG DataLength = 0; + + return(DataLength); +} + +ULONG +HalSetBusData( + IN BUS_DATA_TYPE BusDataType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length + ) +/*++ + +Routine Description: + + Subset of HalGetBusDataByOffset, just pass the request along. + +--*/ +{ + return HalSetBusDataByOffset( + BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length + ); +} + +NTSTATUS +HalAssignSlotResources ( + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN INTERFACE_TYPE BusType, + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine it's required resources. + Calls IoAssignResources to allocate them. + Sets the targeted device with it's assigned resoruces + and returns the assignments to the caller. + +Arguments: + + RegistryPath - Passed to IoAssignResources. + A device specific registry path in the current-control-set, used + to check for pre-assigned settings and to track various resource + assignment information for this device. + + DriverClassName Used to report the assigned resources for the driver/device + DriverObject - Used to report the assigned resources for the driver/device + DeviceObject - Used to report the assigned resources for the driver/device + (ie, IoReportResoruceUsage) + BusType + BusNumber + SlotNumber - Together BusType,BusNumber,SlotNumber uniquely + indentify the device to be queried & set. + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + // + // This HAL doesn't support any buses which support + // HalAssignSlotResources + // + + return STATUS_NOT_SUPPORTED; + +} + +NTSTATUS +HalAdjustResourceList ( + IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList + ) +/*++ + +Routine Description: + + Takes the pResourceList and limits any requested resource to + it's corrisponding bus requirements. + +Arguments: + + pResourceList - The resource list to adjust. + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + // + // BUGBUG: This function should verify that the resoruces fit + // the bus requirements - for now we will assume that the bus + // can support anything the device may ask for. + // + + return STATUS_SUCCESS; +} + + +#endif //K015 diff --git a/private/ntos/nthals/halr98mp/mips/r98info.c b/private/ntos/nthals/halr98mp/mips/r98info.c new file mode 100644 index 000000000..c574c0a6c --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98info.c @@ -0,0 +1,99 @@ +#ident "@(#) NEC r98info.c 1.1 95/06/19 11:34:28" +/*++ + +Copyright (C) 1991-1995 Microsoft Corporation +All rights reserved. + +Module Name: + + ixinfo.c + +Abstract: + +Environment: + + Kernel mode only. + +Revision History + + A002 1995/6/17 ataka@oa2.kb.nec.co.jp + - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h + +--*/ + + +#include "halp.h" + +NTSTATUS +HalpQueryInstalledBusInformation ( + OUT PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength + ); + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HaliQuerySystemInformation) +#pragma alloc_text(PAGE,HaliSetSystemInformation) +#endif + +NTSTATUS +HaliQuerySystemInformation( + IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + OUT PVOID Buffer, + OUT PULONG ReturnedLength + ) +{ + NTSTATUS Status; + PVOID InternalBuffer; + ULONG Length; + + PAGED_CODE(); + + Status = STATUS_SUCCESS; + *ReturnedLength = 0; + Length = 0; + + switch (InformationClass) { + case HalInstalledBusInformation: + Status = HalpQueryInstalledBusInformation ( + Buffer, + BufferSize, + ReturnedLength + ); + break; + + default: + Status = STATUS_INVALID_LEVEL; + break; + } + + // + // If non-zero Length copy data to callers buffer + // + + if (Length) { + if (BufferSize < Length) { + Length = BufferSize; + } + + *ReturnedLength = Length; + RtlCopyMemory (Buffer, InternalBuffer, Length); + } + + return Status; +} + +NTSTATUS +HaliSetSystemInformation ( + IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN PVOID Buffer + ) +{ + PAGED_CODE(); + return STATUS_INVALID_LEVEL; +} + + diff --git a/private/ntos/nthals/halr98mp/mips/r98int.s b/private/ntos/nthals/halr98mp/mips/r98int.s new file mode 100644 index 000000000..d5d05d25d --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98int.s @@ -0,0 +1,522 @@ +// "@(#) NEC r98int.s 1.14 95/06/19 11:35:43" +// TITLE("Interrupts service routine") +//++ +// +// Copyright (c) 1994 Kobe NEC Software +// +// Module Name: +// +// r98int.s +// +// Abstract: +// +// +// Author: +// +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// S001 '94.6/03 T.Samezima +// +// Del iRSF interrupt clear +// +//************************************************************** +// +// S002 94.6/13 T.Samezima +// +// Del Compile err +// +//************************************************************** +// +// S003 94.7/15 T.Samezima +// +// Chg change register access from 8byte access to 4byte access +// +//************************************************************** +// +// S004 94.7/20 T.Samezima +// +// Del Compile err +// K001 94/10/11 N.Kugimoto +// Add.chg HalpNmiHandler() from r98hwsup.c and chg +// +// S005 94/01/15 T.Samezima +// Add HalpReadPhysicalAddr() +// +// S006 94/01/24 T.Samezima +// Add HalpWritePhysicalAddr(),HalpReadAndWritePhysicalAddr(), +// +// S007 94/03/10-17 T.Samezima +// Chg HalpNMIHandler(). +// +// A002 1995/6/17 ataka@oa2.kb.nec.co.jp +// - resolve compile error or logic error? +//-- + +#include "halmips.h" +#include "r98def.h" + + + SBTTL("Timer Interrupt") +//++ +// +// Routine Description: +// +// This routine is enterd as the result of an timer interrupt. +// +// Argments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpTimerDispatch) + + move a0,s8 + j HalpTimerScDispatch + + .end HalpTimerDispatch + + + SBTTL("Read Large Register") +//++ +// +// Routine Description: +// +// This routine is read of large register +// +// Argments: +// +// a0 - Virtual address +// +// a1 - pointer to buffer of upper 32bit large register +// +// a2 - pointer to buffer of lower 32bit large register +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpReadLargeRegister) + +// Start S003 +#if 0 + DISABLE_INTERRUPTS(t7) // disable interrupts + + mfc1 t0,f0 // save f0 register + mfc1 t1,f1 // save f1 register + + ldc1 f0,0x0(a0) // read register + mfc1 t2,f0 // get register(upper) + mfc1 t3,f1 // get register(lower) +#endif + + lw t2,0x0(a0) // get register(upper) + lw t3,0x4(a0) // get register(lower) + + sw t2,0x0(a1) // set upper register value + sw t3,0x0(a2) // set lower register value + +#if 0 + mtc1 t0,f0 // restore f0 register + mtc1 t1,f1 // restore f1 register + + sync // + + ENABLE_INTERRUPTS(t7) // enable interrupts +#endif +// End S003 + 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 upper 32bit of large register +// +// a2 - pointer to value of lower 32bit of large register +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpWriteLargeRegister) + +// Start S003 +#if 0 + DISABLE_INTERRUPTS(t7) // disable interrupts + + mfc1 t0,f0 // save f0 register + mfc1 t1,f1 // save f1 register +#endif + + lw t2,0x0(a1) // load upper register value + lw t3,0x0(a2) // load lower register value + + sw t2,0x0(a0) // set upper register value + sw t3,0x4(a0) // set lower register value + +#if 0 + mtc1 t2,f0 // set register(upper) + mtc1 t3,f1 // set register(lower) + sdc1 f0,0x0(a0) // write register + + mtc1 t0,f0 // restore f0 register + mtc1 t1,f1 // restore f1 register +#endif + + sync // + +// ENABLE_INTERRUPTS(t7) // enable interrupts +// End S003 + + j ra // return + + .end HalpWriteLargeRegister + + + 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 + + +// 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 ^^^ + + 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 + +// S007 vvv + // + // reset NMIR register, set NMI flag and save CPU register. + // + + li k0,0xb9980308 // Set STSR address + li k1,0x08080000 // Disable NMI + sw k1,0x0(k0) // + + la k0,HalpNMIFlag // set NMI flag address +// li k1,0xa0000000 // KSEG1_ACCESS +// or k0,k0,k1 // + li k1,0xb9980030 // set NMIR address + lw k1,(k1) // get NMIR register + addi k1,k1,1 // set NMI flag + sw k1,(k0) // + + li k1,0xb8c80000 // Reset NMI + sb zero,0x0(k1) // + +#if 1 +// lw k0,KiPcr + PcPrcb(zero) // get current processor block address +// la k1,HalpNMIBuf // get performance counter address +// lbu k0,PbNumber(k0) // get processor number +// sll k0,k0,7 // compute address of nmi buffer +// addu k0,k0,k1 // + + li k0,0xb9980300 // get CNFG Register Addr of PMC + li k1,0x00007000 // Mask Node Of CPU0-CPU3 + lw k0 ,0x0(k0) // get value of etc of PMC + and k0,k0,k1 // get value of NODE + la k1,HalpNMIBuf // get performance counter address + srl k0,k0,5 // shift right 7 bit for offset + addu k0,k0,k1 // compute address of nmi buffer + +// sw at,0x0(k0) // register save. + sw v0,0x4(k0) // + sw v1,0x8(k0) // + sw a0,0xc(k0) // + sw a1,0x10(k0) // + sw a2,0x14(k0) // + sw a3,0x18(k0) // + sw t0,0x1c(k0) // + sw t1,0x20(k0) // + sw t2,0x24(k0) // + sw t3,0x28(k0) // + sw t4,0x2c(k0) // + sw t5,0x30(k0) // + sw t6,0x34(k0) // + sw t7,0x38(k0) // + sw t8,0x3c(k0) // + sw t9,0x40(k0) // + sw gp,0x44(k0) // + sw sp,0x48(k0) // + sw s8,0x4c(k0) // + sw ra,0x50(k0) // + + .set noreorder + + mfc0 k1,psr // + sw k1,0x54(k0) // + mfc0 k1,cause // + sw k1,0x58(k0) // + mfc0 k1,epc // + sw k1,0x5c(k0) // + mfc0 k1,errorepc // + sw k1,0x60(k0) // + + .set reorder + +#endif + + li k0,0xb9980038 // set NMIRST address + li k1,0x8 // it is DUMP Key NMI + sw k1,(k0) // reset nmi + .set noreorder // A002 + nop +// +// This is a test code. +// We must clear BEV bit of psr register. +// + + mfc0 k1,psr // get psr + li k0,0xffafffff // BEV bit clear + nop // fill + and k1,k1,k0 // + nop // + mtc0 k1,psr // set psr + nop // fill + nop // + nop // + +// li k0,0xb9980308 // Read STSR Register +// lw k1,(k0) // +// or k1,k1,0x80800000// make eif +// sw k1,(k0) // +// nop + + li k0,0xb9980100 // IntIR Register addr + li k1,0x0082f000 // Do eif to CPU0 only. + sw k1,(k0) // + + nop + eret // return to errorepc + nop + nop + nop + eret // errata + nop +#if 0 + mfc0 k0,epc // As if behave No Nmi + nop + nop + j k0 // As if behave No Nmi. +#endif // I Hope EIF Interrut + // Occur later!!. + // +// S007 ^^^ + + .set at + .set reorder + + + .end HalpNmiHandler + diff --git a/private/ntos/nthals/halr98mp/mips/r98ipint.s b/private/ntos/nthals/halr98mp/mips/r98ipint.s new file mode 100644 index 000000000..b6176b490 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98ipint.s @@ -0,0 +1,176 @@ +// "@(#) NEC r98ipint.s 1.5 94/10/11 23:04:02" +// TITLE("Interprocessor Interrupts") +//++ +// +// +// Module Name: +// +// r98ipint.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interprocessor interrupts on a r98 +// +// Author: +// +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// +// S001 94.6/13 T.Samezima +// +// Del Compile err +// +// S002 94.7/14 T.Samezima +// +// Chg define register base address +// change register access from 8byte access to 4byte access +// +// S003 94.7/20 T.Samezima +// +// Del Compile err del +// +// S004 94.10/11 T.Samezima +// +// Fix Version Up at build807 +// +// +//-- + +#include "halmips.h" +#include "r98def.h" +//#include "r98reg.h" // S001 + +// Start S002 +// +// Define interrupt control registers base +// + +#define PMC_BASE PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+KSEG1_BASE +// End S002 + + + 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. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 +IiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +IiRa: .space 4 // saved return address +IiFrameLength: // + + NESTED_ENTRY(HalpIpiInterrupt, IiFrameLength, zero) + + subu sp,sp,IiFrameLength // allocate stack frame + sw ra,IiRa(sp) // save return address + + PROLOGUE_END + +// Start S002 +// mfc1 t5,f0 // save f0 register +// sw t5,IiF0(sp) // +// mfc1 t6,f1 // save f1 register +// sw t6,IiF1(sp) // +// End S002 + + li t7,PMC_BASE // get register address // S002 + +// Start S002 + lw t0,0x0(t7) // get upper 32bit of IPR register + +// ldc1 f0,0x0(t7) // read IPR register +// mfc1 t0,f0 // get upper 32bit of IPR register + +10: lw t1,0x8(t7) // get upper 32bit of MKR register + +// ldc1 f0,0x8(t7) // read MKR register +// mfc1 t1,f0 // get upper 32bit of MKR register +// End S002 + + and t1,t0,t1 // calculate upper 32bit of 'IPR & MKR' + andi t2,t1,IPR_IPI0_BIT_HIGH // check IPI0 bit + bne t2,zero,20f // if not eq, ip interrupt from processor0 + andi t2,t1,IPR_IPI1_BIT_HIGH // check IPI1 bit + bne t2,zero,20f // if not eq, ip interrupt from processor1 + andi t2,t1,IPR_IPI2_BIT_HIGH // check IPI2 bit + bne t2,zero,20f // if not eq, ip interrupt from processor2 + andi t2,t1,IPR_IPI3_BIT_HIGH // check IPI3 bit + bne t2,zero,20f // if not eq, ip interrupt from processor3 + +// +// Unknown interrupt. +// + + li t4,MKR_INT4_ENABLE_HIGH // make argument + and a0,t1,t4 // + and a1,zero,a1 // + jal HalpUnknownInterrupt // call unknown interrupt handler + b 30f + +// +// Interprocessor interrupt. +// + +// Start S002 +20: sw t2,0x10(t7) // set IPRR register + sw zero,0x14(t7) // + +// mtc1 t2,f0 // set IPRR register +// mtc1 zero,f1 // +// sdc1 f0,0x10(t7) // +// End S002 + + lw t1,__imp_KeIpiInterrupt // process interprocessor requests // S004 + jal t1 // // S004 + +// +// check other interrupt. +// + +30: li t7,PMC_BASE // get register address // S002 +// Start S002 + lw t0,0x0(t7) // get upper 32bit of IPR register +// ldc1 f0,0x0(t7) // read IPR register +// mfc1 t0,f0 // get upper 32bit of IPR register +// End S002 + andi t1,t0,MKR_INT4_ENABLE_HIGH // check interrupt of int4 level + bne t1,zero,10b // if neq, occur new interrupt. + + READ_CAUSE_REGISTER(t2) // get cause // S002 + + andi t3,t2,1 << (CAUSE_INTPEND + IPI_LEVEL - 1 ) // check interrupt + bne t3,zero,30b // if neq, check new interrupt + +// Start S003 +// lw t0,IiF0(sp) // restore f0 register +// mtc1 t0,f0 // +// lw t1,IiF1(sp) // restore f1 register +// mtc1 t1,f1 // +// End S003 + + lw ra,IiRa(sp) // save return address + addu sp,sp,IiFrameLength // deallocate stack frame + j ra // return + + .end HalpIpiInterrupt diff --git a/private/ntos/nthals/halr98mp/mips/r98led.c b/private/ntos/nthals/halr98mp/mips/r98led.c new file mode 100644 index 000000000..219d3abd9 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98led.c @@ -0,0 +1,252 @@ +#ident "@(#) NEC r98led.c 1.5 95/06/19 11:36:14" +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + r98led.c + +Abstract: + + This module implements the Led output routines for R98 + +Author: + + + +Environment: + + Kernel mode + +Revision History: + + S001 9/26/94 By T.Samezima + + Add Debug Print + A002 1995/6/17 ataka@oa2.kb.nec.co.jp + - resolve compile error. + +--*/ + +#include "halp.h" + +// +// Set table size +// +#define SEGMENT_TABLE_SIZE 16 + +// +// Define spin lock +// +KSPIN_LOCK HalpLedLock; + +// +// Define flag of initialize led +// +ULONG HalpLedInitFlg = 0; + +// +// Buffer of output data at port +// +UCHAR HalpSegmentDisplayData[4] = { 0, 0, 0, 0 }; + +// +// Define character table +// +UCHAR HalpSegmentCharTableL[] = "0123456789abcdef"; +UCHAR HalpSegmentCharTableU[] = "0123456789ABCDEF"; + +// +// Define table of change from output character data to output port data +// +UCHAR HalpSegmentPatternTable[] = { 0xfa, 0x30, 0xdc, 0x7c, //0-3 + 0x36, 0x6e, 0xee, 0x3a, //4-7 + 0xfe, 0x7e, 0xfc, 0xe6, //8-b + 0xc4, 0xf4, 0xce, 0x8e, //c-f + 0x04 }; //err + + +VOID +HalpOutputSegment( + IN ULONG Number, + IN UCHAR Data + ) + +/*++ + +Routine Description: + + This routine is output a character data in led segment. + +Arguments: + + Number - Segment number(range 0-3.) + + Data - Output data on port. + +Return Value: + + none. + +--*/ + +{ + ULONG lednumber; + + // + // Get segment number. + // + + lednumber = Number & 0x3; + + if(HalpLedInitFlg == 0){ + KeInitializeSpinLock(&HalpLedLock); + HalpLedInitFlg = 1; + } + + KiAcquireSpinLock(&HalpLedLock); + + // + // Display data. + // + + HalpSegmentDisplayData[Number] = Data; + + WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData3, + HalpSegmentDisplayData[3] ); + WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData2, + HalpSegmentDisplayData[2] ); + WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData1, + HalpSegmentDisplayData[1] ); + WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData0, + HalpSegmentDisplayData[0] ); + + KiReleaseSpinLock(&HalpLedLock); + + return; +} + +VOID +HalpDisplaySegment( + IN ULONG Number, + IN UCHAR Data + ) + +/*++ + +Routine Description: + + This routine is display a character in led segment. + +Arguments: + + Number - Segment number(range 0-3.) + + Data - Output data character on port. + +Return Value: + + none. + +--*/ + +{ + ULONG counter; + + // + // Search character data. + // + + for( counter=0 ; counter= R98DebugLevel) { + if (DebugOutput & DBG_LED) { + // Message is "1-a-f" + for(p=(char *)DebugMessageLed,LedNumber=0; LedNumber<4;p++,LedNumber++) // A002 + HalpDisplaySegment(LedNumber,*p); + } + + // sdk/inc/crt/stdarg.h + va_start(ap, DebugMessage); + + // stdlib ?? (sdk/inc/crt/stdio.h) + (VOID) vsprintf(buffer, DebugMessage, ap); + + // + if (DebugOutput & DBG_SERIAL) { + DbgPrint(buffer); + } + + // Console =Vram Write + // + if (DebugOutput & DBG_COLOR) { + HalDisplayString(buffer); + } + + } + + va_end(ap); + +} +#endif +// End S001 diff --git a/private/ntos/nthals/halr98mp/mips/r98pci.c b/private/ntos/nthals/halr98mp/mips/r98pci.c new file mode 100644 index 000000000..64703837d --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98pci.c @@ -0,0 +1,289 @@ +#ident "@(#) NEC r98pci.c 1.8 95/01/11 22:30:24" +/*++ + +Copyright (c) 1994 Kobe NEC Software + +Module Name: + + r98pci.c + +Abstract: + + This module implements the pci bus support routine for R98 + +Author: + + +Environment: + + Kernel mode + +Revision History: + + S001 94.7/20 T.Samezima + Chg Del compile err + + S002 '94.10/14 T.Samezima + Add Set PCI bus interrupt affinity. + + S003 '94.10/24 T.Samezima + Add Error register read and print. + + S004 '94.12/07 T.Samezima + Add Error register read and print. + + S005 '94.01/11 T.Samezima + Del del werning. + +--*/ + +#include "halp.h" +#include "stdio.h" // S005 + +// +// Enable PCI count +// + +ULONG HalpEnablePCIInterruptCount; + +// Start S002 +// Define PCI bus interrupt affinity. +// + +KAFFINITY HalpPCIBusAffinity; +// End S002 + +// S001 +BOOLEAN +HalpPCIDispatch( // S001 + IN PKINTERRUPT Interrupt + ) + +/*++ + +Routine Description: + + This routine is entered as the result of PCI err interrupt. + +Arguments: + + Interrupt - Supplies a pointer to the interrupt function address. + +Return Value: + + +--*/ + +{ + // S003 vvv + // S004 vvv + ULONG errsBuffer; + ULONG pearBuffer; + ULONG aearBuffer; + UCHAR messageBuffer[256]; + + errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ); + pearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR ); + aearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR ); + + if ( errsBuffer & 0x80000000 ) { + sprintf( (char *)messageBuffer, + "PCI Bus: Master Abort: PEAR=0x%08lX\n", + pearBuffer + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if ( errsBuffer & 0x40000000 ) { + sprintf( (char *)messageBuffer, + "PCI Bus: Target Abort: PEAR=0x%08lX\n", + pearBuffer + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if ( errsBuffer & 0x20000000 ) { + sprintf( (char *)messageBuffer, + "PCI Bus: System error\n" + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if ( errsBuffer & 0x10000000 ) { + sprintf( (char *)messageBuffer, + "PCI Bus: Parity error\n" + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + + if ( errsBuffer & 0x08000000 ) { + sprintf( (char *)messageBuffer, + "Page fault in NA Bus master transaction\n" + " ERRS=0x%08lX, AEAR=0x%08lX\n", + errsBuffer, + aearBuffer + ); + HalDisplayString( (char *)messageBuffer ); + KdPrint(( (char *)messageBuffer )); + } + // S004 ^^^ + + KeBugCheckEx(DATA_BUS_ERROR, + READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ), + READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR ), + READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR ), + 0 ); + // S003 ^^^ + + return TRUE; +} + + +BOOLEAN +HalpCreatePciStructures ( + VOID + ) + +/*++ + +Routine Description: + + This routine initializes the structures necessary for PCI operations + and connects the intermediate interrupt dispatcher. + +Arguments: + + None. + +Return Value: + + If the second level interrupt dispatcher is connected, then a value of + TRUE is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + // + // Initialize the interrupt dispatcher for PCI err interrupts. + // + + PCR->InterruptRoutine[PCI_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpPCIDispatch; + + // Start S002 + // Set PCI bus interrupt affinity. + // + + HalpPCIBusAffinity = PCR->SetMember; + // End S002 + + // + // Enable PCI err interrupt + // + + KiAcquireSpinLock(&HalpSystemInterruptLock); + + HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_ERR_INTERRUPT; + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + + KiReleaseSpinLock(&HalpSystemInterruptLock); + + return TRUE; +} + + +VOID +HalpEnablePciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function enables the PCI bus specified PCI bus interrupt. + + memo: This routine enter following condition + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is enabled. + +Return Value: + + None. + +--*/ + +{ + // + // Count up enable count + // + + HalpEnablePCIInterruptCount++; + + // + // Check interrupt enable count. if interrupt is not already enable, then + // enable PCI interrupt. + // + + if(HalpEnablePCIInterruptCount == 1){ + HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_INTERRUPT; + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + } + +} + + +VOID +HalpDisablePciInterrupt( + IN ULONG Vector + ) + +/*++ + +Routine Description: + + This function disables the PCI bus specified PCI bus interrupt. + + memo: This routine enter following condition + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + KiAcquireSpinLock(&HalpSystemInterruptLock); + +Arguments: + + Vector - Supplies the vector of the PCI interrupt that is Disabled. + +Return Value: + + None. + +--*/ + +{ + // + // Count down enable count + // + + if( HalpEnablePCIInterruptCount > 0){ + --HalpEnablePCIInterruptCount; + } + + // + // Check interrupt enable count. if count equal zero, then disable + // PCI interrupt. + // + + if(HalpEnablePCIInterruptCount == 0){ + HalpBuiltinInterruptEnable &= ~iREN_ENABLE_PCI_INTERRUPT; + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable); + } +} diff --git a/private/ntos/nthals/halr98mp/mips/r98pcibs.c b/private/ntos/nthals/halr98mp/mips/r98pcibs.c new file mode 100644 index 000000000..bca258f3e --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98pcibs.c @@ -0,0 +1,3180 @@ +#ident "@(#) NEC r98pcibs.c 1.20 95/06/29 16:09:32" +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpcidat.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + Ken Reneris (kenr) 14-June-1994 + +Environment: + + Kernel mode + +Revision History: + +A001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:33:30 JST 1994 + - 各種DbgPrintの挿入 + - r98DoPciTest = 1, r98DoGetDataPrint = 1 + - r98PCIIoBaseの変更(全て1ecd0000に設定) +K001 kugimoto@oa2 + -defined(DBG) chg IF DBG +K002 kugimoto@oa2 + -1:r98DoPciTest = 0, r98DoGetDataPrint = 0 + -2:ASSERT del +S001 samezima@oa2 + - disable DbgPrint +S002 samezima@oa2 + - Bug. Change potision of #ifdef. +A002 1995/6/17 ataka@oa2.kb.nec.co.jp + - Marge 807-halr98mp-r98pcibus.c to 1050 ixpcibus.c + and named r98pcibs.c +K003 95/06/29 Kugimoto@oa2 + -Mips Arc have not BIOS. So Set ROM Enable always. +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + + +typedef ULONG (*FncConfigIO) ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +typedef VOID (*FncSync) ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +typedef VOID (*FncReleaseSync) ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +typedef struct _PCI_CONFIG_HANDLER { + FncSync Synchronize; + FncReleaseSync ReleaseSynchronzation; + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER; + + + +// +// Prototypes +// + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +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 + ); + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + + +#if defined (_R98_) // A002 +VOID HalpPCISynchronizeTypeR98 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationTypeR98 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); +#endif // _R98_ A002 + +// +// Globals +// + +KSPIN_LOCK HalpPCIConfigLock; + +PCI_CONFIG_HANDLER PCIConfigHandler; + +PCI_CONFIG_HANDLER PCIConfigHandlerType1 = { + HalpPCISynchronizeType1, + HalpPCIReleaseSynchronzationType1, + { + HalpPCIReadUlongType1, // 0 + HalpPCIReadUcharType1, // 1 + HalpPCIReadUshortType1 // 2 + }, + { + HalpPCIWriteUlongType1, // 0 + HalpPCIWriteUcharType1, // 1 + HalpPCIWriteUshortType1 // 2 + } +}; + +PCI_CONFIG_HANDLER PCIConfigHandlerType2 = { + HalpPCISynchronizeType2, + HalpPCIReleaseSynchronzationType2, + { + HalpPCIReadUlongType2, // 0 + HalpPCIReadUcharType2, // 1 + HalpPCIReadUshortType2 // 2 + }, + { + HalpPCIWriteUlongType2, // 0 + HalpPCIWriteUcharType2, // 1 + HalpPCIWriteUshortType2 // 2 + } +}; + +#if defined (_R98_) // A002 +PCI_CONFIG_HANDLER PCIConfigHandlerTypeR98 = { + HalpPCISynchronizeTypeR98, + HalpPCIReleaseSynchronzationTypeR98, + { + HalpPCIReadUlongTypeR98, // 0 + HalpPCIReadUcharTypeR98, // 1 + HalpPCIReadUshortTypeR98 // 2 + }, + { + HalpPCIWriteUlongTypeR98, // 0 + HalpPCIWriteUcharTypeR98, // 1 + HalpPCIWriteUshortTypeR98 // 2 + } +}; +#endif // _R98_ A002 + +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +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 + ); +#if defined (_R98_) // A002 +VOID +HalpTestPciNec ( + ULONG + ); +VOID +HalpTestPciPrintResult( + IN PULONG Buffer, + IN ULONG Length + ); +VOID +HalpOtherTestNec ( + ULONG + ); +ULONG r98DbgCfg = 0; +ULONG r98DoPciTest = 0; // A001 K002-1 +ULONG r98DoOthrTest = 0; +ULONG r98DoMultiBytes = 0; +ULONG r98DoGetDataPrint = 0; // A001 K002-1 +#define r98DbgCfgBits { \ + if (r98DbgCfg) {\ + DbgPrint("RegNo=%x ", PciCfgR98->u.bits.RegisterNumber); \ + DbgPrint("FncNo=%x ", PciCfgR98->u.bits.FunctionNumber); \ + DbgPrint("SltNo=%x ", PciCfgR98->u.bits.SlotNumber); \ + DbgPrint("All=%x", PciCfgR98->u.AsULONG); \ + } \ + } +#endif // _R98_ A002 +#else +#define DBGMSG(a) +#endif + +#if defined(_R98_) // A002 +ULONG r98PCIIoBase[] = { // This must be fixed to flexible configration + 0x00000000, + 0x1ecd0000, + 0x1ecd0000, + 0x1ecd0000 + }; +#endif // _R98_ A002 + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitializePciBus) +#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler) +#pragma alloc_text(INIT,HalpIsValidPCIDevice) +#pragma alloc_text(PAGE,HalpAssignPCISlotResources) +#endif + + + +VOID +HalpInitializePciBus ( + VOID + ) +{ + PPCI_REGISTRY_INFO PCIRegInfo; + UNICODE_STRING unicodeString, ConfigName, IdentName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE hMFunc, hBus; + NTSTATUS status; + UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99]; + PWSTR p; + WCHAR wstr[8]; + ULONG i, d, junk, HwType, BusNo, f; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PKEY_VALUE_FULL_INFORMATION ValueInfo; + PCM_FULL_RESOURCE_DESCRIPTOR Desc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc; + + PCI_REGISTRY_INFO tPCIRegInfo; // only for debug A002 + +#if 0 // A002 + // + // Search the hardware description looking for any reported + // PCI bus. The first ARC entry for a PCI bus will contain + // the PCI_REGISTRY_INFO. + + RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, // handle + NULL); + + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + return ; + } + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + + for (i=0; TRUE; i++) { + RtlIntegerToUnicodeString (i, 10, &unicodeString); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + hMFunc, + NULL); + + status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + // + // Out of Multifunction adapter entries... + // + + ZwClose (hMFunc); + return ; + } + + // + // Check the Indentifier to see if this is a PCI entry + // + + status = ZwQueryValueKey ( + hBus, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + if (!NT_SUCCESS (status)) { + ZwClose (hBus); + continue; + } + + p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset); + if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) { + ZwClose (hBus); + continue; + } + + // + // The first PCI entry has the PCI_REGISTRY_INFO structure + // attached to it. + // + + status = ZwQueryValueKey ( + hBus, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + ZwClose (hBus); + if (!NT_SUCCESS(status)) { + continue ; + } + + Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) + ValueInfo + ValueInfo->DataOffset); + PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR) + Desc->PartialResourceList.PartialDescriptors); + + if (PDesc->Type == CmResourceTypeDeviceSpecific) { + // got it.. + PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + break; + } + } +#endif // only for debug A002 + + +#if defined (_R98_) // only for debug A002 +// PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + PCIRegInfo = &tPCIRegInfo; + PCIRegInfo->NoBuses = 1; + PCIRegInfo->HardwareMechanism=0xF; // LR4360 PCI Config Type +#if DBG // S001, S002 + DbgPrint("PCI System Get Data:\n"); + DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision ); + DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision ); + DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses ); + DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism ); +#endif // S001, S002 +#endif // only for debug A002 + // + // Initialize spinlock for synchronizing access to PCI space + // + + KeInitializeSpinLock (&HalpPCIConfigLock); + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // PCIRegInfo describes the system's PCI support as indicated by the BIOS. + // + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + + // + // Some AMI bioses claim machines are Type2 configuration when they + // are really type1. If this is a Type2 with at least one bus, + // try to verify it's not really a type1 bus + // + + if (PCIRegInfo->NoBuses && HwType == 2) { + + // + // Check each slot for a valid device. Which every style configuration + // space shows a valid device first will be used + // + + SlotNumber.u.bits.Reserved = 0; + SlotNumber.u.bits.FunctionNumber = 0; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + // + // First try what the BIOS claims - type 2. Allocate type2 + // test handle for PCI bus 0. + // + + HwType = 2; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + // + // Valid device not found on Type2 access for this slot. + // Reallocate the bus handler are Type1 and take a look. + // + + HwType = 1; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + HwType = 2; + } + + // + // Reset handler for PCI bus 0 to whatever style config space + // was finally decided. + // + + HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE); + } + + + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + + do { + for (i=0; i < PCIRegInfo->NoBuses; i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // + + } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ; + + // + // Fixup SUPPORTED_RANGES + // + + HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses); + + + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) { + BusHandler = HalpHandlerForBus (PCIBus, BusNo); + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Check for chips with known work-arounds to apply + // + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x04A3 && + PciData->RevisionID < 0x11) { + + // + // 82430 PCMC controller + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + + buffer[0] &= ~0x08; // turn off bit 3 register 0x53 + + if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn + buffer[1] &= ~0x01; // bit 0 register 0x54 + } + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + } + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x0484 && + PciData->RevisionID <= 3) { + + // + // 82378 ISA bridge & SIO + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + + buffer[0] &= ~0x1; // turn off bit 0 register 0x41 + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + } + + } // next function + } // next device + } // next bus + +#if DBG + HalpTestPci (0); +#if defined (_R98_) // A002 + HalpTestPciNec (r98DoPciTest); + HalpOtherTestNec (r98DoOthrTest); + DbgPrint("HalpInitializePciBus: return\n"); +#endif // _R98_ A002 +#endif +} + + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ) +{ + PBUS_HANDLER Bus; + PPCIPBUSDATA BusData; + + Bus = HalpAllocateBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // bus # + Internal, // child of this bus + 0, // and number + sizeof (PCIPBUSDATA) // sizeof bus specific buffer + ); + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus; + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + Bus->BusAddresses->Dma.Limit = 0; + + BusData = (PPCIPBUSDATA) Bus->BusData; + + // + // Fill in common PCI data + // + + BusData->CommonData.Tag = PCI_DATA_TAG; + BusData->CommonData.Version = PCI_DATA_VERSION; + BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig; + BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig; + BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine; + BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin; + + // + // Set defaults + // + + BusData->MaxDevice = PCI_MAX_DEVICES; + BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq; + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof (PCIConfigHandler)); + + BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT; + BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; + break; + + case 2: + // + // Initialize access port information for Type2 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); + + BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; + BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; + BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; + + // + // Early PCI machines didn't decode the last bit of + // the device id. Shrink type 2 support max device. + // + BusData->MaxDevice = 0x10; + + break; +#if defined (_R98_) // A002 + case 0xF: + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerTypeR98, + sizeof (PCIConfigHandler)); + BusData->MaxDevice = 0x4; + break; +#endif // _R98_ A002 + 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 DBG //K001 A002 + if (r98DoGetDataPrint) { + DbgPrint("HalpGetPCIData: \n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx\n", + BusHandler->BusNumber, Slot.u.bits.DeviceNumber, + Slot.u.bits.FunctionNumber, PciData->VendorID, + PciData->DeviceID, PciData->RevisionID); + if (PciData->u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData->u.type0.InterruptPin); + } + + if (PciData->u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData->u.type0.InterruptLine); + } + + if (PciData->u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData->u.type0.ROMBaseAddress); + } + + DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData->ProgIf, PciData->SubClass, PciData->BaseClass); + {ULONG j; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData->u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx\n", j, PciData->u.type0.BaseAddresses[j]); + } + }} + DbgPrint("\n"); + } +#endif // A002 + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + + } else { + + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData); + } + + // + // Has this PCI device been configured? + // + +#if DBG + + // + // On DBG build, if this PCI device has not yet been configured, + // then don't report any current configuration the device may have. + // + + bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) { + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + PciData->u.type0.BaseAddresses[i] = 0; + } + + PciData->u.type0.ROMBaseAddress = 0; + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + } +#endif + + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len, cnt; + + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + // no device, or header type unkown + return 0; + } + + + // + // Set this device as configured + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; +#if DBG + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&BusData->DeviceConfigured, cnt, 1); +#endif + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + + // in case interrupt line or pin was editted + BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n"); + DbgBreakPoint (); + } +#endif + // + // Set new PCI configuration + // + + HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + 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; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { + return FALSE; + } + + if (Slot.u.bits.FunctionNumber == 0) { + return TRUE; + } + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return FALSE; + } + + return TRUE; +} + + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + UCHAR State[20]; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State); + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (BusData, State, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql); +} + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = 0; + PciCfg1->u.bits.BusNumber = BusHandler->BusNumber; + PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; + PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; + PciCfg1->u.bits.Enable = TRUE; + + // + // Synchronize with PCI type1 config space + // + + if (!HalpDoingCrashDump) { + KeRaiseIrql (HIGH_LEVEL,Irql); // A002 + KiAcquireSpinLock (&HalpPCIConfigLock); + } else { + *Irql = HIGH_LEVEL; + } +} + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + PCI_TYPE1_CFG_BITS PciCfg1; + PPCIPBUSDATA BusData; + + // + // Disable PCI configuration space + // + + PciCfg1.u.AsULONG = 0; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG); + + // + // Release spinlock + // + + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); // A002 + } +} + + +ULONG +HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i)); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i)); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data); + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer)); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer)); + return sizeof (ULONG); +} + + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr + ) +{ + PCI_TYPE2_CSE_BITS PciCfg2Cse; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Initialize Cfg2Addr + // + + PciCfg2Addr->u.AsUSHORT = 0; + PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber; + PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base; + + // + // Synchronize with type2 config space - type2 config space + // remaps 4K of IO space, so we can not allow other I/Os to occur + // while using type2 config space. + // + + HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql); + + PciCfg2Cse.u.AsUCHAR = 0; + PciCfg2Cse.u.bits.Enable = TRUE; + PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber; + PciCfg2Cse.u.bits.Key = 0xff; + + // + // Select bus & enable type 2 configuration space + // + + WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber); + WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); +} + + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + PCI_TYPE2_CSE_BITS PciCfg2Cse; + PPCIPBUSDATA BusData; + + // + // disable PCI configuration space + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + PciCfg2Cse.u.AsUCHAR = 0; + WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR); + WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0); + + // + // Restore interrupts, release spinlock + // + + HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql); +} + + +ULONG +HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT); + return sizeof(ULONG); +} + + +ULONG +HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer)); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset; + WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer)); + return sizeof(ULONG); +} + +#if defined (_R98_) // A002 +VOID HalpPCISynchronizeTypeR98 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPER98_CFG_BITS PciCfgR98 + ) +{ + // + // Initialize PciCfgR98 + // + + PciCfgR98->u.AsULONG = PCI_CONFIG_BASE_ADDRESS; +//K002-2 ASSERT(Slot.u.bits.DeviceNumber >=0 && Slot.u.bits.DeviceNumber < 4); /* only 0-3 */ + PciCfgR98->u.bits.SlotNumber = (Slot.u.bits.DeviceNumber & 3); + PciCfgR98->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; + + // + // Synchronize with PCI type1 config space + // + + KeRaiseIrql (PROFILE_LEVEL, Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); +} + +VOID HalpPCIReleaseSynchronzationTypeR98 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + // + // Release spinlock + // + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); +} +// LR4360 bug work around for debug time B004 +halplrbug0(){ + ULONG reg1; + reg1 = READ_REGISTER_ULONG(0xb8c0a00c); + WRITE_REGISTER_ULONG(0xb8c0a00c,(reg1&0xffbfffff)); + return reg1; +} + +halplrbug1(ULONG reg1){ + ULONG err,ERR_VALUE,iRRE; + ERR_VALUE = READ_REGISTER_ULONG(0xb8c09008); + if(ERR_VALUE & 0x80000000){ + WRITE_REGISTER_ULONG(0xb8c09008,0x80000000); + iRRE = READ_REGISTER_ULONG(0xb8c0a008); + WRITE_REGISTER_ULONG(0xb8c0a008,(iRRE & 0xffbfffff)); + err=1; + }else{ + err=0; + } + WRITE_REGISTER_ULONG(0xb8c0a00c,reg1); + return err; +} + +ULONG +HalpPCIReadUcharTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + ULONG reg1; + reg1=halplrbug0(); + + i = Offset % sizeof(ULONG); + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfgR98->u.AsULONG + i)); + if(halplrbug1(reg1)) //B004 + *Buffer=0xFF; +#if DBG // B009 + r98DbgCfgBits("Read Uchar: ",*Buffer); +#endif + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + ULONG reg1; + reg1=halplrbug0(); + + ASSERT((Offset % sizeof(USHORT)) == 0); + + i = Offset % sizeof(ULONG); + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + *((PUSHORT)Buffer) = READ_PORT_USHORT ((PUSHORT) (PciCfgR98->u.AsULONG + i)); + if(halplrbug1(reg1)) //B004 + *((PUSHORT)Buffer)=0xFFFF; +#if DBG // B009 + r98DbgCfgBits("Read Ushort: ",*((PUSHORT)Buffer)); +#endif + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + + + + ULONG reg1; + reg1=halplrbug0(); + ASSERT((Offset % sizeof(ULONG)) == 0); + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + +#if DBG // B008 + if (r98DoMultiBytes) { + HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset); + HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1); + HalpPCIReadUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2); + } else +#endif + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfgR98->u.AsULONG)); + if(halplrbug1(reg1)) + *((PULONG)Buffer)=0xFFFFFFFF; +#if DBG + r98DbgCfgBits("Read Ulong: ",*((PULONG)Buffer)); +#endif + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + ULONG reg1; + reg1=halplrbug0(); + + i = Offset % sizeof(ULONG); + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_UCHAR(((PUCHAR)(PciCfgR98->u.AsULONG + i)), (*((PUCHAR)Buffer))); +#if DBG + r98DbgCfgBits("Write Uchar: ",*((PUCHAR)Buffer)); +#endif + halplrbug1(reg1); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + ULONG reg1; + reg1=halplrbug0(); + + ASSERT((Offset % sizeof(USHORT)) == 0); + + i = Offset % sizeof(ULONG); + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + WRITE_PORT_USHORT(((PULONG)(PciCfgR98->u.AsULONG + i)), (*((PUSHORT)Buffer))); +#if DBG + r98DbgCfgBits("Write Ushort: ",*((PUSHORT)Buffer)); +#endif + halplrbug1(reg1); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongTypeR98 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPER98_CFG_BITS PciCfgR98, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG reg1; + reg1=halplrbug0(); + ASSERT((Offset % sizeof(ULONG)) == 0); + + PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG); + +#if DBG + if (r98DoMultiBytes) { + HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset); + HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1); + HalpPCIWriteUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2); + } else +#endif + WRITE_PORT_ULONG (((PULONG)(PciCfgR98->u.AsULONG)), (*((PULONG)Buffer))); +#if DBG + r98DbgCfgBits("Write Ulong: ",*((PULONG)Buffer)); +#endif + halplrbug1(reg1); + return sizeof (ULONG); +} +#endif // A002 + + + +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; + + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + BusNumber = BusHandler->BusNumber; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Allocate some pool for working space + // + + i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) + + sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 + + PCI_COMMON_HDR_LENGTH * 3; + + WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i); + if (!WorkingPool) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero initialize pool, and get pointers into memory + // + + RtlZeroMemory (WorkingPool, i); + CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool; + PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3); + PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2); + PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1); + + // + // Read the PCI device's configuration + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); +#if DBG // A002 + DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + BusNumber, Slot, 0, 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); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData->u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]); + } + } + DbgPrint("\n"); +#endif // A002 + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // Make a copy of the device's current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + // + // Initialize base addresses base on configuration data type + // + + switch (PCI_CONFIG_TYPE(PciData)) { + case 0 : + NoBaseAddress = PCI_TYPE0_ADDRESSES+1; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type0.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type0.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress; + RomIndex = j; + break; + case 1: + NoBaseAddress = PCI_TYPE1_ADDRESSES+1; + for (j=0; j < PCI_TYPE1_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type1.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type1.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress; + RomIndex = j; + break; + + default: + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // If the BIOS doesn't have the device's ROM enabled, then we won't + // enable it either. Remove it from the list. + // + + EnableRomBase = TRUE; +#if 0 //K003 + if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) { + ASSERT (RomIndex+1 == NoBaseAddress); + EnableRomBase = FALSE; + NoBaseAddress -= 1; + } +#endif + // + // Set resources to all bits on to see what type of resources + // are required. + // + + for (j=0; j < NoBaseAddress; j++) { + *BaseAddress[j] = 0xFFFFFFFF; + } + + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); +#if DBG // A002 + DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + BusNumber, Slot, 0, 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); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData->u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]); + } + } + DbgPrint("\n"); +#endif // A002 + + // 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; +#if DBG // A002 + DbgPrint("\nCmResourceTypeInterrupt: CmResourceShared\n"); + DbgPrint("CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE "); + DbgPrint("Min=%x Max=%x\n", Descriptor->u.Interrupt.MinimumVector, + Descriptor->u.Interrupt.MaximumVector); +#endif // A002 + 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)) { + goto CleanUp; + } + + // + // Slurp the assigments back into the PciData structure and + // perform them + // + + CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors; + + // + // If PCI device has an interrupt resource then that was + // passed in as the first requested resource + // + + if (PciData->u.type0.InterruptPin) { + PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector; + BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData); + CmDescriptor++; + } + + // + // Pull out resources in the order they were passed to IoAssignResources + // + + for (j=0; j < NoBaseAddress; j++) { + i = *BaseAddress[j]; + if (i) { + if (i & PCI_ADDRESS_IO_SPACE) { +#if defined (_R98_) // A002 +#if DBG + DbgPrint("Assigned: Port Address %x\n", CmDescriptor->u.Port.Start.LowPart); +#endif + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart | r98PCIIoBase[Slot]; +#if DBG + DbgPrint("Assign: Port Address %x\n", *BaseAddress[j]); +#endif +#else + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart; +#endif // _R98_ // ADD001 + } else { + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; +#if DBG // A002 + DbgPrint("Assign: memory Address %x\n", *BaseAddress[j]); +#endif // _R98_ // ADD001 + } + CmDescriptor++; + } + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + + // + // 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 (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + Match = FALSE; + } + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) { + i = (ULONG) ~0x3; + } else { + i = (ULONG) ~0xF; + } + + if ((*BaseAddress[j] & i) != + *((PULONG) ((PUCHAR) BaseAddress[j] - + (PUCHAR) PciData + + (PUCHAR) PciData2)) & i) { + + Match = FALSE; + } + + if (Is64BitBaseAddress(*BaseAddress[j])) { + // skip upper 32 bits + j++; + } + } + } + + if (!Match) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); +#endif + status = STATUS_DEVICE_PROTOCOL_ERROR; + goto CleanUp; + } + + // + // Settings took - turn on the appropiate decodes + // + + if (EnableRomBase && *BaseAddress[RomIndex]) { + // a rom address was allocated and should be enabled + *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig ( + BusHandler, + PciSlot, + BaseAddress[RomIndex], + (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData), + sizeof (ULONG) + ); + } + + // + // Enable IO, Memory, and BUS_MASTER decodes + // (use HalSetBusData since valid settings now set) + // + + PciData->Command |= PCI_ENABLE_IO_SPACE | + PCI_ENABLE_MEMORY_SPACE | + PCI_ENABLE_BUS_MASTER; + + HalSetBusDataByOffset ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + &PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (PciData->Command) + ); + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + if (*pAllocatedResources) { + IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + NULL, + NULL + ); + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + ExFreePool (WorkingPool); + return status; +} + +#if DBG +VOID +HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Note: This is reading the DeviceSpecific area of + // the device's configuration - normally this should + // only be done on device for which the caller understands. + // I'm doing it here only for debugging. + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + +#if 0 + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); +#endif + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.Command, PciData.Status, PciData.ProgIf, + PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + +#if 0 + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } +#endif + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + +#if 0 + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); +#endif + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} +#if defined (_R98_) // A002 +VOID +HalpTestPciNec (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag && bus < 1; bus++) { /* R98 Support Only 1 */ + + for (i = 0; i < 4; i++) { /* R98 Support Only 4 slots(include bridge) */ + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < 8; f++) { + SlotNumber.u.bits.FunctionNumber = f; + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, j); + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + HalpTestPciPrintResult((PULONG)&PciData, 1); + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData)); + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + PciData.u.type0.InterruptLine = 5; // For trial + DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific) + ); + HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH); + DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f); + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData)); + + DbgPrint ("--------------->>> Now Print the Slot Information\n"); + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.ProgIf, PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("We got the bridge\n"); + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + + // + // now print original data + // + DbgPrint ("--------------->>> Now Print the Original Slot Information\n"); + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f); + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); + HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData)); + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} + + +VOID +HalpTestPciPrintResult( + IN PULONG Buffer, + IN ULONG Length +) +{ + ULONG i, Lines, pchar; + + DbgPrint("----- I/O Data. (%d)byts.\n", Length); + + for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) { + DbgPrint("%08x: ", Lines); + for (i = 0; i < 4; pchar += 4, i++) { + if (pchar >= Length) + break; + DbgPrint("%08x ", *Buffer++); + } + DbgPrint("\n"); + } +} + +VOID +HalpOtherTestNec ( + IN ULONG doOtherTest +) +{ + if (!doOtherTest) + return; + + + DbgPrint("\n\n===== Additional Testing...\n"); + { + CM_EISA_SLOT_INFORMATION EisaSlotInfo; + PCM_EISA_SLOT_INFORMATION EisaBuffer; + PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo; + ULONG slot, funcs, Length; + + #define MAX_EISA_SLOT 4 + + DbgPrint("----- Read Eisa Configration:\n"); + for (slot = 0; slot < MAX_EISA_SLOT; slot++) { + Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo)); + if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) { + + // + // The data is messed up since this should never occur + // + + break; + } + Length = sizeof(CM_EISA_SLOT_INFORMATION) + + (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions); + EisaBuffer = ExAllocatePool(NonPagedPool, Length); + HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length); + // Print all Eisa Data + + EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION) + ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION)); + + DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot); + DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n", + EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags, + EisaBuffer->MajorRevision, EisaBuffer->MinorRevision); + DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n", + EisaBuffer->Checksum, + EisaBuffer->NumberFunctions, + EisaBuffer->FunctionInformation, + EisaBuffer->CompressedId); + for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) { + DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n", + EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1, + EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision, + EisaFunctionInfo->MajorRevision); + + // EisaFunctionInfo->Selections[26]; + // EisaFunctionInfo->FunctionFlags; + // EisaFunctionInfo->TypeString[80]; + // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9]; + // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7]; + // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4]; + // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20]; + // UCHAR EisaFunctionInfo->InitializationData[60]; + EisaFunctionInfo++; + } + + } + } + DbgBreakPoint (); + { + #define MEMORY_SPACE 0 + #define IO_SPACE 1 + PHYSICAL_ADDRESS cardAddress; + ULONG addressSpace = IO_SPACE; + PHYSICAL_ADDRESS PhysAddr; + + PhysAddr.LowPart = 0; + PhysAddr.HighPart = 0; + + + DbgPrint("----- \nTranslate Internal Bus Address(I/O): "); + HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Eisa Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Isa Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate PCI Bus Address(I/O): "); + addressSpace = IO_SPACE; + HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Internal Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Eisa Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate Isa Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + + DbgPrint("Translate PCI Bus Address(MEMORY): "); + addressSpace = MEMORY_SPACE; + HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress); + DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart); + } + DbgBreakPoint (); + + { + KAFFINITY affinity; + KIRQL Irql; + ULONG Vec; + + DbgPrint("----- \nGetInterruptVector internal\n"); + Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector Eisa\n"); + Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector Isa\n"); + Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + DbgPrint("GetInterruptVector PCI\n"); + Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity); + DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec); + + } + DbgBreakPoint (); +} +#endif // A002 + + + +#endif + diff --git a/private/ntos/nthals/halr98mp/mips/r98pcint.c b/private/ntos/nthals/halr98mp/mips/r98pcint.c new file mode 100644 index 000000000..d54acb3eb --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98pcint.c @@ -0,0 +1,384 @@ +#ident "@(#) NEC r98pcint.c 1.13 95/06/29 16:13:28" +/*++ + + +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: + + A001 1995/6/17 ataka@oa2.kb.nec.co.jp + - Marge 807-halr98mp-r98pciint.c to 1050 ixpciint.c + and named r98pcint.c + + K001 '95/6/29 Kugimoto@oa2 + - PPCIBUSDATA-->PPCIPBUSDATA +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +ULONG PciIsaIrq; +ULONG HalpEisaELCR; +BOOLEAN HalpDoingCrashDump; + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus) +#pragma alloc_text(PAGE,HalpAdjustPCIResourceList) +#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq) +#endif + + +ULONG +HalpGetPCIIntOnISABus ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ) +{ +#if defined(_R98_) // A001 + *Affinity = HalpPCIBusAffinity; + + *Irql = INT1_LEVEL; + return(PCI_DEVICE_VECTOR); + + if (BusInterruptLevel < 1) { + // bogus bus level + return 0; + } +#else + + // + // 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 + ); +#endif //_R98_ +} + + +VOID +HalpPCIPin2ISALine ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + + This function maps the device's InterruptPin to an InterruptLine + value. + + On the current PC implementations, the bios has already filled in + InterruptLine as it's ISA value and there's no portable way to + change it. + + On a DBG build we adjust InterruptLine just to ensure driver's + don't connect to it without translating it on the PCI bus. + +--*/ +{ + if (!PciData->u.type0.InterruptPin) { + return ; + } + +#if defined(_R98_) // A001 + PciData->u.type0.InterruptLine = PciData->u.type0.InterruptPin; +#else + // + // Set vector as a level vector. (note: this code assumes the + // irq is static and does not move). + // + + if (PciData->u.type0.InterruptLine >= 1 && + PciData->u.type0.InterruptLine <= 15) { + + // + // If this bit was on the in the PIC ELCR register, + // then mark it in PciIsaIrq. (for use in hal.dll, + // such that we can assume the interrupt controller + // has been properly marked as a level interrupt for + // this IRQ. Other hals probabily don't care.) + // + + PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine); + } + + // + // On a PC there's no Slot/Pin/Line mapping which needs to + // be done. + // + + PciData->u.type0.InterruptLine ^= IRQXOR; +#endif // _R98_ +} + + + +VOID +HalpPCIISALine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + On the current PC implementations, this information is + fixed by the BIOS. Just make sure the value isn't being + editted since PCI doesn't tell us how to dynically + connect the interrupt. + +--*/ +{ + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + +#if defined(_R98_) // A001 + PciNewData->u.type0.InterruptLine = PciOldData->u.type0.InterruptPin; +#else + PciNewData->u.type0.InterruptLine ^= IRQXOR; + +#if DBG + if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine || + PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) { + DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n"); + DbgBreakPoint (); + } +#endif +#endif // _R98_ +} + +#if !defined(SUBCLASSPCI) + +VOID +HalpPCIAcquireType2Lock ( + PKSPIN_LOCK SpinLock, + PKIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { + KeRaiseIrql (PROFILE_LEVEL, Irql); // A001 + KiAcquireSpinLock (SpinLock); + } else { + *Irql = HIGH_LEVEL; + } +} + + +VOID +HalpPCIReleaseType2Lock ( + PKSPIN_LOCK SpinLock, + KIRQL Irql + ) +{ + if (!HalpDoingCrashDump) { + KiReleaseSpinLock (SpinLock); + KeLowerIrql (Irql); // A001 + } +} + +#endif + + +halpPciMemoryLimit=64* 1024*1024; // K001 + + +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; + + // Start K000 A001 + PIO_RESOURCE_DESCRIPTOR Descriptor; + PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList; + PIO_RESOURCE_LIST InResourceList; + ULONG cnt,alt; + + InCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) *pResourceList; + InResourceList = InCompleteList->List; +#if DBG + DbgPrint("\n HalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit); +#endif + for (alt=0; alt < InCompleteList->AlternativeLists; alt++) { + + Descriptor = InResourceList->Descriptors; + + for (cnt = InResourceList->Count; cnt; cnt--) { + if( + Descriptor->Type==CmResourceTypeMemory + && halpPciMemoryLimit < (1024*1024*256-1) + ){ + halpPciMemoryLimit=( + ( halpPciMemoryLimit + +Descriptor->u.Memory.Length + +(Descriptor->u.Memory.Alignment-1) + ) & ~ (Descriptor->u.Memory.Alignment-1) + )-1; + + if(halpPciMemoryLimit >= (1024*1024*256-1)){ + halpPciMemoryLimit=(1024*1024*256-1); + } + + +#if DBG + DbgPrint("\n InHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit); + DbgPrint("\n Length= 0x%x\n",Descriptor->u.Memory.Length); + DbgPrint("\n Alignment= 0x%x\n",Descriptor->u.Memory.Alignment); +#endif + } + Descriptor++; + } + + } +#if DBG + DbgPrint("\n FixHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit); +#endif + // End of K001 A002 + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + BusHandler->BusAddresses->Memory.Limit = halpPciMemoryLimit; //K001 A002 + 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; + } + + // + // Adjust resources + // + + Status = HaliAdjustResourceListRange ( + BusHandler->BusAddresses, + Interrupt, + pResourceList + ); + + ExFreePool (Interrupt); + return Status; +} + + +NTSTATUS +HalpGetISAFixedPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ) +{ + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciData; +#if defined(_R98_) // A001 K001 + PPCIPBUSDATA BusData; +#endif // _R98_ + + + PciData = (PPCI_COMMON_CONFIG) buffer; + HalGetBusData ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + return STATUS_UNSUCCESSFUL; + } + + *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE)); + if (!*Interrupt) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE)); + (*Interrupt)->Base = 1; // base = 1, limit = 0 + + +#if defined(_R98_) // A001 + BusData = (PPCIPBUSDATA) BusHandler->BusData; + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); +#else + if (!PciData->u.type0.InterruptPin) { + return STATUS_SUCCESS; + } + + if (PciData->u.type0.InterruptLine == IRQXOR) { +#if DBG + DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n"); +#endif + // + // We need to let the caller continue, since the caller may + // not care that the interrupt vector is connected or not + // + + return STATUS_SUCCESS; + } +#endif // _R98_ + + (*Interrupt)->Base = PciData->u.type0.InterruptLine; + (*Interrupt)->Limit = PciData->u.type0.InterruptLine; + return STATUS_SUCCESS; +} diff --git a/private/ntos/nthals/halr98mp/mips/r98reg.h b/private/ntos/nthals/halr98mp/mips/r98reg.h new file mode 100644 index 000000000..d89d560bd --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/r98reg.h @@ -0,0 +1,475 @@ +#ident "@(#) NEC r98reg.h 1.8 95/02/20 17:25:49" +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Module Name: + + r98reg.h + +Abstract: + + This module is the header file that structure I/O registers for the r98. + +Author: + + +Revision History: + +--*/ + +/* + *********************************************************************** + * + * S001 6/10 T.Samezima + * + * Del Compile err + * + *********************************************************************** + * + * S002 6/10 T.Samezima + * + * Add I/O access macro + * + *********************************************************************** + * + * S003 7/5 T.Samezima + * + * Chg define miss + * structure define miss + *********************************************************************** + * + * S004 7/12 T.Samezima + * + * Chg structure define change + * + *********************************************************************** + * + * S005 7/14 T.Samezima + * + * Chg structure define change + * + *********************************************************************** + * + * S006 7/22 T.Samezima + * + * Add define IOB and SIC register dummy read macro + * (correspondence PMC3 bug) + * + * S007 12/24 T.Samezima + * Add define EIFR register define. + * + * S008 '95.1/7 T.Samezima + * Add define EIF0,STS2 register define. + * + * S009 '95.1/11 T.Samezima + * Del miss define + * + * + */ + +#ifndef _R98REG_ +#define _R98REG_ + +// +// Define PMC register structure. +// +typedef struct _PMC_REGISTER { + ULONG Long; + ULONG Fill; +} PMC_REGISTER, *PPMC_REGISTER; + +typedef struct _PMC_LARGE_REGISTER { +// Start S005 + ULONG High; + ULONG Low; +// End S005 +} PMC_LARGE_REGISTER, *PPMC_LARGE_REGISTER; + +typedef volatile struct _PMC_REGISTERS1 { + // offset(H) + PMC_LARGE_REGISTER IPR; // 0 + PMC_LARGE_REGISTER MKR; // 8 + PMC_LARGE_REGISTER IPRR; // 10 + PMC_REGISTER IPSR; // 18 + PMC_REGISTER MKRR; // 20 + PMC_REGISTER MKSR; // 28 + PMC_REGISTER NMIR; // 30 + PMC_REGISTER NMIRST; // 38 + PMC_REGISTER TMSR1; // 40 + PMC_REGISTER TMR1; // 48 + PMC_REGISTER TOVCT1; // 50 + PMC_REGISTER TMCR1; // 58 + PMC_REGISTER TMSR2; // 60 + PMC_REGISTER TMR2; // 68 + PMC_REGISTER TOVCT2; // 70 + PMC_REGISTER TMCR2; // 78 + PMC_REGISTER WDTSR; // 80 + PMC_REGISTER WDT; // 88 + PMC_REGISTER WDTCR; // 90 + PMC_REGISTER Reserved1[13]; // 98-F8 + PMC_REGISTER IntIR; // 100 + PMC_REGISTER Reserved2; // 108 + PMC_REGISTER TCIR; // 110 + PMC_REGISTER Reserved3[29]; // 118-1F8 + PMC_REGISTER CTAddr; // 200 + PMC_REGISTER CTData; // 208 + PMC_REGISTER CTCTL; // 210 + PMC_REGISTER EVCNT1H; // 218 + PMC_REGISTER EVCNT1L; // 220 + PMC_REGISTER EVCNTCR1; // 228 + PMC_REGISTER Reserved4[26]; // 230-2F8 + PMC_REGISTER CNFG; // 300 + PMC_REGISTER STSR; // 308 + PMC_REGISTER ERRRST; // 310 + PMC_REGISTER ERR; // 318 + PMC_REGISTER AERR; // 320 + PMC_REGISTER ERRMK; // 328 + PMC_REGISTER TOSR; // 330 + PMC_REGISTER EVCNT0H; // 338 + PMC_REGISTER EVCNT0L; // 340 + PMC_REGISTER EVCNTCR0; // 348 +} PMC_REGISTERS1, *PPMC_REGISTERS1; + +typedef volatile struct _PMC_REGISTERS2 { + // offset(H) + PMC_REGISTER RRMT0H; // 0 + PMC_REGISTER RRMT0L; // 8 + PMC_REGISTER RRMT1H; // 10 + PMC_REGISTER RRMT1L; // 18 + PMC_REGISTER RRMT2H; // 20 + PMC_REGISTER RRMT2L; // 28 + PMC_REGISTER RRMT3H; // 30 + PMC_REGISTER RRMT3L; // 38 + PMC_REGISTER RRMT4H; // 40 + PMC_REGISTER RRMT4L; // 48 + PMC_REGISTER RRMT5H; // 50 + PMC_REGISTER RRMT5L; // 58 + PMC_REGISTER RRMT6H; // 60 + PMC_REGISTER RRMT6L; // 68 + PMC_REGISTER RRMT7H; // 70 + PMC_REGISTER RRMT7L; // 78 + PMC_REGISTER Reserved1[2]; // 80-88 + PMC_REGISTER DISCON; // 90 + PMC_REGISTER Reserved2[3]; // 98-a8 + PMC_REGISTER EADRH; // b0 + PMC_REGISTER EADRL; // b8 + PMC_REGISTER Reserved3[2]; // c0-c8 + PMC_REGISTER RTYCNT; // d0 +} PMC_REGISTERS2, *PPMC_REGISTERS2; + +// +// Define pointer to PMC registers. +// +#define PMC_GLOBAL_CONTROL1 ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1)) +#define PMC_GLOBAL_CONTROL2 ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2)) +/* Start S002 */ +#define PMC_GLOBAL_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1 | (x) )) +#define PMC_GLOBAL_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2 | (x) )) +/* End S002 */ +/* Start S001 */ +#define PMC_CONTROL1 ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET)) +#define PMC_CONTROL2 ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET)) +/* End S001 */ +/* Start S002 */ +#define PMC_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET | (x) )) +#define PMC_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET | (x) )) +/* End S002 */ + +/* Start S006 */ +// +// Define dummy read macro. This macro use to not lead to time out of PMC +// + +#define IOB_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR) +#define SIC_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR) +/* End S006 */ + +// +// Define IOB register structure. +// +typedef struct _IOB_REGISTER { + ULONG Long; + ULONG Fill; +} IOB_REGISTER, *PIOB_REGISTER; + +typedef volatile struct _IOB_REGISTERS { + // offset(H) + IOB_REGISTER AIMR; // 0 + IOB_REGISTER AII0; // 8 + IOB_REGISTER AII1; // 10 + IOB_REGISTER AII2; // 18 + IOB_REGISTER AII3; // 20 + IOB_REGISTER AISR; // 28 + IOB_REGISTER ITRR; // 30 + IOB_REGISTER ADC0; // 38 + IOB_REGISTER ADC1; // 40 + IOB_REGISTER ADC2; // 48 + IOB_REGISTER ADC3; // 50 + IOB_REGISTER AMMD; // 58 + IOB_REGISTER ANMD; // 60 + IOB_REGISTER IERR; // 68 + IOB_REGISTER IEMR; // 70 + IOB_REGISTER IEER; // 78 + IOB_REGISTER AMAL; // 80 + IOB_REGISTER AMAH; // 88 + IOB_REGISTER ANAL; // 90 + IOB_REGISTER ANAH; // 98 + IOB_REGISTER AMRC; // a0 + IOB_REGISTER ANRC; // a8 + IOB_REGISTER AMRT; // b0 + IOB_REGISTER ANMT; // b8 + IOB_REGISTER ANST; // c0 + IOB_REGISTER Reserved1[7]; // c8-f8 + IOB_REGISTER ADG0; // 100 + IOB_REGISTER ADG1; // 108 + IOB_REGISTER CNTD; // 110 + IOB_REGISTER CNTE; // 118 + IOB_REGISTER CABS; // 120 + IOB_REGISTER CAWS; // 128 + IOB_REGISTER CTGL; // 130 + IOB_REGISTER CTGH; // 138 + IOB_REGISTER ARMS; // 140 + IOB_REGISTER ARML; // 148 + IOB_REGISTER ARMH; // 150 + IOB_REGISTER Reserved2[21]; // 158-1f8 + IOB_REGISTER SCFR; // 200 + IOB_REGISTER MPER; // 208 + IOB_REGISTER EIMR; // 210 + IOB_REGISTER EIFR; // 218 + IOB_REGISTER Reserved3[28]; // 220-2f8 +// DCDW; // 300 +// IOB_REGISTER ATCNF; // 400 +} IOB_REGISTERS, *PIOB_REGISTERS; + +// S007 vvv +// +// Define EIFR register +// +typedef struct _EIFR_REGISTER { + ULONG Reserved : 21; + ULONG MPDISCN : 1; + ULONG IOBERR : 1; + ULONG Reserved2 : 1; + ULONG EISANMI : 1; + ULONG LRERR : 1; + ULONG SIC1ERR : 1; + ULONG SIC0ERR : 1; + ULONG PMC3ERR : 1; + ULONG PMC2ERR : 1; + ULONG PMC1ERR : 1; + ULONG PMC0ERR : 1; +} EIFR_REGISTER, *PEIFR_REGISTER; +// S007 ^^^ + +// +// Define pointer to IOB registers. +// +#define IOB_CONTROL ((volatile PIOB_REGISTERS)(KSEG1_BASE | IOB_PHYSICAL_BASE)) + + +// +// Define SIC register structure. +// +typedef struct _SIC_REGISTER { + ULONG Long; + ULONG Fill; +} SIC_REGISTER, *PSIC_REGISTER; + +typedef volatile struct _SIC_ERR_REGISTERS { + // offset(H) + SIC_REGISTER EIF0; // 0 + SIC_REGISTER EIF1; // 8 + SIC_REGISTER CKE0; // 10 + SIC_REGISTER CKE1; // 18 + SIC_REGISTER SECT; // 20 + SIC_REGISTER Reserved; // 28 + SIC_REGISTER STS1; // 30 + SIC_REGISTER STS2; // 38 + SIC_REGISTER RSRG; // 40 +} SIC_ERR_REGISTERS, *PSIC_ERR_REGISTERS; + +typedef volatile struct _SIC_DATA_REGISTERS { + // offset(H) + SIC_REGISTER DPCM; // 0 + SIC_REGISTER DSRG; // 8 + SIC_REGISTER SDLM; // 10 +// SIC_REGISTER Reserved[3]; // 18-28 // S009 +// SIC_REGISTER SDCR; // 30 // S009 +} SIC_DATA_REGISTERS, *PSIC_DATA_REGISTERS; + +// S008 vvv +// +// Define EIF0 register +// +typedef struct _EIF0_REGISTER { + ULONG Reserved : 2; + ULONG EXTD0MBE : 1; + ULONG EXTD0SBE : 1; + ULONG Reserved1 : 1; + ULONG INTD0PTE : 1; + ULONG INTD0MBE : 1; + ULONG INTD0SBE : 1; + ULONG ICEC : 1; + ULONG CPEC : 1; + ULONG APEC : 1; + ULONG RE1C : 1; + ULONG RE0C : 1; + ULONG SREC : 1; + ULONG RSEC : 1; + ULONG DTEJ : 1; + ULONG RSEJ : 1; + ULONG USYC : 1; + ULONG Reserved2 : 4; + ULONG IRMC : 1; + ULONG IRRC : 1; + ULONG Reserved3 : 3; + ULONG SBE : 1; + ULONG DPCG : 1; + ULONG APCG : 1; + ULONG MPRG : 1; + ULONG SWRG : 1; +} EIF0_REGISTER, *PEIF0_REGISTER; + +// +// Define STS2 register +// +typedef struct _STS2_REGISTER { + ULONG COL0_9 : 10; + ULONG COL10 : 1; + ULONG LOW0_9 : 10; + ULONG LOW10 : 1; + ULONG Reserved : 2; + ULONG RW : 1; + ULONG EXTMBE0 : 1; + ULONG EXTSBE0 : 1; + ULONG MBE0 : 1; + ULONG SBE0 : 1; + ULONG SIMN : 1; + ULONG ARE : 2; +} STS2_REGISTER, *PSTS2_REGISTER; +// S008 ^^^ + +// +// Define pointer to SIC registers. +// +#define SIC_ERR_CONTROL ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET)) +#define SIC_DATA_CONTROL ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET)) +/* Start S002 */ +#define SIC_ERR_CONTROL_OR(x) ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET | (x) )) +#define SIC_DATA_CONTROL_OR(x) ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET | (x) )) +/* End S002 */ + +// +// Define LR4360 register structure. +// +typedef volatile struct _LR_REGISTERS1 { + /* Start S004 */ + // offset(H) + ULONG RSTC; // 0x0 + ULONG DPRC; // 0x4 + ULONG Reserved[1024]; // 0x8-0x1004 + ULONG ERRS; // 0x1008 + /* End S004 */ +} LR_REGISTERS1, *PLR_REGISTERS1; + +typedef volatile struct _LR_REGISTERS2 { + // offset(H) + ULONG iRPo; // 0 + ULONG iRED; // 4 + ULONG iRRE; // 8 + ULONG iREN; // c + ULONG iRSF; // 10 + ULONG iPoE; // 14 + ULONG Reserved0[2]; // 18-1c + ULONG iFGE; // 20 + ULONG iFGi; // 24 + ULONG iRCS0; // 28 + ULONG iRCS1; // 2c +} LR_REGISTERS2, *PLR_REGISTERS2; + +typedef volatile struct _LR_PCI_DEVICE_REGISTERS { + // offset(H) + ULONG PTBAR0; // 0 + ULONG PTBAR1; // 4 + ULONG PTBAR2; // 8 + ULONG PTBAR3; // c + ULONG PTBAR4; // 10 + ULONG PTBAR5; // 14 + ULONG PTBAR6; // 18 + ULONG PTBAR7; // 1c + ULONG PTSZR; // 20 + ULONG TPASZR; // 24 + ULONG TFLR; // 28 + ULONG PABAR; // 2c + ULONG AEAR; // 30 + ULONG PEAR; // 34 +} LR_PCI_DEVICE_REGISTERS, *PLR_PCI_DEVICE_REGISTERS; + +// +// Define Bbus LR4360 DMA channel register structure. +// +typedef struct _DMA_CHANNEL { // offset(H) + ULONG CnCF; // 0 + ULONG CnDF; // 4 + ULONG CnDC; // 8 + ULONG Reserved1; // c + ULONG CnMA; // 10 + ULONG CnBC; // 14 + ULONG CnAK; // 18 + ULONG CnFA; // 1c + ULONG CnCA; // 20 +} DMA_CHANNEL, *PDMA_CHANNEL; + +// +// Define Device Channel # DMA Configuration register (CnDF register) +// +typedef struct _LR_DMA_CONFIG { + ULONG SWAP :1; + ULONG ASET :1; + ULONG ACKP :1; + ULONG REQP :1; + ULONG EOPCF :2; + ULONG EOPHO :1; + ULONG BUOFF :1; + ULONG EDEDE :1; + ULONG EXEDi :1; + ULONG iNEDE :1; + ULONG iNEDi :1; + ULONG CPUTi :1; + ULONG Reserved1 :3; + ULONG TMODE :2; + ULONG Reserved2 :14; +} LR_DMA_CONFIG,*PLR_DMA_CONFIG; + +// +// Define Device Channel # DMA Control register (CnDC register) +// +typedef struct _LR_DMA_CONTROL { + ULONG REQiE :1; + ULONG REQii :1; + ULONG REQWE :1; + ULONG REQiS :1; + ULONG MEMWT :1; + ULONG MEMWE :1; + ULONG Reserved1:2; + ULONG EXEDS :1; + ULONG iNEDS :1; + ULONG CREQS :1; + ULONG CERRS :1; + ULONG BFiFo :4; + ULONG FiFoV :1; + ULONG FiFoD :1; + ULONG FiFoF :1; + ULONG CHACOM :1; + ULONG Reserved2 :12; +} LR_DMA_CONTROL,*PLR_DMA_CONTROL; + +// +// Define pointer to LR4360 registers. +// +#define LR_CONTROL1 ((volatile PLR_REGISTERS1)(KSEG1_BASE | LR_PHYSICAL_CMNBASE1)) +#define LR_CONTROL2 ((volatile PLR_REGISTERS2)(KSEG1_BASE | LR_PHYSICAL_CMNBASE2)) +#define LR_PCI_DEV_REG_CONTROL ((volatile PLR_PCI_DEVICE_REGISTERS)(KSEG1_BASE | LR_PHYSICAL_PCI_DEV_REG_BASE)) + +#endif // _R98REG_ diff --git a/private/ntos/nthals/halr98mp/mips/tga.h b/private/ntos/nthals/halr98mp/mips/tga.h new file mode 100644 index 000000000..a8db1925a --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/x86bios.c b/private/ntos/nthals/halr98mp/mips/x86bios.c new file mode 100644 index 000000000..4d65ad4e7 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/x86bios.c @@ -0,0 +1,2 @@ +#pragma comment(exestr, "@(#) x86bios.c 1.3 95/06/19 11:44:39 nec") +#include <..\..\halfxs\mips\x86bios.c> diff --git a/private/ntos/nthals/halr98mp/mips/xxcalstl.c b/private/ntos/nthals/halr98mp/mips/xxcalstl.c new file mode 100644 index 000000000..1ae682434 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/xxcalstl.c @@ -0,0 +1,290 @@ +#ident "@(#) NEC xxcalstl.c 1.4 94/10/17 11:57:45" +/*++ + +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 R3000 or R4000 system. + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/16-5/13 T.Samezima + * + * change HalpClockInterrupt0 vector + * HalpProfileInterrupt vector + * + * add PROFILE interrupt control + * + * del interrupt clear + * '#if defined(R3000)' with content + * only '#if defined(R4000)' + * + *********************************************************************** + * + * S002 94.03/16-5/13 T.Samezima + * + * Chg Designate member of structures + * + * S003 94.08/22 N.Kugimoto + * Chg Number 0 Bit Position is MSB (64Bit). So decremenet from 0x3f. + */ + + +#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 -= 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. + // + + /* Start S001 */ + PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt0; + /* End S001 */ + + // + // Write the compare register and clear the count register, and + // connect the profile interrupt. + // + + HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT); + /* Start S001 */ + PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt; + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO ); // S002 S003 + WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->TMCR2.Long, 0x3 ); // S002 + /* End S001 */ + + 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/halr98mp/mips/xxclock.c b/private/ntos/nthals/halr98mp/mips/xxclock.c new file mode 100644 index 000000000..51559bd63 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/xxclock.c @@ -0,0 +1,131 @@ +#ident "@(#) NEC xxclock.c 1.4 94/10/23 20:39:13" +/*++ + +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) + * + *********************************************************************** + * + * M001 94.05/31 T.Samezima + * + * add check timer increment value + * set value use from HalpClockInterrupt1 + * + * change increment unit from 1ms to 1us + * + * S002 '94.10/14 T.Samezima + * chg interval change flag + * + * S003 '94.10/23 T.Samezima + * chg variable size from ULONG to UCHAR + * + * + */ + + +#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; +/* Start M001 */ +UCHAR HalpChangeIntervalFlg[4]={0, 0, 0, 0}; // S003 +ULONG HalpChangeIntervalCount; +/* End M001 */ + +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; + + /* Start M001 */ + // + // 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; + } + /* End S001 */ + + // + // Raise IRQL to the highest level, set the new clock interrupt + // parameters, lower IRQl, and return the new time increment value. + // + + KeRaiseIrql(HIGH_LEVEL, &OldIrql); + /* Start M001 */ + NextIntervalCount = DesiredIncrement / 10; + NewTimeIncrement = NextIntervalCount * 10; + /* End M001 */ + HalpNextIntervalCount = NextIntervalCount; + HalpNewTimeIncrement = NewTimeIncrement; + /* Start M001 */ + HalpChangeIntervalFlg[1] = 0xff; // S002 + HalpChangeIntervalFlg[2] = 0xff; // S002 + HalpChangeIntervalFlg[3] = 0xff; // S002 + HalpChangeIntervalCount = HalpNextIntervalCount; + /* End M001 */ + KeLowerIrql(OldIrql); + return NewTimeIncrement; +} diff --git a/private/ntos/nthals/halr98mp/mips/xxidle.s b/private/ntos/nthals/halr98mp/mips/xxidle.s new file mode 100644 index 000000000..e202c795c --- /dev/null +++ b/private/ntos/nthals/halr98mp/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/halr98mp/mips/xxinithl.c b/private/ntos/nthals/halr98mp/mips/xxinithl.c new file mode 100644 index 000000000..917e97d75 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/xxinithl.c @@ -0,0 +1,660 @@ +#ident "@(#) NEC xxinithl.c 1.12 95/06/19 11:45:28" +/*++ + +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 R3000 or R4000 system. + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * S001 94.03/09 T.Samezima + * + * add Spinlock HalpEifInterruptLock + * + * del only '#if defined(_DUO_)' + * + * K001 '94.5/30 (Mon) N.Kugimoto + * Add allocate contigus phys memory for Internal device + * use buffer. + * + * S002 '94.6/02 T.Samezima + * + * Add call HalpRegisterNmi + * + * S003 '94.8/25 T.Samezima + * + * Chg Set Io address before initialize interrupt + * + * S004 '94.9/26 T.Samezima + * + * Add Merge PCI Source Code + * + * K002 94/10/11 N.Kugimoto + * Fix 807 Base + * K003 94/10/13 N.Kugimoto + * Chg HalpBugCheckBuffer -->HalpEifRegisterBuffer + * -1 Chg HalpBusError logic change + * K004 94/10/13 N.Kugimoto + * + * S005 '94.12/08 T.Samezima + * Add Disable NMI. + * + * A002 1995/6/17 ataka@oa2.kb.nec.co.jp + * - marge 1050 halx86 + * S006 1995/7/17 T.Samezima + * Del Init header. + */ + +#include "halp.h" + +// +// 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 + ); + +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalInitSystem) +#pragma alloc_text(INIT, HalInitializeProcessor) +#pragma alloc_text(INIT, HalStartNextProcessor) + +#endif + +// +// Define global spin locks used to synchronize various HAL operations. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; +/* Start S001 */ +KSPIN_LOCK HalpEifInterruptLock; +/* End S001 */ + + +// K002 vvvvv +// Define bug check information buffer and callback record. +// +#if !defined(_R98_) //K003 +typedef struct _HALP_BUGCHECK_BUFFER { + ULONG FailedAddress; + ULONG DiagnosticLow; + ULONG DiagnosticHigh; +} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER; + +HALP_BUGCHECK_BUFFER HalpBugCheckBuffer; +#endif + +KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord; + +UCHAR HalpComponentId[] = "hal.dll"; +// K002^^^^ + +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; + ULONG BuildType = 0; + //K002 vvvv + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS ZeroAddress; + ULONG AddressSpace; + //K002 ^^^^ + // + // Initialize the HAL components based on the phase of initialization + // and the processor number. + // + + Prcb = PCR->Prcb; + PCR->DataBusError = HalpBusError; //K002 + PCR->InstructionBusError = HalpBusError; //K002 + 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(); + + // + // If processor 0 is being initialized, then initialize various + // variables, spin locks, and the display adapter. + // + + if (Prcb->Number == 0) { + + + /* Start S002 */ + // + // Set NMI interrupt service routine + // + +#if !defined(DISABLE_NMI) // + HalpRegisterNmi(); +#endif + /* End S002 */ + + // + // Set the number of process id's and TB entries. + // + + **((PULONG *)(&KeNumberProcessIds)) = 256; + **((PULONG *)(&KeNumberTbEntries)) = 48; + + // + // Set the interval clock increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNextTimeIncrement = MAXIMUM_INCREMENT; + HalpNextIntervalCount = 0; + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // A002 + // 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); + /* Start S001 */ + KeInitializeSpinLock(&HalpEifInterruptLock); + /* End S001 */ + + // + // Set address of cache error routine. + // + + KeSetCacheErrorRoutine(HalpCacheErrorRoutine); + + // + // Initialize the display adapter. + // + + HalpInitializeDisplay0(LoaderBlock); + + // + // Allocate map register memory. + // + + HalpAllocateMapRegisters(LoaderBlock); + + // K001 Start + // For Internal Device use buffer + // + HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE; + + // + // Allocate map buffers for the adapter objects + // + + HalpMapBufferPhysicalAddress.LowPart = + HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS, + HalpMapBufferSize >> PAGE_SHIFT, TRUE); + HalpMapBufferPhysicalAddress.HighPart = 0; + + + if (!HalpMapBufferPhysicalAddress.LowPart) { + + // + // There was not a satisfactory block. Clear the allocation. + // + + HalpMapBufferSize = 0; + + } // End of K001 + // K002 vvvv + // Initialize and register a bug check callback record. + // + + KeInitializeCallbackRecord(&HalpCallbackRecord); + KeRegisterBugCheckCallback(&HalpCallbackRecord, + HalpBugCheckCallback, +#if defined(_R98_) //K003 + HalpEifRegisterBuffer, +#else + &HalpBugCheckBuffer, +#endif + 41*4, //K003 + &HalpComponentId[0]); + + // K002 ^^^^ + + } + + // Start S003 +#if defined(_R98_) + // + // Initialize I/O address + // + + HalpMapIoSpace(); +#endif + // End S003 + + // + // 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 (); // A002 + + if (HalpInitializeDisplay1(LoaderBlock) == FALSE) { + return FALSE; + + } else { + + // + // Map I/O space, calibrate the stall execution scale factor, + // and create DMA data structures. + // + + // Start S003 +#if !defined(_R98_) + HalpMapIoSpace(); +#endif + // End S003 + HalpCalibrateStall(); + HalpCreateDmaStructures(); + + // K002 vvvvv + // 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); + + HalpInitializeX86DisplayAdapter(); + + // K002 ^^^^^ + + return TRUE; + } + } +} + +//K002 vvvv +// 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. + +--*/ + +{ + +#if !defined(_R98_) //K003 + PHALP_BUGCHECK_BUFFER DumpBuffer; + + // + // Capture the failed memory address and diagnostic registers. + // + + DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer; + +#if defined(_DUO_) + + DumpBuffer->DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long; + + DumpBuffer->DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart; + +#else + + DumpBuffer->DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long; + + DumpBuffer->DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long; + +#endif + + DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; +#endif //_R98_ + return; +} + +BOOLEAN +HalpBusError ( + IN PEXCEPTION_RECORD ExceptionRecord, + IN PKEXCEPTION_FRAME ExceptionFrame, + IN PKTRAP_FRAME TrapFrame, + IN PVOID VirtualAddress, + IN PHYSICAL_ADDRESS PhysicalAddress + ) + +/*++ + +Routine Description: + + This function provides the default bus error handling routine for NT. + + N.B. There is no return from this routine. + +Arguments: + + ExceptionRecord - Supplies a pointer to an exception record. + + ExceptionFrame - Supplies a pointer to an exception frame. + + TrapFrame - Supplies a pointer to a trap frame. + + VirtualAddress - Supplies the virtual address of the bus error. + + PhysicalAddress - Supplies the physical address of the bus error. + +Return Value: + + None. + +--*/ + +{ + + ULONG DiagnosticHigh; + ULONG DiagnosticLow; +#if !defined(_R98_) //K003-1 + ULONG FailedAddress; + + + // + // Bug check specifying the exception code, the virtual address, the + // failed memory address, and either the ECC diagnostic registers or + // the parity diagnostic registers depending on the platform. + // + +#if defined(_DUO_) + + DiagnosticLow = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long; + + DiagnosticHigh = + (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart; + +#else + + DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long; + DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long; + +#endif + + FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long; +#else //_R98_ + ULONG AllError; + DiagnosticLow =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRL.Long); + DiagnosticHigh =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRH.Long); + AllError =READ_REGISTER_ULONG(&( PMC_CONTROL1 )->AERR.Long); //K003 +#endif + + KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff, + (ULONG)VirtualAddress, +#if defined(_R98_) //K003 + AllError, +#else + FailedAddress, +#endif + DiagnosticLow, + + DiagnosticHigh); + + return FALSE; +} + +//K002 ^^^^ + +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; + } + + 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/halr98mp/mips/xxinitnt.c b/private/ntos/nthals/halr98mp/mips/xxinitnt.c new file mode 100644 index 000000000..ad3750771 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/xxinitnt.c @@ -0,0 +1,556 @@ +#ident "@(#) NEC xxinitnt.c 1.18 95/03/17 11:59:37" +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + xxinitnt.c + +Abstract: + + + This module implements the interrupt initialization for a MIPS R3000 + or R4000 system. + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * L001 94.03/22-5/13 T.Samezima + * + * add control of Eif interrupt. + * make table of change from iRRE bit number to NABus code. + * make table of arbitration table and arbitration pointer. + * make variable for access of registers. + * connect the timer interrupt service routine. + * clear unknown interrupt counter + * + * del only '#if defined(_DUO_)' + * '#if defined(_JAZZ_)' with content + * HalpCountInterrupt() + * + * change interrupt control + * various vector of interrupt service routine + * + *********************************************************************** + * + * S002 94.5/17 T.Samezima + * + * del Arbitration table + * + *********************************************************************** + * + * S003 94.6/10-14 T.Samezima + * + * del Compile err + * + *********************************************************************** + * + * S004 94.7/7 T.Samezima + * + * Chg Use UNKNOWN_COUNT_BUF_LEN to max + * for HalpUnknownInterruptCount + * + *********************************************************************** + * + * S005 94.7/7 T.Samezima + * + * Del move interrupt arbitration pointer to r98dspt.c + * + *********************************************************************** + * + * S006 94.7/23 T.Samezima + * + * Add Enable EIF interrupt on SIC. + * + *********************************************************************** + * + * S007 94.8/22 T.Samezima on SNES + * + * Chg Register buffer size from USHORT to ULONG + * Value of set to MKSR register + * Condition change + * + * Add Clear interrupt pending bit on edge level interrupt + * + * Del Move EISA NMI enable logic to HalpCreateEisaStructure() + * + *********************************************************************** + * + * S008 94.9/5 T.Samezima + * + * Add Institute number of repeat for interrupt clear loop + * + *********************************************************************** + * + * S009 94.9/16 T.Samezima + * + * Chg Only CPU#0 on I/O Initerrupt clear + * + *********************************************************************** + * + * S00a 94.10/14 T.Samezima + * + * Fix Version Up at build807 + * -Move Int1 interrupt enable to allstart.c + * + * S00b 94.10/18 T.Samezima + * Chg Enable interrupt on MKR register only exist device, + * + * S00c 94.12/06 T.Samezima + * Bug Disable ECC 1bit error interrupt. + * + * S00d 94.12/06 T.Samezima + * Add Disable NMI + * + * S00e 95.01/10 T.Samezima + * Add Enable ECC 1bit error interrupt + * Rewrite cycle start on ecc 1bit error + * + * S00f 95.01/24 T.Samezima + * Add Disable rewrite cycle on ecc 1bit error + * + * S010 95.03/13 T.Samezima + * Add Enable HW cache flush. + * + */ + +#include "halp.h" +#include "eisa.h" // S003 + + +// +// 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 + +// +// Define global data for builtin device interrupt enables. +// + +ULONG HalpBuiltinInterruptEnable; // S007 + +// +// 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 + +/* Start L001 */ +// +// Define table of change from iRRE bit number to NABus code +// +ULONG HalpNaBusCodeTable[] = {0x8000, 0x0010, // iRRE bit0,1 + 0x0006, 0x0000, // iRRE bit2,3 + 0x0002, 0x0002, // iRRE bit4,5 + 0x000a, 0x000a, // iRRE bit6,7 + 0x0008, 0x000c, // iRRE bit8,9 + 0x8000, 0x8000, // iRRE bit10,11 + 0x8000, 0x8000, // iRRE bit12,13 + 0x8000, 0x8000, // iRRE bit14,15 + 0x8000, 0x0004, // iRRE bit16,17 + 0x8000, 0x8000, // iRRE bit18,19 + 0x8000, 0x8000, // iRRE bit20,21 + 0x000c, 0x8000, // iRRE bit22,23 + 0x8000, 0x8000, // iRRE bit24,25 + 0x8000, 0x8000, // iRRE bit26,27 + 0x8000, 0x8000, // iRRE bit28,29 + 0x8000, 0x8000 }; // iRRE bit30,31 + +// +// Define table of order of interrupt arbitration +// + +ULONG HalpUnknownInterruptCount[UNKNOWN_COUNT_BUF_LEN]; // S004 + +/* End L001*/ + + +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. + +--*/ + +{ + + USHORT DataShort; + ULONG DataLong; + ULONG Index; + PKPRCB Prcb; + /* Start L001 */ + ULONG pmcRegisterAddr; + ULONG pmcRegisterUpperPart; + ULONG pmcRegisterLowerPart; + ULONG bitCount; + ULONG buffer; + ULONG buffer2; // S006 + UCHAR charBuffer; + LONG repeatCounter; // S008 + /* End L001 */ + + // + // 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. + // + + 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]; + } + + /* Start L001 */ + // + // All interrupt disables. + // + + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003 + pmcRegisterUpperPart = MKR_DISABLE_ALL_INTERRUPT_HIGH; + pmcRegisterLowerPart = MKR_DISABLE_ALL_INTERRUPT_LOW; + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + // + // If processor 0 is being initialized, then set all device + // interrupt disables. + // + + if (Prcb->Number == 0) { + HalpBuiltinInterruptEnable = iREN_DISABLE_ALL_INTERRUPT; + + for (Index = 0; Index < UNKNOWN_COUNT_BUF_LEN; Index += 1) { // S004 + HalpUnknownInterruptCount[Index] = 0; + } +// } // S009 + /* End L001 */ + + // + // Disable individual device interrupts and make sure no device interrupts + // are pending. + // + + /* Start L001 */ + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, + HalpBuiltinInterruptEnable ); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long, + EIMR_DISABLE_ALL_EIF ); + + repeatCounter = 0; // S008 + + while( ((DataLong = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE) & iRRE_MASK) != 0) && + (++repeatCounter < 16) ) { // S008 + for( bitCount = 0 ; bitCount <= 31 ; bitCount++ ) { + if( (DataLong & ( 1 << bitCount )) != 0) { + // Start S007 + if( bitCount < 15 ){ + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF, + ( 1 << bitCount ) ); + } + // End S007 + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AIMR.Long, + HalpNaBusCodeTable[bitCount] ); + } + } + WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF, + iRSF_CLEAR_INTERRUPT ); + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->IPRR ); // S003 + pmcRegisterUpperPart = 0x0; + pmcRegisterLowerPart = 0xffffffff; + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + } + /* End L001 */ + + HalpBuiltinInterruptEnable |= 0x10; // S010 + + // + // If processor 0 is being initialized, then enable device interrupts. + // + +// if (Prcb->Number == 0) { // S009 + /* Start L001 */ + // + // Enable INT0-1 interrupt on PMC + // + + /* Start S003 */ + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII0.Long, + AII_INIT_DATA ); + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long, + AII_INIT_DATA ); + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long, + AII_INIT_DATA ); + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII3.Long, + AII_INIT_DATA ); + /* End S003 */ + + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003 + HalpReadLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + pmcRegisterLowerPart = ( pmcRegisterLowerPart + | MKR_INT0_DEVICE_ENABLE_LOW // S00b +// | MKR_INT1_DEVICE_ENABLE_LOW // S00a, S00b + | MKR_INT2_DEVICE_ENABLE_LOW // S00b + ); // S003 + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + +// DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long); +// DataLong |= ENABLE_DEVICE_INTERRUPTS; +// WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long, +// DataLong); + /* End L001 */ + } + + /* Start L001 */ + // + // Connect the eif interrupt to the eif interrupt routine + // + + PCR->InterruptRoutine[EIF_LEVEL] = HalpEifDispatch; + + // + // Enable the eif interrupt + // + + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003 + HalpReadLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT5_ENABLE_HIGH ); + pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT5_ENABLE_LOW ); + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + + buffer = READ_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long); + buffer = (buffer | STSR_EIF_ENABLE); +#if defined(DISABLE_NMI) // S00d + buffer = (buffer | STSR_NMI_DISABLE); +#endif + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long, buffer); + + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->ERRMK.Long, ERRMK_EIF_ENABLE); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->IEMR.Long, IEMR_ENABLE_ALL_EIF); + + WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long, EIMR_ENABLE_ALL_EIF); + + /* Start S006 */ + buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long ); + IOB_DUMMY_READ; + + if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S007 + buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO0_OFFSET))->CKE0.Long ); + buffer2 &= CKE0_DISABLE_SBE; // S00c + buffer2 |= CKE0_ENABLE_ALL_EIF; + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE0.Long, + buffer2 + ); + // S00e vvv + buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO0_OFFSET))->DPCM.Long ); + buffer2 &= DPCM_ENABLE_MASK; // S00c + WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET0_OFFSET) )->DPCM.Long, + buffer2 + ); + +#if 0 // S00f + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->SECT.Long, + SECT_REWRITE_ENABLE + ); +#endif + // S00e ^^^ + + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE1.Long, + CKE1_ENABLE_ALL_EIF + ); + } + + if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S007 + buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO2_OFFSET))->CKE0.Long ); + buffer2 &= CKE0_DISABLE_SBE; // S00c + buffer2 |= CKE0_ENABLE_ALL_EIF; + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE0.Long, + buffer2 + ); + // S00e vvv + buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO2_OFFSET))->DPCM.Long ); + buffer2 &= DPCM_ENABLE_MASK; // S00c + WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET1_OFFSET) )->DPCM.Long, + buffer2 + ); +#if 0 // S00f + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->SECT.Long, + SECT_REWRITE_ENABLE + ); +#endif + // S00e ^^^ + + WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE1.Long, + CKE1_ENABLE_ALL_EIF + ); + } + /* End S006 */ + + // S007 + + // + // 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. + // + + PCR->InterruptRoutine[TIMER_LEVEL] = HalpTimerDispatch; // S003 + + if (Prcb->Number == 0) { + /* Start L001 */ + PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt; + /* End L001 */ + } else { + /* Start L001 */ + PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1; + /* End L001 */ + PCR->StallScaleFactor = HalpStallScaleFactor; + } + + // + // Initialize the interval timer to interrupt at the specified interval. + // + + /* Start L001 */ + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR1.Long, CLOCK_INTERVAL); + + // + // Initialize the profile timer to interrupt at the default interval. + // + + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, + DEFAULT_PROFILETIMER_COUNT); + /* End L001 */ + + // + // Enable the interval timer interrupt on the current processor. + // + + /* Start L001 */ + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_CLOCK_BIT_NO); // S007 + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR1.Long, 0x3); + /* End L001 */ + + // + // 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. + // + + /* Start L001 */ + if (Prcb->Number != 0) { + PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt; + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO); // S007 + WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3); + } + /* End L001 */ + + // + // Connect the interprocessor interrupt service routine and enable + // interprocessor interrupts. + // + + PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt; + + /*Start L001 */ + pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003 + HalpReadLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT4_ENABLE_HIGH ); + pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT4_ENABLE_LOW ); + HalpWriteLargeRegister( pmcRegisterAddr, + &pmcRegisterUpperPart, + &pmcRegisterLowerPart ); + /*End L001 */ + + // + // Reserve the local device interrupt vector for exclusive use by the HAL. + // + + + /* Start L001 */ +// PCR->ReservedVectors |= (1 << DEVICE_LEVEL); +// PCR->ReservedVectors |= (1 << INT1_LEVEL); // S00a + PCR->ReservedVectors |= (1 << INT2_LEVEL); + /* End L001 */ + + return TRUE; +} diff --git a/private/ntos/nthals/halr98mp/mips/xxmemory.c b/private/ntos/nthals/halr98mp/mips/xxmemory.c new file mode 100644 index 000000000..bd7dba343 --- /dev/null +++ b/private/ntos/nthals/halr98mp/mips/xxmemory.c @@ -0,0 +1,184 @@ +#pragma comment(exestr, "@(#) xxmemory.c 1.3 94/10/17 13:25:21 nec") +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + xxmemory.c + +Abstract: + + Provides routines to allow the HAL to map physical memory. + +Environment: + + Phase 0 initialization only. + +Revision History: + +--*/ + +/* + * Original source: Build Number 1.612 + * + * Modify for R98(MIPS/R4400) + * + *********************************************************************** + * + * K001 '94.5/30 (Mon) N.Kugimoto + * FRM HalpAllocPhysicalMemory() From halx86 + * + *********************************************************************** + * + * S001 '94.6/14 T.Samezima + * Chg Compile err del + * + * + */ + +#include "halp.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpAllocPhysicalMemory) +#endif + +// S001 +MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor; + +ULONG +HalpAllocPhysicalMemory( + IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN ULONG MaxPhysicalAddress, + IN ULONG NoPages, + IN BOOLEAN bAlignOn64k + ) +/*++ + +Routine Description: + + Carves out N pages of physical memory from the memory descriptor + list in the desired location. This function is to be called only + during phase zero initialization. (ie, before the kernel's memory + management system is running) + +Arguments: + + MaxPhysicalAddress - The max address where the physical memory can be + NoPages - Number of pages to allocate + +Return Value: + + The physical address or NULL if the memory could not be obtained. + +--*/ +{ + PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; + PLIST_ENTRY NextMd; + ULONG AlignmentOffset; + ULONG MaxPageAddress; + ULONG PhysicalAddress; + + MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT; + + // + // 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); + + AlignmentOffset = bAlignOn64k ? + ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage : + 0; + + // + // 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 >= NoPages + AlignmentOffset) && + (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) { + + PhysicalAddress = + (Descriptor->BasePage + AlignmentOffset) << 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 (ULONG)NULL; + + // + // Adjust the memory descriptors. + // + + if (AlignmentOffset == 0) { + + Descriptor->BasePage += NoPages; + Descriptor->PageCount -= NoPages; + + if (Descriptor->PageCount == 0) { + + // + // The whole block was allocated, + // Remove the entry from the list completely. + // + + RemoveEntryList(&Descriptor->ListEntry); + + } + + } else { + + if (Descriptor->PageCount - NoPages - AlignmentOffset) { + + // + // Currently we only allow one Align64K allocation + // + ASSERT (HalpExtraAllocationDescriptor.PageCount == 0); + + // + // The extra descriptor is needed so intialize it and insert + // it in the list. + // + HalpExtraAllocationDescriptor.PageCount = + Descriptor->PageCount - NoPages - AlignmentOffset; + + HalpExtraAllocationDescriptor.BasePage = + Descriptor->BasePage + NoPages + AlignmentOffset; + + HalpExtraAllocationDescriptor.MemoryType = MemoryFree; + InsertTailList( + &Descriptor->ListEntry, + &HalpExtraAllocationDescriptor.ListEntry + ); + } + + + // + // Use the current entry as the descriptor for the first block. + // + + Descriptor->PageCount = AlignmentOffset; + } + + return PhysicalAddress; +} -- cgit v1.2.3