Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3239 lines
105 KiB

/*-------------------------------------------------------------------
| ioctl.c - handle all the misc. serial ioctl calls.
4-05-00 - Add address (&) operator to actual parameter passed to sWriteTxBlk
5-13-99 - enable RTS toggling for VS
2-15-99 - make SerialSetHandflow() public, so pnp can call it. kpb
1-21-99 - fix immed char send to trigger EV_TXEMPTY, add some support
for VS immediate char send.
11-24-98 - update DBG kdprint messages for event handling tests - kpb
9-24-98 - include tx-shift-reg in getcommstat report - kpb.
4-29-98 - adjust break output to start immediately if possible - kpb.
Copyright 1993-98 Comtrol Corporation. All rights reserved.
|--------------------------------------------------------------------*/
#include "precomp.h"
typedef struct {
ULONG struct_size;
ULONG num_ports;
ULONG total_loads;
ULONG good_loads;
ULONG backup_server;
ULONG state;
ULONG iframes_sent;
ULONG rawframes_sent; // was send_rawframes
ULONG ctlframes_sent; // was send_ctlframes
ULONG iframes_resent; // was pkt_resends
ULONG iframes_outofseq; // was ErrBadIndex
ULONG frames_rcvd; // was: rec_pkts
ULONG nic_index;
unsigned char dest_addr[6];
} PROBE_DEVICE_STRUCT;
typedef struct {
ULONG struct_size;
ULONG Open;
ULONG pkt_sent;
ULONG pkt_rcvd_ours;
ULONG pkt_rcvd_not_ours;
char NicName[64];
unsigned char address[6];
} PROBE_NIC_STRUCT;
static PSERIAL_DEVICE_EXTENSION find_ext_mac_match(unsigned char *mac_addr);
static int ProbeDevices(unsigned char *pPtr, int availableLength);
static int ProbeNic(unsigned char *pPtr, int availableLength);
/*-------------------------------------------------------------------
Function : SerialIoControl
Purpose: Process Ioctls for a device.
Call: SerialIoControl(DeviceObject,Irp)
PDEVICE_OBJECT DeviceObject: Pointer to the Device Object
PIRP Irp: Pointer to the I/O Request Packet
Return: STATUS_SUCCESS: always
STATUS_FAIL: if request couldn't be fulfilled
Comments: This function is the device driver IOCTL entry point.
|--------------------------------------------------------------------*/
NTSTATUS SerialIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
KIRQL OldIrql;
BOOLEAN acceptingIRPs;
acceptingIRPs = SerialIRPPrologue(Extension);
if (acceptingIRPs == FALSE) {
MyKdPrint(D_Ioctl,("Ioctl:no irps accepted!\n"))
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
SerialCompleteRequest(Extension, Irp, IO_NO_INCREMENT);
return STATUS_NO_SUCH_DEVICE;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0L;
MyKdPrint(D_Ioctl,("SerialIoControl: %x\n",
IrpSp->Parameters.DeviceIoControl.IoControlCode))
// Make sure we aren't aborting due to error (ERROR_ABORT)
if (Extension->ErrorWord)
{
if (Extension->DeviceType == DEV_PORT)
{
if (SerialCompleteIfError(DeviceObject, Irp) != STATUS_SUCCESS)
{
MyKdPrint(D_Ioctl,("ErrSet, Cancel!\n"))
{ExtTrace(Extension,D_Ioctl,"ErrSet!");}
return STATUS_CANCELLED;
}
}
}
//
// Make sure IOCTL is applicable for the device type (i.e. ignore port
// level IOCTL's if board object is specified
//
if (Extension->DeviceType == DEV_BOARD)
{
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_SERIAL_CONFIG_SIZE:
case IOCTL_SERIAL_GET_COMMCONFIG:
case IOCTL_SERIAL_SET_COMMCONFIG:
case IOCTL_RCKT_GET_STATS:
case IOCTL_RCKT_ISR_CNT:
case IOCTL_RCKT_CHECK:
case IOCTL_RCKT_MONALL:
case IOCTL_RCKT_SET_MODEM_RESET:
case IOCTL_RCKT_CLEAR_MODEM_RESET:
case IOCTL_RCKT_SEND_MODEM_ROW:
case IOCTL_RCKT_SET_MODEM_RESET_OLD:
case IOCTL_RCKT_CLEAR_MODEM_RESET_OLD:
case IOCTL_RCKT_GET_RCKTMDM_INFO_OLD:
case IOCTL_RCKT_SEND_MODEM_ROW_OLD:
break; // Allowable board level IOCTL's
default:
MyKdPrint (D_Ioctl, (" Bad Status: %xH on IIOCTL: %xH\n", Status,
IrpSp->Parameters.DeviceIoControl.IoControlCode));
ExtTrace2 (Extension, D_Ioctl, " Bad Status:%xH on IIOCTL:%xH",
Status, IrpSp->Parameters.DeviceIoControl.IoControlCode);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
SerialCompleteRequest(Extension, Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
};
// Main IOCTL switch
//ExtTrace1(Extension,D_Ioctl,"Ioctl:%x",
// IrpSp->Parameters.DeviceIoControl.IoControlCode);
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
//******************************
case IOCTL_SERIAL_GET_STATS : // get performace stats
{
PSERIALPERF_STATS sp = Irp->AssociatedIrp.SystemBuffer;
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIALPERF_STATS)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIALPERF_STATS);
Status = STATUS_SUCCESS;
sp->TransmittedCount = Extension->OurStats.TransmittedCount -
Extension->OldStats.TransmittedCount;
sp->FrameErrorCount = Extension->OurStats.FrameErrorCount -
Extension->OldStats.FrameErrorCount;
sp->SerialOverrunErrorCount = Extension->OurStats.SerialOverrunErrorCount -
Extension->OldStats.SerialOverrunErrorCount;
sp->BufferOverrunErrorCount = Extension->OurStats.BufferOverrunErrorCount -
Extension->OldStats.BufferOverrunErrorCount;
sp->ParityErrorCount = Extension->OurStats.ParityErrorCount -
Extension->OldStats.ParityErrorCount;
}
break;
//******************************
case IOCTL_SERIAL_CLEAR_STATS : // clear performace stats
{
Extension->OldStats.TransmittedCount =
Extension->OurStats.TransmittedCount;
Extension->OldStats.FrameErrorCount =
Extension->OurStats.FrameErrorCount;
Extension->OldStats.SerialOverrunErrorCount =
Extension->OurStats.SerialOverrunErrorCount;
Extension->OldStats.BufferOverrunErrorCount =
Extension->OurStats.BufferOverrunErrorCount;
Extension->OldStats.ParityErrorCount =
Extension->OurStats.ParityErrorCount;
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
//******************************
case IOCTL_SERIAL_SET_BAUD_RATE :
{
ULONG DesiredBaudRate;
MyKdPrint(D_Ioctl,("[Set Baud Rate]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_BAUD_RATE))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl,("[Buffer too Small]\n"))
break;
}
DesiredBaudRate =
((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate;
ExtTrace1(Extension,D_Ioctl,"Set Baud Rate:%d",DesiredBaudRate);
Status = ProgramBaudRate(Extension,DesiredBaudRate);
break;
}
//******************************
case IOCTL_SERIAL_GET_BAUD_RATE:
{
PSERIAL_BAUD_RATE Br =
(PSERIAL_BAUD_RATE)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("[Get Baud Rate]\n"))
ExtTrace1(Extension,D_Ioctl,"Get Baud Rate:%d",Extension->BaudRate);
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_BAUD_RATE))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&Extension->ControlLock,&OldIrql);
Br->BaudRate = Extension->BaudRate;
KeReleaseSpinLock(&Extension->ControlLock,OldIrql);
Irp->IoStatus.Information = sizeof(SERIAL_BAUD_RATE);
break;
}
//*********************************
case IOCTL_SERIAL_SET_LINE_CONTROL:
{
PSERIAL_LINE_CONTROL DesiredLineControl;
MyKdPrint(D_Ioctl,("[Set Line Control]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_LINE_CONTROL))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
DesiredLineControl =
((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer));
ExtTrace(Extension,D_Ioctl, "Set Line Ctrl");
Status = ProgramLineControl(Extension,DesiredLineControl);
break;
}
//*********************************
case IOCTL_SERIAL_GET_LINE_CONTROL:
{
PSERIAL_LINE_CONTROL Lc =
(PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("[Get Line Control]\n"))
ExtTrace(Extension,D_Ioctl,"Get Line Ctrl");
Irp->IoStatus.Information = sizeof(SERIAL_LINE_CONTROL);
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_LINE_CONTROL))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Lc->Parity=Extension->LineCtl.Parity;
Lc->WordLength=Extension->LineCtl.WordLength;
Lc->StopBits=Extension->LineCtl.StopBits;
break;
}
//******************************
case IOCTL_SERIAL_SET_TIMEOUTS:
{
PSERIAL_TIMEOUTS NewTimeouts =
((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
MyKdPrint(D_Ioctl,("[Set Timeouts]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_TIMEOUTS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
(NewTimeouts->ReadTotalTimeoutConstant == MAXULONG))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
ExtTrace3(Extension,D_Ioctl,"Timeouts-RIT:%xH RM:%xH RC:%xH",
NewTimeouts->ReadIntervalTimeout,
NewTimeouts->ReadTotalTimeoutMultiplier,
NewTimeouts->ReadTotalTimeoutConstant);
ExtTrace2(Extension,D_Ioctl," WM:%xH WC:%xH",
NewTimeouts->WriteTotalTimeoutMultiplier,
NewTimeouts->WriteTotalTimeoutConstant);
KeAcquireSpinLock( &Extension->ControlLock, &OldIrql );
Extension->Timeouts.ReadIntervalTimeout =
NewTimeouts->ReadIntervalTimeout;
Extension->Timeouts.ReadTotalTimeoutMultiplier =
NewTimeouts->ReadTotalTimeoutMultiplier;
Extension->Timeouts.ReadTotalTimeoutConstant =
NewTimeouts->ReadTotalTimeoutConstant;
Extension->Timeouts.WriteTotalTimeoutMultiplier =
NewTimeouts->WriteTotalTimeoutMultiplier;
Extension->Timeouts.WriteTotalTimeoutConstant =
NewTimeouts->WriteTotalTimeoutConstant;
KeReleaseSpinLock( &Extension->ControlLock, OldIrql );
break;
}
//******************************
case IOCTL_SERIAL_GET_TIMEOUTS:
{
MyKdPrint(D_Ioctl,("[Get Timeouts]\n"))
ExtTrace(Extension,D_Ioctl,"Get Timeouts");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_TIMEOUTS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock( &Extension->ControlLock, &OldIrql );
*((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = Extension->Timeouts;
Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);
KeReleaseSpinLock( &Extension->ControlLock, OldIrql );
break;
}
//**************************
case IOCTL_SERIAL_SET_CHARS:
{
SERIAL_IOCTL_SYNC S;
PSERIAL_CHARS NewChars =
((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
MyKdPrint(D_Ioctl,("[Set Xon/Xoff Chars]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_CHARS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
ExtTrace3(Extension,D_Ioctl,"Set Chars Xon:%xH, Xoff:%xH Evt:%xH",
NewChars->XonChar,NewChars->XoffChar, NewChars->EventChar);
// The only thing that can be wrong with the chars
// is that the xon and xoff characters are the same.
#ifdef COMMENT_OUT
// comment out kpb, problem with hardware flow control, nt
// may connect and do this(Delrina WinFaxPro, SAPS modem pooling
// had trouble erroring out, but not on standard microsoft port.
if (NewChars->XonChar == NewChars->XoffChar)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
#endif
// We acquire the control lock so that only
// one request can GET or SET the characters
// at a time. The sets could be synchronized
// by the interrupt spinlock, but that wouldn't
// prevent multiple gets at the same time.
S.Extension = Extension;
S.Data = NewChars;
KeAcquireSpinLock(&Extension->ControlLock,&OldIrql);
Extension->SpecialChars.EofChar = NewChars->EofChar;
Extension->SpecialChars.ErrorChar = NewChars->ErrorChar;
Extension->SpecialChars.BreakChar=NewChars->BreakChar;
// Only set up byte in case we're already EventChar-ing it,
// Actual programming of interrupt is done in wait on mask call.
Extension->SpecialChars.EventChar=NewChars->EventChar;
Extension->SpecialChars.XonChar=NewChars->XonChar;
Extension->SpecialChars.XoffChar=NewChars->XoffChar;
#ifdef S_RK
sSetRxCmpVal1(Extension->ChP,NewChars->EventChar);
sSetTxXONChar(Extension->ChP,NewChars->XonChar);
sSetTxXOFFChar(Extension->ChP,NewChars->XoffChar);
#else
pSetEventChar(Extension->Port,NewChars->EventChar);
pSetXONChar(Extension->Port,NewChars->XonChar);
pSetXOFFChar(Extension->Port,NewChars->XoffChar);
#endif
KeReleaseSpinLock(&Extension->ControlLock,OldIrql);
break;
}
//**************************
case IOCTL_SERIAL_GET_CHARS:
{
MyKdPrint(D_Ioctl,("[Get Xon/Xoff Chars]\n"))
ExtTrace(Extension,D_Ioctl,"Get Xon/Xoff Chars");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_CHARS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
KeAcquireSpinLock(&Extension->ControlLock,&OldIrql);
// Copy the whole struct over to the buffer
*((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer) =
Extension->SpecialChars;
Irp->IoStatus.Information = sizeof(SERIAL_CHARS);
KeReleaseSpinLock(&Extension->ControlLock,OldIrql);
break;
}
case IOCTL_SERIAL_SET_DTR:
case IOCTL_SERIAL_CLR_DTR:
{
MyKdPrint(D_Ioctl,("[Set and Clr DTR]\n"))
// We acquire the lock so that we can check whether
// automatic dtr flow control is enabled. If it is,
// then return an error since the app is not allowed
// to touch this if it is automatic.
KeAcquireSpinLock(&Extension->ControlLock, &OldIrql);
if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK)
== SERIAL_DTR_HANDSHAKE)
{ // bogus
//Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
//Status = STATUS_INVALID_PARAMETER;
}
else
{
if(IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_SET_DTR )
{
ExtTrace(Extension,D_Ioctl,"Set DTR");
#ifdef S_VS
pSetDTR(Extension->Port);
#else
sSetDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
}
else
{
//must be IOCTL_SERIAL_CLR_DTR
ExtTrace(Extension,D_Ioctl,"Clr DTR");
#ifdef S_VS
pClrDTR(Extension->Port);
#else
sClrDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
}
}
KeReleaseSpinLock(&Extension->ControlLock, OldIrql);
break;
}
//************************
case IOCTL_SERIAL_RESET_DEVICE:
MyKdPrint(D_Ioctl,("[Reset Device]\n"));
ExtTrace(Extension,D_Ioctl,"Reset Device");
// Example driver also takes no action
break;
//************************
case IOCTL_SERIAL_SET_RTS:
MyKdPrint(D_Ioctl,("[Set RTS]\n"));
ExtTrace(Extension,D_Ioctl,"Set RTS");
// Make sure RTS isn't already used for handshake or toggle
if( ( (Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_RTS_HANDSHAKE) ||
( (Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
)
{
Status = STATUS_INVALID_PARAMETER;
ExtTrace(Extension,D_Ioctl," not set,flow");
}
else
{
if (!(Extension->Option & OPTION_RS485_OVERRIDE))
{
#ifdef S_VS
pSetRTS(Extension->Port);
#else
sSetRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
else
{
ExtTrace(Extension,D_Ioctl," not set,485");
}
}
break;
//************************
case IOCTL_SERIAL_CLR_RTS:
MyKdPrint(D_Ioctl,("[Clr RTS]\n"));
ExtTrace(Extension,D_Ioctl,"Clr RTS");
// Make sure RTS isn't already used for handshake or toggle
if( ( (Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_RTS_HANDSHAKE) ||
( (Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) ==
SERIAL_TRANSMIT_TOGGLE)
)
{
Status = STATUS_INVALID_PARAMETER;
ExtTrace(Extension,D_Ioctl," not clr,flow");
}
else
{
if (!(Extension->Option & OPTION_RS485_OVERRIDE))
{
#ifdef S_VS
pClrRTS(Extension->Port);
#else
sClrRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
}
else
{
ExtTrace(Extension,D_Ioctl," not clr,485");
}
}
break;
//*************************
case IOCTL_SERIAL_SET_XOFF:
MyKdPrint(D_Ioctl,("[Set Xoff]\n"));
ExtTrace(Extension,D_Ioctl,"Set Xoff");
#ifdef S_RK
if (sIsTxSoftFlowCtlEnabled(Extension->ChP))
{
sDisTxSoftFlowCtl(Extension->ChP); // turn off Tx software flow control
sDisTransmit(Extension->ChP); // Stop the transmitter
sEnRxIntCompare2(Extension->ChP,(unsigned char) Extension->SpecialChars.XonChar);
Extension->TXHolding |= SERIAL_TX_XOFF;
Extension->TXHolding |= ST_XOFF_FAKE;
}
#else
if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
{
Extension->TXHolding |= SERIAL_TX_XOFF;
pOverrideSetXoff(Extension->Port);
}
#endif
break;
//************************
case IOCTL_SERIAL_SET_XON:
MyKdPrint(D_Ioctl,("[Set Xon]\n"));
ExtTrace(Extension,D_Ioctl,"Set Xon");
#ifdef S_VS
{
pOverrideClearXoff(Extension->Port);
Extension->TXHolding &= ~SERIAL_TX_XOFF;
}
#else
if (Extension->TXHolding & ST_XOFF_FAKE)
{
Extension->TXHolding &= ~SERIAL_TX_XOFF;
Extension->TXHolding &= ~ST_XOFF_FAKE;
if ((Extension->TXHolding &
(SERIAL_TX_DCD | SERIAL_TX_DSR | ST_XOFF_FAKE)) == 0)
sEnTransmit(Extension->ChP); // Start up the transmitter
sDisRxCompare2(Extension->ChP);
sEnTxSoftFlowCtl(Extension->ChP); // turn off Tx software flow control
}
// override an actual XOFF from remote
sClrTxXOFF(Extension->ChP);
// check for IOCTL_SERIAL_SET_XOFF state
if(Extension->TXHolding & SERIAL_TX_XOFF)
{
// Make sure BREAK state hasn't disabled the Transmitter
if(!(Extension->TXHolding & SERIAL_TX_BREAK))
sEnTransmit(Extension->ChP);
Extension->TXHolding &= ~SERIAL_TX_XOFF;
}
#endif
break;
//******************************
case IOCTL_SERIAL_SET_BREAK_ON:
{
ExtTrace(Extension,D_Ioctl,"Set Break on");
#ifdef S_VS
pSetBreak(Extension->Port);
Extension->TXHolding |= SERIAL_TX_BREAK;
#else
IoAcquireCancelSpinLock(&OldIrql);
if( !(Extension->TXHolding & SERIAL_TX_BREAK) )
{
// Stop the transmitter
sDisTransmit(Extension->ChP);
// Request break, Polling will check on Transmitter empty
Extension->TXHolding |= SERIAL_TX_BREAK;
// Make sure Transmitter is empty before slamming BREAK
// Check the bit twice in case of time between buf and txshr load
if( (sGetChanStatusLo(Extension->ChP) & TXSHRMT) &&
(sGetChanStatusLo(Extension->ChP) & TXSHRMT) )
{
sSendBreak(Extension->ChP);
Extension->DevStatus &= ~COM_REQUEST_BREAK;
}
else
Extension->DevStatus |= COM_REQUEST_BREAK;
}
IoReleaseCancelSpinLock(OldIrql);
#endif
break;
}
//******************************
case IOCTL_SERIAL_SET_BREAK_OFF:
{
ExtTrace(Extension,D_Ioctl,"Set Break Off");
#ifdef S_VS
if (Extension->TXHolding & SERIAL_TX_BREAK)
{
Extension->TXHolding &= ~SERIAL_TX_BREAK;
pClrBreak(Extension->Port);
}
#else
IoAcquireCancelSpinLock(&OldIrql);
if(Extension->TXHolding & SERIAL_TX_BREAK)
{
Extension->TXHolding &= ~SERIAL_TX_BREAK;
sClrBreak(Extension->ChP);
if(!(Extension->TXHolding & SERIAL_TX_XOFF))
{
sEnTransmit(Extension->ChP);
}
}
if(Extension->DevStatus & COM_REQUEST_BREAK)
{
// If we hit this code, the requested BREAK will not have gone out
Extension->DevStatus &= ~COM_REQUEST_BREAK;
}
IoReleaseCancelSpinLock(OldIrql);
#endif
break;
}
//******************************
case IOCTL_SERIAL_SET_QUEUE_SIZE:
{
LONG new_size;
PUCHAR NewBuf;
PSERIAL_QUEUE_SIZE Rs =
((PSERIAL_QUEUE_SIZE)(Irp->AssociatedIrp.SystemBuffer));
MyKdPrint(D_Ioctl,("[Set Queue Size]\n"));
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_QUEUE_SIZE))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
new_size = (LONG) Rs->InSize;
ExtTrace1(Extension,D_Ioctl,"Set Queue Size, In:%d", new_size);
if (new_size > 0x20000L)
new_size = 0x20000L; /// limit to about 128K
// try to allocate buffer here if user requests larger buffer
// don't resize if they want to shrink(why bother)
if (new_size <= Extension->RxQ.QSize)
{
Status = STATUS_SUCCESS;
break;
}
++new_size; // some circular queue wierdness
IoAcquireCancelSpinLock(&OldIrql);
NewBuf = our_locked_alloc(new_size+16, "exRX"); // add some slop
if (NewBuf != NULL)
{
// Eprintf("Resized Buffer, new:%d, old:%d",new_size-1, Extension->RxQ.QSize-1);
Extension->RxQ.QSize = new_size;
our_free(Extension->RxQ.QBase, "exRX");
Extension->RxQ.QBase= NewBuf;
Extension->RxQ.QGet = 0;
Extension->RxQ.QPut = 0;
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_INVALID_PARAMETER; // not the greatest choise
}
IoReleaseCancelSpinLock(OldIrql);
break;
}
//******************************
case IOCTL_SERIAL_GET_WAIT_MASK:
// This mask contains the various Events the WaitIrp is waiting
// for from SetCommMask(), such as EV_BREAK, EV_CTS, EV_DSR,
// EV_ERR, EV_RING, EV_RLSD, EV_RXCHAR, EV_RXFLAG, EV_TXEMPTY
MyKdPrint(D_Ioctl,("[Get Wait Mask:%xH\n]",Extension->IsrWaitMask))
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
ExtTrace1(Extension,D_Ioctl,"Get Wait Mask:%xH",Extension->IsrWaitMask);
Irp->IoStatus.Information = sizeof(ULONG);
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) = Extension->IsrWaitMask;
break;
//******************************
case IOCTL_SERIAL_SET_WAIT_MASK:
{
ULONG NewMask;
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG) )
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
else
{
NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
MyKdPrint(D_Ioctl,("set wait mask:%xH\n",NewMask))
ExtTrace1(Extension,D_Ioctl,"Set Wait Mask:%xH",NewMask);
}
//------- Complete the old wait if there is one.
#ifdef NEW_WAIT_SYNC_LOCK
SyncUp(Driver.InterruptObject,
&Driver.TimerLock,
SerialGrabWaitFromIsr,
Extension);
#endif
IoAcquireCancelSpinLock(&OldIrql);
if (Extension->CurrentWaitIrp)
{
PIRP Irp;
Extension->IrpMaskLocation = NULL;
MyKdPrint(D_Ioctl,("[kill old wait]\n"))
ExtTrace(Extension,D_Ioctl, " Kill Old Wait");
*(ULONG *)Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer = 0;
Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
Extension->CurrentWaitIrp->IoStatus.Status = STATUS_SUCCESS;
Irp = Extension->CurrentWaitIrp;
IoSetCancelRoutine(Irp, NULL);
Extension->CurrentWaitIrp = 0;
IoReleaseCancelSpinLock(OldIrql);
SerialCompleteRequest(Extension, Irp, IO_SERIAL_INCREMENT);
}
else
IoReleaseCancelSpinLock(OldIrql);
//----- retain any bits from when no WaitIrp present
Extension->HistoryMask &= NewMask;
//----- set the mask of interested events
Extension->IsrWaitMask = NewMask;
// move this from wait_on_mask call to here, kpb, 1-16-97
#ifdef S_RK
if (Extension->IsrWaitMask & SERIAL_EV_RXFLAG)
{
sEnRxIntCompare1(Extension->ChP,
Extension->SpecialChars.EventChar);
}
else
{
sDisRxCompare1(Extension->ChP);
}
#endif
}
break;
//******************************
case IOCTL_SERIAL_WAIT_ON_MASK:
{
MyKdPrint(D_Ioctl,("[wait on mask]\n"))
ExtTrace(Extension,D_Ioctl,"Wait On Mask");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG))
{
ExtTrace(Extension,D_Ioctl,"Wait IRP, Bad Size");
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
// put this in to fix an incompatibility with WaitOnMultipleObjects()
// 6-26-98 kpb
if (Extension->CurrentWaitIrp)
{
MyKdPrint(D_Ioctl,("[Already pending]\n"))
Status = STATUS_INVALID_PARAMETER;
break;
}
#ifdef NEW_WAIT_SYNC_LOCK
SyncUp(Driver.InterruptObject,
&Driver.TimerLock,
SerialGrabWaitFromIsr,
Extension);
#else
Extension->WaitIsISRs = 0;
Extension->IrpMaskLocation = &Extension->DummyIrpMaskLoc;
#endif
IoAcquireCancelSpinLock(&OldIrql);
//------- Complete the old wait if there is one.
if (Extension->CurrentWaitIrp)
{
PIRP Irp;
MyKdPrint(D_Ioctl,("[kill old wait]\n"))
ExtTrace(Extension,D_Ioctl, " Kill Old Wait");
*(ULONG *)Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer = 0;
Extension->CurrentWaitIrp->IoStatus.Information = sizeof(ULONG);
Extension->CurrentWaitIrp->IoStatus.Status = STATUS_SUCCESS;
Irp = Extension->CurrentWaitIrp;
IoSetCancelRoutine(Irp, NULL);
Extension->CurrentWaitIrp = 0;
IoReleaseCancelSpinLock(OldIrql);
SerialCompleteRequest(Extension, Irp, IO_SERIAL_INCREMENT);
}
else
IoReleaseCancelSpinLock(OldIrql);
if (Extension->IsrWaitMask == 0)
{
ExtTrace(Extension,D_Ioctl," WaitMask==0");
Status = STATUS_INVALID_PARAMETER;
}
else
{
IoAcquireCancelSpinLock(&OldIrql);
if (Irp->Cancel)
{
IoReleaseCancelSpinLock(OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
SerialCompleteRequest(Extension, Irp, 0);
Status = STATUS_CANCELLED;
}
else
{
Extension->CurrentWaitIrp = Irp;
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Extension->CurrentWaitIrp, SerialCancelWait);
IoReleaseCancelSpinLock(OldIrql);
// give to ISR to process
Extension->IrpMaskLocation = (ULONG *)
Extension->CurrentWaitIrp->AssociatedIrp.SystemBuffer;
Extension->WaitIsISRs = 1; // give to ISR
ExtTrace(Extension,D_Ioctl," PENDING.");
return STATUS_PENDING;
}
}
}
break;
case IOCTL_SERIAL_IMMEDIATE_CHAR:
{
UCHAR TxByte;
KIRQL OldIrql;
ExtTrace(Extension,D_Ioctl,"Immed. Char");
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(UCHAR) )
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
IoAcquireCancelSpinLock(&OldIrql);
TxByte = *((UCHAR *)(Irp->AssociatedIrp.SystemBuffer));
Extension->ISR_Flags |= TX_NOT_EMPTY; // fix for EV_TXEMPTY 1-21-99
#ifdef S_RK
if(!sWriteTxPrioByte(Extension->ChP,TxByte))
{
// No room for immediate character in Priority queue
Status = STATUS_INVALID_PARAMETER;
}
#else
if ( (ULONG)(PortGetTxRoom(Extension->Port)) > 0)
{
// Send the byte
q_put(&Extension->Port->QOut,
(PUCHAR) &TxByte,
1);
}
#endif
IoReleaseCancelSpinLock(OldIrql);
break;
}
//**********************
case IOCTL_SERIAL_PURGE:
{
ULONG Mask;
MyKdPrint(D_Ioctl,("[Serial Purge]"));
// Check to make sure that the mask only has 0 or the other
// appropriate values. A null mask is equivalent to a mask of 0
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG) )
{
Status = STATUS_INVALID_PARAMETER;
break;
};
if ( Irp->AssociatedIrp.SystemBuffer )
{
Mask = *((ULONG *)(Irp->AssociatedIrp.SystemBuffer));
ExtTrace1(Extension,D_Ioctl,"Serial Purge:%xH",Mask);
}
else
{
Mask = 0;
}
if ((!Mask) || (Mask & (~(SERIAL_PURGE_TXABORT |
SERIAL_PURGE_RXABORT |
SERIAL_PURGE_TXCLEAR |
SERIAL_PURGE_RXCLEAR )
) ))
{
Status = STATUS_INVALID_PARAMETER;
break;
}
return SerialStartOrQueue(Extension,
Irp,
&Extension->PurgeQueue,
&Extension->CurrentPurgeIrp,
SerialStartPurge );
}
//*****************************
case IOCTL_SERIAL_GET_HANDFLOW:
{
MyKdPrint(D_Ioctl,("[Get Handflow]\n"))
ExtTrace(Extension,D_Ioctl,"Get Handflow");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_HANDFLOW))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIAL_HANDFLOW);
*((PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer) =
Extension->HandFlow;
break;
}
//*****************************
case IOCTL_SERIAL_SET_HANDFLOW:
{
ULONG trace_flags = 0;
SERIAL_IOCTL_SYNC S;
PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("[Set HandFlow]\n"))
ExtTrace(Extension,D_Ioctl,"Set HandFlow");
// Make sure that the buffer is big enough
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_HANDFLOW))
{
ExtTrace(Extension,D_Ioctl,"ErZ!");
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
///////////////////////////////////////////////////////
// Make sure that no invalid parameters have been set
// Check ControlHandShake first
// For Rocket, we or in several that can't be supported
if(HandFlow->ControlHandShake & (SERIAL_CONTROL_INVALID |
SERIAL_DSR_SENSITIVITY
) )
{
{ ExtTrace(Extension,D_Ioctl,"Err M!"); }
if(HandFlow->ControlHandShake & SERIAL_DSR_SENSITIVITY)
{ ExtTrace(Extension,D_Ioctl,"No DSR Sen!"); }
if(HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID)
{ ExtTrace(Extension,D_Ioctl,"Invalid con!"); }
// don't bail out - kpb(5-23-96)
//Status = STATUS_INVALID_PARAMETER;
//break;
}
if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID)
{
ExtTrace(Extension,D_Ioctl,"ErA!");
Status = STATUS_INVALID_PARAMETER;
break;
}
// Make sure that the app hasn't set an invalid DTR mode.
// Both options can't be set
if((HandFlow->ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_MASK)
{
ExtTrace(Extension,D_Ioctl,"ErB!");
Status = STATUS_INVALID_PARAMETER;
break;
}
// Xon/Xoff limits unused for RocketPort (they're internal).
HandFlow->XonLimit=0;
HandFlow->XoffLimit=0;
S.Extension = Extension;
S.Data = HandFlow;
KeAcquireSpinLock(&Extension->ControlLock,&OldIrql);
SerialSetHandFlow(Extension, HandFlow);
KeReleaseSpinLock(&Extension->ControlLock,OldIrql);
if ((Extension->HandFlow.ControlHandShake & SERIAL_RTS_MASK) ==
SERIAL_RTS_HANDSHAKE)
{ExtTrace(Extension,D_Ioctl,"RTS-Auto");}
if (Extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE)
{ExtTrace(Extension,D_Ioctl,"CTS-Auto");}
if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_HANDSHAKE)
{ExtTrace(Extension,D_Ioctl,"DTR-Auto");}
if (Extension->HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE)
{ExtTrace(Extension,D_Ioctl,"DSR-Auto");}
if (Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT)
{ExtTrace(Extension,D_Ioctl,"Xon-Auto");}
}
break;
//********************************
case IOCTL_SERIAL_GET_MODEMSTATUS:
{
if ( IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG) )
{ Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
//Irp->IoStatus.Status = STATUS_SUCCESS; bogus(set at end)
Status = STATUS_SUCCESS; // don't need, default
#ifdef S_RK
// Update the modem inputs, fn() reads and converts the bits
SetExtensionModemStatus(Extension);
#endif
ExtTrace1(Extension,D_Ioctl,"Get ModemStatus:%xH",Extension->ModemStatus);
*(PULONG)Irp->AssociatedIrp.SystemBuffer = Extension->ModemStatus;
break;
}
//***************************
case IOCTL_SERIAL_GET_DTRRTS:
{
MyKdPrint(D_Ioctl,("[Get DTR/RTS]\n"))
// The Rocket cannot truly reflect RTS setting, best guess is returned
if ( IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG) )
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
//Irp->IoStatus.Status = STATUS_SUCCESS; bogus, set at end
Status = STATUS_SUCCESS; // don't need
*(PULONG)Irp->AssociatedIrp.SystemBuffer = Extension->DTRRTSStatus;
ExtTrace1(Extension,D_Ioctl,"Get DTR/RTS:%xH",Extension->DTRRTSStatus);
break;
}
//*******************************
case IOCTL_SERIAL_GET_COMMSTATUS:
{
PSERIAL_STATUS Stat;
LONG RxCount;
LONG TxCount;
if ( IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_STATUS) )
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
Stat = Irp->AssociatedIrp.SystemBuffer;
// EOF is always off, NT only supports binary mode
// This in keeping with the example driver
Stat->EofReceived = FALSE;
// Reading error status clears out the errors.
Stat->Errors = Extension->ErrorWord;
Extension->ErrorWord = 0;
// We only report here what can be read immediately by the next read
// The RocketPort's hardware FIFO is not added into this count
RxCount = q_count(&Extension->RxQ);
Stat->AmountInInQueue = RxCount;
#ifdef NEW_Q
#ifdef S_VS
{
LONG tx_remote;
tx_remote = PortGetTxCntRemote(Extension->Port);
TxCount = PortGetTxCnt(Extension->Port);
Stat->AmountInOutQueue = Extension->TotalCharsQueued + TxCount + tx_remote;
ExtTrace4(Extension,D_Ioctl,"Get CommStat,In:%d IRPOut:%d BufOut:%d Remote:%d",
RxCount, Extension->TotalCharsQueued, TxCount, tx_remote);
}
#else
TxCount = sGetTxCnt(Extension->ChP);
if ((sGetChanStatusLo(Extension->ChP) & DRAINED) != DRAINED)
++TxCount;
Stat->AmountInOutQueue = Extension->TotalCharsQueued + TxCount;
ExtTrace3(Extension,D_Ioctl,"Get CommStat,In:%d IRPOut:%d HardOut:%d",
RxCount, Extension->TotalCharsQueued, TxCount);
#endif
#else
// older q-tracking code....
#ifdef S_VS
TxCount = PortGetTxCnt(Extension->Port);
#else
TxCount = sGetTxCnt(Extension->ChP);
#endif
Stat->AmountInOutQueue = Extension->TotalCharsQueued + TxCount;
ExtTrace3(Extension,D_Ioctl,"Get CommStat,In:%d SoftOut:%d HardOut:%d",
RxCount, Extension->TotalCharsQueued, TxCount);
// end older q-tracking code....
#endif
#ifdef S_RK
// NOTE: this can fail due to the Priority buffer bug.
// If the immediate byte ended up in the FIFO, this will
// not accurately reflect the Immediate char state.
if(sGetTxPriorityCnt(Extension->ChP))
Stat->WaitForImmediate = TRUE;
else
Stat->WaitForImmediate = FALSE;
#else
Stat->WaitForImmediate = FALSE;
#endif
// Holding reasons are hidden in the part
// Hardware takes care of all the details
Stat->HoldReasons = 0;
if (Extension->TXHolding)
{
if (Extension->TXHolding & SERIAL_TX_XOFF)
Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_XON;
if (Extension->TXHolding & SERIAL_TX_CTS)
Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_CTS;
if (Extension->TXHolding & SERIAL_TX_DSR)
Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DSR;
if (Extension->TXHolding & SERIAL_TX_BREAK)
Stat->HoldReasons |= SERIAL_TX_WAITING_ON_BREAK;
if (Extension->TXHolding & SERIAL_TX_DCD)
Stat->HoldReasons |= SERIAL_TX_WAITING_FOR_DCD;
}
if (Extension->RXHolding & SERIAL_RX_DSR)
Stat->HoldReasons |= SERIAL_RX_WAITING_FOR_DSR;
if (Extension->RXHolding & SERIAL_RX_XOFF)
Stat->HoldReasons |= SERIAL_TX_WAITING_XOFF_SENT;
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(SERIAL_STATUS);
break;
}
//*******************************
case IOCTL_SERIAL_GET_PROPERTIES:
{
PSERIAL_COMMPROP Properties;
MyKdPrint(D_Ioctl,("[Get Properties]\n"))
ExtTrace(Extension,D_Ioctl,"Get Properties");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_COMMPROP))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Properties=(PSERIAL_COMMPROP)Irp->AssociatedIrp.SystemBuffer;
RtlZeroMemory(Properties,sizeof(SERIAL_COMMPROP));
Properties->PacketLength = sizeof(SERIAL_COMMPROP);
Properties->PacketVersion = 2;
Properties->ServiceMask = SERIAL_SP_SERIALCOMM;
Properties->MaxTxQueue = 0;
Properties->MaxRxQueue = 0;
Properties->MaxBaud = SERIAL_BAUD_USER;
Properties->SettableBaud = SERIAL_BAUD_075 |
SERIAL_BAUD_110 |
SERIAL_BAUD_134_5 |
SERIAL_BAUD_150 |
SERIAL_BAUD_300 |
SERIAL_BAUD_600 |
SERIAL_BAUD_1200 |
SERIAL_BAUD_1800 |
SERIAL_BAUD_2400 |
SERIAL_BAUD_4800 |
SERIAL_BAUD_7200 |
SERIAL_BAUD_9600 |
SERIAL_BAUD_14400 |
SERIAL_BAUD_19200 |
SERIAL_BAUD_38400 |
SERIAL_BAUD_56K |
SERIAL_BAUD_128K |
SERIAL_BAUD_115200 |
SERIAL_BAUD_57600 |
SERIAL_BAUD_USER;
Properties->ProvSubType = SERIAL_SP_RS232;
Properties->ProvCapabilities = SERIAL_PCF_RTSCTS |
SERIAL_PCF_CD |
SERIAL_PCF_PARITY_CHECK |
SERIAL_PCF_XONXOFF |
SERIAL_PCF_SETXCHAR |
SERIAL_PCF_TOTALTIMEOUTS |
SERIAL_PCF_INTTIMEOUTS;
Properties->SettableParams = SERIAL_SP_PARITY |
SERIAL_SP_BAUD |
SERIAL_SP_DATABITS |
SERIAL_SP_STOPBITS |
SERIAL_SP_HANDSHAKING |
SERIAL_SP_PARITY_CHECK |
SERIAL_SP_CARRIER_DETECT;
Properties->SettableData = SERIAL_DATABITS_7 |
SERIAL_DATABITS_8;
Properties->SettableStopParity = SERIAL_STOPBITS_10 |
SERIAL_STOPBITS_20 |
SERIAL_PARITY_NONE |
SERIAL_PARITY_ODD |
SERIAL_PARITY_EVEN;
Properties->CurrentTxQueue = 0; // as per MS
// circular buffer req's -1
Properties->CurrentRxQueue = Extension->RxQ.QSize -1;
Irp->IoStatus.Information = sizeof(SERIAL_COMMPROP);
//Irp->IoStatus.Status = STATUS_SUCCESS; bogus, set at end
Status = STATUS_SUCCESS; // don't need
break;
}
//*****************************
case IOCTL_SERIAL_XOFF_COUNTER:
{
PSERIAL_XOFF_COUNTER Xc = Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("[Xoff Counter]\n"));
ExtTrace(Extension,D_Ioctl,"Xoff Counter");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_XOFF_COUNTER))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if (Xc->Counter <= 0)
{ Status = STATUS_INVALID_PARAMETER;
break;
}
// write the 13H(don't play the xoff-counter game)
// which queues things up in the write queue. We may
// screw up the order of outgoing data if other writes
// pended, but thats life, and this xoff-counter nonsense
// sucks. Its used in the msdos 16450 uart emuluation on
// com1-com4.
#ifdef S_RK
sWriteTxBlk( Extension->ChP, (PUCHAR) &Xc->XoffChar, 1);
#else
q_put(&Extension->Port->QOut,(unsigned char *)&Xc->XoffChar,1);
#endif
Status = STATUS_SUCCESS;
break;
}
//******************************
case IOCTL_SERIAL_CONFIG_SIZE:
{
ExtTrace(Extension,D_Ioctl,"Config Size");
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
Status = STATUS_SUCCESS;
*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
break;
}
//******************************
case IOCTL_SERIAL_GET_COMMCONFIG:
{
// this function is not defined or used in the sample driver.
ExtTrace(Extension,D_Ioctl,"Get Config");
Status = STATUS_INVALID_PARAMETER;
break;
}
//******************************
case IOCTL_SERIAL_SET_COMMCONFIG:
{
// this function is not defined or used in the sample driver.
ExtTrace(Extension,D_Ioctl,"Set Config");
Status = STATUS_INVALID_PARAMETER;
break;
}
//******************************
case IOCTL_SERIAL_LSRMST_INSERT:
{
PUCHAR escapeChar;
if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (ULONG) )
{
Status = STATUS_INVALID_PARAMETER;
break;
}
else
{
escapeChar = Irp->AssociatedIrp.SystemBuffer;
};
ExtTrace1(Extension,D_Ioctl,"LSRMST Insert, Esc=%xH",
(ULONG) *escapeChar);
MyKdPrint(D_Ioctl,("[LSRMST Insert]\n"))
// this "feature" allows setting a escape character, which when
// non-zero will cause it to be used as an escape character for
// changes in MSR/LSR registers. If the Escape char is seen in
// from the port, it is escaped also. Oh what fun.
// used in Virtual driver of microsofts.
Extension->escapechar = *escapeChar;
#ifdef S_RK
if (Extension->escapechar != 0)
{sEnRxIntCompare2(Extension->ChP,Extension->escapechar);}
else
{sDisRxCompare2(Extension->ChP);}
#endif
// Status = STATUS_INVALID_PARAMETER;
break;
}
#ifdef NT50
//******************************
case IOCTL_SERIAL_GET_MODEM_CONTROL:
{
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Irp->IoStatus.Information = sizeof(ULONG);
//#define SERIAL_DTR_STATE ((ULONG)0x00000001)
//#define SERIAL_RTS_STATE ((ULONG)0x00000002)
//#define SERIAL_IOC_MCR_DTR ((ULONG)0x00000001)
//#define SERIAL_IOC_MCR_RTS ((ULONG)0x00000002)
//#define SERIAL_IOC_MCR_OUT1 ((ULONG)0x00000004)
//#define SERIAL_IOC_MCR_OUT2 ((ULONG)0x00000008)
//#define SERIAL_IOC_MCR_LOOP ((ULONG)0x00000010)
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) =
(Extension->DTRRTSStatus & 3);
ExtTrace1(Extension,D_Ioctl,"get MCR:=%xH",
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) );
}
break;
//******************************
case IOCTL_SERIAL_SET_MODEM_CONTROL:
{
ULONG mcr;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(ULONG)) {
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
mcr = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
#ifdef S_VS
pDisRTSFlowCtl(Extension->Port);
#else
sDisRTSFlowCtl(Extension->ChP);
#endif
if (mcr & SERIAL_RTS_STATE)
{
#ifdef S_VS
pSetRTS(Extension->Port);
#else
sSetRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
else
{
#ifdef S_VS
pClrRTS(Extension->Port);
#else
sClrRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
}
if (mcr & SERIAL_DTR_STATE)
{
#ifdef S_VS
pSetDTR(Extension->Port);
#else
sSetDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
}
else
{
#ifdef S_VS
pClrDTR(Extension->Port);
#else
sClrDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
}
ExtTrace1(Extension,D_Ioctl,"set MCR:=%xH", mcr);
}
break;
//******************************
case IOCTL_SERIAL_SET_FIFO_CONTROL:
{
}
break;
#endif
//******************************
case IOCTL_RCKT_CLR_STATS:
{
Tracer *tr;
PSERIAL_DEVICE_EXTENSION ComDevExt;
// PortStats *Stats;
MyKdPrint(D_Ioctl,("[Get Stats]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(Tracer))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl,("[Buffer too small]\n"))
break;
}
tr = (Tracer *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("Com_port: %s\n",tr->port_name))
ComDevExt = FindDevExt(tr->port_name);
if (ComDevExt == NULL)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
ComDevExt->OurStats.TransmittedCount = 0;
ComDevExt->OurStats.ReceivedCount = 0;
ComDevExt->OurStats.ParityErrorCount = 0;
ComDevExt->OurStats.FrameErrorCount = 0;
ComDevExt->OurStats.SerialOverrunErrorCount = 0;
ComDevExt->OurStats.BufferOverrunErrorCount = 0;
tr->status = 0;
Irp->IoStatus.Information = sizeof(Tracer);
Status = STATUS_SUCCESS;
break;
}
//******************************
case IOCTL_RCKT_SET_LOOPBACK_ON:
{
ExtTrace(Extension,D_Ioctl,"LoopBk On");
MyKdPrint(D_Ioctl,("[Set LoopBack On]"))
#ifdef S_VS
pEnLocalLoopback(Extension->Port);
#else
sEnLocalLoopback(Extension->ChP);
#endif
}
break;
//******************************
case IOCTL_RCKT_SET_LOOPBACK_OFF:
{
ExtTrace(Extension,D_Ioctl,"LoopBk Off");
MyKdPrint(D_Ioctl,("[Set LoopBack Off]"))
#ifdef S_VS
pDisLocalLoopback(Extension->Port);
#else
sDisLocalLoopback(Extension->ChP);
#endif
}
break;
//******************************
case IOCTL_RCKT_SET_TOGGLE_LOW:
{
ExtTrace(Extension,D_Ioctl,"Set 485 Low");
Extension->Option &= ~OPTION_RS485_HIGH_ACTIVE;
Extension->Option &= ~OPTION_RS485_SOFTWARE_TOGGLE;
Extension->Option |= OPTION_RS485_OVERRIDE;
// hardware reverse case
#ifdef S_VS
pEnRTSToggleLow(Extension->Port);
#else
sEnRTSToggle(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
break;
case IOCTL_RCKT_CLEAR_TOGGLE_LOW:
{
ExtTrace(Extension,D_Ioctl,"Clear 485 Low");
Extension->Option &= ~OPTION_RS485_HIGH_ACTIVE;
Extension->Option &= ~OPTION_RS485_SOFTWARE_TOGGLE;
Extension->Option &= ~OPTION_RS485_OVERRIDE;
// hardware reverse case
#ifdef S_VS
pDisRTSToggle(Extension->Port);
pSetRTS(Extension->Port);
#else
sDisRTSToggle(Extension->ChP);
sSetRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
break;
//******************************
case IOCTL_RCKT_GET_STATS:
{
Tracer *tr;
PSERIAL_DEVICE_EXTENSION ComDevExt;
PortStats *Stats;
ExtTrace(Extension,D_Ioctl,"Get_Stats");
MyKdPrint(D_Ioctl,("[Get Stats]\n"));
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(Tracer))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl,("[Buffer too small]\n"))
break;
}
tr = (Tracer *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("Com_port: %s\n",tr->port_name))
ComDevExt = FindDevExt(tr->port_name);
if (ComDevExt == NULL)
{
Status = STATUS_INVALID_PARAMETER;
break;
}
Stats = (PortStats *)tr->data;
if(ComDevExt->DeviceIsOpen)
{
#ifdef S_VS
Stats->transmitFifo = (LONG) (PortGetTxCnt(ComDevExt->Port));
Stats->receiveFifo = (LONG) (PortGetRxCnt(ComDevExt->Port));
#else
Stats->transmitFifo = (LONG) sGetTxCnt(ComDevExt->ChP);
Stats->receiveFifo = (LONG) sGetRxCnt(ComDevExt->ChP);
#endif
}
else
{
Stats->transmitFifo = 0;
Stats->receiveFifo = 0;
}
Stats->transmitBytes = ComDevExt->OurStats.TransmittedCount;
Stats->receiveBytes = ComDevExt->OurStats.ReceivedCount;
Stats->parityErrors = ComDevExt->OurStats.ParityErrorCount;
Stats->framingErrors = ComDevExt->OurStats.FrameErrorCount;
Stats->overrunHardware = ComDevExt->OurStats.SerialOverrunErrorCount;
Stats->overrunSoftware = ComDevExt->OurStats.BufferOverrunErrorCount;
tr->status = 0;
Irp->IoStatus.Information = sizeof(Tracer);
Status = STATUS_SUCCESS;
break;
}
//******************************
case IOCTL_RCKT_ISR_CNT:
{
Tracer *tr;
Global_Track *Gt;
ExtTrace(Extension,D_Ioctl,"Isr_Cnt");
MyKdPrint(D_Ioctl,("[Get Stats]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(Tracer))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl,("[Buffer too small]\n"))
break;
}
tr = (Tracer *)Irp->AssociatedIrp.SystemBuffer;
tr->status = 0;
Gt = (Global_Track *)tr->data;
Gt->int_counter = Driver.PollCnt;
Gt->WriteDpc_counter = Driver.WriteDpcCnt;
Gt->Timer_counter = 0;
Gt->Poll_counter = Driver.PollCnt;
Irp->IoStatus.Information = sizeof(Tracer);
Status = STATUS_SUCCESS;
}
break;
//******************************
case IOCTL_RCKT_CHECK:
{
Tracer *tr;
ExtTrace(Extension,D_Ioctl,"Rckt_Chk");
MyKdPrint(D_Ioctl,("[Check]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(Tracer))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl,("[Buffer too small]\n"))
break;
}
tr = (Tracer *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("Com_port: %s\n",tr->port_name))
tr->status = 0x5555;
Irp->IoStatus.Information = sizeof(Tracer);
Status = STATUS_SUCCESS;
}
break;
//****************************** monitor
case IOCTL_RCKT_MONALL:
{
PSERIAL_DEVICE_EXTENSION extension;
PSERIAL_DEVICE_EXTENSION board_ext;
int Dev;
// int total_size;
PortMonBase *pmb;
PortMonNames *pmn;
PortMonStatus *pms;
char *buf;
MyKdPrint(D_Ioctl,("[MonAll..]"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (PortMonBase) )
{
Status = STATUS_INVALID_PARAMETER;
break;
}
else
{
pmb = (PortMonBase *)Irp->AssociatedIrp.SystemBuffer;
};
switch (pmb->struct_type)
{
case 9: // old probe ioctl
Status = STATUS_SUCCESS; // don't need, default
break;
//***************
case 10: // name array [12] bytes
pmn = (PortMonNames *) &pmb[1]; // ptr to after first struct
if (pmb->struct_size != sizeof(PortMonNames))
{
MyKdPrint(D_Ioctl,("Err1L"))
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
(((NumPorts(NULL)+1) * sizeof(PortMonNames)) + sizeof(PortMonBase)) )
{
MyKdPrint(D_Ioctl,("Err4M, size:%d needed:%d\n",
IrpSp->Parameters.DeviceIoControl.InputBufferLength,
(((NumPorts(NULL)+1) * sizeof(PortMonNames)) + sizeof(PortMonBase))
))
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Dev=0;
board_ext = Driver.board_ext;
while (board_ext)
{
extension = board_ext->port_ext;
while (extension)
{
strcpy(pmn->port_name, extension->SymbolicLinkName);
++pmn;
++Dev;
extension = extension->port_ext; // next in chain
} // while port extension
board_ext = board_ext->board_ext;
} // while port extension
pmb->num_structs = Dev;
pmn->port_name[0] = 0; // null terminate list.
Irp->IoStatus.Information = (sizeof(PortMonBase) +
sizeof(PortMonNames) *(Dev+1));
Status = STATUS_SUCCESS;
break; // case 10, names
//***************
case 11: // status array
pms = (PortMonStatus *) &pmb[1]; // ptr to after first struct
if (pmb->struct_size != sizeof(PortMonStatus))
{
MyKdPrint(D_Ioctl,("Err1M"))
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
((NumPorts(NULL) * sizeof(PortMonStatus)) + sizeof(PortMonBase)) )
{
MyKdPrint(D_Ioctl,("Err3M"))
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
Dev=0;
board_ext = Driver.board_ext;
while (board_ext)
{
extension = board_ext->port_ext;
while (extension)
{
pms->sent_bytes = extension->OurStats.TransmittedCount; // total number of sent bytes
pms->rec_bytes = extension->OurStats.ReceivedCount; // total number of receive bytes
pms->sent_packets = extension->sent_packets; // number of write() packets
pms->rec_packets = extension->rec_packets; // number of read() packets
pms->overrun_errors = (USHORT)(extension->OurStats.SerialOverrunErrorCount +
extension->OurStats.BufferOverrunErrorCount);
pms->framing_errors = (USHORT)(extension->OurStats.FrameErrorCount);
pms->parity_errors = (USHORT)(extension->OurStats.ParityErrorCount);
#ifdef S_VS
if (extension->Port != NULL)
pms->status_flags = // 20H, 10H, 8H
(extension->Port->msr_value & (CTS_ACT | DSR_ACT | CD_ACT)) |
// 1H, 2H
(WORD)(extension->DTRRTSStatus & (SERIAL_DTR_STATE | SERIAL_RTS_STATE));
#else
pms->status_flags = // 20H, 10H, 8H
(extension->ModemCtl & (CTS_ACT | DSR_ACT | CD_ACT)) |
// 1H, 2H
(WORD)(extension->DTRRTSStatus & (SERIAL_DTR_STATE | SERIAL_RTS_STATE));
#endif
if (extension->DeviceIsOpen)
pms->status_flags |= 0x100;
#ifdef COMMENT_OUT
if (sIsCTSFlowCtlEnabled(sIsComDevExt->ChP))
pms->status_flags |= 0x1000;
if (sIsRTSFlowCtlEnabled(sIsComDevExt->ChP))
pms->status_flags |= 0x2000;
if (sIsTxSoftFlowCtlEnabled(sIsComDevExt->ChP))
pms->status_flags |= 0x4000;
#endif
++pms;
++Dev;
extension = extension->port_ext; // next in chain
} // while port extension
board_ext = board_ext->board_ext; // next in chain
} // while board extension
Irp->IoStatus.Information = (sizeof(PortMonBase) +
sizeof(PortMonStatus)*Dev);
Status = STATUS_SUCCESS;
break; // case 11(status)
#ifdef COMMENT_OUT
//****************************** debug PCI
case 12: // debug in/out instructions
{
char *str;
int i,j,k;
// KIRQL newlevel, oldlevel;
Status = STATUS_SUCCESS;
buf = (char *) &pmb[1]; // ptr to after first struct
// Eprintf("dump %s",buf);
str = buf;
while ((*str != 0) && (*str != ' '))
++str;
if (*str == ' ')
++str;
// newlevel = 2;
// KeRaiseIrql(newlevel, &oldlevel);
// KeLowerIrql(oldlevel);
+
if ((buf[0] == 'i') && (buf[1] == 'n'))
{
j = 0;
i = gethint(str, &j);
if (buf[2] == 'w')
{
str = (char *) i;
k = READ_PORT_USHORT((PUSHORT) str);
Sprintf(buf, "InW[%x] = %x\n",i, k);
}
else
{
str = (char *) i;
k = READ_PORT_UCHAR((PUCHAR) str);
// k = inp(i);
Sprintf(buf, "InB[%x] = %x\n",i, k);
}
}
else if ((buf[0] == 'o') && (buf[1] == 'u'))
{
j = 0;
i = gethint(str, &j);
k = gethint(&str[j], &j);
str = (char *) i;
buf[0] = 0;
if (buf[3] == 'd')
{
//sOutDW(i, k);
WRITE_PORT_ULONG((PULONG) str, (ULONG) k);
Sprintf(buf, "OutDW[%x] = %x\n",i, k);
}
else if (buf[3] == 'w')
{
//sOutW(i, k);
WRITE_PORT_USHORT((PUSHORT) str, (USHORT) k);
Sprintf(buf, "OutW[%x] = %x\n",i, k);
}
else
{
WRITE_PORT_UCHAR((PUCHAR) str, (UCHAR) k);
//sOutB(i, k);
Sprintf(buf, "OutB[%x] = %x\n",i, k);
}
// Eprintf("Out[%x] = %x\n",i, k);
}
else
{
Status = STATUS_BUFFER_TOO_SMALL; // return an error
strcpy(buf, "Bad ioctl");
Eprintf("bad io ioctl %s",buf);
}
Irp->IoStatus.Information = sizeof(PortMonBase) +
strlen(buf) + 1;
}
break; // case 12(in/out)
#endif
//*************** driver debug log
case 13: // driver debug log
{
char *str;
int i;
Status = STATUS_SUCCESS;
// someone is actively running the debugger, so don't timeout
if (Driver.DebugTimeOut > 0) // used to timeout inactive debug sessions.
Driver.DebugTimeOut = 100; // about 600 second seconds timeout
buf = (char *) &pmb[1]; // ptr to after first struct
// Eprintf("dump %s",buf);
str = buf;
//----- limit incoming line buffer size
i = 0;
while ((*str != 0) && (i < 160))
{
++str;
++i;
}
*str = 0;
str = buf;
if (*str != 0)
do_cmd_line(str);
if (!q_empty(&Driver.DebugQ))
{
int q_cnt;
q_cnt = q_count(&Driver.DebugQ);
if (q_cnt > 1000)
q_cnt = 1000;
Irp->IoStatus.Information = sizeof(PortMonBase) + q_cnt;
pmb->struct_size = (ULONG) q_cnt;
buf = (char *) &pmb[1]; // ptr to after first struct
q_get(&Driver.DebugQ, (BYTE *) &pmb[1], q_cnt);
}
else
{
pmb->struct_size = (ULONG) 0;
Irp->IoStatus.Information = sizeof(PortMonBase);
}
}
break; // driver debug log
//*************** driver option set
case 14:
{
int stat;
Status = STATUS_SUCCESS;
buf = (char *) &pmb[1]; // ptr to after first struct
MyKdPrint(D_Init, ("Ioctl Option:%s\n", buf))
stat = SetOptionStr(buf);
Sprintf(buf, "Option stat:%d\n",stat);
if (stat != 0)
{
MyKdPrint(D_Init, (" Err:%d\n", stat))
}
Irp->IoStatus.Information = sizeof(PortMonBase) +
strlen(buf) + 1;
}
break; // driver option set
#ifdef S_VS
//*************** mac-address list
case 15:
{
MyKdPrint(D_Ioctl,("start mac list\n"))
Status = STATUS_SUCCESS;
buf = (char *) &pmb[1]; // ptr to after first struct
buf[0] = 0;
MyKdPrint(D_Ioctl,("do find\n"))
find_all_boxes(0); // get list of all boxes out on networks
find_all_boxes(1); // do 2nd scan just to be sure
memcpy(buf, Driver.BoxMacs, 8*Driver.NumBoxMacs);
Irp->IoStatus.Information = sizeof(PortMonBase) +
8*Driver.NumBoxMacs;
MyKdPrint(D_Ioctl,("end mac list\n"))
}
break;
case 16: // advisor sheet: probe NIC status
MyKdPrint(D_Ioctl,("start nic probe"))
Irp->IoStatus.Information =
(ProbeNic((unsigned char *)&pmb[1],
(int)pmb->struct_size)) + sizeof(PortMonBase);
Status = STATUS_SUCCESS; // don't need, default
MyKdPrint(D_Ioctl,("end nic probe"))
break;
case 17: // advisor sheet: probe VS status
MyKdPrint(D_Ioctl,("start vs probe"))
Irp->IoStatus.Information =
(ProbeDevices((unsigned char *)&pmb[1],
(int)pmb->struct_size)) + sizeof(PortMonBase);
MyKdPrint(D_Ioctl,("end vs probe"))
Status = STATUS_SUCCESS; // don't need, default
break;
#endif
default:
Status = STATUS_BUFFER_TOO_SMALL;
break;
} // switch
}
break;
//******************************
case IOCTL_RCKT_SET_MODEM_RESET:
{
char *ResetData;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Set Modem Reset");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (char *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (char *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("Set reset on Port: %s\n", ResetData))
ext = find_ext_by_name(ResetData, NULL);
if (ext)
ModemReset(ext, 1);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
case IOCTL_RCKT_CLEAR_MODEM_RESET:
{
char *ResetData;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Clear Modem Reset");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (char *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (char *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("Clear reset on Port: %s\n", ResetData))
ext = find_ext_by_name(ResetData, NULL);
if (ext)
ModemReset(ext, 0);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
case IOCTL_RCKT_SEND_MODEM_ROW:
{
char *ResetData;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Send Modem ROW");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (char *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (char *)Irp->AssociatedIrp.SystemBuffer;
MyKdPrint(D_Ioctl,("ROW write on Port: %s\n", ResetData))
ext = find_ext_by_name(ResetData, NULL);
if (ext)
ModemWriteROW(ext, Driver.MdmCountryCode);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
#ifdef S_RK
//******************************
// These are the old versions of
// the Reset/ROW ioctls and are
// provided here only for
// compatibility with RktReset
case IOCTL_RCKT_SET_MODEM_RESET_OLD:
{
int *ResetData;
int ChanNum;
int DevNum;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Set Modem Reset");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (int *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (int *)Irp->AssociatedIrp.SystemBuffer;
ChanNum = (*ResetData) & 0xFFFF;
DevNum = (*ResetData) >> 0x10;
MyKdPrint(D_Ioctl,("Set reset on Dev: %x, Chan: %x\n", DevNum, ChanNum))
ext = find_ext_by_index(DevNum, ChanNum);
if (ext)
sModemReset(ext->ChP, 1);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
case IOCTL_RCKT_CLEAR_MODEM_RESET_OLD:
{
int *ResetData;
int ChanNum;
int DevNum;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Clear Modem Reset");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (int *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (int *)Irp->AssociatedIrp.SystemBuffer;
ChanNum = (*ResetData) & 0xFFFF;
DevNum = (*ResetData) >> 0x10;
MyKdPrint(D_Ioctl,("Clear reset on Dev: %x, Chan: %x\n", DevNum, ChanNum))
ext = find_ext_by_index(DevNum, ChanNum);
if (ext)
sModemReset(ext->ChP, 0);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
case IOCTL_RCKT_GET_RCKTMDM_INFO_OLD:
{
// to maintain compatibility with RktReset, only the first
// four boards are reported and only the first eight ports
// on each are allowed.
RocketModemConfig *RMCfg;
int BoardNum;
int PortNum;
int np;
PSERIAL_DEVICE_EXTENSION ext_p; // port extension
PSERIAL_DEVICE_EXTENSION ext_b; // board extension
MyKdPrint(D_Ioctl, ("[Get RktMdm Cfg]\n"))
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof(RocketModemConfig))
{
Status = STATUS_BUFFER_TOO_SMALL;
MyKdPrint(D_Ioctl, ("[Buffer too small]\n"))
break;
}
RMCfg = (RocketModemConfig *)Irp->AssociatedIrp.SystemBuffer;
RMCfg->rm_country_code = Driver.MdmCountryCode;
RMCfg->rm_settle_time = Driver.MdmSettleTime;
ext_b = Driver.board_ext;
BoardNum = 0;
while ((ext_b) && (BoardNum < 4) )
{
if (ext_b->config->ModemDevice) {
//np = ext_b->config->NumChan; [kpb, 5-7-98]
np = ext_b->config->NumPorts;
if (np > 8)
np = 8; // force to 8 since structure only has room for 8
RMCfg->rm_board_cfg[BoardNum].num_rktmdm_ports = np;
PortNum = 0;
ext_p = find_ext_by_index(BoardNum, PortNum);
while ( (ext_p) && (PortNum < np) )
{
if (ext_p)
strcpy(RMCfg->rm_board_cfg[BoardNum].port_names[PortNum],
ext_p->SymbolicLinkName);
else
strcpy(RMCfg->rm_board_cfg[BoardNum].port_names[PortNum], 0);
PortNum++;
ext_p = find_ext_by_index(BoardNum, PortNum);
}
}
ext_b = ext_b->board_ext;
BoardNum++;
}
Irp->IoStatus.Information = sizeof(RocketModemConfig);
Status = STATUS_SUCCESS;
break;
}
case IOCTL_RCKT_SEND_MODEM_ROW_OLD:
{
int *ResetData;
int ChanNum;
int DevNum;
PSERIAL_DEVICE_EXTENSION ext;
ExtTrace(Extension,D_Ioctl,"Send Modem ROW");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength <
sizeof (int *) )
{
Status = STATUS_INVALID_PARAMETER;
}
else
{
ResetData = (int *)Irp->AssociatedIrp.SystemBuffer;
ChanNum = (*ResetData) & 0xFFFF;
DevNum = (*ResetData) >> 0x10;
MyKdPrint(D_Ioctl,("ROW write on Dev: %x, Chan: %x\n", DevNum, ChanNum))
ext = find_ext_by_index(DevNum, ChanNum);
if (ext)
sModemWriteROW(ext->ChP, Driver.MdmCountryCode);
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
};
break;
}
#endif
//******************************
default: // bad IOCTL request
{
MyKdPrint(D_Ioctl,("Err1O"))
ExtTrace1(Extension,D_Ioctl," UnHandle IoCtl:%d",
IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_INVALID_PARAMETER;
break;
}
}
Irp->IoStatus.Status = Status;
if (Status != STATUS_SUCCESS)
{
MyKdPrint(D_Ioctl, (" Bad Status:%xH on IOCTL:%xH",
Status, IrpSp->Parameters.DeviceIoControl.IoControlCode));
ExtTrace2(Extension, D_Ioctl, " Bad Status:%xH on IOCTL:%xH",
Status, IrpSp->Parameters.DeviceIoControl.IoControlCode);
switch (Status)
{
case STATUS_BUFFER_TOO_SMALL:
MyKdPrint(D_Ioctl,(" Err, Buf Too Small!"));
ExtTrace(Extension,D_Ioctl," Err, Buf Too Small!");
break;
case STATUS_INVALID_PARAMETER:
MyKdPrint(D_Ioctl,(" Err, Bad Parm!"));
ExtTrace(Extension,D_Ioctl," Err, Bad Parm!");
break;
default:
break;
}
}
SerialCompleteRequest(Extension, Irp, 0);
return Status;
}
/*--------------------------------------------------------------------------
FindDevExt -
Purpose: To scan through my Dev objects and return a device object ext
Return: PSERIAL_DEVICE_EXTENSION
|--------------------------------------------------------------------------*/
PSERIAL_DEVICE_EXTENSION FindDevExt(IN PCHAR PortName)
{
PSERIAL_DEVICE_EXTENSION extension;
PSERIAL_DEVICE_EXTENSION board_ext;
int Dev;
char *pn;
char *dev_pn;
int done;
Dev =0;
board_ext = Driver.board_ext;
while (board_ext)
{
extension = board_ext->port_ext;
while (extension)
{
pn = PortName;
dev_pn = extension->SymbolicLinkName;
done = 0;
while ((*dev_pn != 0) && (*pn != 0) && (done == 0))
{
if (*dev_pn != *pn)
done = 1; // no match, try next
++dev_pn;
++pn;
}
if ((*dev_pn == 0) && (*pn == 0))
return (extension); // found it, return ext.
++Dev;
extension = extension->port_ext; // next in chain
} // while port extension
board_ext = board_ext->board_ext;
} // while board extension
return NULL;
}
/*--------------------------------------------------------------------------
ProgramBaudRate -
Purpose: Configure channel for desired baud rate
Return: STATUS_SUCCESS: if baud rate was configured
STATUS_INVALID_PARAMETER: if baud rate cannot be configured
|--------------------------------------------------------------------------*/
NTSTATUS
ProgramBaudRate(
IN PSERIAL_DEVICE_EXTENSION Extension,
IN ULONG DesiredBaudRate
)
{
ULONG InBaud = DesiredBaudRate;
//---- handle baud mapping
if (Extension->port_config->LockBaud != 0)
DesiredBaudRate = Extension->port_config->LockBaud;
MyKdPrint(D_Ioctl,("[DesiredBaud %d]",DesiredBaudRate))
if (DesiredBaudRate == 56000) DesiredBaudRate = 57600;
else if (DesiredBaudRate == 128000) DesiredBaudRate = 115200;
else if (DesiredBaudRate == 256000) DesiredBaudRate = 230400;
#ifdef S_VS
if(PortSetBaudRate(Extension->Port,DesiredBaudRate,FALSE,
Extension->board_ext->config->ClkRate,
Extension->board_ext->config->ClkPrescaler))
return(STATUS_INVALID_PARAMETER);
#else
if(sSetBaudRate(Extension->ChP,DesiredBaudRate,FALSE))
return(STATUS_INVALID_PARAMETER);
#endif
Extension->BaudRate = InBaud;
#ifdef S_VS
PortSetBaudRate(Extension->Port,DesiredBaudRate, TRUE,
Extension->board_ext->config->ClkRate,
Extension->board_ext->config->ClkPrescaler);
#else
sSetBaudRate(Extension->ChP,DesiredBaudRate,TRUE);
#endif
return (STATUS_SUCCESS);
}
/*--------------------------------------------------------------------------
ProgramLineControl
Purpose: Configure channels line control (data bits, stop bits, parity)
Return: STATUS_SUCCESS: if line control was programmed as desired
STATUS_INVALID_PARAMETER: if line control setting was invalid
|--------------------------------------------------------------------------*/
NTSTATUS
ProgramLineControl(
IN PSERIAL_DEVICE_EXTENSION Extension,
IN PSERIAL_LINE_CONTROL Lc
)
{
switch (Lc->WordLength)
{
case 7:
ExtTrace(Extension,D_Ioctl, "7-bits");
#ifdef S_VS
pSetData7(Extension->Port);
#else
sSetData7(Extension->ChP);
sSetRxMask(Extension->ChP,0x7f);
#endif
Extension->LineCtl.WordLength = Lc->WordLength;
break;
case 8:
ExtTrace(Extension,D_Ioctl, "8-bits");
#ifdef S_VS
pSetData8(Extension->Port);
#else
sSetData8(Extension->ChP);
sSetRxMask(Extension->ChP,0xff);
#endif
Extension->LineCtl.WordLength = Lc->WordLength;
break;
case 5:
ExtTrace(Extension,D_Ioctl, "Err WL5");
return(STATUS_INVALID_PARAMETER);
case 6:
ExtTrace(Extension,D_Ioctl, "Err WL6");
return(STATUS_INVALID_PARAMETER);
default:
ExtTrace(Extension,D_Ioctl, "Err WL?");
return(STATUS_INVALID_PARAMETER);
}
switch (Lc->Parity)
{
case NO_PARITY:
ExtTrace(Extension,D_Ioctl, "No-Par.");
#ifdef S_VS
pDisParity(Extension->Port);
#else
sDisParity(Extension->ChP);
#endif
Extension->LineCtl.Parity = Lc->Parity;
break;
case EVEN_PARITY:
ExtTrace(Extension,D_Ioctl, "Ev-Par.");
#ifdef S_VS
pSetEvenParity(Extension->Port);
#else
sEnParity(Extension->ChP);
sSetEvenParity(Extension->ChP);
#endif
Extension->LineCtl.Parity = Lc->Parity;
break;
case ODD_PARITY:
ExtTrace(Extension,D_Ioctl, "Odd-Par.");
#ifdef S_VS
pSetOddParity(Extension->Port);
#else
sEnParity(Extension->ChP);
sSetOddParity(Extension->ChP);
#endif
Extension->LineCtl.Parity = Lc->Parity;
break;
case MARK_PARITY:
ExtTrace(Extension,D_Ioctl, "Err PM");
return(STATUS_INVALID_PARAMETER);
case SPACE_PARITY:
ExtTrace(Extension,D_Ioctl, "Err PS");
return(STATUS_INVALID_PARAMETER);
default:
ExtTrace(Extension,D_Ioctl, "Err P?");
return(STATUS_INVALID_PARAMETER);
} // end switch parity...
switch (Lc->StopBits)
{
case STOP_BIT_1:
ExtTrace(Extension,D_Ioctl, "1-StopB");
#ifdef S_VS
pSetStop1(Extension->Port);
#else
sSetStop1(Extension->ChP);
#endif
Extension->LineCtl.StopBits = Lc->StopBits;
break;
case STOP_BITS_1_5:
ExtTrace(Extension,D_Ioctl, "Err S1.5");
return(STATUS_INVALID_PARAMETER);
case STOP_BITS_2:
if (Extension->port_config->Map2StopsTo1)
{
ExtTrace(Extension,D_Ioctl, "2to1-StopB");
#ifdef S_VS
pSetStop1(Extension->Port);
#else
sSetStop1(Extension->ChP);
#endif
}
else
{
ExtTrace(Extension,D_Ioctl, "2-StopB");
#ifdef S_VS
pSetStop2(Extension->Port);
#else
sSetStop2(Extension->ChP);
#endif
}
Extension->LineCtl.StopBits = Lc->StopBits;
break;
}
return (STATUS_SUCCESS);
}
/*--------------------------------------------------------------------
SerialSetHandFlow -
Note: This is somewhat redundant to ForceExtensionSettings() in openclos.c.
|-------------------------------------------------------------------*/
void SerialSetHandFlow(PSERIAL_DEVICE_EXTENSION Extension,
SERIAL_HANDFLOW *HandFlow)
{
//////////////////////////////////////////////
// All invalid parameters have been dealt with.
// Now, program the settings.
//////////////
// DTR control
if ((Extension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) !=
(HandFlow->ControlHandShake & SERIAL_DTR_MASK))
{
Extension->RXHolding &= ~SERIAL_RX_DSR;
if ( (HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_CONTROL )
{
#ifdef S_VS
pSetDTR(Extension->Port);
#else
sSetDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
}
else if ( (HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_HANDSHAKE )
{
#ifdef S_VS
pEnDTRFlowCtl(Extension->Port);
Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
#else
if( (sGetRxCnt(Extension->ChP) >= RX_HIWATER) ||
(!(Extension->DevStatus & COM_RXFLOW_ON))
)
{
// drop DTR
Extension->DevStatus &= ~COM_RXFLOW_ON;
sClrDTR(Extension->ChP);
Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
Extension->RXHolding |= SERIAL_RX_DSR;
}
else
{
// DTR should be on
sSetDTR(Extension->ChP);
Extension->DTRRTSStatus |= SERIAL_DTR_STATE;
}
#endif
}
else
{
#ifdef S_VS
pClrDTR(Extension->Port);
#else
sClrDTR(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_DTR_STATE;
}
}
//////////////
// RTS control
if ((Extension->HandFlow.FlowReplace & SERIAL_RTS_MASK) !=
(HandFlow->FlowReplace & SERIAL_RTS_MASK))
{
Extension->Option &= ~OPTION_RS485_SOFTWARE_TOGGLE;
#ifdef S_VS
pDisRTSFlowCtl(Extension->Port);
#else
sDisRTSFlowCtl(Extension->ChP); // add V2.8.001(2-19-96)
#endif
switch(HandFlow->FlowReplace & SERIAL_RTS_MASK)
{
case SERIAL_RTS_CONTROL: // RTS Should be asserted while open
#ifdef S_VS
pSetRTS(Extension->Port);
#else
sSetRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
break;
case SERIAL_RTS_HANDSHAKE: // RTS hardware input flow control
#ifdef S_VS
pEnRTSFlowCtl(Extension->Port);
#else
sEnRTSFlowCtl(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
break;
case SERIAL_TRANSMIT_TOGGLE: // RTS transmit toggle enabled
if (Extension->Option & OPTION_RS485_HIGH_ACTIVE)
{ // normal case, emulate standard operation
Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
#ifdef S_VS
pEnRTSToggleHigh(Extension->Port);
#else
sClrRTS(Extension->ChP);
#endif
}
else
{ // hardware reverse case
#ifdef S_VS
pEnRTSToggleLow(Extension->Port);
#else
sEnRTSToggle(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
break;
default:
#ifdef S_VS
pClrRTS(Extension->Port);
#else
sClrRTS(Extension->ChP);
#endif
Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
break;
}
}
if (Extension->Option & OPTION_RS485_OVERRIDE) // 485 override
{
if (Extension->Option & OPTION_RS485_HIGH_ACTIVE)
{ // normal case, emulate standard operation
Extension->Option |= OPTION_RS485_SOFTWARE_TOGGLE;
Extension->DTRRTSStatus &= ~SERIAL_RTS_STATE;
#ifdef S_VS
pEnRTSToggleHigh(Extension->Port);
#else
sClrRTS(Extension->ChP);
#endif
}
else
{ // hardware reverse case
#ifdef S_VS
pEnRTSToggleLow(Extension->Port);
#else
sEnRTSToggle(Extension->ChP);
#endif
Extension->DTRRTSStatus |= SERIAL_RTS_STATE;
}
}
///////////////////////////////
// Software output flow control
if ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_TRANSMIT) !=
(HandFlow->FlowReplace & SERIAL_AUTO_TRANSMIT))
{
if (HandFlow->FlowReplace & SERIAL_AUTO_TRANSMIT)
{
#ifdef S_VS
pEnTxSoftFlowCtl(Extension->Port);
#else
sEnTxSoftFlowCtl(Extension->ChP);
#endif
}
else
{
#ifdef S_VS
pDisTxSoftFlowCtl(Extension->Port);
#else
if (Extension->TXHolding & ST_XOFF_FAKE)
{
Extension->TXHolding &= ~ST_XOFF_FAKE;
if ((Extension->TXHolding &
(SERIAL_TX_DCD | SERIAL_TX_DSR | ST_XOFF_FAKE)) == 0)
sEnTransmit(Extension->ChP); // Start up the transmitter
sDisRxCompare2(Extension->ChP);
}
sDisTxSoftFlowCtl(Extension->ChP);
sClrTxXOFF(Extension->ChP);
#endif
Extension->TXHolding &= ~SERIAL_TX_XOFF;
}
}
///////////////////////////////////////////////////////////////
// SERIAL_AUTO_RECEIVE checked only because it may be necessary
// to send an XON if we were using s/w input flow control
// Did the setting change?
if ((Extension->HandFlow.FlowReplace & SERIAL_AUTO_RECEIVE) !=
(HandFlow->FlowReplace & SERIAL_AUTO_RECEIVE))
{
#ifdef S_VS
if (HandFlow->FlowReplace & SERIAL_AUTO_RECEIVE)
{
pEnRxSoftFlowCtl(Extension->Port);
}
else
{
pDisRxSoftFlowCtl(Extension->Port);
}
#endif
// Are we turning AUTO_REC.. off?
if(!(HandFlow->FlowReplace & SERIAL_AUTO_RECEIVE))
{
// Is the remote flowed off?
if(!(Extension->DevStatus & COM_RXFLOW_ON))
{
// send XON
Extension->DevStatus |= COM_RXFLOW_ON;
#ifdef S_RK
sWriteTxPrioByte(Extension->ChP,
Extension->SpecialChars.XonChar);
#endif
}
}
}
/////////////////////////////////////////////////////////
// No need to program the Rocket for following:
// SERIAL_BREAK_CHAR
// Replace Break error (NULL) with SpecialChars.BreakChar
// SERIAL_ERROR_CHAR
// Replace Parity and Framing with SpecialChars.ErrorChar
///////////////////////////////////
// CTS hardware output flow control
if ((Extension->HandFlow.ControlHandShake & SERIAL_CTS_HANDSHAKE) !=
(HandFlow->ControlHandShake & SERIAL_CTS_HANDSHAKE))
{
if (HandFlow->ControlHandShake & SERIAL_CTS_HANDSHAKE)
{
#ifdef S_VS
pEnCTSFlowCtl(Extension->Port);
#else
sEnCTSFlowCtl(Extension->ChP);
#endif
if (!(Extension->ModemStatus & SERIAL_CTS_STATE))
Extension->TXHolding |= SERIAL_TX_CTS; // clear holding
}
else
{
#ifdef S_VS
pDisCTSFlowCtl(Extension->Port);
#else
sDisCTSFlowCtl(Extension->ChP);
#endif
Extension->TXHolding &= ~SERIAL_TX_CTS; // clear holding
}
}
///////////////////////////////////
// DSR hardware output flow control
#ifdef S_VS
if ((Extension->HandFlow.ControlHandShake & SERIAL_DSR_HANDSHAKE) !=
(HandFlow->ControlHandShake & SERIAL_DSR_HANDSHAKE))
{
if (HandFlow->ControlHandShake & SERIAL_DSR_HANDSHAKE)
{
pEnDSRFlowCtl(Extension->Port);
if (!(Extension->ModemStatus & SERIAL_DSR_STATE))
Extension->TXHolding |= SERIAL_TX_DSR;
}
else
{
pDisDSRFlowCtl(Extension->Port);
Extension->TXHolding &= ~SERIAL_TX_DSR;
}
}
#endif
#ifdef S_VS
///////////////////////////////////
// DCD hardware output flow control
if ((Extension->HandFlow.ControlHandShake & SERIAL_DCD_HANDSHAKE) !=
(HandFlow->ControlHandShake & SERIAL_DCD_HANDSHAKE))
{
if (HandFlow->ControlHandShake & SERIAL_DCD_HANDSHAKE)
{
pEnCDFlowCtl(Extension->Port);
if (!(Extension->ModemStatus & SERIAL_DCD_STATE))
Extension->TXHolding |= SERIAL_TX_DCD;
}
else
{
pDisCDFlowCtl(Extension->Port);
Extension->TXHolding &= ~SERIAL_TX_DCD;
}
}
#endif
/////////////////
// Null stripping
if (HandFlow->FlowReplace & SERIAL_NULL_STRIPPING)
{
#ifdef S_VS
pEnNullStrip(Extension->Port);
#else
sEnRxIgnore0(Extension->ChP,0);
#endif
}
else
{
#ifdef S_VS
pDisNullStrip(Extension->Port);
#else
sDisRxCompare0(Extension->ChP);
#endif
}
Extension->HandFlow.FlowReplace = HandFlow->FlowReplace;
Extension->HandFlow.ControlHandShake = HandFlow->ControlHandShake;
#ifdef S_RK
// update this because it handles flow-control and holding update
SetExtensionModemStatus(Extension);
#endif
}
#ifdef NT50
/*--------------------------------------------------------------------
SerialInternalIoControl -
|-------------------------------------------------------------------*/
NTSTATUS
SerialInternalIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp;
PSERIAL_DEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
KIRQL OldIrql;
BOOLEAN acceptingIRPs;
acceptingIRPs = SerialIRPPrologue(Extension);
if (acceptingIRPs == FALSE) {
MyKdPrint(D_Ioctl,("Ioctl:no irps aceepted\n"))
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
SerialCompleteRequest(Extension, Irp, IO_NO_INCREMENT);
return STATUS_NO_SUCH_DEVICE;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0L;
MyKdPrint(D_Ioctl,("SerialIntIoControl: %x\n",
IrpSp->Parameters.DeviceIoControl.IoControlCode))
// Make sure we aren't aborting due to error (ERROR_ABORT)
if (Extension->ErrorWord)
{
if (Extension->DeviceType == DEV_PORT)
{
if (SerialCompleteIfError(DeviceObject, Irp) != STATUS_SUCCESS)
{
{ExtTrace(Extension,D_Ioctl,"ErrSet!");}
return STATUS_CANCELLED;
}
}
}
if (Extension->DeviceType == DEV_BOARD)
{
ExtTrace2 (Extension, D_Ioctl, " Bad Status:%xH on IIOCTL:%xH",
Status, IrpSp->Parameters.DeviceIoControl.IoControlCode);
Status = STATUS_INVALID_DEVICE_REQUEST;
SerialCompleteRequest (Extension, Irp, 0);
return Status;
};
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
{
#if 0
case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE:
// Send a wait-wake IRP
Status = SerialSendWaitWake(Extension);
break;
case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE:
if (Extension->PendingWakeIrp != NULL) {
IoCancelIrp(Extension->PendingWakeIrp);
}
break;
#endif
case IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS:
case IOCTL_SERIAL_INTERNAL_RESTORE_SETTINGS:
{
SERIAL_BASIC_SETTINGS basic;
PSERIAL_BASIC_SETTINGS pBasic;
//SHORT AppropriateDivisor;
//SERIAL_IOCTL_SYNC S;
if (IrpSp->Parameters.DeviceIoControl.IoControlCode ==
IOCTL_SERIAL_INTERNAL_BASIC_SETTINGS)
{
MyKdPrint(D_Ioctl,("[Set Internal Settings]\n"))
ExtTrace(Extension,D_Ioctl,"Set Int Settings");
// Check the buffer size
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_BASIC_SETTINGS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
//
// Everything is 0 -- timeouts and flow control. If
// We add additional features, this zero memory method
// may not work.
//
RtlZeroMemory(&basic, sizeof(SERIAL_BASIC_SETTINGS));
Irp->IoStatus.Information = sizeof(SERIAL_BASIC_SETTINGS);
pBasic = (PSERIAL_BASIC_SETTINGS)Irp->AssociatedIrp.SystemBuffer;
//
// Save off the old settings
//
RtlCopyMemory(&pBasic->Timeouts, &Extension->Timeouts,
sizeof(SERIAL_TIMEOUTS));
RtlCopyMemory(&pBasic->HandFlow, &Extension->HandFlow,
sizeof(SERIAL_HANDFLOW));
//
// Point to our new settings
//
pBasic = &basic;
}
else //restoring settings
{
MyKdPrint(D_Ioctl,("[Restore Internal Settings]\n"))
ExtTrace(Extension,D_Ioctl,"Reset Int Settings");
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength
< sizeof(SERIAL_BASIC_SETTINGS))
{
Status = STATUS_BUFFER_TOO_SMALL;
break;
}
pBasic = (PSERIAL_BASIC_SETTINGS)Irp->AssociatedIrp.SystemBuffer;
}
KeAcquireSpinLock(&Extension->ControlLock, &OldIrql);
//
// Set the timeouts
//
RtlCopyMemory(&Extension->Timeouts, &pBasic->Timeouts,
sizeof(SERIAL_TIMEOUTS));
//
// Set flowcontrol
//
//S.Extension = Extension;
//S.Data = &pBasic->HandFlow;
SerialSetHandFlow(Extension, &pBasic->HandFlow);
//KeSynchronizeExecution(Extension->Interrupt, SerialSetHandFlow, &S);
KeReleaseSpinLock(&Extension->ControlLock, OldIrql);
}
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
Irp->IoStatus.Status = Status;
if (Status != STATUS_SUCCESS)
{
ExtTrace2(Extension, D_Ioctl, " Bad Status:%xH on IIOCTL:%xH",
Status, IrpSp->Parameters.DeviceIoControl.IoControlCode);
}
SerialCompleteRequest(Extension, Irp, 0);
return Status;
}
#endif
#ifdef S_VS
#define RESET_STATS 1
/*--------------------------------------------------------------------
find_ext_mac_match
|-------------------------------------------------------------------*/
static PSERIAL_DEVICE_EXTENSION find_ext_mac_match(unsigned char *mac_addr)
{
PSERIAL_DEVICE_EXTENSION ext;
ext = Driver.board_ext;
while (ext != NULL)
{
if (mac_match(mac_addr, ext->hd->dest_addr))
{
//MyKdPrint(D_Ioctl,("Found ext:%x\n", ext))
return ext;
}
ext = ext->board_ext; // next one
}
return NULL;
}
/*--------------------------------------------------------------------
ProbeNic - determine status associated nic card.
|-------------------------------------------------------------------*/
static int ProbeNic(unsigned char *pPtr, int availableLength)
{
int nic_index;
int stat;
PROBE_NIC_STRUCT *pn;
Nic *nic;
int flag;
pn = (PROBE_NIC_STRUCT *) pPtr;
nic_index = (int) pPtr[0]; // they passed in an index to which nic card
flag = (int) pPtr[1]; // they passed in a flag too
stat = 0;
if (nic_index >= VS1000_MAX_NICS)
{
MyKdPrint(D_Error,("Err PD1F\n"))
stat = 1; // err
}
if (Driver.nics == NULL)
{
MyKdPrint(D_Error,("Err PD1G\n"))
stat = 2; // err
}
if (Driver.nics[nic_index].NICHandle == NULL)
{
MyKdPrint(D_Error,("Err PD1H\n"))
stat = 3; // err
}
if (stat != 0)
{
pn->struct_size = 0;
return sizeof(PROBE_NIC_STRUCT);
}
pn->struct_size = sizeof(PROBE_NIC_STRUCT);
nic = &Driver.nics[nic_index];
#if 0
if (flag & RESET_STATS) {
nic->pkt_sent = 0;
nic->pkt_rcvd_ours = 0;
nic->pkt_rcvd_not_ours = 0;
}
#endif
// copy over the data
memcpy(pn->NicName, nic->NicName, 60);
pn->NicName[59] = 0; // ensure null terminated
memcpy(pn->address, nic->address, 6);
pn->Open = nic->Open;
pn->pkt_sent = nic->pkt_sent;
pn->pkt_rcvd_ours = nic->pkt_rcvd_ours;
pn->pkt_rcvd_not_ours = nic->pkt_rcvd_not_ours;
return sizeof(PROBE_NIC_STRUCT);
}
/*--------------------------------------------------------------------
ProbeDevices - determine status associated with the hex MAC address at pPtr;
find associated Comtrol devices...
|-------------------------------------------------------------------*/
static int ProbeDevices(unsigned char *pPtr, int availableLength)
{
Nic *nic;
PortMan *pm;
Hdlc *hd;
unsigned char mac_address[6];
int flag;
int stat,i;
PSERIAL_DEVICE_EXTENSION ext;
PROBE_DEVICE_STRUCT *pr = (PROBE_DEVICE_STRUCT *) pPtr;
memcpy(mac_address,pPtr,sizeof(mac_address));
flag = pPtr[sizeof(mac_address)];
// find the active device with the matching address
ext = find_ext_mac_match(mac_address);
stat = 0;
if (ext == NULL)
{
MyKdPrint(D_Error,("No found mac:%x %x %x %x %x %x\n",
mac_address[0],mac_address[1],mac_address[2],
mac_address[3],mac_address[4],mac_address[5]))
stat = 1;
}
if (ext != NULL)
{
pm = ext->pm;
hd = ext->hd;
if ((pm == NULL) || (hd == NULL))
{
MyKdPrint(D_Error,("No pm or hd\n"))
stat = 2;
}
}
if (stat != 0)
{
pr->struct_size = 0;
MyKdPrint(D_Error,("ProbeErr1\n"))
return sizeof(PROBE_DEVICE_STRUCT);
}
pr->struct_size = sizeof(PROBE_DEVICE_STRUCT);
#if 0
if (flag & RESET_STATS) {
pm->good_loads = 0;
pm->total_loads = 0;
hd->iframes_sent = 0;
hd->ctlframes_sent = 0;
hd->rawframes_sent = 0;
hd->iframes_resent = 0;
hd->frames_rcvd = 0;
hd->iframes_outofseq = 0;
}
#endif
// give back a nic_index to use as a handle
pr->nic_index = 0; // default
for (i=0; i<VS1000_MAX_NICS; i++)
{
if ((hd->nic == &Driver.nics[i]) && (hd->nic != NULL))
pr->nic_index = i;
}
pr->num_ports = pm->num_ports;
pr->total_loads = pm->total_loads;
pr->good_loads = pm->good_loads;
pr->backup_server = pm->backup_server;
memcpy(pr->dest_addr, hd->dest_addr, 6);
pr->state = pm->state;
pr->iframes_sent = hd->iframes_sent;
pr->rawframes_sent = hd->rawframes_sent;
pr->ctlframes_sent = hd->ctlframes_sent;
pr->iframes_resent = hd->iframes_resent;
pr->iframes_outofseq = hd->iframes_outofseq;
pr->frames_rcvd = hd->frames_rcvd;
return sizeof(PROBE_DEVICE_STRUCT);
}
#endif