diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halmca/i386 | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halmca/i386')
49 files changed, 3458 insertions, 0 deletions
diff --git a/private/ntos/nthals/halmca/i386/halnls.h b/private/ntos/nthals/halmca/i386/halnls.h new file mode 100644 index 000000000..e829faba8 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/halnls.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\halnls.h" diff --git a/private/ntos/nthals/halmca/i386/halp.h b/private/ntos/nthals/halmca/i386/halp.h new file mode 100644 index 000000000..a9dbf1e13 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/halp.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\halp.h" diff --git a/private/ntos/nthals/halmca/i386/ix8259.inc b/private/ntos/nthals/halmca/i386/ix8259.inc new file mode 100644 index 000000000..b9e0a196a --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ix8259.inc @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ix8259.inc diff --git a/private/ntos/nthals/halmca/i386/ixbeep.asm b/private/ntos/nthals/halmca/i386/ixbeep.asm new file mode 100644 index 000000000..f53bd3e58 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixbeep.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixbeep.asm diff --git a/private/ntos/nthals/halmca/i386/ixbusdat.c b/private/ntos/nthals/halmca/i386/ixbusdat.c new file mode 100644 index 000000000..a42039752 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixbusdat.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixbusdat.c" diff --git a/private/ntos/nthals/halmca/i386/ixclock.asm b/private/ntos/nthals/halmca/i386/ixclock.asm new file mode 100644 index 000000000..fa1155436 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixclock.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixclock.asm diff --git a/private/ntos/nthals/halmca/i386/ixcmos.asm b/private/ntos/nthals/halmca/i386/ixcmos.asm new file mode 100644 index 000000000..7f4e7393e --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixcmos.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixcmos.asm diff --git a/private/ntos/nthals/halmca/i386/ixcmos.inc b/private/ntos/nthals/halmca/i386/ixcmos.inc new file mode 100644 index 000000000..2fe289fb0 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixcmos.inc @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixcmos.inc diff --git a/private/ntos/nthals/halmca/i386/ixdat.c b/private/ntos/nthals/halmca/i386/ixdat.c new file mode 100644 index 000000000..f6b0e34de --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixdat.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixdat.c" diff --git a/private/ntos/nthals/halmca/i386/ixenvirv.c b/private/ntos/nthals/halmca/i386/ixenvirv.c new file mode 100644 index 000000000..e194820ba --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixenvirv.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixenvirv.c" diff --git a/private/ntos/nthals/halmca/i386/ixfirm.c b/private/ntos/nthals/halmca/i386/ixfirm.c new file mode 100644 index 000000000..f666e405c --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixfirm.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixfirm.c" diff --git a/private/ntos/nthals/halmca/i386/ixhwsup.c b/private/ntos/nthals/halmca/i386/ixhwsup.c new file mode 100644 index 000000000..ea91dc8d0 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixhwsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixhwsup.c" diff --git a/private/ntos/nthals/halmca/i386/ixidle.asm b/private/ntos/nthals/halmca/i386/ixidle.asm new file mode 100644 index 000000000..9bdd670f3 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixidle.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixidle.asm diff --git a/private/ntos/nthals/halmca/i386/ixinfo.c b/private/ntos/nthals/halmca/i386/ixinfo.c new file mode 100644 index 000000000..7f211f7a9 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixinfo.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixinfo.c" diff --git a/private/ntos/nthals/halmca/i386/ixipi.asm b/private/ntos/nthals/halmca/i386/ixipi.asm new file mode 100644 index 000000000..17eea3bf1 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixipi.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixipi.asm diff --git a/private/ntos/nthals/halmca/i386/ixisa.h b/private/ntos/nthals/halmca/i386/ixisa.h new file mode 100644 index 000000000..f67b35f49 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixisa.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisa.h" diff --git a/private/ntos/nthals/halmca/i386/ixisabus.c b/private/ntos/nthals/halmca/i386/ixisabus.c new file mode 100644 index 000000000..c1edfb067 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixisabus.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisabus.c" diff --git a/private/ntos/nthals/halmca/i386/ixisasup.c b/private/ntos/nthals/halmca/i386/ixisasup.c new file mode 100644 index 000000000..58c426544 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixisasup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixisasup.c" diff --git a/private/ntos/nthals/halmca/i386/ixkdcom.c b/private/ntos/nthals/halmca/i386/ixkdcom.c new file mode 100644 index 000000000..29bb8308e --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixkdcom.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixkdcom.c" diff --git a/private/ntos/nthals/halmca/i386/ixkdcom.h b/private/ntos/nthals/halmca/i386/ixkdcom.h new file mode 100644 index 000000000..22f1aac09 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixkdcom.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixkdcom.h" diff --git a/private/ntos/nthals/halmca/i386/ixmca.h b/private/ntos/nthals/halmca/i386/ixmca.h new file mode 100644 index 000000000..e96b1064e --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixmca.h @@ -0,0 +1,113 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + imhalp.h + +Abstract: + + This header file defines the private Hardware Architecture Layer (HAL) + MCA specific interfaces, defines and structures. + +Author: + + Jeff Havens (jhavens) 20-Jun-91 + + +Revision History: + +--*/ + +#ifndef _IXMCA_ +#define _IXMCA_ + +#include "mca.h" + + +// +// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system +// will allocate for devices which require phyically contigous buffers. +// + +#define MAXIMUM_MAP_BUFFER_SIZE 0x40000 + +// +// Define the initial buffer allocation size for a map buffers for systems with +// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS. +// + +#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000 + +// +// Define the initial buffer allocation size for a map buffers for systems with +// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS. +// + +#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000 + +// +// Define the incremental buffer allocation for a map buffers. +// + +#define INCREMENT_MAP_BUFFER_SIZE 0x10000 + +// +// Define the maximum number of map registers that can be requested at one time +// if actual map registers are required for the transfer. +// + +#define MAXIMUM_MCA_MAP_REGISTER 16 + +// +// Define the maximum physical address which can be handled by an Isa card. +// + +#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000 + +// +// Define the scatter/gather flag for the Map Register Base. +// + +#define NO_SCATTER_GATHER 0x00000001 + +// +// Define the copy buffer flag for the index. +// + +#define COPY_BUFFER 0XFFFFFFFF + +// +// Define adapter object structure. +// + +typedef struct _ADAPTER_OBJECT { + CSHORT Type; + CSHORT Size; + struct _ADAPTER_OBJECT *MasterAdapter; + ULONG MapRegistersPerChannel; + PVOID AdapterBaseVa; + PVOID MapRegisterBase; + ULONG NumberOfMapRegisters; + ULONG CommittedMapRegisters; + struct _WAIT_CONTEXT_BLOCK *CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + KSPIN_LOCK SpinLock; + PRTL_BITMAP MapRegisters; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + DMA_EXTENDED_MODE ExtendedModeFlags; + USHORT DmaPortAddress; + UCHAR AdapterMode; + BOOLEAN NeedsMapRegisters; + BOOLEAN MasterDevice; + BOOLEAN Width16Bits; + BOOLEAN ScatterGather; + BOOLEAN Dma32BitAddresses; +} ADAPTER_OBJECT; + + +#endif // _IXMCA_ diff --git a/private/ntos/nthals/halmca/i386/ixmcabus.c b/private/ntos/nthals/halmca/i386/ixmcabus.c new file mode 100644 index 000000000..82cc981cd --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixmcabus.c @@ -0,0 +1,117 @@ +/*++ +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixmcabus.c + +Abstract: + +Author: + +Environment: + +Revision History: + +--*/ + +#include "halp.h" + +extern KSPIN_LOCK HalpSystemHardwareLock; + +ULONG +HalpGetPosData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG DOffset, + IN ULONG Length + ) +{ + ULONG DataLength = 0; + ULONG Offset = 0; + ULONG Index = 0; + PUCHAR DataBuffer = Buffer; + PVOID McaRegisterBase = 0; + PUCHAR PosBase; + KIRQL Irql; + PHYSICAL_ADDRESS BusAddress; + BOOLEAN Status; + ULONG AddressSpace; + + + if (DOffset != 0) { + // bugbug: should support this + return 0; + } + + // + // Translate the Mca Base port for this MCA bus + // + + BusAddress.LowPart = (ULONG) McaRegisterBase; + BusAddress.HighPart = 0; + AddressSpace = 1; // I/O space + Status = BusHandler->TranslateBusAddress( + BusHandler, + RootHandler, + BusAddress, + &AddressSpace, // I/O Space + &BusAddress); + + if (Status == FALSE || AddressSpace != 1) { + return 0; + } + + McaRegisterBase = (PVOID) BusAddress.LowPart; + + PosBase = (PUCHAR) &((PMCA_CONTROL) McaRegisterBase)->Pos; + + Irql = KfAcquireSpinLock(&HalpSystemHardwareLock); + + // + // Place the specified adapter into setup mode. + // + + WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup, + (UCHAR) ( MCA_ADAPTER_SETUP_ON | SlotNumber )); + + while (DataLength < Length && DataLength < 6) { + DataBuffer[DataLength] = READ_PORT_UCHAR( PosBase + DataLength ); + DataLength++; + } + + while (DataLength < Length) { + + WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT) + PosBase)->SubaddressExtensionLsb, (UCHAR) Index); + + WRITE_PORT_UCHAR((PVOID) &((PPROGRAMMABLE_OPTION_SELECT) + PosBase)->SubaddressExtensionMsb, (UCHAR) (Index >> 8)); + + DataBuffer[Index + 6] = READ_PORT_UCHAR( + (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData2); + + DataLength++; + + if (DataLength < Length) { + Offset = DataLength + ((Length - DataLength) / 2); + DataBuffer[Offset] = READ_PORT_UCHAR( + (PVOID) &((PPROGRAMMABLE_OPTION_SELECT)PosBase)->OptionSelectData3); + DataLength++; + Index++; + } + } + + // + // Disable adapter setup. + // + + WRITE_PORT_UCHAR((PVOID) &((PMCA_CONTROL) McaRegisterBase)->AdapterSetup, + (UCHAR) ( MCA_ADAPTER_SETUP_OFF )); + + + KfReleaseSpinLock( &HalpSystemHardwareLock, Irql ); + return DataLength; +} diff --git a/private/ntos/nthals/halmca/i386/ixmcasup.c b/private/ntos/nthals/halmca/i386/ixmcasup.c new file mode 100644 index 000000000..6e5f3f105 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixmcasup.c @@ -0,0 +1,1344 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixmcasup.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: + + Modified for MCA support - Bill Parry (o-billp) 22-Jul-1991 + +--*/ + +#define MCA 1 +#include "halp.h" + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalGetAdapter) +#endif + +// +// The HalpNewAdapter event is used to serialize allocations +// of new adapter objects, additions to the HalpMCAAdapter +// array, and some global values (MasterAdapterObject) and some +// adapter fields modified by HalpGrowMapBuffers. +// (AdapterObject->NumberOfMapRegisters is assumed not to be +// growable while this even is held) +// +// Note: We don't really need our own an event object for this. +// + +#define HalpNewAdapter HalpBusDatabaseEvent +extern KEVENT HalpNewAdapter; + + +// +// Define save area for MCA adapter objects. Allocate 1 extra slot for +// bus masters (MAX_DMA_CHANNEL_NUMBER is zero-based). +// + +PADAPTER_OBJECT HalpMCAAdapter[MAX_MCA_DMA_CHANNEL_NUMBER + 1 + 1]; + +VOID +HalpCopyBufferMap( + IN PMDL Mdl, + IN PTRANSLATION_ENTRY TranslationEntry, + IN PVOID CurrentVa, + IN ULONG Length, + IN BOOLEAN WriteToDevice + ); + + +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; + KIRQL Irql; + LONG MapRegisterNumber; + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + MasterAdapter = AdapterObject->MasterAdapter; + + // + // 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 )) { + + // + // Save the parameters in case there are not enough map registers. + // + + AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters; + AdapterObject->CurrentWcb = Wcb; + + // + // The adapter was not busy so it has been allocated. Now check + // to see whether this driver wishes to allocate any map registers. + // Ensure that this adapter has enough total map registers + // to satisfy the request. + // + + if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) { + + // + // 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. + // + + if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + return(STATUS_INSUFFICIENT_RESOURCES); + } + + Irql = KfAcquireSpinLock( &MasterAdapter->SpinLock ); + + MapRegisterNumber = -1; + + if (IsListEmpty( &MasterAdapter->AdapterQueue)) { + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + NumberOfMapRegisters, + 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 { + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // + + AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + + } + } + + KfReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); + + } else { + + 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 = ExecutionRoutine( Wcb->DeviceObject, + Wcb->CurrentIrp, + AdapterObject->MapRegisterBase, + Wcb->DeviceContext ); + + // + // If the driver would like to have the adapter deallocated, + // then release the adapter object. + // + + if (Action == DeallocateObject) { + + IoFreeAdapterChannel( AdapterObject ); + + } else if (Action == DeallocateObjectKeepRegisters) { + + // + // Set the NumberOfMapRegisters = 0 in the adapter object. + // This will keep IoFreeAdapterChannel from freeing the + // registers. After this it is the driver's responsiblity to + // keep track of the number of map registers. + // + + AdapterObject->NumberOfMapRegisters = 0; + IoFreeAdapterChannel(AdapterObject); + + } + } + } + + return(STATUS_SUCCESS); + +} + +PVOID +HalAllocateCrashDumpRegisters( + IN PADAPTER_OBJECT AdapterObject, + IN PULONG NumberOfMapRegisters + ) +/*++ + +Routine Description: + + This routine is called during the crash dump disk driver's initialization + to allocate a number map registers permanently. + +Arguments: + + AdapterObject - Pointer to the adapter control object to allocate to the + driver. + NumberOfMapRegisters - Input the number of registers requests and output + the number allocated. + +Return Value: + + Returns STATUS_SUCESS if map registers allocated. + +--*/ +{ + PADAPTER_OBJECT MasterAdapter; + ULONG MapRegisterNumber; + + // + // Begin by obtaining a pointer to the master adapter associated with this + // request. + // + + MasterAdapter = AdapterObject->MasterAdapter; + + // + // Check to see whether this driver needs to allocate any map registers. + // + + if (AdapterObject->NeedsMapRegisters) { + + // + // Ensure that this adapter has enough total map registers to satisfy + // the request. + // + + if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { + AdapterObject->NumberOfMapRegisters = 0; + return NULL; + } + + // + // Attempt to allocate the required number of map registers w/o + // affecting those registers that were allocated when the system + // crashed. + // + + MapRegisterNumber = (ULONG)-1; + + MapRegisterNumber = RtlFindClearBitsAndSet( + MasterAdapter->MapRegisters, + *NumberOfMapRegisters, + 0 + ); + + 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, + 0, + *NumberOfMapRegisters + ); + MapRegisterNumber = 0; + + } + + // + // Calculate the map register base from the allocated map + // register and base of the master adapter object. + // + + AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY) + MasterAdapter->MapRegisterBase + MapRegisterNumber); + + // + // Set the no scatter/gather flag if scatter/gather not + // supported. + // + + if (!AdapterObject->ScatterGather) { + AdapterObject->MapRegisterBase = (PVOID) + ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); + } + + } else { + + AdapterObject->MapRegisterBase = NULL; + AdapterObject->NumberOfMapRegisters = 0; + } + + return AdapterObject->MapRegisterBase; +} + +PADAPTER_OBJECT +HalGetAdapter( + IN PDEVICE_DESCRIPTION DeviceDescriptor, + OUT PULONG NumberOfMapRegisters + ) + +/*++ + +Routine Description: + + This function returns the appropriate adapter object for the device defined + in the device description structure. This code works for MCA systems. + +Arguments: + + DeviceDescriptor - 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 adpater object or NULL if an adapter could not + be created. + +--*/ + +{ + PADAPTER_OBJECT adapterObject; + ULONG channelNumber; + ULONG numberOfMapRegisters; + + PAGED_CODE(); + + // + // Determine the number of map registers for this device. + // + + if (DeviceDescriptor->ScatterGather && (LessThan16Mb || + DeviceDescriptor->Dma32BitAddresses || + DeviceDescriptor->InterfaceType == PCIBus)) { + + // + // Since the device support scatter/Gather then map registers are not + // required. + // + + numberOfMapRegisters = 0; + + } else { + + // + // Determine the number of map registers required based on the maximum + // transfer length, up to a maximum number. + // + + numberOfMapRegisters = BYTES_TO_PAGES(DeviceDescriptor->MaximumLength) + + 1; + numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_MCA_MAP_REGISTER ? + MAXIMUM_MCA_MAP_REGISTER : numberOfMapRegisters; + + // + // If the device is not a master and does scatter/gather then it only + // needs one map register. + // + + if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) { + + numberOfMapRegisters = 1; + } + } + + channelNumber = DeviceDescriptor->DmaChannel; + + // + // Determine if a new adapter object is necessary. If so then allocate it. + // + + if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) { + + adapterObject = HalpMCAAdapter[ channelNumber]; + + } else { + + // + // Serialize before allocating a new adapter + // + + KeWaitForSingleObject ( + &HalpNewAdapter, + WrExecutive, + KernelMode, + FALSE, + NULL + ); + + + // + // Determine if a new adapter object has already been allocated. + // If so use it, otherwise allocate a new adapter object + // + + if (!DeviceDescriptor->Master && HalpMCAAdapter[channelNumber] != NULL) { + + adapterObject = HalpMCAAdapter[ channelNumber]; + + } else { + + // + // Allocate an adapter object. + // + + // + // bugbug- need to pass in MCA base address instead of 0. + // + + adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter( + numberOfMapRegisters, + (PVOID) 0, + NULL + ); + + if (adapterObject == NULL) { + KeSetEvent (&HalpNewAdapter, 0, FALSE); + return(NULL); + } + + if (!DeviceDescriptor->Master) { + HalpMCAAdapter[channelNumber] = adapterObject; + } + + // + // Set the maximum number of map registers for this channel bus on + // the number requested and the type of device. + // + + if (numberOfMapRegisters) { + + // + // The specified number of registers are actually allowed to be + // allocated. + // + + adapterObject->MapRegistersPerChannel = numberOfMapRegisters; + + // + // Increase the commitment for the map registers. + // + + if (DeviceDescriptor->Master) { + + // + // Master I/O devices use several sets of map registers double + // their commitment. + // + + MasterAdapterObject->CommittedMapRegisters += + numberOfMapRegisters * 2; + + } else { + + MasterAdapterObject->CommittedMapRegisters += + numberOfMapRegisters; + + } + + // + // If the committed map registers is signicantly greater than the + // number allocated then grow the map buffer. + // + + if (MasterAdapterObject->CommittedMapRegisters > + MasterAdapterObject->NumberOfMapRegisters && + MasterAdapterObject->CommittedMapRegisters - + MasterAdapterObject->NumberOfMapRegisters > + MAXIMUM_MCA_MAP_REGISTER ) { + + HalpGrowMapBuffers( + MasterAdapterObject, + INCREMENT_MAP_BUFFER_SIZE + ); + } + + adapterObject->NeedsMapRegisters = TRUE; + + } else { + + // + // No real map registers were allocated. If this is a master + // device, then the device can have as may registers as it wants. + // + + adapterObject->NeedsMapRegisters = FALSE; + + if (DeviceDescriptor->Master) { + + adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES( + DeviceDescriptor->MaximumLength + ) + + 1; + + } else { + + // + // The device only gets one register. It must call + // IoMapTransfer repeatedly to do a large transfer. + // + + adapterObject->MapRegistersPerChannel = 1; + } + } + } + + KeSetEvent (&HalpNewAdapter, 0, FALSE); + + } + + adapterObject->Dma32BitAddresses = DeviceDescriptor->Dma32BitAddresses; + adapterObject->ScatterGather = DeviceDescriptor->ScatterGather; + *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel; + + // + // set up channel number. + // + + adapterObject->ChannelNumber = (UCHAR) channelNumber; + + // + // initialize MCA Extended DMA Mode flags. + // + + *((PUCHAR) &adapterObject->ExtendedModeFlags) = 0; + + // + // set up auto-initialize if necessary. + // + + if ( DeviceDescriptor->AutoInitialize) { + + adapterObject->ExtendedModeFlags.AutoInitialize = 1; + + } + + // + // set up PIO address if necessary. + // + + if ( DeviceDescriptor->DmaPort) { + + adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_USE_PIO; + adapterObject->DmaPortAddress = (USHORT) DeviceDescriptor->DmaPort; + + } else { + + adapterObject->ExtendedModeFlags.ProgrammedIo = DMA_EXT_NO_PIO; + } + + // + // indicate data transfer operation for DMA. + // + + adapterObject->ExtendedModeFlags.DmaOpcode = DMA_EXT_DATA_XFER; + + switch (DeviceDescriptor->DmaWidth) { + case Width8Bits: + adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_8_BIT; + break; + + case Width16Bits: + adapterObject->ExtendedModeFlags.DmaWidth = DMA_EXT_WIDTH_16_BIT; + break; + + case Width32Bits: + // + // If it's a master, it doesn't need DmaWidth filled in + // + + if (!DeviceDescriptor->Master) { + ObDereferenceObject( adapterObject ); + return(NULL); + } + break; + + default: + ObDereferenceObject( adapterObject ); + return(NULL); + + } // switch + + if (DeviceDescriptor->Master) { + + adapterObject->MasterDevice = TRUE; + + } else { + + adapterObject->MasterDevice = FALSE; + } // if + + return(adapterObject); +} + + +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 that should be used bus master controllers. + +--*/ + +{ + BOOLEAN useBuffer; + ULONG transferLength; + ULONG logicalAddress; + PHYSICAL_ADDRESS returnAddress; + ULONG index; + PULONG pageFrame; + PTRANSLATION_ENTRY translationEntry; + PMCA_DMA_CONTROLLER dmaControl; + UCHAR channelNumber; + KIRQL Irql; + KIRQL Irql2; + ULONG pageOffset; + + pageOffset = BYTE_OFFSET(CurrentVa); + + // + // Calculate how must of the transfer is contiguous. + // + + transferLength = PAGE_SIZE - pageOffset; + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE; + logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset; + + // + // If the buffer is contigous then just extend the buffer. + // + + while( transferLength < *Length ){ + + if (*pageFrame + 1 != *(pageFrame + 1)) { + break; + } + + transferLength += PAGE_SIZE; + pageFrame++; + + } + + transferLength = transferLength > *Length ? *Length : transferLength; + + // + // Determine if the data transfer needs to use the map buffer. + // + + if (MapRegisterBase != NULL) { + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER + && transferLength < *Length) { + + logicalAddress = translationEntry->PhysicalAddress + pageOffset; + translationEntry->Index = COPY_BUFFER; + index = 0; + transferLength = *Length; + useBuffer = TRUE; + + } else { + + // + // If there are map registers, then update the index to indicate + // how many have been used. + // + + useBuffer = FALSE; + index = translationEntry->Index; + translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES( + CurrentVa, + transferLength + ); + } + + // + // It must require memory to be at less than 16 MB. If the + // logical address is greater than 16MB then map registers must be used + // + + if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) { + + logicalAddress = (translationEntry + index)->PhysicalAddress + + pageOffset; + useBuffer = TRUE; + + if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) { + translationEntry->Index = COPY_BUFFER; + index = 0; + + } + } + + // + // Copy the data if necessary. + // + + if (useBuffer && WriteToDevice) { + + HalpCopyBufferMap( + Mdl, + translationEntry + index, + CurrentVa, + *Length, + WriteToDevice + ); + + } + } + + // + // Return the length. + // + + *Length = transferLength; + + // + // We only support 32 bits, but the return is 64. Just + // zero extend + // + + returnAddress.LowPart = logicalAddress; + returnAddress.HighPart = 0; + + // + // If no adapter was specificed, or device is bus master, then there + // is no more work to do so return. + // + + if (AdapterObject == NULL || AdapterObject->MasterDevice) { + + return(returnAddress); + } + + // + // grab the spinlock for the Microchannel system DMA controller + // + + Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock ); + + // + // Raise to high level. On systems with ABIOS disks + // the ABIOS can reprogram the DMA from its interrupt. Raising to high + // prevents the ABIOS from running while the DMA controller is being + // maniulated. Note this will not work on MP systems, however there are + // no know MP systems with non-SCSI ABIOS disks. + // + + Irql2 = KfRaiseIrql(HIGH_LEVEL); + + // + // Set up the Microchannel system DMA controller + // + + dmaControl = (PMCA_DMA_CONTROLLER) + &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))-> + ExtendedDmaBasePort[0]; + channelNumber = AdapterObject->ChannelNumber; + + // + // set the mask bit + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( SET_MASK_BIT | channelNumber)); + + // + // set mode register + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( WRITE_MODE | channelNumber)); + + // + // Set up for read or write, appropriately + // + + if ( WriteToDevice) { + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) (*((PUCHAR) &AdapterObject-> + ExtendedModeFlags) + | (UCHAR) DMA_MODE_READ)); + + } else { + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) ( *((PUCHAR) &AdapterObject-> + ExtendedModeFlags) + | DMA_MODE_WRITE)); + } + + // + // if there is a DMA Programmed I/O address, set it up + // + + if ( AdapterObject->ExtendedModeFlags.ProgrammedIo) { + + // + // set up I/O base address + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( WRITE_IO_ADDRESS | channelNumber)); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) AdapterObject->DmaPortAddress); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) ( AdapterObject->DmaPortAddress >> 8)); + + } + + // + // set the DMA transfer count + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( WRITE_TRANSFER_COUNT | channelNumber)); + + // + // adjust transfer count for 16-bit transfers as required. + // + + if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) { + + // + // Round up on odd byte transfers and divide by 2. + // + + transferLength++; + transferLength >>= 1; + } + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) ( transferLength - 1)); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) ( ( transferLength - 1) >> 8)); + + // + // set the DMA transfer start address + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( WRITE_MEMORY_ADDRESS | channelNumber)); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) logicalAddress); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) (logicalAddress >> 8)); + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionData, + (UCHAR) (logicalAddress >> 16)); + + // + // clear the mask bit + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( CLEAR_MASK_BIT | channelNumber)); + + KfLowerIrql(Irql2); + + // + // release the spinlock for the Microchannel system DMA controller + // + + KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql ); + + return(returnAddress); +} + +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 adpater object buffers. + +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 - No errors are detected so the transfer must succeed. + +--*/ + +{ + PMCA_DMA_CONTROLLER dmaControl; + KIRQL Irql; + KIRQL Irql2; + PTRANSLATION_ENTRY translationEntry; + PULONG pageFrame; + ULONG transferLength; + ULONG partialLength; + BOOLEAN masterDevice; + + masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ? + TRUE : FALSE; + + // + // If this is a slave device then stop the DMA controller be flushing + // the data. + // + + if (!masterDevice) { + + // + // grab the spinlock for the Microchannel system DMA controller + // + + Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock ); + + // + // Raise to high level. On systems with ABIOS disks + // the ABIOS can reprogram the DMA from its interrupt. Raising to high + // prevents the ABIOS from running while the DMA controller is being + // maniulated. Note this will not work on MP systems, however there are + // no know MP systems with non-SCSI ABIOS disks. + // + + Irql2 = KfRaiseIrql(HIGH_LEVEL); + + // + // Set up the Microchannel system DMA controller + // + + dmaControl = (PMCA_DMA_CONTROLLER) + &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))-> + ExtendedDmaBasePort[0]; + // + // clear the mask bit + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( SET_MASK_BIT | AdapterObject->ChannelNumber)); + + // + // release the spinlock for the Microchannel system DMA controller + // + + KfLowerIrql(Irql2); + KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql ); + + } + + if (MapRegisterBase == NULL) { + return(TRUE); + } + + // + // 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. + // + + if (!WriteToDevice) { + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // If this is not a master device, then just transfer the buffer. + // + + if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) { + + if (translationEntry->Index == COPY_BUFFER) { + + if (!masterDevice) { + + // + // Copy only the bytes that have actually been transfered. + // + + Length -= HalReadDmaCounter(AdapterObject); + } + + // + // The adapter does not support scatter/gather copy the buffer. + // + + HalpCopyBufferMap( + Mdl, + translationEntry, + CurrentVa, + Length, + WriteToDevice + ); + + } + + } else { + + // + // Cycle through the pages of the transfer to determine if there + // are any which need to be copied back. + // + + transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa); + partialLength = transferLength; + pageFrame = (PULONG)(Mdl+1); + pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) / PAGE_SIZE; + + while( transferLength <= Length ){ + + if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) { + + HalpCopyBufferMap( + Mdl, + translationEntry, + CurrentVa, + partialLength, + WriteToDevice + ); + + } + + (PCCHAR) CurrentVa += partialLength; + partialLength = PAGE_SIZE; + + // + // Note that transferLength indicates the amount which will be + // transfered after the next loop; thus, it is updated with the + // new partial length. + // + + transferLength += partialLength; + pageFrame++; + translationEntry++; + } + + // + // Process the any remaining residue. + // + + partialLength = Length - transferLength + partialLength; + if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) { + + HalpCopyBufferMap( + Mdl, + translationEntry, + CurrentVa, + partialLength, + WriteToDevice + ); + + } + + } + + } + + // + // Strip no scatter/gather flag. + // + + translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); + + // + // Clear the index of used buffers. + // + + if (translationEntry) { + + translationEntry->Index = 0; + } + + return TRUE; +} + +ULONG +HalReadDmaCounter( + IN PADAPTER_OBJECT AdapterObject + ) +/*++ + +Routine Description: + + This function reads the DMA counter and returns the number of bytes left + to be transfered. + +Arguments: + + AdapterObject - Supplies a pointer to the adapter object to be read. + +Return Value: + + Returns the number of bytes still be be transfered. + +--*/ + +{ + ULONG count; + ULONG high; + PMCA_DMA_CONTROLLER dmaControl; + UCHAR channelNumber; + KIRQL Irql; + KIRQL Irql2; + + // + // grab the spinlock for the Microchannel system DMA controller + // + + Irql = KfAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock ); + + // + // Raise to high level. On systems with ABIOS disks + // the ABIOS can reprogram the DMA from its interrupt. Raising to high + // prevents the ABIOS from running while the DMA controller is being + // maniulated. Note this will not work on MP systems, however there are + // no know MP systems with non-SCSI ABIOS disks. + // + + Irql2 = KfRaiseIrql(HIGH_LEVEL); + + // + // Set up the Microchannel system DMA controller + // + + dmaControl = (PMCA_DMA_CONTROLLER) + &( (PMCA_CONTROL) (AdapterObject->AdapterBaseVa))-> + ExtendedDmaBasePort[0]; + channelNumber = AdapterObject->ChannelNumber; + + count = 0XFFFF00; + + // + // Loop until the high byte matches. + // + + do { + + high = count; + + // + // read the DMA transfer count + // + + WRITE_PORT_UCHAR( &dmaControl->DmaFunctionLsb, + (UCHAR) ( READ_TRANSFER_COUNT | channelNumber)); + + count = READ_PORT_UCHAR( &dmaControl->DmaFunctionData); + + count |= READ_PORT_UCHAR( &dmaControl->DmaFunctionData) << 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; + + // + // adjust transfer count for 16-bit transfers as required. + // + + if ( AdapterObject->ExtendedModeFlags.DmaWidth == DMA_EXT_WIDTH_16_BIT ) { + count <<= 1; + } + + + KfLowerIrql(Irql2); + + // + // release the spinlock for the Microchannel system DMA controller + // + + KfReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql ); + + return(count); +} diff --git a/private/ntos/nthals/halmca/i386/ixnmi.c b/private/ntos/nthals/halmca/i386/ixnmi.c new file mode 100644 index 000000000..2ab99a52b --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixnmi.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixnmi.c" diff --git a/private/ntos/nthals/halmca/i386/ixpcibrd.c b/private/ntos/nthals/halmca/i386/ixpcibrd.c new file mode 100644 index 000000000..02fd82821 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixpcibrd.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixpcibrd.c" diff --git a/private/ntos/nthals/halmca/i386/ixpcibus.c b/private/ntos/nthals/halmca/i386/ixpcibus.c new file mode 100644 index 000000000..640cebfba --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixpcibus.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixpcibus.c" diff --git a/private/ntos/nthals/halmca/i386/ixpciint.c b/private/ntos/nthals/halmca/i386/ixpciint.c new file mode 100644 index 000000000..5243acee5 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixpciint.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixpciint.c" diff --git a/private/ntos/nthals/halmca/i386/ixphwsup.c b/private/ntos/nthals/halmca/i386/ixphwsup.c new file mode 100644 index 000000000..a1cdab598 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixphwsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixphwsup.c" diff --git a/private/ntos/nthals/halmca/i386/ixproc.c b/private/ntos/nthals/halmca/i386/ixproc.c new file mode 100644 index 000000000..fdb962b05 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixproc.c @@ -0,0 +1,163 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + ixsproc.c + +Abstract: + + Stub functions for UP hals. + +Author: + + Ken Reneris (kenr) 22-Jan-1991 + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + +UCHAR HalName[] = "PC Compatible MicroChannel HAL"; + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ); + +VOID HalpInitOtherBuses (VOID); +VOID HalpInitializePciBus (VOID); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitMP) +#pragma alloc_text(INIT,HalStartNextProcessor) +#pragma alloc_text(INIT,HalAllProcessorsStarted) +#pragma alloc_text(INIT,HalReportResourceUsage) +#pragma alloc_text(INIT,HalpInitOtherBuses) +#endif + + + +BOOLEAN +HalpInitMP ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) +{ + // do nothing + return TRUE; +} + + +VOID +HalpResetAllProcessors ( + VOID + ) +{ + // Just return, that will invoke the standard PC reboot code +} + + +BOOLEAN +HalStartNextProcessor ( + IN PLOADER_PARAMETER_BLOCK pLoaderBlock, + IN PKPROCESSOR_STATE pProcessorState + ) +{ + // no other processors + return FALSE; +} + +BOOLEAN +HalAllProcessorsStarted ( + VOID + ) +{ + return TRUE; +} + + +VOID +HalReportResourceUsage ( + VOID + ) +{ + INTERFACE_TYPE interfacetype; + ANSI_STRING AHalName; + UNICODE_STRING UHalName; + + HalInitSystemPhase2(); + + switch (HalpBusType) { + case MACHINE_TYPE_ISA: interfacetype = Isa; break; + case MACHINE_TYPE_EISA: interfacetype = Eisa; break; + case MACHINE_TYPE_MCA: interfacetype = MicroChannel; break; + default: interfacetype = Internal; break; + } + + RtlInitAnsiString (&AHalName, HalName); + RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE); + HalpReportResourceUsage ( + &UHalName, // descriptive name + interfacetype // 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 +} + +NTSTATUS +HalpGetMcaLog ( + OUT PMCA_EXCEPTION Exception, + OUT PULONG ReturnedLength + ) +{ + return STATUS_NOT_SUPPORTED; +} + +NTSTATUS +HalpMcaRegisterDriver( + IN PMCA_DRIVER_INFO DriverInfo + ) +{ + return STATUS_NOT_SUPPORTED; +} + +VOID +HalpMcaQueueDpc ( + VOID + ) +{ +} + + +ULONG +FASTCALL +HalSystemVectorDispatchEntry ( + IN ULONG Vector, + OUT PKINTERRUPT_ROUTINE **FlatDispatch, + OUT PKINTERRUPT_ROUTINE *NoConnection + ) +{ + return FALSE; +} diff --git a/private/ntos/nthals/halmca/i386/ixprofil.asm b/private/ntos/nthals/halmca/i386/ixprofil.asm new file mode 100644 index 000000000..c33b273ae --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixprofil.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixprofil.asm diff --git a/private/ntos/nthals/halmca/i386/ixreboot.c b/private/ntos/nthals/halmca/i386/ixreboot.c new file mode 100644 index 000000000..15d7bd898 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixreboot.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixreboot.c" diff --git a/private/ntos/nthals/halmca/i386/ixstall.asm b/private/ntos/nthals/halmca/i386/ixstall.asm new file mode 100644 index 000000000..115c6c9c1 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixstall.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixstall.asm diff --git a/private/ntos/nthals/halmca/i386/ixswint.asm b/private/ntos/nthals/halmca/i386/ixswint.asm new file mode 100644 index 000000000..68b302dfe --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixswint.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\ixswint.asm diff --git a/private/ntos/nthals/halmca/i386/ixsysbus.c b/private/ntos/nthals/halmca/i386/ixsysbus.c new file mode 100644 index 000000000..b4776da76 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixsysbus.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixsysbus.c" diff --git a/private/ntos/nthals/halmca/i386/ixthunk.c b/private/ntos/nthals/halmca/i386/ixthunk.c new file mode 100644 index 000000000..6f15aad73 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixthunk.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixthunk.c" diff --git a/private/ntos/nthals/halmca/i386/ixusage.c b/private/ntos/nthals/halmca/i386/ixusage.c new file mode 100644 index 000000000..519ec31f3 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/ixusage.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\ixusage.c" diff --git a/private/ntos/nthals/halmca/i386/mcirql.asm b/private/ntos/nthals/halmca/i386/mcirql.asm new file mode 100644 index 000000000..02d355cd4 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/mcirql.asm @@ -0,0 +1,1121 @@ + title "Irql Processing" +;++ +; +; Copyright (c) 1989 Microsoft Corporation +; +; Module Name: +; +; ixirql.asm +; +; Abstract: +; +; This module implements the code necessary to raise and lower i386 +; Irql and dispatch software interrupts with the 8259 PIC. +; +; Author: +; +; Shie-Lin Tzong (shielint) 8-Jan-1990 +; +; Environment: +; +; Kernel mode only. +; +; Revision History: +; +; John Vert (jvert) 27-Nov-1991 +; Moved from kernel into HAL +; +;-- + +.386p + .xlist +include hal386.inc +include callconv.inc ; calling convention macros +include i386\ix8259.inc +include i386\kimacro.inc +include mac386.inc + .list + + + EXTRNP _KeBugCheck,1,IMPORT + EXTRNP _KeSetEventBoostPriority, 2, IMPORT + EXTRNP _KeWaitForSingleObject,5, IMPORT + + extrn _HalpApcInterrupt:near + extrn _HalpDispatchInterrupt:near + extrn _KiUnexpectedInterrupt:near + extrn _HalpBusType:DWORD + extrn _HalpApcInterrupt2ndEntry:NEAR + extrn _HalpDispatchInterrupt2ndEntry:NEAR + +ifdef NT_UP + LOCK_ADD equ add + LOCK_DEC equ dec +else + LOCK_ADD equ lock add + LOCK_DEC equ lock dec +endif + + +; +; Initialization control words equates for the PICs +; + +ICW1_ICW4_NEEDED equ 01H +ICW1_CASCADE equ 00H +ICW1_INTERVAL8 equ 00H +ICW1_LEVEL_TRIG equ 08H +ICW1_EDGE_TRIG equ 00H +ICW1_ICW equ 10H + +ICW4_8086_MODE equ 001H +ICW4_NORM_EOI equ 000H +ICW4_NON_BUF_MODE equ 000H +ICW4_SPEC_FULLY_NESTED equ 010H +ICW4_NOT_SPEC_FULLY_NESTED equ 000H + +OCW2_NON_SPECIFIC_EOI equ 020H +OCW2_SPECIFIC_EOI equ 060H +OCW2_SET_PRIORITY equ 0c0H + +PIC_SLAVE_IRQ equ 2 +PIC1_BASE equ 30H +PIC2_BASE equ 38H + +; +; Interrupt flag bit maks for EFLAGS +; + +EFLAGS_IF equ 200H +EFLAGS_SHIFT equ 9 + + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +; +; PICsInitializationString - Master PIC initialization command string +; + +PS2PICsInitializationString dw PIC1_PORT0 + +; +; Master PIC initialization command +; + + db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC1_BASE + db 1 SHL PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE +; +; Slave PIC initialization command strings +; + + dw PIC2_PORT0 + db ICW1_ICW + ICW1_LEVEL_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC2_BASE + db PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE + dw 0 ; end of string + + +PICsInitializationString dw PIC1_PORT0 + +; +; Master PIC initialization command +; + + db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC1_BASE + db 1 SHL PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE + +; Slave PIC initialization command strings +; + + dw PIC2_PORT0 + db ICW1_ICW + ICW1_EDGE_TRIG + ICW1_INTERVAL8 +\ + ICW1_CASCADE + ICW1_ICW4_NEEDED + db PIC2_BASE + db PIC_SLAVE_IRQ + db ICW4_NOT_SPEC_FULLY_NESTED + \ + ICW4_NON_BUF_MODE + \ + ICW4_NORM_EOI + \ + ICW4_8086_MODE + dw 0 ; end of string + + align 4 + public KiI8259MaskTable +KiI8259MaskTable label dword + dd 00000000000000000000000000000000B ; irql 0 + dd 00000000000000000000000000000000B ; irql 1 + dd 00000000000000000000000000000000B ; irql 2 + dd 00000000000000000000000000000000B ; irql 3 + dd 11111111100000000000000000000000B ; irql 4 + dd 11111111110000000000000000000000B ; irql 5 + dd 11111111111000000000000000000000B ; irql 6 + dd 11111111111100000000000000000000B ; irql 7 + dd 11111111111110000000000000000000B ; irql 8 + dd 11111111111111000000000000000000B ; irql 9 + dd 11111111111111100000000000000000B ; irql 10 + dd 11111111111111110000000000000000B ; irql 11 + dd 11111111111111111000000000000000B ; irql 12 + dd 11111111111111111100000000000000B ; irql 13 + dd 11111111111111111110000000000000B ; irql 14 + dd 11111111111111111111000000000000B ; irql 15 + dd 11111111111111111111100000000000B ; irql 16 + dd 11111111111111111111110000000000B ; irql 17 + dd 11111111111111111111111000000000B ; irql 18 + dd 11111111111111111111111000000000B ; irql 19 + dd 11111111111111111111111010000000B ; irql 20 + dd 11111111111111111111111011000000B ; irql 21 + dd 11111111111111111111111011100000B ; irql 22 + dd 11111111111111111111111011110000B ; irql 23 + dd 11111111111111111111111011111000B ; irql 24 + dd 11111111111111111111111011111000B ; irql 25 + dd 11111111111111111111111011111010B ; irql 26 + dd 11111111111111111111111111111010B ; irql 27 + dd 11111111111111111111111111111011B ; irql 28 + dd 11111111111111111111111111111011B ; irql 29 + dd 11111111111111111111111111111011B ; irql 30 + dd 11111111111111111111111111111011B ; irql 31 + + align 4 +; +; The following tables define the addresses of software interrupt routers +; + +; +; Use this table if there is NO machine state frame on stack already +; + + public SWInterruptHandlerTable +SWInterruptHandlerTable label dword + dd offset FLAT:_KiUnexpectedInterrupt ; irql 0 + dd offset FLAT:_HalpApcInterrupt ; irql 1 + dd offset FLAT:_HalpDispatchInterrupt ; irql 2 + +; +; Use this table if there is a machine state frame on stack already +; + + public SWInterruptHandlerTable2 +SWInterruptHandlerTable2 label dword + dd offset FLAT:_KiUnexpectedInterrupt ; irql 0 + dd offset FLAT:_HalpApcInterrupt2ndEntry ; irql 1 + dd offset FLAT:_HalpDispatchInterrupt2ndEntry ; irql 2 + +; +; The following table picks up the highest pending software irq level +; from software irr +; + + public SWInterruptLookUpTable +SWInterruptLookUpTable label byte + db 0 ; SWIRR=0, so highest pending SW irql= 0 + db 0 ; SWIRR=1, so highest pending SW irql= 0 + db 1 ; SWIRR=2, so highest pending SW irql= 1 + db 1 ; SWIRR=3, so highest pending SW irql= 1 + db 2 ; SWIRR=4, so highest pending SW irql= 2 + db 2 ; SWIRR=5, so highest pending SW irql= 2 + db 2 ; SWIRR=6, so highest pending SW irql= 2 + db 2 ; SWIRR=7, so highest pending SW irql= 2 + +_DATA ENDS + + page ,132 + subttl "Raise Irql" + +_TEXT SEGMENT PARA PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:FLAT, FS:NOTHING, GS:NOTHING +;++ +; +; KIRQL +; FASTCALL +; KfRaiseIrql ( +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to the specified value. +; Also, a mask will be used to mask off all the lower lever 8259 +; interrupts. +; +; Arguments: +; +; (cl) = NewIrql - the new irql to be raised to +; +; Return Value: +; +; OldIrql - the addr of a variable which old irql should be stored +; +;-- + +cPublicFastCall KfRaiseIrql,1 +cPublicFpo 0,0 + + movzx ecx, cl ; 32bit extend NewIrql + mov al, PCR[PcIrql] ; get current irql + +if DBG + cmp al,cl ; old > new? + jbe short Kri99 ; no, we're OK + movzx ecx, cl + movzx eax, al + push ecx ; put new irql where we can find it + push eax ; put old irql where we can find it + mov byte ptr PCR[PcIrql],0 ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL > ; never return +Kri99: +endif + cmp cl,DISPATCH_LEVEL ; software level? + jbe short kri10 ; Skip setting 8259 masks + + mov edx, eax ; Save OldIrql + + pushfd + cli ; disable interrupt + mov PCR[PcIrql], cl ; set the new irql + mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks + + popfd + + mov eax, edx ; (al) = OldIrql + fstRET KfRaiseIrql + +align 4 +kri10: +; +; Note it is very important that we set the old irql AFTER we raised to +; the new irql. Otherwise, if there is an interrupt comes in between and +; the OldIrql is not a local variable, the caller will get wrong OldIrql. +; The bottom line is the raising irql and returning old irql has to be +; atomic to the caller. +; + mov PCR[PcIrql], cl + fstRET KfRaiseIrql + +fstENDP KfRaiseIrql + +;++ +; +; VOID +; KIRQL +; KeRaiseIrqlToDpcLevel ( +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to DPC level. +; +; Arguments: +; +; Return Value: +; +; OldIrql - the addr of a variable which old irql should be stored +; +;-- + +cPublicProc _KeRaiseIrqlToDpcLevel,0 +cPublicFpo 0, 0 + + mov al, PCR[PcIrql] ; (al) = Old Irql + mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql + +ifdef IRQL_METRICS + inc HalRaiseIrqlCount +endif +if DBG + cmp al, DISPATCH_LEVEL ; old > new? + ja short Krid99 ; yes, go bugcheck +endif + + stdRET _KeRaiseIrqlToDpcLevel + +if DBG +cPublicFpo 0,1 +Krid99: movzx eax, al + push eax ; put old irql where we can find it + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return + stdRET _KeRaiseIrqlToDpcLevel +endif + +stdENDP _KeRaiseIrqlToDpcLevel + +;++ +; +; VOID +; KIRQL +; KeRaiseIrqlToSynchLevel ( +; ) +; +; Routine Description: +; +; This routine is used to raise IRQL to SYNC level. +; +; Arguments: +; +; Return Value: +; +; OldIrql - the addr of a variable which old irql should be stored +; +;-- + +cPublicProc _KeRaiseIrqlToSynchLevel,0 +cPublicFpo 0, 0 + pushfd + cli ; disable interrupt + mov eax, KiI8259MaskTable[SYNCH_LEVEL*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks + + mov al, PCR[PcIrql] ; (al) = Old irql + mov byte ptr PCR[PcIrql], SYNCH_LEVEL ; set new irql + + popfd + +if DBG + cmp al, SYNCH_LEVEL + ja short Kris99 +endif + +ifdef IRQL_METRICS + inc HalRaiseIrqlCount +endif + stdRET _KeRaiseIrqlToSynchLevel + +if DBG +cPublicFpo 0,1 +Kris99: movzx eax, al + push eax ; put old irql where we can find it + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return + stdRET _KeRaiseIrqlToSynchLevel +endif + +stdENDP _KeRaiseIrqlToSynchLevel + + page ,132 + subttl "Lower irql" + +;++ +; +; VOID +; FASTCALL +; KfLowerIrql ( +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL to the specified value. +; The IRQL and PIRQL will be updated accordingly. Also, this +; routine checks to see if any software interrupt should be +; generated. The following condition will cause software +; interrupt to be simulated: +; any software interrupt which has higher priority than +; current IRQL's is pending. +; +; NOTE: This routine simulates software interrupt as long as +; any pending SW interrupt level is higher than the current +; IRQL, even when interrupts are disabled. +; +; On a UP system, HalEndSystenInterrupt is treated as a +; LowerIrql. +; +; Arguments: +; +; (cl) = NewIrql - the new irql to be set. +; +; Return Value: +; +; None. +; +;-- + + +cPublicFastCall KfLowerIrql ,1 +cPublicFpo 0,1 + + pushfd ; save caller's eflags + movzx ecx, cl ; zero extend irql + +if DBG + cmp cl,PCR[PcIrql] + ja short Kli99 +endif + cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level? + cli + jbe short kli02 ; no, go set 8259 hw + + mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks +kli02: + mov PCR[PcIrql], cl ; set the new irql + mov eax, PCR[PcIRR] ; get SW interrupt request register + mov al, SWInterruptLookUpTable[eax] ; get the highest pending + ; software interrupt level + cmp al, cl ; Is highest SW int level > irql? + ja Kli10 ; yes, go simulate interrupt + +kil03: popfd ; restore flags, including ints +cPublicFpo 1,0 + fstRET KfLowerIrql + +if DBG +cPublicFpo 1,3 +Kli99: + push ecx ; new irql for debugging + push PCR[PcIrql] ; old irql for debugging + mov byte ptr PCR[PcIrql],HIGH_LEVEL ; avoid recursive error + stdCall _KeBugCheck, <IRQL_NOT_LESS_OR_EQUAL> ; never return +endif + +; +; When we come to Kli10, (eax) = soft interrupt index +; +; Note Do NOT: +; +; popfd +; jmp SWInterruptHandlerTable[eax*4] +; +; We want to make sure interrupts are off after entering SWInterrupt +; Handler. +; + +align 4 +cPublicFpo 1,1 +Kli10: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT + popfd ; restore flags, including ints +cPublicFpo 1,0 + fstRET KfLowerIrql ; cRetURN + +fstENDP KfLowerIrql + +;++ +; +; KIRQL +; FASTCALL +; KfAcquireSpinLock ( +; IN PKSPIN_LOCK SpinLock, +; ) +; +; Routine Description: +; +; This function raises to DISPATCH_LEVEL and then acquires a the +; kernel spin lock. +; +; In a UP hal spinlock serialization is accomplished by raising the +; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for +; debugging purposes if the UP hal is compiled with the NT_UP flag +; not set (ie, MP) we take the SpinLock. +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock. +; +; Return Value: +; +; OldIrql +; +;-- + +cPublicFastCall KfAcquireSpinLock,1 +cPublicFpo 0,0 + + mov al, PCR[PcIrql] ; (al) = Old Irql + mov byte ptr PCR[PcIrql], DISPATCH_LEVEL ; set new irql + +ifndef NT_UP +asl10: ACQUIRE_SPINLOCK ecx,<short asl20> +endif + +ifdef IRQL_METRICS + inc HalRaiseIrqlCount +endif +if DBG + cmp al, DISPATCH_LEVEL ; old > new? + ja short asl99 ; yes, go bugcheck +endif + fstRET KfAcquireSpinLock + +ifndef NT_UP +asl20: SPIN_ON_SPINLOCK ecx,<short asl10> +endif + +if DBG +cPublicFpo 2, 1 +asl99: + push ecx ; put old irql where we can find it + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return +endif + fstRET KfAcquireSpinLock +fstENDP KfAcquireSpinLock + + +;++ +; +; KIRQL +; FASTCALL +; KeAcquireSpinLockRaiseToSynch ( +; IN PKSPIN_LOCK SpinLock, +; ) +; +; Routine Description: +; +; This function acquires the SpinLock at SYNCH_LEVEL. The function +; is optmized for hoter locks (the lock is tested before acquired. +; Any spin should occur at OldIrql; however, since this is a UP hal +; we don't have the code for it) +; +; In a UP hal spinlock serialization is accomplished by raising the +; IRQL to SYNCH_LEVEL. The SpinLock is not used; however, for +; debugging purposes if the UP hal is compiled with the NT_UP flag +; not set (ie, MP) we take the SpinLock. +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an kernel spin lock. +; +; Return Value: +; +; OldIrql +; +;-- + +cPublicFastCall KeAcquireSpinLockRaiseToSynch,1 +cPublicFpo 0,0 + + push ecx + mov ecx, SYNCH_LEVEL + fstCall KfRaiseIrql ; Raise to SYNCH_LEVEL + pop ecx + +ifndef NT_UP +asls10: ACQUIRE_SPINLOCK ecx,<short asls20> +endif + +ifdef IRQL_METRICS + inc HalRaiseIrqlCount +endif +if DBG + cmp al, SYNCH_LEVEL ; old > new? + ja short asls99 ; yes, go bugcheck +endif + fstRET KeAcquireSpinLockRaiseToSynch + +ifndef NT_UP +asls20: SPIN_ON_SPINLOCK ecx,<short asls10> +endif + +if DBG +cPublicFpo 2, 1 +asls99: + push ecx ; put old irql where we can find it + stdCall _KeBugCheck, <IRQL_NOT_GREATER_OR_EQUAL> ; never return +endif + fstRET KeAcquireSpinLockRaiseToSynch +fstENDP KeAcquireSpinLockRaiseToSynch + + + PAGE + SUBTTL "Release Kernel Spin Lock" +;++ +; +; VOID +; FASTCALL +; KfReleaseSpinLock ( +; IN PKSPIN_LOCK SpinLock, +; IN KIRQL NewIrql +; ) +; +; Routine Description: +; +; This function releases a kernel spin lock and lowers to the new irql +; +; In a UP hal spinlock serialization is accomplished by raising the +; IRQL to DISPATCH_LEVEL. The SpinLock is not used; however, for +; debugging purposes if the UP hal is compiled with the NT_UP flag +; not set (ie, MP) we use the SpinLock. +; +; +; Arguments: +; +; (ecx) = SpinLock - Supplies a pointer to an executive spin lock. +; (dl) = NewIrql - New irql value to set +; +; Return Value: +; +; None. +; +;-- + +align 16 +cPublicFastCall KfReleaseSpinLock ,2 +cPublicFpo 0,1 + pushfd + +ifndef NT_UP + RELEASE_SPINLOCK ecx ; release it +endif + movzx ecx, dl ; (ecx) = NewIrql + cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level? + cli + jbe short rsl02 ; no, go set 8259 hw + + mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks +rsl02: + mov PCR[PcIrql], cl + mov eax, PCR[PcIRR] ; get SW interrupt request register + mov al, SWInterruptLookUpTable[eax] ; get the highest pending + ; software interrupt level + cmp al, cl ; Is highest SW int level > irql? + ja short rsl20 ; yes, go simulate interrupt + + popfd + fstRet KfReleaseSpinLock ; all done + +align 4 +rsl20: call SWInterruptHandlerTable[eax*4] ; SIMULATE INTERRUPT + popfd ; restore flags, including ints +cPublicFpo 2,0 + fstRET KfReleaseSpinLock ; all done + +fstENDP KfReleaseSpinLock + + +;++ +; +; VOID +; FASTCALL +; ExAcquireFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function acquire ownership of the FastMutex +; +; Arguments: +; +; (ecx) = FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall ExAcquireFastMutex,1 +cPublicFpo 0,1 + + push ecx ; Save FastMutex + mov ecx, APC_LEVEL + fstCall KfRaiseIrql ; Raise to APC_LEVEL + pop ecx ; (ecx) = FastMutex + +cPublicFpo 0,0 + LOCK_DEC dword ptr [ecx].FmCount ; Get count + jz short afm_ret ; The owner? Yes, Done + + inc dword ptr [ecx].FmContention + +cPublicFpo 0,2 + push ecx ; Save FastMutex + push eax ; Save OldIrql + add ecx, FmEvent ; Wait on Event + stdCall _KeWaitForSingleObject,<ecx,WrExecutive,0,0,0> + pop eax + pop ecx + +afm_ret: + mov byte ptr [ecx].FmOldIrql, al ; (al) = OldIrql + fstRet ExAcquireFastMutex + +fstENDP ExAcquireFastMutex + +;++ +; +; BOOLEAN +; FASTCALL +; ExTryToAcquireFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function acquire ownership of the FastMutex +; +; Arguments: +; +; (ecx) = FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; Returns TRUE if the FAST_MUTEX was acquired; otherwise false +; +;-- + +cPublicFastCall ExTryToAcquireFastMutex,1 +cPublicFpo 0,1 + +; +; Try to acquire - but needs to support 386s. +; *** Warning: This code is NOT MP safe *** +; But, we know that this hal really only runs on UP machines +; + + push ecx ; Save FAST_MUTEX + + mov ecx, APC_LEVEL + fstCall KfRaiseIrql ; (al) = OldIrql + + pop edx ; (edx) = FAST_MUTEX + +cPublicFpo 0,0 + + cli + cmp dword ptr [edx].FmCount, 1 ; Busy? + jne short tam20 ; Yes, abort + + mov dword ptr [edx].FmCount, 0 ; acquire count + sti + + mov byte ptr [edx].FmOldIrql, al + mov eax, 1 ; return TRUE + fstRet ExTryToAcquireFastMutex + +tam20: sti + mov ecx, eax ; (cl) = OldIrql + fstCall KfLowerIrql ; resture OldIrql + xor eax, eax ; return FALSE + fstRet ExTryToAcquireFastMutex ; all done + +fstENDP ExTryToAcquireFastMutex + + +;++ +; +; VOID +; FASTCALL +; ExReleaseFastMutex ( +; IN PFAST_MUTEX FastMutex +; ) +; +; Routine description: +; +; This function releases ownership of the FastMutex +; +; Arguments: +; +; (ecx) = FastMutex - Supplies a pointer to the fast mutex +; +; Return Value: +; +; None. +; +;-- + +cPublicFastCall ExReleaseFastMutex,1 +cPublicFpo 0,0 + mov al, byte ptr [ecx].FmOldIrql ; (cl) = OldIrql + + LOCK_ADD dword ptr [ecx].FmCount, 1 ; Remove our count + xchg ecx, eax ; (cl) = OldIrql + js short rfm05 ; if < 0, set event + jnz @KfLowerIrql@4 ; if != 0, don't set event + +rfm05: add eax, FmEvent + push ecx + stdCall _KeSetEventBoostPriority, <eax, 0> + pop ecx + jmp @KfLowerIrql@4 + +fstENDP ExReleaseFastMutex + + + + +;++ +; +; VOID +; HalpEndSystemInterrupt +; IN KIRQL NewIrql, +; IN ULONG Vector +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL to the specified value. +; The IRQL and PIRQL will be updated accordingly. Also, this +; routine checks to see if any software interrupt should be +; generated. The following condition will cause software +; interrupt to be simulated: +; any software interrupt which has higher priority than +; current IRQL's is pending. +; +; NOTE: This routine simulates software interrupt as long as +; any pending SW interrupt level is higher than the current +; IRQL, even when interrupts are disabled. +; +; Arguments: +; +; NewIrql - the new irql to be set. +; +; Vector - Vector number of the interrupt +; +; Note that esp+12 is the beginning of interrupt/trap frame and upon +; entering to this routine the interrupts are off. +; +; Return Value: +; +; None. +; +;-- + +HeiNewIrql equ [esp + 4] + +cPublicProc _HalEndSystemInterrupt ,2 +cPublicFpo 2, 0 + + movzx ecx, byte ptr HeiNewIrql; get new irql value + cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level? + jbe short Hei02 ; no, go set 8259 hw + + mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks + +Hei02: + mov PCR[PcIrql], cl ; set the new irql + mov eax, PCR[PcIRR] ; get SW interrupt request register + mov al, SWInterruptLookUpTable[eax] ; get the highest pending + ; software interrupt level + cmp al, cl ; Is highest SW int level > irql? + ja short Hei10 ; yes, go simulate interrupt + + stdRET _HalEndSystemInterrupt ; cRetURN + +; When we come to Hei10, (eax) = soft interrupt index + +Hei10: add esp, 12 ; esp = trap frame + jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT + ; to the appropriate handler + +stdENDP _HalEndSystemInterrupt + +;++ +; +; VOID +; HalpEndSoftwareInterrupt +; IN KIRQL NewIrql, +; ) +; +; Routine Description: +; +; This routine is used to lower IRQL from software interrupt +; level to the specified value. +; The IRQL and PIRQL will be updated accordingly. Also, this +; routine checks to see if any software interrupt should be +; generated. The following condition will cause software +; interrupt to be simulated: +; any software interrupt which has higher priority than +; current IRQL's is pending. +; +; NOTE: This routine simulates software interrupt as long as +; any pending SW interrupt level is higher than the current +; IRQL, even when interrupts are disabled. +; +; Arguments: +; +; NewIrql - the new irql to be set. +; +; Note that esp+8 is the beginning of interrupt/trap frame and upon +; entering to this routine the interrupts are off. +; +; Return Value: +; +; None. +; +;-- + +HesNewIrql equ [esp + 4] + +cPublicProc _HalpEndSoftwareInterrupt ,1 +cPublicFpo 1, 0 + + movzx ecx, byte ptr HesNewIrql; get new irql value + + cmp byte ptr PCR[PcIrql],DISPATCH_LEVEL ; Software level? + jbe short Hes02 ; no, go set 8259 hw + + mov eax, KiI8259MaskTable[ecx*4]; get pic masks for the new irql + or eax, PCR[PcIDR] ; mask irqs which are disabled + SET_8259_MASK ; set 8259 masks + +Hes02: + mov PCR[PcIrql], cl ; set the new irql + mov eax, PCR[PcIRR] ; get SW interrupt request register + mov al, SWInterruptLookUpTable[eax] ; get the highest pending + ; software interrupt level + cmp al, cl ; Is highest SW int level > irql? + ja short Hes10 ; yes, go simulate interrupt + + stdRET _HalpEndSoftwareInterrupt ; cRetURN + +; When we come to Hes10, (eax) = soft interrupt index + +Hes10: add esp, 8 + jmp SWInterruptHandlerTable2[eax*4] ; SIMULATE INTERRUPT + + ; to the appropriate handler +stdENDP _HalpEndSoftwareInterrupt + + + page ,132 + subttl "Get current irql" + +;++ +; +; KIRQL +; KeGetCurrentIrql (VOID) +; +; Routine Description: +; +; This routine returns to current IRQL. +; +; Arguments: +; +; None. +; +; Return Value: +; +; The current IRQL. +; +;-- + +cPublicProc _KeGetCurrentIrql ,0 +cPublicFpo 0, 0 + movzx eax, word ptr PCR[PcIrql] ; Current irql is in the PCR + stdRET _KeGetCurrentIrql +stdENDP _KeGetCurrentIrql + + +;++ +; +; VOID +; HalpDisableAllInterrupts (VOID) +; +; Routine Description: +; +; This routine is called during a system crash. The hal needs all +; interrupts disabled. +; +; Arguments: +; +; None. +; +; Return Value: +; +; None - all interrupts are masked off +; +;-- + +cPublicProc _HalpDisableAllInterrupts,0 +cPublicFpo 0, 0 + + ; + ; Raising to HIGH_LEVEL disables interrupts for the microchannel HAL + ; + + mov ecx, HIGH_LEVEL + fstCall KfRaiseIrql + stdRET _HalpDisableAllInterrupts + +stdENDP _HalpDisableAllInterrupts + + + page ,132 + subttl "Interrupt Controller Chip Initialization" +;++ +; +; VOID +; HalpInitializePICs ( +; ) +; +; Routine Description: +; +; This routine sends the 8259 PIC initialization commands and +; masks all the interrupts on 8259s. +; +; Arguments: +; +; None +; +; Return Value: +; +; None. +; +;-- +cPublicProc _HalpInitializePICs ,0 + + push esi ; save caller's esi + cli ; disable interrupt + lea esi, PICsInitializationString + + test _HalpBusType, MACHINE_TYPE_MCA + jz short Hip00 + +; Is this a PS2 or PS700 series machine? + + in al, 07fh ; get PD700 ID byte + and al, 0F0h ; Mask high nibble + cmp al, 0A0h ; Is the ID Ax? + jz short Hip00 + cmp al, 090h ; Or an 9X? + jz short Hip00 ; Yes, it's a 700 + + lea esi, PS2PICsInitializationString +Hip00: + lodsw ; (AX) = PIC port 0 address +Hip10: movzx edx, ax + outsb ; output ICW1 + IODelay + inc edx ; (DX) = PIC port 1 address + outsb ; output ICW2 + IODelay + outsb ; output ICW3 + IODelay + outsb ; output ICW4 + IODelay + mov al, 0FFH ; mask all 8259 irqs + out dx,al ; write mask to PIC + lodsw + cmp ax, 0 ; end of init string? + jne short Hip10 ; go init next PIC + + pop esi ; restore caller's esi + sti ; enable interrupt + stdRET _HalpInitializePICs +stdENDP _HalpInitializePICs + + +_TEXT ends + + end diff --git a/private/ntos/nthals/halmca/i386/mcsysint.asm b/private/ntos/nthals/halmca/i386/mcsysint.asm new file mode 100644 index 000000000..f00b5c6e7 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/mcsysint.asm @@ -0,0 +1,385 @@ +;++ +; +;Copyright (c) 1991 Microsoft Corporation +; +;Module Name: +; +; ixsysint.asm +; +;Abstract: +; +; This module implements the HAL routines to enable/disable system +; interrupts. +; +;Author: +; +; John Vert (jvert) 22-Jul-1991 +; +;Environment: +; +; Kernel Mode +; +;Revision History: +; +;-- + + +.386p + .xlist +include hal386.inc +include i386\ix8259.inc +include i386\kimacro.inc +include mac386.inc +include callconv.inc + .list + + extrn KiI8259MaskTable:DWORD + EXTRNP _KeBugCheck,1,IMPORT + +; +; Constants used to initialize CMOS/Real Time Clock +; + +CMOS_CONTROL_PORT EQU 70h ; command port for cmos +CMOS_DATA_PORT EQU 71h ; cmos data port + +; +; Macros to Read/Write/Reset CMOS to initialize RTC +; + +; CMOS_READ +; +; Description: This macro read a byte from the CMOS register specified +; in (AL). +; +; Parameter: (AL) = address/register to read +; Return: (AL) = data +; + +CMOS_READ MACRO + OUT CMOS_CONTROL_PORT,al ; ADDRESS LOCATION AND DISABLE NMI + IODelay ; I/O DELAY + IN AL,CMOS_DATA_PORT ; READ IN REQUESTED CMOS DATA + IODelay ; I/O DELAY +ENDM + +_DATA SEGMENT DWORD PUBLIC 'DATA' + +align dword +; +; HalDismissSystemInterrupt does an indirect jump through this table so it +; can quickly execute specific code for different interrupts. +; + public HalpSpecialDismissTable +HalpSpecialDismissTable label dword + dd offset FLAT:HalpDismissNormal ; irq 0 + dd offset FLAT:HalpDismissNormal ; irq 1 + dd offset FLAT:HalpDismissNormal ; irq 2 + dd offset FLAT:HalpDismissNormal ; irq 3 + dd offset FLAT:HalpDismissNormal ; irq 4 + dd offset FLAT:HalpDismissNormal ; irq 5 + dd offset FLAT:HalpDismissNormal ; irq 6 + dd offset FLAT:HalpDismissIrq07 ; irq 7 + dd offset FLAT:HalpDismissNormal ; irq 8 + dd offset FLAT:HalpDismissNormal ; irq 9 + dd offset FLAT:HalpDismissNormal ; irq A + dd offset FLAT:HalpDismissNormal ; irq B + dd offset FLAT:HalpDismissNormal ; irq C + dd offset FLAT:HalpDismissNormal ; irq D + dd offset FLAT:HalpDismissNormal ; irq E + dd offset FLAT:HalpDismissIrq0f ; irq F + dd offset FLAT:HalpDismissNormal ; irq 10 + dd offset FLAT:HalpDismissNormal ; irq 11 + dd offset FLAT:HalpDismissNormal ; irq 12 + dd offset FLAT:HalpDismissNormal ; irq 13 + dd offset FLAT:HalpDismissNormal ; irq 14 + dd offset FLAT:HalpDismissNormal ; irq 15 + dd offset FLAT:HalpDismissNormal ; irq 16 + dd offset FLAT:HalpDismissNormal ; irq 17 + dd offset FLAT:HalpDismissNormal ; irq 18 + dd offset FLAT:HalpDismissNormal ; irq 19 + dd offset FLAT:HalpDismissNormal ; irq 1A + dd offset FLAT:HalpDismissNormal ; irq 1B + dd offset FLAT:HalpDismissNormal ; irq 1C + dd offset FLAT:HalpDismissNormal ; irq 1D + dd offset FLAT:HalpDismissNormal ; irq 1E + dd offset FLAT:HalpDismissNormal ; irq 1F + dd offset FLAT:HalpDismissNormal ; irq 20 + dd offset FLAT:HalpDismissNormal ; irq 21 + dd offset FLAT:HalpDismissNormal ; irq 22 + dd offset FLAT:HalpDismissNormal ; irq 23 + +_DATA ENDS + +_TEXT$01 SEGMENT DWORD PUBLIC 'CODE' + ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING + + +;++ +;BOOLEAN +;HalBeginSystemInterrupt( +; IN KIRQL Irql +; IN CCHAR Vector, +; OUT PKIRQL OldIrql +; ) +; +; +; +;Routine Description: +; +; This routine is used to dismiss the specified vector number. It is called +; before any interrupt service routine code is executed. +; +; N.B. This routine does NOT preserve EAX or EBX +; +; On a UP machine the interrupt dismissed at BeginSystemInterrupt time. +; This is fine since the irql is being raise to mask it off. +; HalEndSystemInterrupt is simply a LowerIrql request. +; +; +;Arguments: +; +; Irql - Supplies the IRQL to raise to +; +; Vector - Supplies the vector of the interrupt to be dismissed +; +; OldIrql- Location to return OldIrql +; +; +;Return Value: +; +; FALSE - Interrupt is spurious and should be ignored +; +; TRUE - Interrupt successfully dismissed and Irql raised. +; +;-- +align dword +HbsiIrql equ byte ptr [esp+4] +HbsiVector equ byte ptr [esp+8] +HbsiOldIrql equ dword ptr [esp+12] + +cPublicProc _HalBeginSystemInterrupt ,3 +cPublicFpo 3, 0 + movzx ebx,HbsiVector ; (ebx) = System Vector + sub ebx, PRIMARY_VECTOR_BASE ; (ebx) = 8259 IRQ # +if DBG + cmp ebx, 23h + jbe hbsi00 + int 3 +hbsi00: + +endif + jmp HalpSpecialDismissTable[ebx*4] + +HalpDismissIrq0f: +; +; Check to see if this is a spurious interrupt +; + mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR + out PIC2_PORT0, al + IODelay ; delay + in al, PIC2_PORT0 ; (al) = content of PIC 1 ISR + test al, 10000000B ; Is In-Service register set? + jnz short HalpDismissNormal ; No, this is NOT a spurious int, + ; go do the normal interrupt stuff + +; +; This is a spurious interrupt. +; Because the slave PIC is cascaded to irq2 of master PIC, we need to +; dismiss the interupt on master PIC's irq2. +; + + mov al, PIC2_EOI ; Specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master + mov eax,0 ; return FALSE +; sti + stdRET _HalBeginSystemInterrupt + +HalpDismissIrq07: +; +; Check to see if this is a spurious interrupt +; + mov al, OCW3_READ_ISR ; tell 8259 we want to read ISR + out PIC1_PORT0, al + IODelay ; delay + in al, PIC1_PORT0 ; (al) = content of PIC 1 ISR + test al, 10000000B ; Is In-Service register set? + jnz short HalpDismissNormal ; No, so this is NOT a spurious int + mov eax, 0 ; return FALSE +; sti + stdRET _HalBeginSystemInterrupt + +HalpDismissNormal: +; +; Store OldIrql +; + mov eax, HbsiOldIrql + movzx ecx, word ptr PCR[PcIrql] + mov byte ptr [eax], cl + +; +; Raise IRQL to requested level +; + movzx eax, HbsiIrql ; (eax) = irql + ; (ebx) = IRQ # + + mov PCR[PcIrql], al ; set new Irql + + + mov eax, KiI8259MaskTable[eax*4] ; get 8259's masks + or eax, PCR[PcIDR] ; mask disabled irqs + SET_8259_MASK ; send mask to 8259s + +; +; Dismiss interrupt. Current interrupt is already masked off. +; + mov eax, ebx ; (eax) = IRQ # + cmp eax, 8 ; EOI to master or slave? + + jae short Hbsi100 ; EIO to both master and slave + or al, PIC1_EOI_MASK ; create specific eoi mask for master + out PIC1_PORT0, al ; dismiss the interrupt + jmp short Hbsi200 ; IO delay - This is not enough for 486 + +Hbsi100: + mov al, OCW2_NON_SPECIFIC_EOI ; send non specific eoi to slave + out PIC2_PORT0, al + mov al, PIC2_EOI ; specific eoi to master for pic2 eoi + out PIC1_PORT0, al ; send irq2 specific eoi to master +Hbsi200: + PIC1DELAY ; *MUST* wait for 8259 before sti + sti + mov eax, 1 ; return TRUE, interrupt dismissed + stdRET _HalBeginSystemInterrupt +stdENDP _HalBeginSystemInterrupt + + +;++ +;VOID +;HalDisableSystemInterrupt( +; IN CCHAR Vector, +; IN KIRQL Irql +; ) +; +; +; +;Routine Description: +; +; Disables a system interrupt. +; +;Arguments: +; +; Vector - Supplies the vector of the interrupt to be disabled +; +; Irql - Supplies the interrupt level of the interrupt to be disabled +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalDisableSystemInterrupt ,2 +cPublicFpo 2, 0 + +; + + movzx ecx, byte ptr [esp+4] ; (ecx) = Vector + sub ecx, PRIMARY_VECTOR_BASE ; (ecx) = 8259 irq # + mov edx, 1 + shl edx, cl ; (ebx) = bit in IMR to disable + cli + or PCR[PcIDR], edx + xor eax, eax + +; +; Get the current interrupt mask register from the 8259 +; + in al, PIC2_PORT1 + shl eax, 8 + in al, PIC1_PORT1 +; +; Mask off the interrupt to be disabled +; + or eax, edx +; +; Write the new interrupt mask register back to the 8259 +; + out PIC1_PORT1, al + shr eax, 8 + out PIC2_PORT1, al + PIC2DELAY + + sti + stdRET _HalDisableSystemInterrupt + +stdENDP _HalDisableSystemInterrupt + +;++ +; +;BOOLEAN +;HalEnableSystemInterrupt( +; IN ULONG Vector, +; IN KIRQL Irql, +; IN KINTERRUPT_MODE InterruptMode +; ) +; +; +;Routine Description: +; +; Enables a system interrupt +; +;Arguments: +; +; Vector - Supplies the vector of the interrupt to be enabled +; +; Irql - Supplies the interrupt level of the interrupt to be enabled. +; +;Return Value: +; +; None. +; +;-- +cPublicProc _HalEnableSystemInterrupt ,3 +cPublicFpo 3, 0 + + movzx ecx, byte ptr [esp+4] ; (ecx) = vector + sub ecx, PRIMARY_VECTOR_BASE + jc hes_error + cmp ecx, CLOCK2_LEVEL + jnc hes_error + + mov eax, 1 + shl eax, cl ; (ebx) = bit in IMR to enable + not eax + + cli + and PCR[PcIDR], eax + +; +; Get the PIC masks for the current Irql +; + movzx eax, byte ptr PCR[PcIrql] + mov eax, KiI8259MaskTable[eax*4] + or eax, PCR[PcIDR] +; +; Write the new interrupt mask register back to the 8259 +; + SET_8259_MASK + + sti + mov eax, 1 ; return TRUE + stdRET _HalEnableSystemInterrupt + +hes_error: +if DBG + int 3 +endif + xor eax, eax ; FALSE + stdRET _HalEnableSystemInterrupt + +stdENDP _HalEnableSystemInterrupt + + +_TEXT$01 ENDS + + END diff --git a/private/ntos/nthals/halmca/i386/pcip.h b/private/ntos/nthals/halmca/i386/pcip.h new file mode 100644 index 000000000..476bab1e4 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/pcip.h @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\pcip.h" diff --git a/private/ntos/nthals/halmca/i386/xxbiosa.asm b/private/ntos/nthals/halmca/i386/xxbiosa.asm new file mode 100644 index 000000000..bc0173a17 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxbiosa.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\xxbiosa.asm diff --git a/private/ntos/nthals/halmca/i386/xxbiosc.c b/private/ntos/nthals/halmca/i386/xxbiosc.c new file mode 100644 index 000000000..60cf92748 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxbiosc.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxbiosc.c" diff --git a/private/ntos/nthals/halmca/i386/xxdisp.c b/private/ntos/nthals/halmca/i386/xxdisp.c new file mode 100644 index 000000000..d48977df0 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxdisp.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxdisp.c" diff --git a/private/ntos/nthals/halmca/i386/xxflshbf.c b/private/ntos/nthals/halmca/i386/xxflshbf.c new file mode 100644 index 000000000..b054121cf --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxflshbf.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxflshbf.c" diff --git a/private/ntos/nthals/halmca/i386/xxhal.c b/private/ntos/nthals/halmca/i386/xxhal.c new file mode 100644 index 000000000..198d08346 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxhal.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxhal.c" diff --git a/private/ntos/nthals/halmca/i386/xxioacc.asm b/private/ntos/nthals/halmca/i386/xxioacc.asm new file mode 100644 index 000000000..8445c3404 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxioacc.asm @@ -0,0 +1,5 @@ +; +; Include code from halx86 +; This is a cpp style symbolic link + +include ..\halx86\i386\xxioacc.asm diff --git a/private/ntos/nthals/halmca/i386/xxkdsup.c b/private/ntos/nthals/halmca/i386/xxkdsup.c new file mode 100644 index 000000000..6e569b5ac --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxkdsup.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxkdsup.c" diff --git a/private/ntos/nthals/halmca/i386/xxmemory.c b/private/ntos/nthals/halmca/i386/xxmemory.c new file mode 100644 index 000000000..920714540 --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxmemory.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxmemory.c" diff --git a/private/ntos/nthals/halmca/i386/xxstubs.c b/private/ntos/nthals/halmca/i386/xxstubs.c new file mode 100644 index 000000000..8421fb30a --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxstubs.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxstubs.c" diff --git a/private/ntos/nthals/halmca/i386/xxtime.c b/private/ntos/nthals/halmca/i386/xxtime.c new file mode 100644 index 000000000..92abb2aeb --- /dev/null +++ b/private/ntos/nthals/halmca/i386/xxtime.c @@ -0,0 +1,5 @@ +// +// Include code from halx86 +// This is a cpp style symbolic link + +#include "..\halx86\i386\xxtime.c" |