mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4771 lines
119 KiB
4771 lines
119 KiB
#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 [email protected]
|
|
* - 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 <request (use copy buffer)
|
|
// 5. Internal Slave LR4360 DMA(Floppy)
|
|
// When contigus buffer <request (use copy buffer)
|
|
// 6. PCI,EISA,ISA Master Device is used Mapregister For LR4360
|
|
// TLB.(Page Table)
|
|
// 7. EISA,ISA Slave(ESC DMA) Device is used Mapregister For LR4360
|
|
// TLB.(Page Table)
|
|
|
|
ULONG DataWord;
|
|
ULONG Channel;
|
|
ULONG value;
|
|
|
|
|
|
PINTERNAL_TRANSLATION_ENTRY translationEntry;
|
|
|
|
ULONG i;
|
|
UCHAR DataByte;
|
|
//
|
|
//
|
|
if ( MapRegisterBase == NULL ) {
|
|
|
|
// Case:
|
|
// 1. Internal Master with Scatter/Gather. Never use Mapregiter.
|
|
// So MaregisterBase allways NULL
|
|
//if(AdapterObject == NULL )
|
|
//
|
|
//
|
|
//
|
|
return(TRUE);
|
|
}else{
|
|
//
|
|
// Case: 2,3,4,5,6,7
|
|
//
|
|
if(AdapterObject==NULL){
|
|
if( ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) == 0){ //K00D,K017
|
|
WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
|
|
//
|
|
// Case: 6
|
|
//
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// At This Point case is 2,3,4,5,7
|
|
//
|
|
//
|
|
if (AdapterObject->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
|