#ident "@(#) NEC r98hwsup.c 1.41 95/06/19 11:31:38" /*++ Copyright (c) 1990-1994 Microsoft Corporation Module Name: r98hwsup.c Abstract: This module contains the HalpXxx routines for the NT I/O system that are hardware dependent. Were these routines not hardware dependent, they would normally reside in the internal.c module. --*/ /* * Original source: Build Number 1.612 * * Modify for R98(MIPS/R4400) * *********************************************************************** * * HalpCreateDmaStructures() * * L001 94.03/24 T.Samezima * * Change Interrupt service routine * * Add Call initialize of PCI interrupt * Interrupt enable * * K001 '94.5/30 (Mon) N.Kugimoto * -1 Add HalAllocateAdapterChannel(): * -2 Add HalAllocateCommonBuffer(): * -3 Non HalFlushCommonBuffer() * -4 Add HalFreeCommonBuffer(): For Internal Device * -5 Chg HalGetAdapter(): New!! * -6 Mix HalpAllocateAdapter(): mix halfxs,halx86 * -7 Add IoFreeMapRegisters(): For Internal Device * -8 Add IoFreeAdapterChannel(): For Internal Device * -9 FRM HalpAllocateMapRegisters() From halx86 * -A Mix IoMapTransfer() mix halfxs,halx86 * -B Mix IoFlushAdapterBuffers() mix halfxs,halx86 * -C FRM HalpAllocationRoutine () From halfxs * -D FRM HalReadDmaCounter() From halfxs * -E Del HalpDmaInterrupt() allways retrun 1 * -F FRM HalpGrowMapBuffers() halx86 * -G FRM HalpCopyBufferMap() from halx86 and Argument chg. * * K002 Add MasterAdapterObjectForInternal * K003 Chg HalpInternalAdapters[5]: LR4360 DMA have 5 channel * K004 Add HalpDmaInterrupt() * K005 fix spell miss * K006 FRM global value define!! From halx86 * K007 Chg if def chg * K008 94/5/31 N.Kugimoto * Chg HalTranslateBusAddress() * N.B. Pci trans addr is per slot ??. * K009 94/5/31 N.Kugimoto * BUG AddressSpace!! * K00A 94/6/2 (Thu) N.Kugimoto * Chg HalAllocateCrashDumpRegisters() * N.B. check is OK?? * * S002 94.03/24 T.Samezima * * Add HalpNmiHandler() * HalpRegisterNmi() ??? * * K00B 94/6/3 (Fri) N.Kugimoto * Del * K00C 94/6/6 (Mon) N.Kugimoto * Chg K007 enable * K00D 94/6/9 (Thu) N.kugimoto * Chg Compile err del. * K00E 94/7/1 (Fri) N.Kugimoto * -1 Chg IoFlushAdapterBuffers() * -2 Add IoFlushAdapterBuffers() Reserved Bit set 0. * -3 Del HalAllocateCrashDumpRegisters() limit check del. * -4 Bug IoMapTransfer() transferLength is Bad!!. * -5 Bug MasterAdapterObject ==> AdapterObject. * -6 Bug at this line. LR4360 dma * -7 Bug enable #if 0 and eisadma is del. * -8 Del This code is never use. so del. * K00F 94/7/6 (Wed) N.Kugimoto * Mov HalGetAdapter() CnDC->FiFoF Flush LR4360 DMA FiFo Move IoMapTransfer() * Per DMA Translation. * K010 94/7/8 (Fri) N.Kugimoto * -1 Chg enable check logic. * -2 Add comment add. LR4360 DMA Byte Count Register 64M. Bit25-Bit0. * -3 Add Comment add. This value use only as flag. Not Port Addr. * K011 94/8/22 (Mon) N.Kugimoto * -1 Bug if {} else not match!!. Debug On SNES. * -2 Bug HalpDmaInterrupt() enable Because First run rather than * IoFlushAdapterBuffers().Debug On SNES. * K012 94/9/22 N.Kugimoto * -1 Bug MasterAdapterObject->NumberOfMapRegiser is Non Initialize. * K013 94/9/22 N.Kugimoto * -1 Chg Externl logical addr first allocation 1M align. * second allocaton is start offset 0. * -2 Bug MasterAdapter can't use this line. * K014 94/9/22 N.Kugimoto * compile err * K015 94/09/26 N.Kugimoto * Mov move code to r98busdat.c * K016 94/09/29 N.Kugimoto * -1 Chg allocate memory is less than 512M. To see from KSEG1_BASE. * -2 Add cast ULONG . * K017 94/10/05 N.Kugimoto * -1 Bug must be () . * K018 94/10/07 N.Kugimoto * -1 Bug align 1m Logic Bug. * K019 94/10/06 N.Kugimoto * -1 Bug LR4360 PTBARn Register must be PFN. Not KSEG1_BASE value. * K020 94/10/11 N.Kugimoto * -1 Fix Version Up At 807 Base. * K021 94/10/11 N.Kugimoto * -1 Add page table clear * -2 Add tlb flush * K022 94/10/11 N.Kugimoto * Add NMI Logic * K023 94/10/12 N.Kugimoto * K024 94/10/13 N.Kugimoto * Chg Compile err * S025 94/10/14 T.Samezima * Del Move logic on connect int1 interrupt to allstart.c * K025 94/10/17 N.Kugimoto * Bug K020-1 miss * K026 94/10/18 N.Kugimoto * -1 Bug LR4360 Page Table is KSEG0_BASE * -2 Chg Page table Entry Invalidate. * -3 Chg tlb flush timing chg * K027 94/11/11 N.Kugimoto * -1 Chg cache enable * -2 Chg Som Logical addr range not Used. * * K028 95/2/22 N.Kugimoto * Chg PCEB Prefetch sycle caused LR4360 page fault * K029 95/2/22 N.Kugimoto * Add LR4360 TLB RoundUp. * K030 95/2/22 N.Kugimoto * Chg LR4360 TLB No Flush. Because At DMA .... * K031 95/2/22 N.Kugimoto * Add LR4360 I/O Read Cache Flush * K032 95/3/13 N.Kugimoto * Chg #if #else fix Miss. * * S003 95/3/14 T.Samezima * Add Add HalpLRErrorInterrupt() at dispatch table. * K034 95/04/12 N.Kugimoto * Del NOTLBFLUSH * Add DUMMYDMA This is Work around. * LR4360 can't TLB flush while dma. So ESC DMAC channel 2 use * Dummy dma 1byte. It't cause TLB flush . * S004 95/5/15 T.Samezima * Chg vaild page table on LR4360 * A002 1995/6/17 ataka@oa2.kb.nec.co.jp * - resolve compile error. * ------------------------------------------------------------------- * K035 95/6/16 N.Kugimoto * Up version Up 3.51 */ #include "halp.h" #include "bugcodes.h" #include "eisa.h" #include "jazznvr.h" //K00D // // Put all code for HAL initialization in the INIT section. It will be // deallocated by memory management when phase 1 initialization is // completed. // #if defined(ALLOC_PRAGMA) #pragma alloc_text(INIT, HalpCreateDmaStructures) #pragma alloc_text(PAGE,HalpGrowMapBuffers) //K035 #endif extern POBJECT_TYPE IoAdapterObjectType; // // The DMA controller has a larger number of map registers which may be used // by any adapter channel. In order to pool all of the map registers a master // adapter object is used. This object is allocated and saved internal to this // file. It contains a bit map for allocation of the registers and a queue // for requests which are waiting for more map registers. This object is // allocated during the first request to allocate an adapter. // PADAPTER_OBJECT MasterAdapterObject; // // K002 // PADAPTER_OBJECT MasterAdapterObjectForInternal; // K006 // Map buffer prameters. These are initialized in HalInitSystem // PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress; ULONG HalpMapBufferSize; // // Pointer to phyiscal memory for map registers. // ULONG HalpMapRegisterPhysicalBase; // PCEB Prefetch sycle cause LR4360 Page Fault // So reserved DummyPhysicalPage ULONG HalpNec0DummyPhysicalBase; // K028 ULONG HalpNec1DummyPhysicalBase; // K028 ULONG HalpLogicalAddrArbPoint=0; KSPIN_LOCK HalpIoMapSpinLock; // K004 // The following function is called when a DMA channel interrupt occurs. // BOOLEAN HalpDmaInterrupt( VOID //K00D ); // // The following is an array of adapter object structures for the internal DMA // channels. // K003 // N.B: Internal Device without Scatter/Gather not use this array. // PADAPTER_OBJECT HalpInternalAdapters[5]; IO_ALLOCATION_ACTION HalpAllocationRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context ); // A002 PVOID RtlFillMemoryUlong ( IN PVOID Destination, IN ULONG Length, IN ULONG Pattern ); // A002 VOID HalpDummyTlbFlush( IN PADAPTER_OBJECT AdapterObject, IN ULONG Offset, IN ULONG Length, IN BOOLEAN WriteToDevice ); BOOLEAN HalpCreateDmaStructures ( VOID ) /*++ Routine Description: This routine initializes the structures necessary for DMA operations and connects the intermediate interrupt dispatcher. It also connects an interrupt handler to the DMA channel interrupt. Arguments: None. Return Value: If the second level interrupt dispatcher is connected, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { /* Start L001 */ ULONG buffer; // // Initialize the interrupt dispatcher for I/O interrupts. // // N.B. This vector is reserved for exclusive use by the HAL (see // interrupt initialization). // PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch; // PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; // S025 PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch; // // Directly connect the local device interrupt dispatcher to the local // device interrupt vector. // PCR->InterruptRoutine[DMA_VECTOR] = (PKINTERRUPT_ROUTINE) HalpDmaInterrupt; // S003 PCR->InterruptRoutine[LR_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpLRErrorInterrupt; // // // KiAcquireSpinLock(&HalpSystemInterruptLock); HalpBuiltinInterruptEnable |= (iREN_ENABLE_DMA_INTERRUPT | iREN_ENABLE_LR_ERR_INTERRUPT ); // S003 WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, HalpBuiltinInterruptEnable); KiReleaseSpinLock(&HalpSystemInterruptLock); #if 0 // Start S025 // // Initialize EISA bus interrupts. // HalpCreateEisaStructures(); // // Initialize PCI bus interrupts. // return HalpCreatePciStructures (); #else return TRUE; #endif // End S025 /* End L001 */ } // K001: // // NTSTATUS HalAllocateAdapterChannel( IN PADAPTER_OBJECT AdapterObject, IN PWAIT_CONTEXT_BLOCK Wcb, IN ULONG NumberOfMapRegisters, IN PDRIVER_CONTROL ExecutionRoutine ) /*++ Routine Description: This routine allocates the adapter channel specified by the adapter object. This is accomplished by placing the device object of the driver that wants to allocate the adapter on the adapter's queue. If the queue is already "busy", then the adapter has already been allocated, so the device object is simply placed onto the queue and waits until the adapter becomes free. Once the adapter becomes free (or if it already is), then the driver's execution routine is invoked. Also, a number of map registers may be allocated to the driver by specifying a non-zero value for NumberOfMapRegisters. Then the map register must be allocated from the master adapter. Once there are a sufficient number of map registers available, then the execution routine is called and the base address of the allocated map registers in the adapter is also passed to the driver's execution routine. Arguments: AdapterObject - Pointer to the adapter control object to allocate to the driver. Wcb - Supplies a wait context block for saving the allocation parameters. The DeviceObject, CurrentIrp and DeviceContext should be initalized. NumberOfMapRegisters - The number of map registers that are to be allocated from the channel, if any. ExecutionRoutine - The address of the driver's execution routine that is invoked once the adapter channel (and possibly map registers) have been allocated. Return Value: Returns STATUS_SUCESS unless too many map registers are requested. Notes: Note that this routine MUST be invoked at DISPATCH_LEVEL or above. --*/ { PADAPTER_OBJECT MasterAdapter; BOOLEAN Busy = FALSE; IO_ALLOCATION_ACTION Action; LONG MapRegisterNumber; KIRQL Irql; ULONG srachPoint; // // Begin by obtaining a pointer to the master adapter associated with this // request. // dicide MasterAdapter whitch Intrenal Scatter/gathero or PCI,EISA,ISA // if (AdapterObject->MasterAdapter != NULL) { MasterAdapter = AdapterObject->MasterAdapter; } else { MasterAdapter = AdapterObject; } // // Initialize the device object's wait context block in case this device // must wait before being able to allocate the adapter. // Wcb->DeviceRoutine = ExecutionRoutine; Wcb->NumberOfMapRegisters = NumberOfMapRegisters; // // Allocate the adapter object for this particular device. If the // adapter cannot be allocated because it has already been allocated // to another device, then return to the caller now; otherwise, // continue. // if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue, &Wcb->WaitQueueEntry )){ // // The adapter was not busy so it has been allocated. Now check // to see whether this driver wishes to allocate any map registers. // If so, then queue the device object to the master adapter queue // to wait for them to become available. If the driver wants map // registers, ensure that this adapter has enough total map registers // to satisfy the request. // AdapterObject->CurrentWcb = Wcb; AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters; // // // // if (NumberOfMapRegisters != 0 && AdapterObject->MasterAdapter != NULL) { if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ //K011-1 // // At Internal check adapterobject itself. // if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { AdapterObject->NumberOfMapRegisters = 0; IoFreeAdapterChannel(AdapterObject); return(STATUS_INSUFFICIENT_RESOURCES); } }else{ // // At PCI,EISA,ISA check with Masteradapter // if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { AdapterObject->NumberOfMapRegisters = 0; IoFreeAdapterChannel(AdapterObject); return(STATUS_INSUFFICIENT_RESOURCES); } } //K011-1 // // Lock the map register bit map and the adapter queue in the // master adapter object. The channel structure offset is used as // a hint for the register search. // KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); MapRegisterNumber = -1; if (IsListEmpty( &MasterAdapter->AdapterQueue)) { if(MasterAdapter == MasterAdapterObject){ srachPoint = HalpLogicalAddrArbPoint; HalpLogicalAddrArbPoint = (HalpLogicalAddrArbPoint+256) % (DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)); } else { srachPoint = 0; } MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, MasterAdapter == MasterAdapterObject ? NumberOfMapRegisters+1 : NumberOfMapRegisters, //K028 srachPoint ); } if (MapRegisterNumber == -1) { // // There were not enough free map registers. Queue this request // on the master adapter where is will wait until some registers // are deallocated. // InsertTailList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue ); Busy = 1; } else { if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ AdapterObject->MapRegisterBase = (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); // // Set the no scatter/gather flag if scatter/gather not // supported on Internal Device. // ~~~~~~~ // AdapterObject->MapRegisterBase = (PVOID)((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); }else{ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber ); //add1 non } } KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); }else { AdapterObject->MapRegisterBase = NULL; } // // If there were either enough map registers available or no map // registers needed to be allocated, invoke the driver's execution // routine now. // if (!Busy) { Action = ExecutionRoutine( Wcb->DeviceObject, Wcb->CurrentIrp, AdapterObject->MapRegisterBase, Wcb->DeviceContext ); // // If the driver wishes to keep the map registers then set the number // allocated to zero and set the action to deallocate object. // if (Action == DeallocateObjectKeepRegisters) { AdapterObject->NumberOfMapRegisters = 0; Action = DeallocateObject; } // // If the driver would like to have the adapter deallocated, // then deallocate any map registers allocated and then release // the adapter object. // if (Action == DeallocateObject) IoFreeAdapterChannel( AdapterObject ); } } return(STATUS_SUCCESS); } // K001-2 // // PVOID HalAllocateCommonBuffer( IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, OUT PPHYSICAL_ADDRESS LogicalAddress, IN BOOLEAN CacheEnabled ) /*++ Routine Description: This function allocates the memory for a common buffer and maps so that it can be accessed by a master device and the CPU. Arguments: AdapterObject - Supplies a pointer to the adapter object used by this device. Length - Supplies the length of the common buffer to be allocated. LogicalAddress - Returns the logical address of the common buffer. CacheEnable - Indicates whether the memeory is cached or not. Return Value: Returns the virtual address of the common buffer. If the buffer cannot be allocated then NULL is returned. --*/ { PVOID virtualAddress; PVOID mapRegisterBase; ULONG numberOfMapRegisters; ULONG mappedLength; WAIT_CONTEXT_BLOCK wcb; KEVENT allocationEvent; NTSTATUS status; PMDL mdl; KIRQL irql; PHYSICAL_ADDRESS physicalAddress; CacheEnabled =TRUE; //K027-1 // Is it Internal Device ?. // if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal || (AdapterObject->MasterAdapter==NULL ) // K00B ){ // // Internal Device Not use LR4360 TLB. // LowPart is Any. // physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1; physicalAddress.HighPart = 0; virtualAddress = MmAllocateContiguousMemory( Length, physicalAddress ); if (virtualAddress == NULL) { return(NULL); } *LogicalAddress = MmGetPhysicalAddress(virtualAddress); return(virtualAddress); } // // PCI,EISA,ISA Device use LR4360 TLB. // numberOfMapRegisters = BYTES_TO_PAGES(Length); // // Allocate the actual buffer. // if (CacheEnabled != FALSE) { //K020-1 virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length); } else { virtualAddress = MmAllocateNonCachedMemory(Length); } if (virtualAddress == NULL) { return(virtualAddress); } // // Initialize an event. // KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE); // // Initialize the wait context block. Use the device object to indicate // where the map register base should be stored. // wcb.DeviceObject = &mapRegisterBase; wcb.CurrentIrp = NULL; wcb.DeviceContext = &allocationEvent; // // Allocate the adapter and the map registers. // KeRaiseIrql(DISPATCH_LEVEL, &irql); status = HalAllocateAdapterChannel( AdapterObject, &wcb, numberOfMapRegisters, HalpAllocationRoutine ); KeLowerIrql(irql); if (!NT_SUCCESS(status)) { // // Cleanup and return NULL. // if (CacheEnabled != FALSE) { //K020-1 ExFreePool(virtualAddress); } else { MmFreeNonCachedMemory(virtualAddress, Length); } return(NULL); } // // Wait for the map registers to be allocated. // status = KeWaitForSingleObject( &allocationEvent, Executive, KernelMode, FALSE, NULL ); if (!NT_SUCCESS(status)) { // // Cleanup and return NULL. // if (CacheEnabled != FALSE) { //K020-1 ExFreePool(virtualAddress); } else { MmFreeNonCachedMemory(virtualAddress, Length); } return(NULL); } // // Create an mdl to use with call to I/O map transfer. // mdl = IoAllocateMdl( virtualAddress, Length, FALSE, FALSE, NULL ); MmBuildMdlForNonPagedPool(mdl); // // Map the transfer so that the controller can access the memory. // // mapRegisterBase was set up at HalAllocateAdapterChannel()-->ExecutionRoutine()--> // HalpAllocationRoutine() (value same MapRegisterBase) // // mappedLength = Length; *LogicalAddress = IoMapTransfer( NULL, mdl, mapRegisterBase, virtualAddress, &mappedLength, TRUE ); //DbgPrint("\n Common Logical = 0x %x \n",*LogicalAddress); IoFreeMdl(mdl); if (mappedLength < Length) { // // Cleanup and indicate that the allocation failed. // HalFreeCommonBuffer( AdapterObject, Length, *LogicalAddress, virtualAddress, CacheEnabled //K020-1 ); return(NULL); } // // The allocation completed successfully. // return(virtualAddress); } // K00A // PVOID HalAllocateCrashDumpRegisters( IN PADAPTER_OBJECT AdapterObject, IN PULONG NumberOfMapRegisters //K020-1 ) /*++ Routine Description: This routine is called during the crash dump disk driver's initialization to allocate a number map registers permanently. Arguments: AdapterObject - Pointer to the adapter control object to allocate to the driver. NumberOfMapRegisters - Number of map registers requested and update to show number actually allocated. Return Value: Returns STATUS_SUCESS if map registers allocated. --*/ { PADAPTER_OBJECT MasterAdapter; //K020-1 ULONG NumberOfMapRegisters; ULONG MapRegisterNumber; #if !defined(_R98_) ULONG Hint; #endif // // Begin by obtaining a pointer to the master adapter associated with this // request. // if (AdapterObject->MasterAdapter) { MasterAdapter = AdapterObject->MasterAdapter; } else { #if defined(_R98_) // MasterAdapter==NULL This is Internal Device with Scatter/Gather. // So Nothing to Do. Never Use Mapregisters for contigus memory. // N.B. MasterAdapterObject[ForInternal] does not come here!!. // So No check !!. AdapterObject->MapRegisterBase = NULL; AdapterObject->NumberOfMapRegisters = 0; return AdapterObject->MapRegisterBase; #else MasterAdapter = AdapterObject; #endif } // // Set the number of map registers required. // //K020-1 *NumberOfMapRegisters = 16; // // Ensure that this adapter has enough total map registers to satisfy // the request. // #if 1 // K010-1 // K00E-3 // if(MasterAdapter == MasterAdapterObjectForInternal){ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { //K020-1 AdapterObject->NumberOfMapRegisters = 0; return NULL; } }else{ // PCI,EISA,ISA device's limit is MasterAdapter. // if (*NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { //K020-1 AdapterObject->NumberOfMapRegisters = 0; return NULL; } } #endif // // Attempt to allocate the required number of map registers w/o // affecting those registers that were allocated when the system // crashed. Note that once again the map registers to be allocated // must be above the 1MB range if this is an EISA bus device. // MapRegisterNumber = (ULONG)-1; #if !defined(_R98_) Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0; #endif MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, MasterAdapter == MasterAdapterObject ? *NumberOfMapRegisters+1 : *NumberOfMapRegisters, //K028 #if defined(_R98_) 0 #else Hint #endif ); #if !defined(_R98_) // // Ensure that any allocated map registers are valid for this adapter. // if ((ULONG) MapRegisterNumber < Hint) { // // Make it appear as if there are no map registers. // RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, *NumberOfMapRegisters //K020-1 ); MapRegisterNumber = (ULONG) -1; } #endif if (MapRegisterNumber == (ULONG)-1) { // // Not enough free map registers were found, so they were busy // being used by the system when it crashed. Force the appropriate // number to be "allocated" at the base by simply overjamming the // bits and return the base map register as the start. // RtlSetBits( MasterAdapter->MapRegisters, #if defined(_R98_) 0, // 0M was reserved #else Hint, #endif // K00D *NumberOfMapRegisters+1 ); #if defined(_R98_) MapRegisterNumber = 0x0; #else MapRegisterNumber = Hint; #endif } // // Calculate the map register base from the allocated map // register and base of the master adapter object. // #if defined(_R98_) if(MasterAdapter == MasterAdapterObjectForInternal){ AdapterObject->MapRegisterBase = ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); // // Set the no scatter/gather flag . // in there R98 Internal Device is Not always Scatter/Gather supported. // AdapterObject->MapRegisterBase = (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); }else #endif AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); return AdapterObject->MapRegisterBase; } // K001-3 // BOOLEAN HalFlushCommonBuffer( IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress ) /*++ Routine Description: This function is called to flush any hardware adapter buffers when the driver needs to read data written by an I/O master device to a common buffer. Arguments: AdapterObject - Supplies a pointer to the adapter object used by this device. Length - Supplies the length of the common buffer. This should be the same value used for the allocation of the buffer. LogicalAddress - Supplies the logical address of the common buffer. This must be the same value return by HalAllocateCommonBuffer. VirtualAddress - Supplies the virtual address of the common buffer. This must be the same value return by HalAllocateCommonBuffer. Return Value: Returns TRUE if no errors were detected; otherwise, FALSE is return. --*/ { UNREFERENCED_PARAMETER( AdapterObject ); UNREFERENCED_PARAMETER( Length ); UNREFERENCED_PARAMETER( LogicalAddress ); UNREFERENCED_PARAMETER( VirtualAddress ); return(TRUE); } // K001-4 // VOID HalFreeCommonBuffer( IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled ) /*++ Routine Description: This function frees a common buffer and all of the resouces it uses. Arguments: AdapterObject - Supplies a pointer to the adapter object used by this device. Length - Supplies the length of the common buffer. This should be the same value used for the allocation of the buffer. LogicalAddress - Supplies the logical address of the common buffer. This must be the same value return by HalAllocateCommonBuffer. VirtualAddress - Supplies the virtual address of the common buffer. This must be the same value return by HalAllocateCommonBuffer. CacheEnable - Indicates whether the memeory is cached or not. Return Value: None --*/ { PTRANSLATION_ENTRY mapRegisterBase; ULONG numberOfMapRegisters; ULONG mapRegisterNumber; CacheEnabled = TRUE; //K027-1 if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal|| (AdapterObject->MasterAdapter==NULL ) // K00B ){ // // Internal Device // MmFreeContiguousMemory (VirtualAddress); }else{ // // PCI,EISA,ISA. // // // Calculate the number of map registers, the map register number and // the map register base. // numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length); // // For PCI,EISA,ISA Logical address started at PCI_LOGICAL_START_ADDRESS // See. IoMapTransfer!!. // mapRegisterNumber = (LogicalAddress.LowPart - PCI_LOGICAL_START_ADDRESS) >> PAGE_SHIFT; mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase + mapRegisterNumber; // // Free the map registers. // IoFreeMapRegisters( AdapterObject, (PVOID) mapRegisterBase, numberOfMapRegisters ); // // Free the memory for the common buffer. // if (CacheEnabled != FALSE) { //K020-1 ExFreePool(VirtualAddress); } else { MmFreeNonCachedMemory(VirtualAddress, Length); } } return; } // K001-5 // As PCI,EISA,ISA Device is used TLB of LR4360. // Scatter/Gather is supported By Hal. // // Internal Device Never use TLB of LR4360. // So Device without Scatter/Gather is use continuguas memory. // // Internal Device at Bbus Device is used LR4360 DMA. // LR4360's DMA have Scatter/Gather .But Not use this version hal. // So use continuguas memory. // // // // // Source Base 612 halfxs/mips/jxhwsup.c,halx86/i386/ixisasup.c // // // // // PADAPTER_OBJECT HalGetAdapter( IN PDEVICE_DESCRIPTION DeviceDescription, IN OUT PULONG NumberOfMapRegisters ) /*++ Routine Description: This function returns the appropriate adapter object for the device defined in the device description structure. Three bus types are supported for the system: Internal, Isa, and Eisa. Arguments: DeviceDescription - Supplies a description of the deivce. NumberOfMapRegisters - Returns the maximum number of map registers which may be allocated by the device driver. Return Value: A pointer to the requested adapter object or NULL if an adapter could not be created. --*/ { PADAPTER_OBJECT adapterObject; ULONG maximumLength; ULONG numberOfMapRegisters; ULONG value; //K00D // // Make sure this is the correct version. // if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) //K020-1,K025 return(NULL); // // Return number of map registers requested based on the maximum // transfer length. // *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1; #if 0 // // 612 halfx code not use. Because Number of R98 PCI,EISA device is 8 and // Limit By MasterAdapterObject->MapRegisterPerChannel / 8 // if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) { *NumberOfMapRegisters = DMA_REQUEST_LIMIT; } #endif // // Get AdapterObject // At 1 st call HalpAllocateAdapter() Allocateted MasterAdapterObject or // MasterAdapterObjectForInternal. switch(DeviceDescription->InterfaceType){ case Internal: // // Return the adapter pointer for internal adapters. // such as SCSI,SONIC,Floppy LR4360 // K00D if(DeviceDescription->Master){ // Bus Master Device if(DeviceDescription->ScatterGather){ // Device is Scatter/Gather support!! numberOfMapRegisters=0; // then no use Mapregister. }else{ numberOfMapRegisters=1; // else use 1 Mapregister. } #if defined(NONARB) if (((HalpInternalAdapters[3] == NULL) && DeviceDescription->ScatterGather) || ( (HalpInternalAdapters[4] == NULL) && (DeviceDescription->ScatterGather==0)) ) { #endif adapterObject= HalpAllocateAdapter( numberOfMapRegisters, NULL, (PVOID)-1 // K00D ); #if defined(NONARB) if(DeviceDescription->ScatterGather ){ HalpInternalAdapters[3] = adapterObject; //SCSI0,SCSI1 adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; return(adapterObject); // K005 }else{ HalpInternalAdapters[4] = adapterObject; //SONIC } }else{ if(DeviceDescription->ScatterGather){ return(HalpInternalAdapters[3]); }else{ adapterObject=HalpInternalAdapters[4]; } } #endif // K00D K00E-6 }else if (HalpInternalAdapters[DeviceDescription->DmaChannel] != NULL ) { // // If necessary allocate an adapter; otherwise, // just return the adapter for the requested channel. // // LR4360 DMA channel 1 is floppy. // // K00D adapterObject = HalpInternalAdapters[DeviceDescription->DmaChannel]; // // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K // *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters; }else{ // // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K // *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ? MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters; adapterObject= HalpAllocateAdapter( 1, // KSEG1_BASE K00D // K010-3 This value use only as flag. &(DMA_CONTROL ( DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))->CnDC, // K00D (PVOID)-1 // K00D ); // // Driver of use LR4360 DMA // HalpInternalAdapters[] // HalpInternalAdapters[DeviceDescription->DmaChannel] = adapterObject; adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; } #if !defined(NONARB) // // Bus Master of Internal Device with Scatter/gather then Nothing to Do. // K00D if(DeviceDescription->Master && DeviceDescription->ScatterGather){ // // No Limit Because MapRegisters were not used. // adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; return(adapterObject); // K005 } #endif // // new request > primiry request // if (*NumberOfMapRegisters > adapterObject->MapRegistersPerChannel) { adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters; } // K00D if(DeviceDescription->Master){ // // Internal device Master without Scatter/Gather. // // // Master I/O devices use several sets of map registers double // their commitment. // MasterAdapterObjectForInternal->CommittedMapRegisters += (*NumberOfMapRegisters) * 2; }else{ // // Internal device with LR4360 DMA. etc floppy // MasterAdapterObjectForInternal->CommittedMapRegisters += (*NumberOfMapRegisters); } // // See MasterAdapterObjectForInternal and // Grow--!!. && Link To MapRegister. // if (MasterAdapterObjectForInternal->CommittedMapRegisters > MasterAdapterObjectForInternal->NumberOfMapRegisters && MasterAdapterObjectForInternal->CommittedMapRegisters - MasterAdapterObjectForInternal->NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER) { // // increment INCREMENT_MAP_BUFFER_SIZE=64K // Number of Mapregister is 64K*4 /4K // HalpGrowMapBuffers( MasterAdapterObjectForInternal, INCREMENT_MAP_BUFFER_SIZE ); } // // check LR4360 DMA Channel // K00D if(!DeviceDescription->Master){ adapterObject->ChannelNumber =(UCHAR)DeviceDescription->DmaChannel; //K00D // // LR4360 DMA have Scatter/Gather But not support this version. // Set Up DMA default value. // // 1.DMA mode :Normal mode // // K00D ULONG value; value=READ_REGISTER_ULONG( &(DMA_CONTROL( (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT)) )->CnDF ); ((PLR_DMA_CONFIG)&value)->Reserved1=0; ((PLR_DMA_CONFIG)&value)->Reserved2=0; ((PLR_DMA_CONFIG)&value)->TMODE=LR_DMA_MODE_NORMAL; ((PLR_DMA_CONFIG)&value)->iNEDi=1; //K00D ((PLR_DMA_CONFIG)&value)->iNEDE=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT)) )->CnDF, value ); // K00F Under Code Move IoMapTransfer() } return(adapterObject); // K005 K00D case Isa: case Eisa: // // Create an adapter object For Pci Device // adapterObject = HalpAllocateEisaAdapter( DeviceDescription ); //DbgPrint("\nEISA: = 0x%x\n",adapterObject); break; case PCIBus: // // Create an adapter object For Pci Device. // adapterObject = HalpAllocateAdapter( 0,NULL,NULL ); break; default: // Another Bus Not Suport !! return(NULL); } #if defined(DUMMYDMA) // K034 vvv // Max is 1M-2: 0xffe000 // // if (*NumberOfMapRegisters > 0x100 -2) *NumberOfMapRegisters = 0x100-2; #else // // PCI,EISA,ISA Device use LR4360 TLB.(PCI<-->ASOBus) // Max Limit Of MapRegister Per Channel For PCI,EISA,ISA Device Set beyond MasterRegisterPerChannel // if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 8) *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 8; #endif // K034 ^^^ // Check By HalAllocateAdapterChannel for MasterAdapter. // adapterObject->NeedsMapRegisters = TRUE; // return(adapterObject); } #if 0 //K015 BOOLEAN HalTranslateBusAddress( IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PHYSICAL_ADDRESS BusAddress, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress ) /*++ Routine Description: This function returns the system physical address for a specified I/O bus address. The return value is suitable for use in a subsequent call to MmMapIoSpace. Arguments: InterfaceType - Supplies the type of bus which the address is for. BusNumber - Supplies the bus number for the device. BusAddress - Supplies the bus relative address. AddressSpace - Supplies the address space number for the device: 0 for memory and 1 for I/O space. Returns the address space on this system. TranslatedAddress - Supplies a pointer to return the translated address Return Value: A return value of TRUE indicates that a system physical address corresponding to the supplied bus relative address and bus address number has been returned in TranslatedAddress. A return value of FALSE occurs if the translation for the address was not possible --*/ { // // R98 HighPart never carry!! // TranslatedAddress->HighPart = 0; // // If this is for the internal bus then just return the passed parameter. // if (InterfaceType == Internal) { // // Return the passed parameters. // TranslatedAddress->LowPart = BusAddress.LowPart; return(TRUE); } #if defined(_R98_) // K008 switch(InterfaceType){ case PCIBus: if(*AddressSpace){ // I/O // N.B. Pci trans addr is per slot ??. // So How get slot number!!. // TranslatedAddress->LowPart = BusAddress.LowPart+PCI_CONTROL_SLOT1_PHYSICAL_BASE; }else{ // Memory TranslatedAddress->LowPart = BusAddress.LowPart+PCI_MEMORY_PHYSICAL_BASE; } break; case Eisa: case Isa: if(*AddressSpace){ // I/O TranslatedAddress->LowPart = BusAddress.LowPart+EISA_CONTROL_PHYSICAL_BASE; }else{ // Memory TranslatedAddress->LowPart = BusAddress.LowPart+EISA_MEMORY_PHYSICAL_BASE; } break; default: // UnKnow K00D TranslatedAddress->LowPart = 0; return(FALSE); } *AddressSpace = 0; // K009 return(TRUE); #else // _R98_ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != Pci) { // // Not on this system return nothing. // *AddressSpace = 0; TranslatedAddress->LowPart = 0; return(FALSE); } // // There is only one I/O bus which is an EISA, so the bus number is unused. // // Determine the address based on whether the bus address is in I/O space // or bus memory space. // if (*AddressSpace) { // // The address is in I/O space. // *AddressSpace = 0; TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE; if (TranslatedAddress->LowPart < BusAddress.LowPart) { // // A carry occurred. // TranslatedAddress->HighPart = 1; } return(TRUE); } else { // // The address is in memory space. // *AddressSpace = 0; #if !defined(_DUO_) if (DMA_CONTROL->RevisionLevel.Long < 2) { TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE; } else { TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; } #else TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW; TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH; #endif if (TranslatedAddress->LowPart < BusAddress.LowPart) { // // A carry occurred. // TranslatedAddress->HighPart = 1; } return(TRUE); } #endif // _R98_ } #endif //K015 // K00-6 // MapRegistersPerChannel,AdapterBaseVa,MapRegisterBase //--------------------+-----------------------+-------------+---------------+ // Internal with S/G 0 0 -1 // Internal no S/G 1 0 -1 // Internal DMA 1 XX -1 // Internal MasterAdp 1 -1 -1 // EISA 0 XX 0 // PCI 0 0 0 // MasterAdp 0 -1 -1 // PADAPTER_OBJECT HalpAllocateAdapter( IN ULONG MapRegistersPerChannel, IN PVOID AdapterBaseVa, IN PVOID MapRegisterBase ) /*++ Routine Description: This routine allocates and initializes an adapter object to represent an adapter or a DMA controller on the system. Arguments: MapRegistersPerChannel - Unused. AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa is NULL then the MasterAdapterObject is allocated. MapRegisterBase - If (PVOID) -1 then Not MasterAdapter allocate. Return Value: The function value is a pointer to the allocate adapter object. --*/ { PADAPTER_OBJECT AdapterObject; OBJECT_ATTRIBUTES ObjectAttributes; ULONG Size; ULONG BitmapSize; HANDLE Handle; NTSTATUS Status; ULONG i; //K021-2 // // Internal without Scatter/Gather or LR4360 DMA // then allocate MasterAdapterObjectForInternal // if (MasterAdapterObjectForInternal == NULL && AdapterBaseVa !=(PVOID)-1 && MapRegistersPerChannel ){ MasterAdapterObjectForInternal = HalpAllocateAdapter( 1, (PVOID) -1, (PVOID) -1 ); // // If we could not allocate the master adapter For Internal then give up. // if (MasterAdapterObjectForInternal == NULL) return(NULL); }else if (MasterAdapterObject == NULL && MapRegisterBase !=(PVOID)-1) { MasterAdapterObject = HalpAllocateAdapter( 0, (PVOID)-1, (PVOID)-1 ); // // If we could not allocate the master adapter then give up. // if (MasterAdapterObject == NULL) return(NULL); } // // Begin by initializing the object attributes structure to be used when // creating the adapter object. // InitializeObjectAttributes( &ObjectAttributes, NULL, OBJ_PERMANENT, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); // // Determine the size of the adapter object. If this is the master object // then allocate space for the register bit map; otherwise, just allocate // an adapter object. // if (AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel) { // // MasterAdapterForInternal // BitmapSize = (((sizeof( RTL_BITMAP ) + (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3); Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; }else if(AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel==0) { // // MasterAdapter // BitmapSize = (((sizeof( RTL_BITMAP ) + ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3)) + 3) & ~3); Size = sizeof( ADAPTER_OBJECT ) + BitmapSize; } else // // Not Master Adapter.(Have not Bit Map) // Size = sizeof( ADAPTER_OBJECT ); // // Now create the adapter object. // Status = ObCreateObject( KernelMode, *((POBJECT_TYPE *)IoAdapterObjectType), &ObjectAttributes, KernelMode, (PVOID) NULL, Size, 0, 0, (PVOID *)&AdapterObject ); // This code is 612 base. // Reference the object. // if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByPointer( AdapterObject, FILE_READ_DATA | FILE_WRITE_DATA, *((POBJECT_TYPE *)IoAdapterObjectType), KernelMode ); } // // If the adapter object was successfully created, then attempt to insert // it into the the object table. // if (NT_SUCCESS( Status )) { RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT)); //K035 Status = ObInsertObject( AdapterObject, NULL, FILE_READ_DATA | FILE_WRITE_DATA, 0, (PVOID *) NULL, &Handle ); if (NT_SUCCESS( Status )) { ZwClose( Handle ); // // Initialize the adapter object itself. // AdapterObject->Type = IO_TYPE_ADAPTER; AdapterObject->Size = (USHORT) Size; AdapterObject->AdapterBaseVa = AdapterBaseVa; AdapterObject->PagePort = NULL; // // Set ->MasterAdapter // if(AdapterBaseVa == (PVOID)-1) // I am // Masteradpter or MasterAdapterForInternal. // AdapterObject->MasterAdapter = NULL; else if(MapRegistersPerChannel) // I am // Bbus (LR4360 DMA)or ASOBus with No Scatter/Gather. // AdapterObject->MasterAdapter = MasterAdapterObjectForInternal; else if(MapRegisterBase ==NULL){ // // I am PCI or EISA or ISA. // AdapterObject->MasterAdapter = MasterAdapterObject; // Limit was Set End of HalGetAdapter(). //AdapterObject->MapRegistersPerChannel = // DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY); // }else // I am // Internal Device With Scatter/Gather. // AdapterObject->MasterAdapter = NULL; // // Initialize the channel wait queue for this // adapter. // KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue ); // // If this is the MasterAdatper then initialize the register bit map, // AdapterQueue and the spin lock. // if(AdapterBaseVa == (PVOID)-1){ // // MasterAdapterObject and MasterAdapterObjectForInternal. // KeInitializeSpinLock( &AdapterObject->SpinLock ); InitializeListHead( &AdapterObject->AdapterQueue ); AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1); AdapterObject->NumberOfMapRegisters = 0; //K012 if(MapRegistersPerChannel) { // // MasterAdapterObjectForInternal. // (For Bbus LR4360 DMA and Internal Device without Scatter/Gather // may be continuguas memory) // AdapterObject->MapRegistersPerChannel =1; RtlInitializeBitMap( AdapterObject->MapRegisters, (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )), ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) ); // // Set all the bits in the memory to indicate that memory // has not been allocated for the map buffers // RtlSetAllBits( AdapterObject->MapRegisters ); // K012 AdapterObject->NumberOfMapRegisters = 0; AdapterObject->CommittedMapRegisters = 0; // // ALlocate the memory map registers. // AdapterObject->MapRegisterBase = ExAllocatePool( NonPagedPool, (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) * sizeof(INTERNAL_TRANSLATION_ENTRY) ); if (AdapterObject->MapRegisterBase == NULL) { ObDereferenceObject( AdapterObject ); AdapterObject = NULL; return(NULL); } // // Zero the map registers. // RtlZeroMemory( AdapterObject->MapRegisterBase, (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) * sizeof(INTERNAL_TRANSLATION_ENTRY) ); if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE)) { // // If no map registers could be allocated then free the // object. // ObDereferenceObject( AdapterObject ); AdapterObject = NULL; return(NULL); } }else{ // Not use R98 //ULONG MapRegisterSize; // PULONG Map; // // Limit is This code. // The Number of MapRegisters For PCI,EISA,ISA use LR4360 TLB. // AdapterObject->MapRegistersPerChannel = DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY); RtlInitializeBitMap( AdapterObject->MapRegisters, (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )), DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY) ); RtlClearAllBits( AdapterObject->MapRegisters ); // // The memory for the map registers was allocated by // HalpAllocateMapRegisters during phase 0 initialization. // // On PCI,EISA,ISA Set Up LR4360TLB Mapping and // PECB EISA->PCI Mapping. // // // Not use R98 //MapRegisterSize = DMA_TRANSLATION_LIMIT; //MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize); // // Convert the physical address to a non-cached virtual address. // // HalpMapRegisterPhysicalBase is Set up HalpAllocateMapRegisters(). // area of KSEG1_BASE is 512M. So get less than Physical addr 512M // by HalpAllocateMapRegisters(). AdapterObject->MapRegisterBase = (PVOID) (HalpMapRegisterPhysicalBase | KSEG0_BASE); //K026-1 // dummy page data is "CEN CEN CEN". for What happend!!. K028 RtlFillMemoryUlong( (PULONG)((HalpNec0DummyPhysicalBase) |KSEG0_BASE), PAGE_SIZE,0x4E454320); // A002 RtlFillMemoryUlong( (PULONG)((HalpNec1DummyPhysicalBase) |KSEG0_BASE), PAGE_SIZE,0x4E454e20); // A002 // LR4360 Page table Set DumyPhysicalBase. // LR4360 Page Table Size is DMA_TRANSLATION_LIMIT. K028 // Set to InValid. RtlFillMemoryUlong( AdapterObject->MapRegisterBase, #if defined(PTEINVALID) // S004 vvv DMA_TRANSLATION_LIMIT,(HalpNec0DummyPhysicalBase | 0x1)); #else DMA_TRANSLATION_LIMIT,HalpNec0DummyPhysicalBase ); #endif // S004 ^^^ #if defined(DUMMYDMA) // K034 vvv // 256 is Number of page teble entry per 1 TLB // 1M Align Logical Last Page is DUMYY page for TLB FLush!!. // Map =AdapterObject->MapRegisterBase; for(i=0;i<(DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) / 256;i++){ RtlSetBits ( AdapterObject->MapRegisters, 0xff+0x100*i,//1M*i-1 page. Start 0x1 //1 page DUMMY ); Map[i* 0x100+0xff] =HalpNec1DummyPhysicalBase; } #else // Reserved For PCEB PreFetch cycle Cause LR4360 TLB miss. RtlSetBits ( AdapterObject->MapRegisters, 0xfff, //0xFFFFFF 0x1 ); #endif // K034 ^^^ // 1M Low del RtlSetBits ( AdapterObject->MapRegisters, 0x0, //0x0 0xff ); // eisa vram del RtlSetBits ( AdapterObject->MapRegisters, 0xE00, //0xe00000 0xff ); // 16M Low del RtlSetBits ( AdapterObject->MapRegisters, 0xf00, //0xf00000 0xff ); // // LR4360 TLB Set Up // LR4360:PTBAR0 // ( Use 0M-4M-1 Logical address) K013 WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PTBAR0, (ULONG)HalpMapRegisterPhysicalBase );//K013-2,K016-2,K019-1 // // LR4360:PTBAR1 ( Use 4M-8M-1 Logical address) // WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PTBAR1, // K013 (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE //K019-1 ); // // LR4360:PTBAR2 ( Use 8M-12M-1 Logical address) // K013 WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PTBAR2, (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*2 //K019-1 ); // // LR4360:PTBAR3 ( Use 12M-12M-1 Logical address) // K013 WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PTBAR3, (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*3 //K019-1 ); // // LR4360:PTSZR (Set Page Table Size is 4K) // K00D WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PTSZR, LR4360PTSZ4K << LR4360PTSZSHIFT ); // // LR4360:PABAR Logical addr start 0x00000000(0M) // Logical addr end 0x00ffffff(16M-1) // WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->PABAR,0x0); //K021-2 Flush TLB all ,K0026-3 for (i = 0;i < 16; i++) { //K024 WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->TFLR,i); } #if 0 //snes 302 // K007, K00C, K013 // EISA-->PCI map 0M-16M // PCEB MEMREGN[4:1] // WRITE_REGISTER_ULONG( &((volatile PULONG ) (KSEG1_BASE|EISA_CONFIG_REGISTERS_MEMREGN))[0], 0xff0000|0x00 ); #endif WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); #if defined(DUMMYDMA) // K034 vvv { UCHAR adapterMode; DMA_EXTENDED_MODE extendedMode; PVOID adapterBaseVa; PDMA1_CONTROL dmaControl; // // SetUp Ext Mode reg. adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort; *((PUCHAR) &extendedMode) = 0; extendedMode.ChannelNumber = 2; //2 is floppy extendedMode.TimingMode = COMPATIBLITY_TIMING; //ISA compati extendedMode.TransferSize = BY_BYTE_8_BITS; //8bit DMA WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode)); // // SetUp Mode reg dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; adapterMode=0; ((PDMA_EISA_MODE) &adapterMode)->Channel = 2; ((PDMA_EISA_MODE) &adapterMode)->RequestMode = BLOCK_REQUEST_MODE; ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 0; // // Determine the mode based on the transfer direction. // Read From The Device. it is little first. // ((PDMA_EISA_MODE) &adapterMode)->TransferType = READ_TRANSFER; // it is safety. ((PDMA_EISA_MODE) &adapterMode)->TransferType = WRITE_TRANSFER; // // This request is for DMA controller 1 // WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode ); KeInitializeSpinLock (&HalpIoMapSpinLock); } #endif // K034 ^^^ } // MasterAdapterObject (For PCI,EISA,ISA) } // MasterAdapterObject and MasterAdapterObjectForInternal. } else { // // An error was incurred for some reason. Set the return value // to NULL. // AdapterObject = (PADAPTER_OBJECT) NULL; } } else { AdapterObject = (PADAPTER_OBJECT) NULL; } return AdapterObject; // K00E-8 // return (PADAPTER_OBJECT) NULL; } // K001-7 // VOID IoFreeMapRegisters( PADAPTER_OBJECT AdapterObject, PVOID MapRegisterBase, ULONG NumberOfMapRegisters ) /*++ Routine Description: This routine deallocates the map registers for the adapter. If there are any queued adapter waiting for an attempt is made to allocate the next entry. Arguments: AdapterObject - The adapter object to where the map register should be returned. MapRegisterBase - The map register base of the registers to be deallocated. NumberOfMapRegisters - The number of registers to be deallocated. Return Value: None --+*/ { PADAPTER_OBJECT MasterAdapter; LONG MapRegisterNumber; PWAIT_CONTEXT_BLOCK Wcb; PLIST_ENTRY Packet; IO_ALLOCATION_ACTION Action; KIRQL Irql; #if defined(DUMMYDMA) ULONG i; PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase; #endif // // Begin by getting the address of the master adapter. // if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) { MasterAdapter = AdapterObject->MasterAdapter; } else { // // There are no map registers to return. // // // Internal Master Device with Scatter/Gather. // Mapregister Not Used. // return; } if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ // // Internal Device without Scatter/Gather. // Strip no scatter/gather flag. // MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); MapRegisterNumber = (PINTERNAL_TRANSLATION_ENTRY) MapRegisterBase - (PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase; }else{ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase; } // // Acquire the master adapter spinlock which locks the adapter queue and the // bit map for the map registers. // KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql); // // Return the registers to the bit map. // #if defined(DUMMYDMA) RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, MasterAdapter == MasterAdapterObject ? NumberOfMapRegisters+1 :NumberOfMapRegisters //K028 ); // // LR4360 PTE InValid. if(MasterAdapter==MasterAdapterObject){ for (i = 0; i < NumberOfMapRegisters+1; i++) { #if defined(PTEINVALID) // S004 vvv (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1); #else (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; #endif // S004 ^^^ DmaMapRegister++; } } #else RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, MasterAdapter == MasterAdapterObject ? NumberOfMapRegisters+1 :NumberOfMapRegisters //K028 ); #endif // // Process any requests waiting for map registers in the adapter queue. // Requests are processed until a request cannot be satisfied or until // there are no more requests in the queue. // while(TRUE) { if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){ break; } Packet = RemoveHeadList( &MasterAdapter->AdapterQueue ); AdapterObject = CONTAINING_RECORD( Packet, ADAPTER_OBJECT, AdapterQueue ); Wcb = AdapterObject->CurrentWcb; // // Attempt to allocate map registers for this request. Use the previous // register base as a hint. // MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, AdapterObject->MasterAdapter == MasterAdapterObject ? AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters, //K028 MasterAdapter->NumberOfMapRegisters ); if (MapRegisterNumber == -1) { // // There were not enough free map registers. Put this request back on // the adapter queue where is came from. // InsertHeadList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue ); break; } KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ AdapterObject->MapRegisterBase = (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); // // Set the no scatter/gather flag. // if there device Not Sactter/Gather // AdapterObject->MapRegisterBase = (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); }else{ // DbgPrint("\nIoFreeMapRegisters = 0x%x\n",MapRegisterNumber+1); AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber );//add1 non } // // Invoke the driver's execution routine now. // Action = Wcb->DeviceRoutine( Wcb->DeviceObject, Wcb->CurrentIrp, AdapterObject->MapRegisterBase, Wcb->DeviceContext ); // // If the driver wishes to keep the map registers then set the number // allocated to zero and set the action to deallocate object. // if (Action == DeallocateObjectKeepRegisters) { AdapterObject->NumberOfMapRegisters = 0; Action = DeallocateObject; } // // If the driver would like to have the adapter deallocated, // then deallocate any map registers allocated and then release // the adapter object. // if (Action == DeallocateObject) { // // The map registers registers are deallocated here rather than in // IoFreeAdapterChannel. This limits the number of times // this routine can be called recursively possibly overflowing // the stack. The worst case occurs if there is a pending // request for the adapter that uses map registers and whos // excution routine decallocates the adapter. In that case if there // are no requests in the master adapter queue, then IoFreeMapRegisters // will get called again. // if (AdapterObject->NumberOfMapRegisters != 0) { // // Deallocate the map registers and clear the count so that // IoFreeAdapterChannel will not deallocate them again. // KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); RtlClearBits( MasterAdapter->MapRegisters, MapRegisterNumber, AdapterObject->MasterAdapter == MasterAdapterObject ? AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters //K028 ); #if defined(DUMMYDMA) if(MasterAdapter == MasterAdapterObject){ DmaMapRegister= (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber; for (i = 0; i < AdapterObject->NumberOfMapRegisters+1; i++) { #if defined(PTEINVALID) // S004 vvv (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1); #else (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; #endif // S004 ^^^ DmaMapRegister++; } } #endif AdapterObject->NumberOfMapRegisters = 0; KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); } IoFreeAdapterChannel( AdapterObject ); } KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); } KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); } // K001-8 // VOID IoFreeAdapterChannel( IN PADAPTER_OBJECT AdapterObject ) /*++ Routine Description: This routine is invoked to deallocate the specified adapter object. Any map registers that were allocated are also automatically deallocated. No checks are made to ensure that the adapter is really allocated to a device object. However, if it is not, then kernel will bugcheck. If another device is waiting in the queue to allocate the adapter object it will be pulled from the queue and its execution routine will be invoked. Arguments: AdapterObject - Pointer to the adapter object to be deallocated. Return Value: None. --*/ { PKDEVICE_QUEUE_ENTRY Packet; PADAPTER_OBJECT MasterAdapter; BOOLEAN Busy = FALSE; IO_ALLOCATION_ACTION Action; PWAIT_CONTEXT_BLOCK Wcb; KIRQL Irql; LONG MapRegisterNumber; ULONG Hint; // // Begin by getting the address of the master adapter. // if (AdapterObject->MasterAdapter != NULL) { MasterAdapter = AdapterObject->MasterAdapter; } else { MasterAdapter = AdapterObject; } // // Pull requests of the adapter's device wait queue as long as the // adapter is free and there are sufficient map registers available. // while( TRUE ){ // // Begin by checking to see whether there are any map registers that // need to be deallocated. If so, then deallocate them now. // if (AdapterObject->NumberOfMapRegisters != 0) { IoFreeMapRegisters( AdapterObject, AdapterObject->MapRegisterBase, AdapterObject->NumberOfMapRegisters ); } // // Simply remove the next entry from the adapter's device wait queue. // If one was successfully removed, allocate any map registers that it // requires and invoke its execution routine. // Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue ); if (Packet == NULL) { // // There are no more requests break out of the loop. // break; } Wcb = CONTAINING_RECORD( Packet, WAIT_CONTEXT_BLOCK, WaitQueueEntry ); AdapterObject->CurrentWcb = Wcb; AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters; // // Check to see whether this driver wishes to allocate any map // registers. If so, then queue the device object to the master // adapter queue to wait for them to become available. If the driver // wants map registers, ensure that this adapter has enough total // map registers to satisfy the request. // // // CASE: // Internal Master Device without Scatter/Gather. // Internal Device with LR4360 DMA(Always without Scatter/Gather) // PCI,EISA,ISA Device with LR4360 TLB. // if (Wcb->NumberOfMapRegisters != 0 && AdapterObject->MasterAdapter!=NULL) { // K00D // MasterAdapterObject?? // if ( MasterAdapter== MasterAdapterObject) // // PCI,EISA,ISA Device with LR4360 TLB. // if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS ); } // // Lock the map register bit map and the adapter queue in the // master adapter object. The channel structure offset is used as // a hint for the register search. // KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql ); MapRegisterNumber = -1; if (IsListEmpty( &MasterAdapter->AdapterQueue)) { MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters, MasterAdapter == MasterAdapterObject ? Wcb->NumberOfMapRegisters+1:Wcb->NumberOfMapRegisters, //K028 0 ); } if (MapRegisterNumber == -1) { // // There were not enough free map registers. Queue this request // on the master adapter where is will wait until some registers // are deallocated. // InsertTailList( &MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue ); Busy = 1; } else { if (MasterAdapter == MasterAdapterObjectForInternal){ // // Internal Device without Sactter/Gather. // AdapterObject->MapRegisterBase = (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); AdapterObject->MapRegisterBase = (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER); }else{ // // PCI,EISA,ISA with LR4360 TLB // AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber); } } KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql ); }else{ // // Only Internal Master Device with Scatter/Gather. // Always AdapterObject->MasterAdapter ==NULL. // AdapterObject->MapRegisterBase = NULL; AdapterObject->NumberOfMapRegisters = 0; } // // If there were either enough map registers available or no map // registers needed to be allocated, invoke the driver's execution // routine now. // if (!Busy) { AdapterObject->CurrentWcb = Wcb; Action = Wcb->DeviceRoutine( Wcb->DeviceObject, Wcb->CurrentIrp, AdapterObject->MapRegisterBase, Wcb->DeviceContext ); // // If the execution routine would like to have the adapter // deallocated, then release the adapter object. // if (Action == KeepObject) { // // This request wants to keep the channel a while so break // out of the loop. // break; } // // If the driver wants to keep the map registers then set the // number allocated to 0. This keeps the deallocation routine // from deallocating them. // if (Action == DeallocateObjectKeepRegisters) { AdapterObject->NumberOfMapRegisters = 0; } } else { // // This request did not get the requested number of map registers so // out of the loop. // break; } } } // K001-9 // VOID HalpAllocateMapRegisters( IN PLOADER_PARAMETER_BLOCK LoaderBlock ) /*++ Routine Description: This routine allocates memory for map registers directly from the loader block information. This memory must be non-cached and contiguous. Arguments: LoaderBlock - Pointer to the loader block which contains the memory descriptors. Return Value: None. --*/ { PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; PLIST_ENTRY NextMd; ULONG MaxPageAddress; ULONG PhysicalAddress; ULONG MapRegisterSize; MapRegisterSize = PAGE_SIZE*2+DMA_TRANSLATION_LIMIT; //K028 MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize); // // The address must be in KSEG 0. // //MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ; // less than 512M. MaxPageAddress = (0x20000000 >> PAGE_SHIFT) - 1 ; //K016 // // Scan the memory allocation descriptors and allocate map buffers // NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { Descriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); // // Search for a block of memory which is contains a memory chuck // that is greater than size pages, and has a physical address less // than MAXIMUM_PHYSICAL_ADDRESS. // if ((Descriptor->MemoryType == LoaderFree || Descriptor->MemoryType == MemoryFirmwareTemporary) && (Descriptor->BasePage) && (Descriptor->PageCount >= MapRegisterSize) && (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) { PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT; break; } NextMd = NextMd->Flink; } // // Use the extra descriptor to define the memory at the end of the // original block. // ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead); if (NextMd == &LoaderBlock->MemoryDescriptorListHead) return; // // Adjust the memory descriptors. // Descriptor->BasePage += MapRegisterSize; Descriptor->PageCount -= MapRegisterSize; if (Descriptor->PageCount == 0) { // // The whole block was allocated, // Remove the entry from the list completely. // RemoveEntryList(&Descriptor->ListEntry); } //K028 // // Save the map register base. // HalpNec0DummyPhysicalBase =PhysicalAddress; HalpNec1DummyPhysicalBase =HalpNec0DummyPhysicalBase+PAGE_SIZE; HalpMapRegisterPhysicalBase=HalpNec0DummyPhysicalBase+PAGE_SIZE*2; } #if defined(DUMMYDMA) // K034 vvv VOID HalpDummyTlbFlush( IN PADAPTER_OBJECT AdapterObject, IN ULONG Offset, IN ULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: This function programs the EISA DMA controller for a transfer. Arguments: Adapter - Supplies the DMA adapter object to be programed. DUMMY DUMMY DUMMY DUMMY Offset - Supplies the logical address to use for the transfer. Length - Supplies the length of the transfer in bytes. DUMMY DUMMY DUMMY DUMMY WriteToDevice - Indicates the direction of the transfer. DUMMY DUMMY DUMMY DUMMY Return Value: None. --*/ { volatile UCHAR Status; // volatile UCHAR Mask; UCHAR adapterMode; PUCHAR PagePort; PUCHAR BytePtr; volatile PUCHAR BytePtr2; volatile ULONG Count; PDMA1_CONTROL dmaControl; // PDMA2_CONTROL dmaControl2; BytePtr2 = (PUCHAR) &Count; BytePtr = (PUCHAR) &Offset; PagePort = &((PDMA_PAGE) 0)->Channel2; dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort; // dmaControl2 = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort; // Mask=READ_REGISTER_UCHAR( &dmaControl2->AllMask ); // WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, (UCHAR) (0xf) ); WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[0] ); WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[1] ); WRITE_REGISTER_UCHAR( ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) + (ULONG)PagePort, BytePtr[2] ); // // Write the high page register with zero value. This enable a special mode // which allows ties the page register and base count into a single 24 bit // address register. // WRITE_REGISTER_UCHAR( ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) + (ULONG)PagePort, 0 ); // // Notify DMA chip of the length to transfer. // transfer Count is 1 Byte . So Set 1-1=0 WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0x1); WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0); WRITE_REGISTER_UCHAR( ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]), (UCHAR) 0 ); //Flush LR4360 Read Cache. WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031 // // SoftWare DMA Request, channel 2 // WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x4 | 0x2) ); // // check dma transfer was finished!!. // do{ Count=0; WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 ); BytePtr2[0]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount); BytePtr2[1]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount); BytePtr2[2]= READ_REGISTER_UCHAR( ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]) ); if((Count & 0xffffff)== 0xffffff) break; }while(1); // WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x0 | 0x2) ); // WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, 0x0 ); } #endif // K034 ^^^ // K001-A // PHYSICAL_ADDRESS IoMapTransfer( IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN OUT PULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: This routine is invoked to set up the map registers in the DMA controller to allow a transfer to or from a device. Arguments: AdapterObject - Pointer to the adapter object representing the DMA controller channel that has been allocated. Mdl - Pointer to the MDL that describes the pages of memory that are being read or written. MapRegisterBase - The address of the base map register that has been allocated to the device driver for use in mapping the transfer. CurrentVa - Current virtual address in the buffer described by the MDL that the transfer is being done to or from. Length - Supplies the length of the transfer. This determines the number of map registers that need to be written to map the transfer. Returns the length of the transfer which was actually mapped. WriteToDevice - Boolean value that indicates whether this is a write to the device from memory (TRUE), or vice versa. Return Value: Returns the logical address to be used by bus masters. --*/ { #if defined(DUMMYDMA) // K034 vvv KIRQL Irql; #endif // K034 ^^^ ULONG value; // // May be check Bus Master: AdapterObject==NULL!!. // Internal Device: // ASOBus with Scatter/Gather:MapRegisterBase ==NULL // without Scatter/Gather always allocate MapRegister // So check As if use MapRegister. // // ASOBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1 // BBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1 // // PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase; PULONG PageFrameNumber; ULONG NumberOfPages; ULONG Offset; ULONG i; ULONG logicalAddress; ULONG transferLength; PINTERNAL_TRANSLATION_ENTRY translationEntry; ULONG index; //K00D //K00E-4 transferLength=PAGE_SIZE - BYTE_OFFSET((PUCHAR) CurrentVa ); Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa ); PageFrameNumber = (PULONG) (Mdl + 1); PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT); logicalAddress = (*PageFrameNumber << PAGE_SHIFT) + Offset; //K00D if((MapRegisterBase== NULL) || ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) ){ // BusMaster with Scatter/gather || witout Scatter/Gather // while(transferLength < *Length ){ if (*PageFrameNumber + 1 != *(PageFrameNumber + 1)) { break; } transferLength += PAGE_SIZE; PageFrameNumber++; } // // Limit the transferLength to the requested Length. // transferLength = transferLength > *Length ? *Length : transferLength; // // ASOBus Master without Scatter/Gather && contigous < request // or // Bbus Device Floppy use LR4360 DMA(it's not use Scatter/Gater) && contigous < request // // if ( (ULONG)MapRegisterBase & NO_SCATTER_GATHER && transferLength < *Length ){ translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); logicalAddress = translationEntry->PhysicalAddress + Offset; // // It's means I have not Scatter/Gather && contigous < request then I use buffer // At IoFlushAdapterBuffers() Do ?Hal Buffer-->user mem // translationEntry->Index = COPY_BUFFER; index = 0; // Do Copy So avaleable transfer is request size transferLength = *Length; // When Memory --> Device, Copy From memory to conigous buffer // if ( WriteToDevice) HalpCopyBufferMap( Mdl, translationEntry + index, CurrentVa, *Length, WriteToDevice ); } *Length=transferLength; // // ASOBus Master without Scatter/Gather. || // ASOBus Master with Scatter/Gather // // (Thus ASObus Master Don't use LR4360 DMA.) // if ( AdapterObject == NULL || MapRegisterBase ==NULL) return(RtlConvertUlongToLargeInteger(logicalAddress)); // // Bbus DMA used Device etc..Floppy // Then Set Up LR4360 DMA Controlor // //K00F From HalGetAdapter() // Flush LR4360 FiFo. // Note: LR4360 DMA Set up Do Drain. So At this time // FiFo have Never Data..... value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); ((PLR_DMA_CONTROL)&value)->Reserved1=0; ((PLR_DMA_CONTROL)&value)->FiFoF=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); // // Sleep till CnDC->iNED =1 ?? // value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); //K00D if(((PLR_DMA_CONTROL)&value)->iNEDS){ // // what sec to wait !! // K00D N.B microsecond KeStallExecutionProcessor(100); value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); // // the die ..... // K00D if(((PLR_DMA_CONTROL)&value)->iNEDS) KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS ); } // // transfer count set //K010-2 // N.B *Length must be below 0x03ffffff.(64M) WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnBC, *Length ); // // transfer addr set // WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnMA, // K00D RtlConvertUlongToLargeInteger(logicalAddress) logicalAddress ); // // direction set // value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); //K00D ((PLR_DMA_CONTROL)&value)->Reserved1=0; ((PLR_DMA_CONTROL)&value)->MEMWE=1; if ( WriteToDevice) { ((PLR_DMA_CONTROL)&value)->MEMWT=0; // // For End of DMA function .see HalpDmaInterrupt() // // // Memory --> Device // // // AdapterObject->TransferType = WRITE_TRANSFER; // }else{ ((PLR_DMA_CONTROL)&value)->MEMWT=1; // // Device --> Memory // // AdapterObject->TransferType = READ_TRANSFER; // } WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); // // Enable Input BREQ line // value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); ((PLR_DMA_CONTROL)&value)->Reserved1=0; //K00D ((PLR_DMA_CONTROL)&value)->REQWE=1; //K00D ((PLR_DMA_CONTROL)&value)->REQiE=1; //K00D WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); // // End of LR4360 DMA Set Up. // return(RtlConvertUlongToLargeInteger(logicalAddress)); }else{ #if defined(DUMMYDMA) // K034 vvv KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql); #endif // // Determine the maximum number of pages required to satisfy this request. // NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT; // // Set up phys addr in LR4360 Page table entry. // for (i = 0; i < NumberOfPages; i++) { (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT; } // // PCI,EISA,ISA is used TLB of LR4360. // So There is Inside Logical address Pci. // K00D offset -->Offset Offset += ( (PTRANSLATION_ENTRY) MapRegisterBase - (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase ) << PAGE_SHIFT; // Not use LR4360 PTBA0 Register ( 0-4M) // // use only 4M-8M. !!!! // Offset += PCI_LOGICAL_START_ADDRESS; #if defined(DUMMYDMA) // K034 // If PTE is InValid. Set to DummyPage for PCEB Prefetch. // else It was seted by another IoMapTransfer. #if defined(PTEINVALID) // S004 vvv if((DmaMapRegister)->PageFrame & 0x1) (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase; #endif // S004 ^^^ HalpDummyTlbFlush((PADAPTER_OBJECT)NULL,(Offset & 0x00f00000) | 0x000ff800,(ULONG)NULL,(BOOLEAN)NULL); // A002 #else // // Flush Translation Look a Side Buffer. // ( 1 Entry is 1M ) for (i = Offset >>20 ; i <= ((Offset+NumberOfPages*PAGE_SIZE)>>20); i++) { WRITE_REGISTER_ULONG( &LR_PCI_DEV_REG_CONTROL->TFLR,i); } #endif // K034 ^^^ if ( AdapterObject != NULL) //K00D // // Set Up ESC DMA of EISA,ISA. // HalpEisaMapTransfer( AdapterObject, Offset, *Length, WriteToDevice ); // // BUS Master // else PCI(always Master) or EISA,ISA Busmaster. // } #if defined(DUMMYDMA) // K034 vvv KeReleaseSpinLock( &HalpIoMapSpinLock, Irql ); #endif return(RtlConvertUlongToLargeInteger(Offset)); } // // K001-B // BOOLEAN IoFlushAdapterBuffers( IN PADAPTER_OBJECT AdapterObject, IN PMDL Mdl, IN PVOID MapRegisterBase, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: This routine flushes the DMA adapter object buffers and clears the enable flag which aborts the dma. Arguments: AdapterObject - Pointer to the adapter object representing the DMA controller channel. Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down buffer to/from which the I/O occured. MapRegisterBase - A pointer to the base of the map registers in the adapter or DMA controller. CurrentVa - The current virtual address in the buffer described the the Mdl where the I/O operation occurred. Length - Supplies the length of the transfer. WriteToDevice - Supplies a BOOLEAN value that indicates the direction of the data transfer was to the device. Return Value: TRUE - If the transfer was successful. FALSE - If there was an error in the transfer. --*/ { // case: Not use Mapregister. // 1. Internal Master with Scatter/Gather. Never use Mapregiter. // 2. Internal Master without Scatter/Gather But Not use Mapregister. // When contigus buffer > request // 3. Internal Slave with LR4360 DMA (Floppy)But Not use Mapregister. // When contigus buffer > request // // Internal or external device and use Mapregister. // Case: // 4. Internal Master without Scatter/Gather use Mapregister. // When contigus buffer PagePort) { WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031 // // case 7. // // // If this is a master channel, then just return since the DMA // request does not need to be disabled. // DataByte = AdapterObject->AdapterMode; if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) { return(TRUE); } // // Clear the EISA DMA adapter. // if (AdapterObject->AdapterNumber == 1) { // // This request is for DMA controller 1 // PDMA1_CONTROL dmaControl; dmaControl = AdapterObject->AdapterBaseVa; WRITE_REGISTER_UCHAR( &dmaControl->SingleMask, (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) ); } else { // // This request is for DMA controller 2 // PDMA2_CONTROL dmaControl; dmaControl = AdapterObject->AdapterBaseVa; WRITE_REGISTER_UCHAR( &dmaControl->SingleMask, (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber) ); } return(TRUE); } // // At case 2,3,4,5 // ~ ~ if(AdapterObject != NULL){ // Master Device is allways NULL // // case 3,5 use LR4360 DMA // // this line it's may be HalpDmaInterrupt(). but it is not good that // two End of DMA function (this func,and HalpDmaInterrupt()). // Because Work at Interrupt from LR4360DMA is Not first (100%) // // // Read CnDC register. // value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); // K00E-2 // Do Write then Reserved Bit must be 0. // ((PLR_DMA_CONTROL)&value)->Reserved1=0; ((PLR_DMA_CONTROL)&value)->Reserved2=0; // // At Memory-->Device Do drain So Not FiFo flush !!. // // // Device --> Memory // K00D if(!WriteToDevice){ if( ((PLR_DMA_CONTROL)&value)->FiFoV){ // // FiFo have valid Data So Flush!! // K00D ((PLR_DMA_CONTROL)&value)->FiFoD=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); } } // // iNEDS is clear by set 1 write // K00D ((PLR_DMA_CONTROL)&value)->iNEDS=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); } // // Determine if the data needs to be copied to the orginal buffer. // This only occurs if the data tranfer is from the device, the // MapReisterBase is not NULL and the transfer spans a page. // // Device --> Memory. // if (!WriteToDevice) { // // Strip no scatter/gather flag. // translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); // // If this is not a master device, then just transfer the buffer. // if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) { // // case: 2,3,4,5 // if (translationEntry->Index == COPY_BUFFER) { // // case: 4,5 // if(AdapterObject != NULL) // // case: 5 used DMA // // Copy only the bytes that have actually been transfered. // Length -= HalReadDmaCounter(AdapterObject); // // case: 4,5 // // // The adapter does not support scatter/gather copy the buffer. // HalpCopyBufferMap( Mdl, translationEntry, CurrentVa, Length, WriteToDevice ); } //else // // case: 2,3 // Not Used Copy Buffer then Nothing to Do. through !!. // // // Strip no scatter/gather flag. // K00D } } translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER); // // Clear index in map register. // translationEntry->Index = 0; return( TRUE ); } // K001-C // IO_ALLOCATION_ACTION HalpAllocationRoutine ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID MapRegisterBase, IN PVOID Context ) /*++ Routine Description: This function is called by HalAllocateAdapterChannel when sufficent resources are available to the driver. This routine saves the MapRegisterBase, and set the event pointed to by the context parameter. Arguments: DeviceObject - Supplies a pointer where the map register base should be stored. Irp - Unused. MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer. Context - Supplies a pointer to an event which is set to indicate the AdapterObject has been allocated. Return Value: DeallocateObjectKeepRegisters - Indicates the adapter should be freed and mapregisters should remain allocated after return. --*/ { UNREFERENCED_PARAMETER(Irp); *((PVOID *) DeviceObject) = MapRegisterBase; (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE ); return(DeallocateObjectKeepRegisters); } // K001-D // // ULONG HalReadDmaCounter( IN PADAPTER_OBJECT AdapterObject ) /*++ Routine Description: This function reads the DMA counter and returns the number of bytes left to be transfered. Arguments: AdapterObject - Supplies a pointer to the adapter object to be read. Return Value: Returns the number of bytes still be be transfered. --*/ { #if defined(DUMMYDMA) KIRQL Irql; #endif ULONG i; ULONG saveEnable; ULONG count; ULONG high; if (AdapterObject->PagePort) { // // PCI,EISA,ISA // // // // Determine the controller number based on the Adapter number. // #if defined(DUMMYDMA) KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql); #endif if (AdapterObject->AdapterNumber == 1) { // // This request is for DMA controller 1 // PDMA1_CONTROL dmaControl; dmaControl = AdapterObject->AdapterBaseVa; // // Initialize count to a value which will not match. // count = 0xFFFF00; // // Loop until the same high byte is read twice. // do { high = count; WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); // // Read the current DMA count. // count = READ_PORT_UCHAR( &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] .DmaBaseCount ); count |= READ_PORT_UCHAR( &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] .DmaBaseCount ) << 8; } while ((count & 0xFFFF00) != (high & 0xFFFF00)); } else { // // This request is for DMA controller 2 // PDMA2_CONTROL dmaControl; dmaControl = AdapterObject->AdapterBaseVa; // // Initialize count to a value which will not match. // count = 0xFFFF00; // // Loop until the same high byte is read twice. // do { high = count; WRITE_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 ); // // Read the current DMA count. // count = READ_PORT_UCHAR( &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] .DmaBaseCount ); count |= READ_PORT_UCHAR( &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber] .DmaBaseCount ) << 8; } while ((count & 0xFFFF00) != (high & 0xFFFF00)); } // // The DMA counter has a bias of one and can only be 16 bit long. // count = (count + 1) & 0xFFFF; #if defined(DUMMYDMA) KeReleaseSpinLock( &HalpIoMapSpinLock, Irql ); #endif } else { // // Internal Device With LR4360 DMA. // // // read CnBC register. // count=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnBC ); } return(count); } // // K001-E // always return 1: See IoFlushAdapterBuffers() // BOOLEAN HalpDmaInterrupt( VOID ) /*++ Routine Description: This routine is called when a DMA channel interrupt occurs. LR4360 DMA Arguments: Return Value: Returns TRUE. --*/ { #if 0 //K011-2 return(TRUE); #else PADAPTER_OBJECT AdapterObject; ULONG DataWord; ULONG Channel; ULONG value; // // Read the Inerrupt Service Factor Register. // DataWord = READ_REGISTER_ULONG(&(LR_CONTROL2)->iRSF); for (Channel = 0; Channel < 5; Channel++) { // // Determine which channel is interrupting. // if (!(DataWord & ( 1 << (Channel+LR_iRSF_REG_iNSF_SHIFT)))) { continue; } // // DMA Channel LR4360 is 1 origin. // if((AdapterObject=HalpInternalAdapters[Channel+1])==NULL){ #if 0 DmaChannelMsg[18] = (CHAR) Channel+ '1'; HalDisplayString(DmaChannelMsg); #endif // // // KeBugCheck(NMI_HARDWARE_FAILURE); } // // read CnDC register. // value=READ_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC ); // // At Memory-->Device drain So Don't FiFo flush. // // // Device --> Memory // if( ((PLR_DMA_CONTROL)&value)->MEMWT==0){ if( ((PLR_DMA_CONTROL)&value)->FiFoV){ ((PLR_DMA_CONTROL)&value)->Reserved1=0; ((PLR_DMA_CONTROL)&value)->Reserved2=0; // // FiFo Data is valid So Flush. // ((PLR_DMA_CONTROL)&value)->FiFoD=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); } } // // iNEDS is clear by 1 write // K00D ((PLR_DMA_CONTROL)&value)->iNEDS=1; WRITE_REGISTER_ULONG( &(DMA_CONTROL ( (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT)) )->CnDC, value ); return(TRUE); } #endif } // K001-F // // BOOLEAN HalpGrowMapBuffers( PADAPTER_OBJECT AdapterObject, ULONG Amount ) /*++ Routine Description: This function attempts to allocate additional map buffers for use by I/O devices. The map register table is updated to indicate the additional buffers. Arguments: AdapterObject - Supplies the adapter object for which the buffers are to be allocated. Amount - Indicates the size of the map buffers which should be allocated. Return Value: TRUE is returned if the memory could be allocated. FALSE is returned if the memory could not be allocated. --*/ { ULONG MapBufferPhysicalAddress; PVOID MapBufferVirtualAddress; PINTERNAL_TRANSLATION_ENTRY TranslationEntry ; LONG NumberOfPages; LONG i; KIRQL Irql; PHYSICAL_ADDRESS physicalAddress; PVOID CodeLockHandle; //K035 NumberOfPages = BYTES_TO_PAGES(Amount); // // Make sure there is room for the addition pages. The maximum number of // slots needed is equal to NumberOfPages + Amount / 64K + 1. // i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages + (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 + AdapterObject->NumberOfMapRegisters); if (i < 0) { // // Reduce the allocatation amount to so it will fit. // NumberOfPages += i; } if (NumberOfPages <= 0) { // // No more memory can be allocated. // return(FALSE); } if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) { NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize); // // Since this is the initial allocation, use the buffer allocated by // HalInitSystem rather than allocationg a new one. // MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart; // // Map the buffer for access. // MapBufferVirtualAddress = MmMapIoSpace( HalpMapBufferPhysicalAddress, HalpMapBufferSize, TRUE // Cache enable. ); if (MapBufferVirtualAddress == NULL) { // // The buffer could not be mapped. // HalpMapBufferSize = 0; return(FALSE); } } else { // // Allocate the map buffers. // physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1; physicalAddress.HighPart = 0; MapBufferVirtualAddress = MmAllocateContiguousMemory( NumberOfPages * PAGE_SIZE, physicalAddress ); if (MapBufferVirtualAddress == NULL) { return(FALSE); } // // Get the physical address of the map base. // MapBufferPhysicalAddress = MmGetPhysicalAddress( MapBufferVirtualAddress ).LowPart; } // // Initailize the map registers where memory has been allocated. // CodeLockHandle = MmLockPagableCodeSection (&HalpGrowMapBuffers); KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql ); //K025 TranslationEntry = ((PINTERNAL_TRANSLATION_ENTRY) AdapterObject->MapRegisterBase) + AdapterObject->NumberOfMapRegisters; for (i = 0; (LONG)i < NumberOfPages; i++) { //K00D K035 #if 1 // Enable K00E-7 // // Use at R98: LR4360 DMA Not boundry 64K. But per Grow size is 64K incremnet!!. // // // Make sure the perivous entry is physically contiguous with the next // entry and that a 64K physical bountry is not crossed unless this // is an Eisa system. // if (TranslationEntry != AdapterObject->MapRegisterBase && (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) != MapBufferPhysicalAddress )) { // // An entry needs to be skipped in the table. This entry will // remain marked as allocated so that no allocation of map // registers will cross this bountry. // TranslationEntry++; AdapterObject->NumberOfMapRegisters++; } #endif // // Clear the bits where the memory has been allocated. // RtlClearBits( AdapterObject->MapRegisters, TranslationEntry - (PINTERNAL_TRANSLATION_ENTRY) AdapterObject->MapRegisterBase, 1 ); TranslationEntry->VirtualAddress = MapBufferVirtualAddress; TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress; TranslationEntry++; (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE; MapBufferPhysicalAddress += PAGE_SIZE; } // // Remember the number of pages that where allocated. // AdapterObject->NumberOfMapRegisters += NumberOfPages; KeReleaseSpinLock( &AdapterObject->SpinLock, Irql ); MmUnlockPagableImageSection (CodeLockHandle); //K035 return(TRUE); } // K001-G // // VOID HalpCopyBufferMap( IN PMDL Mdl, IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry, IN PVOID CurrentVa, IN ULONG Length, IN BOOLEAN WriteToDevice ) /*++ Routine Description: This routine copies the speicific data between the user's buffer and the map register buffer. First a the user buffer is mapped if necessary, then the data is copied. Finally the user buffer will be unmapped if neccessary. Arguments: Mdl - Pointer to the MDL that describes the pages of memory that are being read or written. TranslationEntry - The address of the base map register that has been allocated to the device driver for use in mapping the transfer. CurrentVa - Current virtual address in the buffer described by the MDL that the transfer is being done to or from. Length - The length of the transfer. This determines the number of map registers that need to be written to map the transfer. WriteToDevice - Boolean value that indicates whether this is a write to the device from memory (TRUE), or vice versa. Return Value: None. --*/ { PCCHAR bufferAddress; PCCHAR mapAddress; // // Get the system address of the MDL. // bufferAddress = MmGetSystemAddressForMdl(Mdl); // // Calculate the actual start of the buffer based on the system VA and // the current VA. // bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl); mapAddress = (PCCHAR) TranslationEntry->VirtualAddress + BYTE_OFFSET(CurrentVa); // // Copy the data between the user buffer and map buffer // if (WriteToDevice) { RtlMoveMemory( mapAddress, bufferAddress, Length); } else { RtlMoveMemory(bufferAddress, mapAddress, Length); } } #if 0 //K023 move to r98int.s /* Start S002 */ VOID HalpNmiHandler( VOID ) /*++ Routine Description: This routine is call from ROM at NMI Arguments: None. Return Value: None. --*/ { // K022 // NMI was not happend!!. // HalpResetNmi(); // // Cause EIF !! // WRITE_REGISTER_UCHAR(0xB9980100,0x00828000); return; } #endif VOID HalpRegisterNmi( VOID ) /*++ Routine Description: This routine set NMI handler to nvRAM. Arguments: None. Return Value: None. --*/ { // VOID (*funcAddr)(); ULONG funcAddr; // K00D KIRQL OldIrql; ENTRYLO SavedPte[2]; PNV_CONFIGURATION NvConfiguration; // // Get address of HalpNmiHandler // funcAddr = (ULONG)HalpNmiHandler; // K00D // funcAddr += (KSEG1_BASE - KSEG0_BASE); //K023 ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) && ((ULONG)&HalpNmiHandler < KSEG2_BASE) ); // // Map the NVRAM into the address space of the current process. // OldIrql = HalpMapNvram(&SavedPte[0]); NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE; WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[0], (UCHAR)(funcAddr >> 24)); WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[1], (UCHAR)((funcAddr >> 16) & 0xFF)); WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[2], (UCHAR)((funcAddr >> 8) & 0xFF)); WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[3], (UCHAR)(funcAddr & 0xFF)); // // Unmap the NVRAM from the address space of the current process. // HalpUnmapNvram(&SavedPte[0], OldIrql); return; } /* End S002 */ #if 0 //K015 // // K00D form halfxs/mips/jxhwsup.c // // ULONG HalpReadEisaData ( IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: The function returns the Eisa bus data for a slot or address. Arguments: BusDataType - Supplies the type of bus. BusNumber - Indicates which bus. Buffer - Supplies the space to store the data. Length - Supplies a count in bytes of the maximum amount to return. Return Value: Returns the amount of data stored into the buffer. --*/ { OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES BusObjectAttributes; PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter"; PWSTR ConfigData = L"Configuration Data"; ANSI_STRING TmpString; UCHAR BusString[] = "00"; UNICODE_STRING RootName, BusName; UNICODE_STRING ConfigDataName; NTSTATUS NtStatus; PKEY_VALUE_FULL_INFORMATION ValueInformation; PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource; PCM_EISA_SLOT_INFORMATION SlotInformation; ULONG PartialCount; ULONG TotalDataSize, SlotDataSize; HANDLE EisaHandle, BusHandle; ULONG BytesWritten, BytesNeeded; PUCHAR KeyValueBuffer; ULONG i; ULONG DataLength = 0; PUCHAR DataBuffer = Buffer; BOOLEAN Found = FALSE; RtlInitUnicodeString( &RootName, EisaPath ); InitializeObjectAttributes( &ObjectAttributes, &RootName, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, NULL ); // // Open the EISA root // NtStatus = ZwOpenKey( &EisaHandle, KEY_READ, &ObjectAttributes ); if (!NT_SUCCESS(NtStatus)) { KdPrint(("HAL: Open Status = %x\n",NtStatus)); return(0); } // // Init bus number path // if (BusNumber > 99) { return (0); } if (BusNumber > 9) { BusString[0] += (UCHAR) (BusNumber/10); BusString[1] += (UCHAR) (BusNumber % 10); } else { BusString[0] += (UCHAR) BusNumber; BusString[1] = '\0'; } RtlInitAnsiString( &TmpString, BusString ); RtlAnsiStringToUnicodeString( &BusName, &TmpString, TRUE ); InitializeObjectAttributes( &BusObjectAttributes, &BusName, OBJ_CASE_INSENSITIVE, (HANDLE)EisaHandle, NULL ); // // Open the EISA root + Bus Number // NtStatus = ZwOpenKey( &BusHandle, KEY_READ, &BusObjectAttributes ); if (!NT_SUCCESS(NtStatus)) { KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus)); return(0); } // // opening the configuration data. This first call tells us how // much memory we need to allocate // RtlInitUnicodeString( &ConfigDataName, ConfigData ); // // This should fail. We need to make this call so we can // get the actual size of the buffer to allocate. // NtStatus = ZwQueryValueKey( BusHandle, &ConfigDataName, KeyValueFullInformation, ValueInformation, 0, &BytesNeeded ); KeyValueBuffer = ExAllocatePool( NonPagedPool, BytesNeeded ); if (KeyValueBuffer == NULL) { KdPrint(("HAL: Cannot allocate Key Value Buffer\n")); ZwClose(BusHandle); return(0); } ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer; NtStatus = ZwQueryValueKey( BusHandle, &ConfigDataName, KeyValueFullInformation, ValueInformation, BytesNeeded, &BytesWritten ); ZwClose(BusHandle); if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) { KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus)); ExFreePool(KeyValueBuffer); return(0); } // // We get back a Full Resource Descriptor List // Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation + ValueInformation->DataOffset); PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) &(Descriptor->PartialResourceList.PartialDescriptors); PartialCount = Descriptor->PartialResourceList.Count; for (i = 0; i < PartialCount; i++) { // // Do each partial Resource // switch (PartialResource->Type) { case CmResourceTypeNull: case CmResourceTypePort: case CmResourceTypeInterrupt: case CmResourceTypeMemory: case CmResourceTypeDma: // // We dont care about these. // PartialResource++; break; case CmResourceTypeDeviceSpecific: // // Bingo! // TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize; SlotInformation = (PCM_EISA_SLOT_INFORMATION) ((PUCHAR)PartialResource + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); while (((LONG)TotalDataSize) > 0) { if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) { SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION); } else { SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) + SlotInformation->NumberFunctions * sizeof(CM_EISA_FUNCTION_INFORMATION); } if (SlotDataSize > TotalDataSize) { // // Something is wrong again // ExFreePool(KeyValueBuffer); return(0); } if (SlotNumber != 0) { SlotNumber--; SlotInformation = (PCM_EISA_SLOT_INFORMATION) ((PUCHAR)SlotInformation + SlotDataSize); TotalDataSize -= SlotDataSize; continue; } // // This is our slot // Found = TRUE; break; } // // End loop // i = PartialCount; break; default: KdPrint(("Bad Data in registry!\n")); ExFreePool(KeyValueBuffer); return(0); } } if (Found) { i = Length + Offset; if (i > SlotDataSize) { i = SlotDataSize; } DataLength = i - Offset; RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength); } ExFreePool(KeyValueBuffer); return DataLength; } ULONG HalGetBusDataByOffset( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: The function returns the bus data for a slot or address. Arguments: BusDataType - Supplies the type of bus. BusNumber - Indicates which bus. Buffer - Supplies the space to store the data. Offset - Offset in the BusData buffer Length - Supplies a count in bytes of the maximum amount to return. Return Value: Returns the amount of data stored into the buffer. --*/ { ULONG DataLength = 0; switch (BusDataType) { case EisaConfiguration: DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length); break; } return(DataLength); } ULONG HalGetBusData( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length ) /*++ Routine Description: Subset of HalGetBusDataByOffset, just pass the request along. --*/ { return HalGetBusDataByOffset ( BusDataType, BusNumber, SlotNumber, Buffer, 0, Length ); } ULONG HalSetBusDataByOffset( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length ) /*++ Routine Description: The function sets the bus data for a slot or address. Arguments: BusDataType - Supplies the type of bus. BusNumber - Indicates which bus. Buffer - Supplies the space to store the data. Offset - Offset in the BusData buffer Length - Supplies a count in bytes of the maximum amount to return. Return Value: Returns the amount of data stored into the buffer. --*/ { ULONG DataLength = 0; return(DataLength); } ULONG HalSetBusData( IN BUS_DATA_TYPE BusDataType, IN ULONG BusNumber, IN ULONG SlotNumber, IN PVOID Buffer, IN ULONG Length ) /*++ Routine Description: Subset of HalGetBusDataByOffset, just pass the request along. --*/ { return HalSetBusDataByOffset( BusDataType, BusNumber, SlotNumber, Buffer, 0, Length ); } NTSTATUS HalAssignSlotResources ( IN PUNICODE_STRING RegistryPath, IN PUNICODE_STRING DriverClassName OPTIONAL, IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN INTERFACE_TYPE BusType, IN ULONG BusNumber, IN ULONG SlotNumber, IN OUT PCM_RESOURCE_LIST *AllocatedResources ) /*++ Routine Description: Reads the targeted device to determine it's required resources. Calls IoAssignResources to allocate them. Sets the targeted device with it's assigned resoruces and returns the assignments to the caller. Arguments: RegistryPath - Passed to IoAssignResources. A device specific registry path in the current-control-set, used to check for pre-assigned settings and to track various resource assignment information for this device. DriverClassName Used to report the assigned resources for the driver/device DriverObject - Used to report the assigned resources for the driver/device DeviceObject - Used to report the assigned resources for the driver/device (ie, IoReportResoruceUsage) BusType BusNumber SlotNumber - Together BusType,BusNumber,SlotNumber uniquely indentify the device to be queried & set. Return Value: STATUS_SUCCESS or error --*/ { // // This HAL doesn't support any buses which support // HalAssignSlotResources // return STATUS_NOT_SUPPORTED; } NTSTATUS HalAdjustResourceList ( IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList ) /*++ Routine Description: Takes the pResourceList and limits any requested resource to it's corrisponding bus requirements. Arguments: pResourceList - The resource list to adjust. Return Value: STATUS_SUCCESS or error --*/ { // // BUGBUG: This function should verify that the resoruces fit // the bus requirements - for now we will assume that the bus // can support anything the device may ask for. // return STATUS_SUCCESS; } #endif //K015