📄 pcidio96_aux.c
字号:
/*++
*
* Copyright (c) 1998-2005 Ardence, Inc. All rights reserved.
*
* Nodule Name:
*
* PciDio96_Aux.c
*
* Abstract:
*
* Auxilliary test program for testing interrupts from PCI-DIO-96 card.
* It has four modules:
* PciDio96_Search, PciDio96_Init, PciDio96_Cleanup and PciDio96_Fail.
* Refer to User's Manual of PCI-DIO-96 for initialization procedures and
* device parameters.
*
* Author:
*
* Duncan Xue
*
* Environment:
*
* RTX application
*
--*/
#include <windows.h>
#include <rtapi.h>
#include "pcidio96registeraddressmap.h"
//
// local variables
//
PCHAR vBAR0=NULL, vBAR1=NULL; // pointer virtual memory addresses returned by RtMapMemory
PUCHAR _base_addr; // defined in pcidio96registeraddressmap.h
//
// This routine searches for a PCI-DIO-96 card on the machine's PCI buses.
// It returns the bus number when the specified (by CardNumber) PCI-DIO-96 card has
// been found, or returns -1 if no device found.
//
int
PciDio96_Search(
int CardNumber, // input: PCI card to find
PCI_SLOT_NUMBER *pSlotNumber, // output: pointer to slot number
PPCI_COMMON_CONFIG PciData // output: PCI card information
)
{
ULONG DeviceNumber; // logical slot number for the PCI adapter
ULONG FunctionNumber; // function number on the specified adapter
ULONG BytesWritten; // return value from RtGetBusDataByOffset
ULONG Bus; // bus number
BOOLEAN Flag = TRUE; // TRUE as long as we have PCI busses
int CardIndex = 0;
pSlotNumber->u.bits.Reserved = 0;
//
// All PCI cards have been searched when we are out of PCI busses. (Flag = 0)
//
for (Bus=0; Flag; Bus++)
{
for (DeviceNumber=0; DeviceNumber < PCI_MAX_DEVICES && Flag; DeviceNumber++)
{
pSlotNumber->u.bits.DeviceNumber = DeviceNumber;
for (FunctionNumber=0; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
{
pSlotNumber->u.bits.FunctionNumber = FunctionNumber;
BytesWritten = RtGetBusDataByOffset (
PCIConfiguration,
Bus,
pSlotNumber->u.AsULONG,
PciData,
0,
PCI_COMMON_HDR_LENGTH
);
if (BytesWritten == 0)
{
// out of PCI buses
Flag = FALSE;
break;
}
if (BytesWritten == 2 && PciData->VendorID == PCI_INVALID_VENDORID)
{
// no device at this slot number, skip to next slot
break;
}
//
// A device is found, if this is our card (National Instruments PCI-DIO-96)
// return, otherwise continue until all buses have been searched.
//
if ((PciData->VendorID == 0x1093) && (PciData->DeviceID == 0x0160))
if(++CardIndex == CardNumber) // This is our card!!
return Bus; // stop searching
} // FunctionNumber-loop
} // DeviceNumber-loop
} // Bus-loop
return -1;
}
//
// This routine initializes the PCI-DIO-96 card found on the machine's PCI bus.
// It returns virtual base address of the board registers when succeeds
// or NULL otherwise
//
PCHAR
PciDio96_Init(
int intBusNumber, // input: interrupt bus number
PCI_SLOT_NUMBER *pSlotNumber, // input: pointer to slot number
PPCI_COMMON_CONFIG PciData // input: PCI card information
)
{
LARGE_INTEGER BAR0; // base port address of the MITE
LARGE_INTEGER BAR1; // base port address of the board registers
LARGE_INTEGER tBAR0, tBAR1; // translated base addresses returned by RtMapMemory
ULONG AddressSpace = 0; // indicates memory space
ULONG window_data_value = 0;
//
// Put the BusAddresses into other variables
//
BAR0.QuadPart = PciData->u.type0.BaseAddresses[0]; // MITE address
BAR1.QuadPart = PciData->u.type0.BaseAddresses[1]; // new board address
//
// Translate the base port addresses to system mapped addresses.
//
if (!RtTranslateBusAddress(
PCIBus,
intBusNumber,
BAR0,
&AddressSpace,
&tBAR0
))
{
RtPrintf("tBAR0: RtTranslateBusAddress failed.\n");
return NULL;
}
if (!RtTranslateBusAddress(
PCIBus,
intBusNumber,
BAR1,
&AddressSpace,
&tBAR1
))
{
RtPrintf("tBAR1: RtTranslateBusAddress failed.\n");
return NULL;
}
//
// Map the addresses to virtual addresses the software can use
//
vBAR0=RtMapMemory( tBAR0, 4*1024, 0); // 4K, cache disabled
if (vBAR0 == NULL)
{
RtPrintf("BAR0: Failure on RtMapMemory.\n");
return NULL;
}
vBAR1=RtMapMemory( tBAR1, 4*1024, 0); // 4K, cache disabled
if (vBAR1 == NULL)
{
RtPrintf("BAR1: Failure on RtMapMemory.");
return NULL;
}
_base_addr = vBAR1; // no mapping
//
// Set the command parameter so we can access the PCI device's control registers.
//
PciData->Command = (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE |
PCI_ENABLE_BUS_MASTER | PCI_ENABLE_WRITE_AND_INVALIDATE);
RtSetBusDataByOffset(
PCIConfiguration,
intBusNumber,
pSlotNumber->u.AsULONG,
PciData,
0,
PCI_COMMON_HDR_LENGTH
);
Sleep(500);
//
// Configure PCI MITE ASIC
// No 1 MB limit - no need to remap the memory.
// Note: You need to use the BusRelativeAddress to set the window_data_value.
//
window_data_value = ( (0xffffff00 & (ULONG)BAR1.LowPart) | (0x00000080) );
PTL(vBAR0+0x000000c0) = window_data_value;
return _base_addr;
}
//
// cleanup interrupt vector and mapped memory
//
void PciDio96_Cleanup(
HANDLE aHandle, // handle of interrupt from RtAttachInterruptVector call
int cleanMode // clean mode: 1 or 2, relevant only when aHandle not NULL
// If 1 the test does normal cleanup before exiting
// If 2 the test will use RtPrintf and sleep to allow tester to
// use Windows NT Diagnostict to verify resource use
)
{
BOOL Result;
if(aHandle != NULL)
{
if (cleanMode == 2)
{
RtPrintf("30 sec to verify interrupt resources still is claimed\n");
Sleep(30000);
}
Result = RtReleaseInterruptVector(aHandle);
if (cleanMode == 2)
{
RtPrintf("30 sec to verify interrupt resources is freed\n");
Sleep(30000);
}
//
// no need to enable interrupts here
//
if(!Result)
PciDio96_Fail("Could not release interrupt for this card");
}
if(vBAR0 != NULL )
{
RtUnmapMemory(vBAR0);
vBAR0 = NULL;
}
if(vBAR1 != NULL )
{
RtUnmapMemory(vBAR1);
vBAR1 = NULL;
}
}
/* fail: Utility routine: output error message and terminate the program
* with exit code 1.
*/
void PciDio96_Fail(char *mesg)
{
RtPrintf("Fatal Error: %s (0x%X)\n", mesg, RtGetLastError());
RtExitProcess(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -