📄 cntint.c
字号:
/*
'**********************************************************************
'* Program : CNTINT.C *
'* Revision : 1.00 *
'* Date : 06/25/2004 Shen Xinyang *
'*====================================================================*
'* *
'* pDAQ-722 has 2 16-bit Timer supporting this feature. *
'* They generate INTERRUPT if reaching the terminal count. *
'* *
'* This demo program performs Counter Interrupt by using Counter 2. *
'* It will generate interrupt after 100 event counts. *
'* *
'**********************************************************************
*/
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "PCI.C"
#include "PCI32.h"
/************
* Global variable declare
************/
dword gdwBaseAddr; //CS0 Base address
dword gdwBaseAddrCs1; //CS1 Base address
dword gdwBaseAddrBa1; //Local contrl Base address
int giIrqNum; //IRQ number
int giIntControlRegAddr; //PCI32 Interrupt control register address.
int giIrqFlagBit; //Interrupt flag
long glIntCount; //Interrupt generate count
dword IntCount; //accepted interrupt counter
static dword inpd(int portnum); //input 32 bit ward
/***********
* Local fucntion declare
***********/
void interrupt IrqHandler(void);
byte InitInterrupt( int iIrqNum,
void interrupt (*pIsrHandler)(),
void interrupt (**pOldIsr)() );
void RestoreOldIsr(int iIrqNum, byte ucIrqMask, void interrupt (*pOldIsr)() );
void main(void)
{
word wVendorId, wDeviceId, wIndex;
int iErrCode;
byte ucBusNumber, ucDevAndFunc;
dword dwData,dwINTCSR;
int iPort, iPortAddr, iCfgAddr;
byte ucCfgReg, ucDiCfgWord, ucTrigType;
word wCount;
void interrupt (*pOldIsr)(void);
byte ucIrqMask;
long lPreIntCount;
wVendorId = VENDOR_ID;
wDeviceId = DEVICE_ID;
wIndex = 0;
clrscr();
iPort = 0x31;
iPort = iPort & 0x0f; //port for input
wCount = 100; //Down count value
/***************************
* Get pci32ad resource
***************************/
//
// Search pci32ad
//
for( wIndex=0; wIndex < 32; wIndex++)
{
iErrCode = find_pci_device(
wDeviceId,
wVendorId,
wIndex,
&ucBusNumber,
&ucDevAndFunc );
if (iErrCode == NOT_SUCCESSFUL )
{
printf("\n pci32ad search fail.\n");
exit(1);
}
iErrCode = read_configuration_dword(
ucBusNumber,
ucDevAndFunc,
PCI_CS_SUBSYSTEM_ID,
&dwData);
if(dwData == SUBSYSTEM_ID)
break;
}
//
//Get base address, from PCI base address range 2
//
iErrCode = read_configuration_dword(
ucBusNumber,
ucDevAndFunc,
PCI_CS_BASE_ADDRESS_2,
&dwData);
if (iErrCode == NOT_SUCCESSFUL)
{
printf("\npci32ad gets base address failure.\n");
exit(1);
}
else
gdwBaseAddr = dwData & 0xfffffffc;//base address of Local space 0
//
//Get base address, from PCI base address range 3
//
iErrCode = read_configuration_dword(
ucBusNumber,
ucDevAndFunc,
PCI_CS_BASE_ADDRESS_3,
&dwData);
if (iErrCode == NOT_SUCCESSFUL)
{
printf("\npci32ad gets base address fail.\n");
exit(1);
}
else
gdwBaseAddrCs1 = dwData & 0xfffffffc;//base address of local space 1
//
//Get base address, from PCI base address range 1
//
iErrCode = read_configuration_dword(
ucBusNumber,
ucDevAndFunc,
PCI_CS_BASE_ADDRESS_1,
&dwData);
if (iErrCode == NOT_SUCCESSFUL)
{
printf("\npci32ad gets base address fail.\n");
exit(1);
}
else
gdwBaseAddrBa1 = dwData & 0xfffffffc;//address for i/o access to local address
/***************************
* Device configuration
***************************/
//
// enable PLX 9054 PCI interrupt
//
// dwINTCSR = inportb(gdwBaseAddrBa1+0xe8);
dwINTCSR = inpd(gdwBaseAddrBa1+0x68);
dwData = dwINTCSR;
dwData = dwData | 0x01; //Local Interrupt 1 Enable
outportb(gdwBaseAddrBa1+0x68, dwData);
//
// Get Interrupt line
//
iErrCode = read_configuration_dword(
ucBusNumber,
ucDevAndFunc,
PCI_CS_INTERRUPT_LINE,
&dwData);
if (iErrCode == NOT_SUCCESSFUL)
{
printf("\npci32ad gets interrupt line fail.\n");
exit(1);
}
else
giIrqNum = dwData & 0xf;
/**************
* Install ISR.
**************/
ucIrqMask = InitInterrupt(giIrqNum, IrqHandler, &pOldIsr);
/************
* Polling interrupt count
************/
glIntCount = 0;
lPreIntCount = 1;
while(!kbhit())
{
if(lPreIntCount < glIntCount)
{
printf("\n\nInterrupt generated count: %lu", glIntCount);
printf("\nPress any key to stop...");
lPreIntCount = glIntCount;
}
}
if(kbhit()) getch();
printf("\n The number of interrupt is %lu",IntCount);
/************
* Restore interrupt Control/Status Register
************/
outportb(gdwBaseAddrBa1+0x68,dwINTCSR);
/************
* Stop IRQ and restore system ISR
************/
RestoreOldIsr(giIrqNum, ucIrqMask, pOldIsr);
}//main
/************************************************************************
* Function: Init ISR to handle device generated IRQ
* Paramater: iIrqNum(中断号), IN, IRQ number.
* pIsrHandler,IN, ISR handler for installation.
* pOldIsr, OUT, Old ISR routine.
* return: IRQ mask
* note: 当中断号小于8时,中断向量号为iIrqNum+8,否则为iIrqNum-8+0x70
************************************************************************/
byte InitInterrupt( int iIrqNum,
void interrupt (*pIsrHandler)(),
void interrupt (**pOldIsr)() )
{
byte ucIrqMask, ucTotalMask;
//
// 1. DISABLE PC INTERRUPT
//
disable();
//
// 2. STORE OLD INT. HANDLER */
//
if ( iIrqNum < 8 )
*pOldIsr = getvect(iIrqNum+8);
else
*pOldIsr = getvect(iIrqNum-8+0x70);
//
// 3. SET INTERRUPT VECTOR
//
if(iIrqNum < 8)
setvect(iIrqNum+8, pIsrHandler);
else
setvect(iIrqNum-8+0x70, pIsrHandler);
//
// 4. ENABLE 8259 INT. MASK
//
if(iIrqNum < 8)
{
ucTotalMask = inportb(0x21);
ucIrqMask = ucTotalMask & (0x01<<iIrqNum);
outportb(0x21, ucTotalMask & ~(0x01<<iIrqNum) );
}
else
{
ucTotalMask = inportb(0xa1);
ucIrqMask = ucTotalMask & ~(0x01 << (iIrqNum-8));
outportb(0xa1, ucTotalMask & ~(0x01<<(iIrqNum-8)));
}
IntCount=0;
//
// 5. ENABLE PC INTERRUPT
//
enable();
return(ucIrqMask);
}//InitInterrupt
/**************************************************************
* Function: Restore system ISR.
* Paramater: iIrqNum, IN, IRQ number
* ucIrqMask, IN, IRQ mask before install ISR
* pOldIsr, IN, Old ISR. restore it as service routine.
*
**************************************************************/
void RestoreOldIsr( int iIrqNum,
byte ucIrqMask,
void interrupt (*pOldIsr)() )
{
byte ucTotalMask;
disable();
if ( iIrqNum < 8 )
{
ucTotalMask = (inportb(0x21) & ~(0x01<<iIrqNum)) | ucIrqMask;//inputb(0x20) shen
outportb(0x21, ucTotalMask);
setvect(iIrqNum+8, pOldIsr);
}
else
{
ucTotalMask = (inportb(0xa1) & ~(0x01<<(iIrqNum-8))) | ucIrqMask;
// ucTotalMask = (inportb(0xa0) & ~(0x01<<(iIrqNum-8))) | ucIrqMask;
outportb(0xa1, ucTotalMask);
setvect(iIrqNum-8+0x70, pOldIsr);
}
enable();
}
/**************************************************************
* Function : IrqHandler
* Interrupt service routine for pci32ad DI interrupt.
* fucntion.
**************************************************************/
void interrupt IrqHandler(void)
{
byte ucRegVal;
dword dPCM[8192];
int i,j;
disable();
for(i=0;i<16;i++)//16 channels
{
for(j=0;j<8192;j++)
{
dPCM[j]=inpd(gdwBaseAddr+0x31);
}
}
IntCount++;
//Enable system to accept next interrupt
/* outportb(0x20,0x20);
if ( giIrqNum > 7 )
outportb(0xa0,0x20);
*/
if (giIrqNum < 8)
outportb(0x20,0x20);
else
outportb(0xa0,0x20);
enable();
}//IrqHandler
/**************************************************************
* Function : inpd(int portnum)
* dword input from portnum.
* fucntion.
**************************************************************/
static dword inpd(int portnum)
{
static dword value;
asm mov dx,portnum;
asm lea bx,value;
__emit__(0x66,0x50, //push eax
0x66,0xED, //in eax,dx
0x66,0x89,0x07, //mov [bx],eax
0x66,0x58); //pop eax
return value;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -