📄 driver.c
字号:
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
usCtrByte = (counter%3) << 6;
usCtrByte |= 0x39;
// stop counting by setting counter chan for mode 5
if (counter < 3) // configure 8254 chip 1
{
outportb(usBase+3, usCtrByte);
outportb(usBase+counter, 0x0); /* write low byte */
outportb(usBase+counter, 0x0); /* write high byte */
}
else // configure 8254 chip 2
{
outportb(usBase+7, usCtrByte);
outportb(usBase+(counter%3)+4, 0x0); /* write low byte */
outportb(usBase+(counter%3)+4, 0x0); /* write high byte */
}
// disable frequency output control reg.
usCtrByte = 0x01;
usCtrByte = usCtrByte << counter;
usFoutCtrReg[DeviceNumber] &= (~usCtrByte);
outportb(usBase+24, usFoutCtrReg[DeviceNumber]);
return 0L;
}
//------------------------------------------------------------------
// Function : CounterEventStart
// PURPOSE : Configures the specified counter for an event-counting
// operation and starts the counter.
// The function uses 8254 mode 0 and initialize counter is
// 0xffff
// Parameters : DeviceNumber(IN), counter(IN)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG CounterEventStart(USHORT DeviceNumber, USHORT counter)
{
USHORT usBase;
USHORT usCtrByte, usLowByte, usHighByte, usCurrentCount;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
// initial Global variables for event counter
ulOverflow[DeviceNumber][counter] = 0;
usFirstCount[DeviceNumber][counter] = 1;
// configure counter for external clocking
outportb(usBase+counter+18, usModeCtrReg[DeviceNumber][counter]);
// set control byte for control register & set initial value
usCtrByte = (counter%3) << 6;
usCtrByte |= 0x30;
if (counter < 3) // configure 8254 chip 3
{
outportb(usBase+11, usCtrByte);
outportb(usBase+counter+8, 0xff); /* write low byte */
outportb(usBase+counter+8, 0xff); /* write high byte */
}
else // configure 8254 chip 4
{
outportb(usBase+15, usCtrByte);
outportb(usBase+(counter%3)+12, 0xff); /* write low byte */
outportb(usBase+(counter%3)+12, 0xff); /* write high byte */
}
// Read first counter
usCtrByte = (counter%3) << 6;
usCtrByte |= 0; /* set control byte for read mode */
if (counter < 3) // configure 8254 chip 3
{
outportb(usBase+11, usCtrByte);
usLowByte = inportb(usBase+counter+8); /* read low byte */
usHighByte = inportb(usBase+counter+8); /* read high byte */
}
else // configure 8254 chip 4
{
outportb(usBase+15, usCtrByte);
usLowByte = inportb(usBase+(counter%3)+12); /* read low byte */
usHighByte = inportb(usBase+(counter%3)+12); /* read high byte */
}
usHighByte <<= 8;
usCurrentCount = usHighByte | usLowByte;
usPreCount[DeviceNumber][counter] = usCurrentCount;
return ((ULONG) NULL);
}
//------------------------------------------------------------------
// Function : CounterEventRead
// PURPOSE : Reads the current counter total without disturbing
// the counting process and returns the count and
// overflow conditions.
// When your counter overs 32-BIT , its overflow will be
// set to 1.
// Parameters : DeviceNumber(IN), counter(IN), overflow(OUT), count(OUT)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG CounterEventRead(USHORT DeviceNumber,USHORT counter,
USHORT *overflow, ULONG *count)
{
USHORT usBase;
USHORT usCtrByte, usLowByte, usHighByte, usCurrentCount;
ULONG c_data, carry;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
// Read value
usCtrByte = (counter%3) << 6;
usCtrByte |= 0; /* set control byte for read mode */
if (counter < 3) // configure 8254 chip 3
{
outportb(usBase+11, usCtrByte);
usLowByte = inportb(usBase+counter+8); /* read low byte */
usHighByte = inportb(usBase+counter+8); /* read high byte */
}
else // configure 8254 chip 4
{
outportb(usBase+15, usCtrByte);
usLowByte = inportb(usBase+(counter%3)+12); /* read low byte */
usHighByte = inportb(usBase+(counter%3)+12); /* read high byte */
}
usHighByte <<= 8;
usCurrentCount = usHighByte | usLowByte;
// still wait for first valid count
if(usFirstCount[DeviceNumber][counter])
{
if (usPreCount[DeviceNumber][counter] == usCurrentCount)
{
*count = 0;
*overflow = 0;
return 0L;
}
else
{
usFirstCount[DeviceNumber][counter] = 0; // set not first counter
usPreCount[DeviceNumber][counter] = 65535; // initial previous count
}
}
c_data = ((ULONG)65536 - (ULONG)usCurrentCount); /* convert to up count */
/* check if 16-bit counter register of 8253 is over flow ? */
if(usPreCount[DeviceNumber][counter] < usCurrentCount) // over flow
ulOverflow[DeviceNumber][counter] += 1; /* increament overflow by 1 */
carry = ((ULONG)ulOverflow[DeviceNumber][counter]) << 16; /* shift overflow 16 bits */
c_data |= carry; /* convert 16-bit to 32-bit */
// check 32bit overflow ?
*overflow = 0; // clear overflow flag
if (ulOverflow[DeviceNumber][counter] > 63335L)
*overflow = 1;
*count = c_data; // return data
usPreCount[DeviceNumber][counter] = usCurrentCount; // save data
return 0L;
}
//------------------------------------------------------------------
// Function : CounterFreqStart
// PURPOSE : Configures the specified counter for frequency
// measurement and starts the counter.
// Parameters : DeviceNumber(IN), counter(IN)
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG CounterFreqStart(USHORT DeviceNumber,USHORT counter)
{
USHORT usBase;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
/* configure counter for external clocking */
outportb(usBase+counter+18, usModeCtrReg[DeviceNumber][counter]);
return 0L;
}
//------------------------------------------------------------------
// Function : CounterFreqRead
// PURPOSE : Reads the frequency measurement.
// Parameters : DeviceNumber(IN), counter(IN), FreqLevel(IN), freq(OUT)
// FreqLevel
// = MAX1K_65K(0), RANGE= 1 -- 65KHZ (need 1s)
// = MAX10K_650K(1), RANGE= 10K -- 650KHZ(need 100ms)
// = MAX100K_6500K(2), RANGE=100K -- 6.5MHZ(need 10ms)
//
// Return : NULL (success)
// ErrorCode (failure)
// Call/Called procedure cross reference :
// Call Called Explanation
//------------------------------------------------------------------
ULONG CounterFreqRead(USHORT DeviceNumber,USHORT counter,
USHORT FreqLevel, FLOAT * freq)
{
USHORT usBase;
USHORT usDelay;
USHORT usCtrByte, usCtr1Byte;
USHORT usLow1Byte, usHigh1Byte, usCurrentCount1;
USHORT usLow2Byte, usHigh2Byte, usCurrentCount2;
FLOAT fSampleRate;
usLow1Byte = 0;
usHigh1Byte = 0;
usLow2Byte = 0;
usHigh2Byte = 0;
// Is DeviceNumber out of range ?
if (DeviceNumber > MaxBoardNumber)
return ((ULONG) InvalidDeviceNumber);
// Is BaseAddr valid ?
if (usBaseAddr[DeviceNumber] == NULL)
return ((ULONG) LostBaseAddr);
// check input param correct ?
if (counter > MaxCounterNumber)
return((ULONG) InvalidCounterChannel);
// get base address
usBase = usBaseAddr[DeviceNumber];
// Prepare some thing for BIOS function call
switch(FreqLevel)
{
case MAX1_65K:
usDelay = 1000;
fSampleRate = 1;
break;
case MAX10K_650K:
usDelay = 100;
fSampleRate = 10;
break;
case MAX100K_6500K:
usDelay = 10;
fSampleRate = 100;
break;
default:
usDelay = 1000;
fSampleRate = 1;
break;
}
// first : set control byte for control register
usCtrByte = (counter%3) << 6;
usCtr1Byte = usCtrByte | 0x30;
if (counter < 3) // configure 8254 chip 3
{
outportb(usBase+11, usCtr1Byte);
outportb(usBase+counter+8, 0xff); /* write low byte */
outportb(usBase+counter+8, 0xff); /* write high byte */
}
else // configure 8254 chip 4
{
outportb(usBase+15, usCtr1Byte);
outportb(usBase+(counter%3)+12, 0xff); /* write low byte */
outportb(usBase+(counter%3)+12, 0xff); /* write high byte */
}
// delay 1/2 time
delay(usDelay/2);
// second: read counter
usCtr1Byte = usCtrByte | 0; /* set control byte for read mode */
if (counter < 3) // configure 8254 chip 3
{
outportb(usBase+11, usCtr1Byte);
usLow1Byte = inportb(usBase+counter+8); /* read low byte */
usHigh1Byte = inportb(usBase+counter+8); /* read high byte */
}
else // configure 8254 chip 4
{
outportb(usBase+15, usCtr1Byte);
usLow1Byte = inportb(usBase+(counter%3)+12); /* read low byte */
usHigh1Byte = inportb(usBase+(counter%3)+12); /* read high byte */
}
// second: delay time 1/2
delay(usDelay/2);
// third: read counter again
usCtr1Byte = usCtrByte | 0; /* set control byte for read mode */
if (counter < 3) // configure 8254 chip 3
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -