|
|
/*-------------------------------------------------------------------
| 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
|