📄 par4chkd.c
字号:
/* POWER DOWN AND UP:
The PC can power down and up the PAR4CH board via the parallel port
control register bit PINIT.
Power down and up are not only useful for turning off the PAR4CH when
conversion isn't needed, they are also the only way to ensure an
overall reset of the PAR4CH board. A PowerDown and PowerUp cycle is
automatically done in Par4ch_Init.
Also note that turning off the PC will automatically force a PAR4CH
power down, even if its wall transformer is still plugged in.
Finally, the PAR4CH cannot power up and down instantly. It takes
approx 300 to 900 ms to settle to power up or down respectively.
Settling time is programed into PowerDown and PowerUp by calling the
Par4ch_Wait function.
*/
#define POWER_DOWN_WAIT 900 // milliseconds
#define POWER_UP_WAIT 300 // milliseconds
SRLOCAL int Par4ch_PowerDown( DEVINFO *Dev ) {
dbg4_printk( "Par4ch_PowerDown\n" );
// Program the control register to power down the PAR4CH:
//
// Setting the PINIT bit on the parallel port control register
// to zero powers down the PAR4CH. Other bits on the parallel
// port registers are also programmed to minimize PAR4CH
// power consumption while powered down.
// Set the parallel port data bits to zero.
Par4ch_ParPortDataWr( Dev, 0x00 );
// Power down.
Par4ch_ParPortCtrlWr( Dev, // drive all DB25 rw pins low ...
PWR_WRITE
| PDS_ASSERT
| PINIT_POWERDOWN
| PAS_ASSERT
| PIRQ_DISABLE
| PDIR_WRITE
);
// Wait for the power down settling time.
Par4ch_Wait( Dev, POWER_DOWN_WAIT );
// Check that the PAR4CH voltage good bit shows power off.
//
// This code is conditionally compiled in depending on the
// PAR4CH_TEST_VOLTAGE_BAD define.
//
#if PAR4CH_TEST_VOLTAGE_BAD == 1
if ( !Par4ch_VoltageGood( Dev ) )
// power is indeed off ... all is ok ...
return( 1 );
else
// power is still up, something is wrong!
return( 0);
#else
// don't bother testing for voltage good ... fake success
return( 1 );
#endif
}
SRLOCAL int Par4ch_PowerUp( DEVINFO *Dev ) {
dbg4_printk( "Par4ch_PowerUp\n" );
// Program the control register to power up the PAR4CH:
//
// Setting the PINIT bit on the parallel port control register
// to one powers up the PAR4CH. Other bits are programmed so
// the port is in a state ready for EPP/BPP mode.
// Set the parallel port data bits to zero.
Par4ch_ParPortDataWr( Dev, 0x00 );
// Power up.
//
// ** Other ctrl bits set for subsequent EPP/BPP operations. **
Par4ch_ParPortCtrlWr( Dev,
PWR_READ
| PDS_NEGATE
| PINIT_POWERUP
| PAS_NEGATE
| PIRQ_DISABLE
| PDIR_READ
);
// Wait for the power up settling time.
Par4ch_Wait( Dev, POWER_UP_WAIT );
// Check that the PAR4CH voltage good bit shows power on.
//
// This code is conditionally compiled in depending on the
// PAR4CH_TEST_VOLTAGE_GOOD define.
//
#if PAR4CH_TEST_VOLTAGE_GOOD == 1
if ( Par4ch_VoltageGood( Dev ) )
// then power is up and all is good ...
return( 1 );
else
// power is still down, something is wrong!
return( 0 );
#else
// don't bother testing the voltage good signal ... fake success
return( 1 );
#endif
}
/* ENHANCED PARALLEL PORT (EPP) READ/WRITE FUNCTIONS:
The PAR4CH board is primarily designed to work with the parallel port
in IEEE 1284 EPP (enhanced parallel port) mode. The following
functions are appropriate for accessing the port in the that mode.
The PAR4CH can also work with the lower performance BPP
(bidirectional parallel port) mode with appropriate read/write
functions. The selection of EPP/BPP read/write functions should be
made by specifying the ParPortMode parameter to Par4chOpen.
Besides the automatic Write, As, and Ds strobing done in EPP mode,
those signals can still be controlled by programming the parallel
port control register. For example, after PC power on As is often
asserted in the control register and needs to be turned off. This is
automatically done in the PowerUp routine above.
Note:
A few machines require the parallel port control register PS/2 dir
bit, PDIR, to be toggled for reads and writes when in EPP mode. This
is not correct according to the IEEE 1284 spec, but nevertheless is
the way some EPP ports behave. The functions below assume the PDIR
is normally set to read, toggling it for writes. Since the PC is
normally reading from the PAR4CH, this results in little performance
hit and provides compatibility with the most machines.
*/
SRLOCAL void Par4ch_EppAsRd( DEVINFO *Dev, unsigned char *Value ) {
// Read from EPP AS, assuming control reg PDIR is read ...
OsPortIn( Dev->EppPortAddr, Value );
}
SRLOCAL void Par4ch_EppAsWr( DEVINFO *Dev, unsigned char Value ) {
// Write to EPP AS reg, toggling the control reg PDIR bit ...
Par4ch_ParPortCtrlPdir( Dev, PDIR_WRITE );
OsPortOut( Dev->EppPortAddr, Value );
Par4ch_ParPortCtrlPdir( Dev, PDIR_READ);
}
SRLOCAL void Par4ch_EppDsRd( DEVINFO *Dev, unsigned char *Value ) {
// Read from EPP DS, assuming control reg PDIR is read ...
OsPortIn( Dev->EppPortData, Value );
}
SRLOCAL void Par4ch_EppDsWr( DEVINFO *Dev, unsigned char Value ) {
// Write to EPP DS, toggling the control reg PDIR bit ...
Par4ch_ParPortCtrlPdir( Dev, PDIR_WRITE);
OsPortOut( Dev->EppPortData, Value );
Par4ch_ParPortCtrlPdir( Dev, PDIR_READ);
}
/* BIDIRECTIONAL PARALLEL PORT (BPP) READ/WRITE FUNCTIONS:
These BPP drivers work by synthesizing EPP timing in software, using
the basic parallel port data and control registers. For the most
part this means several IO instructions are required where only a
single IO instruction suffices in EPP mode.
Note:
On some PCs (such as Toshiba), it is important that the parallel port
control register PS/2 dir bit, PDIR, be set *BEFORE* writing to the
data port. On such machines, if the PDIR bit is set to read, the
write to the parallel port data register will be thrown away.
*/
// shorter names for some parallel port control register bit values ...
#define PWR_R PWR_READ
#define PWR_W PWR_WRITE
#define PDS_A PDS_ASSERT
#define PDS_N PDS_NEGATE
#define PAS_A PAS_ASSERT
#define PAS_N PAS_NEGATE
#define PDIR_R PDIR_READ
#define PDIR_W PDIR_WRITE
SRLOCAL void Par4ch_BppAsRd( DEVINFO *Dev, unsigned char *Value ) {
// Synthesize EPP AS read ...
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_A | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_A | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_A | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_A | PDIR_R );
Par4ch_ParPortDataRd( Dev, Value );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
}
SRLOCAL void Par4ch_BppAsWr( DEVINFO *Dev, unsigned char Value ) {
// Synthesize EPP AS write ...
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_N | PAS_N | PDIR_W );
Par4ch_ParPortDataWr( Dev, Value );
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_N | PAS_A | PDIR_W );
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_N | PAS_A | PDIR_W );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
}
SRLOCAL void Par4ch_BppDsRd( DEVINFO *Dev, unsigned char *Value ) {
// Synthesize EPP DS read ...
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_A | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_A | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_A | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_A | PAS_N | PDIR_R );
Par4ch_ParPortDataRd( Dev, Value );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
}
SRLOCAL void Par4ch_BppDsWr( DEVINFO *Dev, unsigned char Value ) {
// Synthesize EPP DS write ...
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_N | PAS_N | PDIR_W );
Par4ch_ParPortDataWr( Dev, Value );
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_A | PAS_N | PDIR_W );
Par4ch_ParPortCtrlRw( Dev, PWR_W | PDS_A | PAS_N | PDIR_W );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
Par4ch_ParPortCtrlRw( Dev, PWR_R | PDS_N | PAS_N | PDIR_R );
}
/* PAR4CH BOARD LEVEL CONTROL REGISTER, BdCtrl:
Primary control of the PAR4CH from the PC is done via the byte wide
board control register, BdCtrl. This write only register is mapped
into EPP AsWr. The physical register is inside the XCR5128 CPLD on
the PAR4CH board.
Since the BdCtrl register is write only, the value of its current bit
settings are saved in the variable BdCtrlValue. See the following
defines for the various bit assigments.
*/
// PAR4CH BdCtrl register bit assignments and values:
#define BDCTRL_MODE0 (1 << 0)
#define BDCTRL_MODE1 (1 << 1)
#define BDCTRL_02 (1 << 2)
#define BDCTRL_SCLK (1 << 3)
#define BDCTRL_SDI (1 << 4)
#define BDCTRL_DSYNC (1 << 5)
#define BDCTRL_FIFORESET (1 << 6)
#define BDCTRL_USERLED (1 << 7)
#define BDCTRL_MODE_HALT_INIT (0x0 << 0)
#define BDCTRL_MODE_HALT_UDIO (0x1 << 0)
#define BDCTRL_MODE_RUN_EF (0x2 << 0) // ef = empty flag
#define BDCTRL_MODE_RUN_BF (0x3 << 0) // bf = buffer ready
#define BDCTRL_SCLK_LOW (0x0 << 3)
#define BDCTRL_SCLK_HIGH (0x1 << 3)
#define BDCTRL_SDI_LOW (0x0 << 4)
#define BDCTRL_SDI_HIGH (0x1 << 4)
#define BDCTRL_DSYNC_LOW (0x0 << 5) // modulators halted
#define BDCTRL_DSYNC_HIGH (0x1 << 5) // modulators running
#define BDCTRL_FIFORESET_LOW (0x0 << 6)
#define BDCTRL_FIFORESET_HIGH (0x1 << 6)
#define BDCTRL_USERLED_OFF (0x0 << 7)
#define BDCTRL_USERLED_ON (0x1 << 7)
SRLOCAL void Par4ch_BdCtrlWr( DEVINFO *Dev, unsigned char Value ) {
dbg5_printk( "Par4ch_BdCtrlWr 0x%X\n", (Value & 0x000000FF) );
// Write a value to the PAR4CH board control register.
Dev->ParPortAsWr( Dev, Value );
}
SRLOCAL void Par4ch_BdCtrlInit( DEVINFO *Dev ) {
dbg4_printk( "Par4ch_BdCtrlInit\n" );
/* Initialize the PAR4CH BdCtrl register. */
Dev->BdCtrlValue =
BDCTRL_MODE_HALT_INIT
| BDCTRL_SCLK_LOW // sclk idles low
| BDCTRL_SDI_LOW // sdi = no care
| BDCTRL_DSYNC_HIGH // modulators running
| BDCTRL_FIFORESET_LOW // leave FIFO alone
| BDCTRL_USERLED_OFF // yellow led off
;
Par4ch_BdCtrlWr( Dev, Dev->BdCtrlValue );
}
SRLOCAL void Par4ch_BdCtrlMode( DEVINFO *Dev, unsigned char Value ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -