Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

354 lines
11 KiB

/*++
*****************************************************************************
* *
* This software contains proprietary and confidential information of *
* *
* Digi International Inc. *
* *
* By accepting transfer of this copy, Recipient agrees to retain this *
* software in confidence, to prevent disclosure to others, and to make *
* no use of this software other than that for which it was delivered. *
* This is an unpublished copyrighted work of Digi International Inc. *
* Except as permitted by federal law, 17 USC 117, copying is strictly *
* prohibited. *
* *
*****************************************************************************
Module Name:
fep2hdw.c
Abstract:
This module exports routines to write commands to the FEP's command
queue, purge transmit and receive queues.
Revision History:
* $Log: /Components/Windows/NT/Async/FEP5/fep2hdw.c $
*
* 1 3/04/96 12:11p Stana
* Module exports reoutines to write commands to the FEP's command queue.
* Revision 1.18.3.2 1995/11/28 12:47:10 dirkh
* Adopt common header file.
*
* Revision 1.18.3.1 1995/09/20 17:34:42 dirkh
* WriteCommandWord is a macro of WriteCommandBytes.
* WriteCommandBytes drops the memory window lock while waiting for the FEP to consume commands.
* Rename Flush*Queue to Flush*Buffer and simplify interface.
*
* Revision 1.18 1994/08/10 19:15:49 rik
* Changed so we keep the memory spinlock while we place commands on
* the command queue. Not doing this resulted in a window where multi-
* processor systems could get in a hosed state.
*
* Revision 1.17 1994/08/03 23:33:36 rik
* changed dbg unicode strings to C strings.
*
* Revision 1.16 1994/05/11 13:53:22 rik
* Put in validation check for placing commands on the controller and making
* sure they are completed before returning.
*
* Revision 1.15 1993/12/03 13:12:12 rik
* Got rid of unused variable.
*
* Revision 1.14 1993/09/24 16:40:39 rik
* Put in wait for a command sent to the controller to complete. This should
* solve some problems with the system setting a baud rate and turning around
* and doing a query of the baud rate and getting the old value.
*
* Revision 1.13 1993/09/07 14:27:51 rik
* Ported necessary code to work properly with DEC Alpha Systems running NT.
* This was primarily changes to accessing the memory mapped controller.
*
* Revision 1.12 1993/09/01 11:02:32 rik
* Ported code over to use READ/WRITE_REGISTER functions for accessing
* memory mapped data. This is required to support computers which don't run
* in 32bit mode, such as the DEC Alpha which runs in 64 bit mode.
*
* Revision 1.11 1993/05/09 09:16:21 rik
* Changed which device name is printed for debugging output.
*
* Revision 1.10 1993/04/05 19:01:04 rik
* Had to hardcode the off for the command queue to 0x3FC because of a BUG in
* some of the FEP binaries reporting 0x3F0. I'm told this should be a
* problem with portability between the different FEPs because the
* offset for the command queue will never change. Time will tell.
*
* Revision 1.9 1993/03/05 06:05:41 rik
* Added Debugging output to help trace when flush requests are made.
*
* Revision 1.8 1993/02/25 21:12:17 rik
* Corrected function definition (ie. spelling error in function name).
*
* Revision 1.7 1993/02/25 21:08:54 rik
* Corrected complier errors. Thats what I get for not compiling before
* checking a module in!
*
* Revision 1.6 1993/02/25 20:55:23 rik
* Added 2 new functions for flushing the transmit and recieve queues on
* the controller for a given device.
*
* Revision 1.5 1993/01/22 12:32:45 rik
* *** empty log message ***
*
* Revision 1.4 1992/12/10 16:06:27 rik
* Added function to support writing byte based commands to the controller.
*
* Revision 1.3 1992/11/12 12:48:15 rik
* changes to better support time-out, read, and write problems.
*
* Revision 1.2 1992/10/28 21:46:41 rik
* Updated to include a conversion function which allows the fep driver
* to read a board address and have it return a FEP5_ADDRESS format
* address.
*
* Revision 1.1 1992/10/19 11:26:18 rik
* Initial revision
*
--*/
#include "header.h"
#ifndef _FEP2HDW_DOT_C
# define _FEP2HDW_DOT_C
static char RCSInfo_Fep2hdwDotC[] = "$Header: /Components/Windows/NT/Async/FEP5/fep2hdw.c 1 3/04/96 12:11p Stana $";
#endif
void
WriteCommandBytes( IN PDIGI_DEVICE_EXTENSION DeviceExt,
IN UCHAR Cmd,
IN UCHAR LoByte,
IN UCHAR HiByte )
{
PDIGI_CONTROLLER_EXTENSION ControllerExt = DeviceExt->ParentControllerExt;
USHORT *pCin, Cin, *pCout, Cout;
PUCHAR pCmd;
const USHORT Cmax = 0x3FC; // alas, some products set this incorrectly
#if DBG
int i;
#endif
DigiDump( DIGIFLOW, ("DigiBoard: Entering WriteCommandWord.\n") );
DigiDump( DIGIFEPCMD, ("WriteCommandWord(Port=%s,Cmd=0x%.2x,LoByte=0x%.2x,HiByte=0x%.2x)\n",
DeviceExt->DeviceDbgString, Cmd, LoByte, HiByte ) );
pCin = (PUSHORT)(ControllerExt->VirtualAddress + FEP_CIN);
pCout = (PUSHORT)(ControllerExt->VirtualAddress + FEP_COUT);
//
// Writing a command must be atomic. However, writing a command actually
// consists of two steps: 1. write command bytes and 2. update CIN.
// Fortunately, CIN and the command queue itself are (currently) in the
// same window, so we hold the window open to make the sequence atomic.
// (The spin lock for the memory window provides us exclusive access.)
// If CIN and the command queue are ever in different windows, we will
// need a per-controller command queue spin lock.
//
ASSERT( ControllerExt->Global.Window == ControllerExt->CommandQueue.Window );
EnableWindow( ControllerExt, ControllerExt->Global.Window );
//
// Wait for the previous command to complete.
//
#if DBG
for (i = 0; ; ++i)
#else
for (;;)
#endif
{
Cin = READ_REGISTER_USHORT( pCin );
Cout = READ_REGISTER_USHORT( pCout );
if( Cin == Cout )
break;
DisableWindow( ControllerExt );
// Enable other threads to access the controller.
EnableWindow( ControllerExt, ControllerExt->Global.Window );
}
ASSERT( Cin <= Cmax && !(Cin & 3) );
DigiDump( DIGIFEPCMD, ("\t%s issuing command after %d stall iterations\n",
DeviceExt->DeviceDbgString, i) );
//
// Send the command.
//
pCmd = ControllerExt->VirtualAddress
+ READ_REGISTER_USHORT( (PUSHORT)(ControllerExt->VirtualAddress + FEP_CSTART) )
+ Cin;
// Write command bytes.
WRITE_REGISTER_UCHAR( pCmd, Cmd );
WRITE_REGISTER_UCHAR( pCmd + 1, (UCHAR)DeviceExt->ChannelNumber );
WRITE_REGISTER_UCHAR( pCmd + 2, LoByte );
WRITE_REGISTER_UCHAR( pCmd + 3, HiByte );
// Update CIN.
// Because CIN != COUT, no other thread will post a command until the FEP consumes ours.
WRITE_REGISTER_USHORT( pCin, (USHORT)((Cin + 4) & Cmax) );
DisableWindow( ControllerExt ); // encourage delay
//
// Wait for the current command to complete.
//
#if DBG
for (i = 0; ; ++i)
#else
for (;;)
#endif
{
EnableWindow( ControllerExt, ControllerExt->Global.Window );
Cout = READ_REGISTER_USHORT( pCout );
DisableWindow( ControllerExt );
// Enable other threads to access the controller.
// If COUT moves, the FEP has executed the command.
if( Cout != Cin )
break;
}
DigiDump( DIGIFEPCMD, ("\t%s completing after %d stall iterations\n",
DeviceExt->DeviceDbgString, i) );
} // end WriteCommandWord
void
FlushReceiveBuffer( IN PDIGI_CONTROLLER_EXTENSION ControllerExt,
IN PDIGI_DEVICE_EXTENSION DeviceExt )
/*++
Routine Description:
Flushes a device's receive buffer on the controller.
Arguments:
ControllerExt - a pointer to the controller extension associated with
this purge request.
DeviceExt - a pointer to the device extension associated with this purge
request.
Return Value:
--*/
{
PFEP_CHANNEL_STRUCTURE ChInfo;
USHORT Rin;
#if DBG
USHORT Rout;
#endif
ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
DeviceExt->ChannelInfo.Offset);
EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
Rin = READ_REGISTER_USHORT( &ChInfo->rin );
#if DBG
Rout = READ_REGISTER_USHORT( &ChInfo->rout );
if( Rout != Rin )
{
// There is data in the buffer when we are about to flush.
LARGE_INTEGER CurrentSystemTime;
KeQuerySystemTime( &CurrentSystemTime );
DigiDump( DIGIFLUSH, (" FLUSHing hardware receive buffer: port = %s\t%u:%u\n"
" flushing %d bytes.\n",
DeviceExt->DeviceDbgString,
CurrentSystemTime.LowPart,
CurrentSystemTime.HighPart,
(Rin - Rout) & READ_REGISTER_USHORT( &ChInfo->rmax ) ) );
}
#endif
WRITE_REGISTER_USHORT( &ChInfo->rout, Rin );
DisableWindow( ControllerExt );
} // end FlushReceiveBuffer
void
FlushTransmitBuffer( IN PDIGI_CONTROLLER_EXTENSION ControllerExt,
IN PDIGI_DEVICE_EXTENSION DeviceExt )
/*++
Routine Description:
Flushes a device's transmit buffer on the controller.
Arguments:
ControllerExt - a pointer to the controller extension associated with
this purge request.
DeviceExt - a pointer to the device extension associated with this purge
request.
Return Value:
--*/
{
PFEP_CHANNEL_STRUCTURE ChInfo;
USHORT Tin;
#if DBG
USHORT Tout, Tmax;
#endif
ChInfo = (PFEP_CHANNEL_STRUCTURE)(ControllerExt->VirtualAddress +
DeviceExt->ChannelInfo.Offset);
EnableWindow( ControllerExt, DeviceExt->ChannelInfo.Window );
Tin = READ_REGISTER_USHORT( &ChInfo->tin );
#if DBG
Tout = READ_REGISTER_USHORT( &ChInfo->tout );
Tmax = READ_REGISTER_USHORT( &ChInfo->tmax );
#endif
DisableWindow( ControllerExt );
#if DBG
if( Tout != Tin )
{
// There is data in the buffer when we are about to flush.
LARGE_INTEGER CurrentSystemTime;
KeQuerySystemTime( &CurrentSystemTime );
DigiDump( DIGIFLUSH, (" FLUSHing hardware transmit buffer: port = %s\t%u:%u\n"
" flushing %d bytes.\n",
DeviceExt->DeviceDbgString,
CurrentSystemTime.LowPart,
CurrentSystemTime.HighPart,
((Tout - Tin) & Tmax) ));
}
#endif
// Even if Tin==Tout on the controller, issue the command to clear the concentrator as well.
WriteCommandWord( DeviceExt, FLUSH_TX, Tin );
} // end FlushTransmitBuffer