diff options
Diffstat (limited to 'private/mvdm/softpc.new/host/src/nt_ntfun.c')
-rw-r--r-- | private/mvdm/softpc.new/host/src/nt_ntfun.c | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/private/mvdm/softpc.new/host/src/nt_ntfun.c b/private/mvdm/softpc.new/host/src/nt_ntfun.c new file mode 100644 index 000000000..8d98c959d --- /dev/null +++ b/private/mvdm/softpc.new/host/src/nt_ntfun.c @@ -0,0 +1,592 @@ +#include <nt.h> +#include <ntrtl.h> +#include <ntddser.h> +#include <nturtl.h> +#include <windows.h> +#include <stdlib.h> +#include <stdio.h> + +#include "insignia.h" +#include "trace.h" +#include "host_trc.h" +#include "debug.h" +#include "nt_com.h" +#include "nt_reset.h" + + +/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Defines */ + +#define SETUPLASTERROR(NtStatus) SetLastError(RtlNtStatusToDosError(NtStatus)) + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::: Magic xoff ioctl and associated functions ::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +typedef struct IoStatusElement +{ + struct IoStatusElement *NxtStatusBlock; //Ptr to next status block + IO_STATUS_BLOCK ioStatusBlock; +} IOSTATUSLIST, *PIOSTATUSLIST ; + + +int SendXOFFIoctl( + +HANDLE FileHandle, // Handle of comms port to send xoff ioctl to +HANDLE Event, // Event to signal completion of ioctl on +int Timeout, // Ioctl timeout +int Count, // Ioctl RX character count value +int XoffChar, // XOFF character +void *StatusElem) // Ptr to IO status block element +{ + int exitcode; + NTSTATUS rtn; // Return code from IOCTL + SERIAL_XOFF_COUNTER ioctl; // XOFF IOCTL + + /*................................................... Setup XOFF ioctl */ + + ioctl.Timeout = Timeout; // IOCTL timeout in milliseconds + ioctl.Counter = (LONG) Count; // RX count + ioctl.XoffChar = (UCHAR) XoffChar; // XOFF character + + /*............................................. issue magic xoff ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL, + &(((PIOSTATUSLIST) StatusElem)->ioStatusBlock), + IOCTL_SERIAL_XOFF_COUNTER, + (PVOID) &ioctl, sizeof(ioctl), NULL, 0))) + { + // Should display an error here + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); + exitcode = FALSE; + } + else + exitcode = TRUE; + + return(exitcode); +} + +/*:::::::::::::::::::::::::::::::::::::::::::::: Allocate IO status element */ + +void *AllocStatusElement() +{ + void *new; + + /*:::::::::::::::::::::::::::::: Allocate space for new io status block */ + + if((new = calloc(1,sizeof(IOSTATUSLIST))) == NULL) + { + // Allocation error do something about it + ; + } + else + ((PIOSTATUSLIST) new)->ioStatusBlock.Status = -1; + + return(new); +} + +/*:::::::::::::::::::::::::::::::::::: Add new iostatusblock to linked list */ + +void *AddNewIOStatusBlockToList(void **firstBlock, void **lastBlock, void *new) +{ + + /*:::::::::::::::::::::::::::::::::::::::: Add new block to linked list */ + + if(*lastBlock) + ((PIOSTATUSLIST)*lastBlock)->NxtStatusBlock = (PIOSTATUSLIST) new; + + /*:::::::::::::::::: Update first and last linked list element pointers */ + + if(!*firstBlock) *firstBlock = new; // First item in list + + *lastBlock = new; // Update last item pointer + + return((void *) new); +} + +/*:::::::::::::::::::::::::: Remove completed XOFF ioctl's from linked list */ + +int RemoveCompletedIOCTLs(void **firstBlock, void **lastBlock) +{ + PIOSTATUSLIST remove, nxt = (PIOSTATUSLIST) *firstBlock; + + /*::::::::::::::::::::::::: Scan linked list removing completed ioctl's */ + + while(nxt && nxt->ioStatusBlock.Status != -1) + { + /*......................... IOCTL completed, remove io status block */ + + remove = nxt; // Element to remove + nxt = nxt->NxtStatusBlock; // Next element to process + +#ifndef PROD + switch(remove->ioStatusBlock.Status) + { + case STATUS_SUCCESS: + sub_note_trace0(HOST_COM_VERBOSE,"XOFF (counter)\n"); + break; + + case STATUS_SERIAL_MORE_WRITES: + sub_note_trace0(HOST_COM_VERBOSE,"XOFF (more writes)\n"); + break; + + case STATUS_SERIAL_COUNTER_TIMEOUT: + sub_note_trace0(HOST_COM_VERBOSE,"XOFF (timeout)\n"); + break; + + default: + sub_note_trace0(HOST_COM_VERBOSE,"XOFF (unknown)\n"); + break; + } +#endif + + free(remove); // Deallocate element + } + + /*::::::::::::::::::::::::::::::: Update first and last element pointers */ + + if(!nxt) + { + // List empty reset first/last pointers + *firstBlock = *lastBlock = NULL; + } + else + { + // Setup new first pointer + *firstBlock = (void *) nxt; + } + + + // Returns true if there are still outstanding XOFF ioctl's + return(nxt ? TRUE : FALSE); +} + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +int FastSetUpComms( + +HANDLE FileHandle, // Handle of comms port to send xoff ioctl to +HANDLE Event, // Event to signal completion of ioctl on +int InputQueueSize, +int OutputQueueSize) +{ + NTSTATUS rtn; + SERIAL_QUEUE_SIZE ioctl; + IO_STATUS_BLOCK ioStatusBlock; + + /*........................................................ Setup ioctl */ + + ioctl.InSize = InputQueueSize; + ioctl.OutSize = OutputQueueSize; + + /*............................................. issue magic xoff ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL, + &ioStatusBlock, + IOCTL_SERIAL_SET_QUEUE_SIZE, + (PVOID) &ioctl, sizeof(ioctl), NULL, 0))) + { + // Should display an error here +#ifndef PROD + fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__); + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); +#endif + return(FALSE); + } + + /*......................................... Wait for IOCTL to complete */ + + if(rtn == STATUS_PENDING) + NtWaitForSingleObject(Event, FALSE, NULL); + + /*............................................ Check completion status */ + +#ifndef PROD + if(ioStatusBlock.Status != STATUS_SUCCESS) + fprintf(trace_file, "FastSetupComm failed (%x)\n",ioStatusBlock.Status); +#endif + + return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::: Fast track SetCommMask call ::::::::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +int FastSetCommMask( + +HANDLE FileHandle, // Handle of comms port to send ioctl to +HANDLE Event, // Event to signal completion of ioctl on +ULONG CommMask) +{ + NTSTATUS rtn; + IO_STATUS_BLOCK ioStatusBlock; + + /*.......................................... issue set comm mask ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL, + &ioStatusBlock, + IOCTL_SERIAL_SET_WAIT_MASK, + (PVOID) &CommMask, sizeof(CommMask), NULL, 0))) + { + // Should display an error here +#ifndef PROD + fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__); + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); +#endif + return(FALSE); + } + + /*......................................... Wait for IOCTL to complete */ + + if(rtn == STATUS_PENDING) + NtWaitForSingleObject(Event, FALSE, NULL); + + /*............................................ Check completion status */ + +#ifndef PROD + if(ioStatusBlock.Status != STATUS_SUCCESS) + fprintf(trace_file,"FastSetCommMask failed (%x)\n",ioStatusBlock.Status); +#endif + + return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::::::::::::: Fast track GetCommModemStatus call ::::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +int FastGetCommModemStatus( + +HANDLE FileHandle, // Handle of comms port to send ioctl to +HANDLE Event, // Event to signal completion of ioctl on +PULONG ModemStatus) +{ + NTSTATUS rtn; + IO_STATUS_BLOCK ioStatusBlock; + + /*.......................................... issue set comm mask ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL, + &ioStatusBlock, + IOCTL_SERIAL_GET_MODEMSTATUS, + NULL, 0, + (PVOID) ModemStatus, sizeof(ModemStatus)))) + { + // Should display an error here +#ifndef PROD + fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__); + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); +#endif + return(FALSE); + } + + /*......................................... Wait for IOCTL to complete */ + + if(rtn == STATUS_PENDING) + NtWaitForSingleObject(Event, FALSE, NULL); + + /*............................................ Check completion status */ + +#ifndef PROD + if(ioStatusBlock.Status != STATUS_SUCCESS) + fprintf(trace_file,"GetCommModemStatus failed (%x)\n",ioStatusBlock.Status); +#endif + + return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE); +} + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*:::::: Wait for a wakeup call from the CPU thread or serial driver :::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + +//WARNING : This function can only be called from one thread within a process + + +BOOL FastWaitCommsOrCpuEvent( +HANDLE FileHandle, //File handle or communications port +PHANDLE CommsCPUWaitEvents, //Table or CPU thread and comms wait events +int CommsEventInx, //Index in above table to comms event +PULONG EvtMask, //Return Comms completion mask there +PULONG SignalledObj) +{ + NTSTATUS rtn; + static IO_STATUS_BLOCK ioStatusBlock; + static BOOL WaitCommEventOutStanding = FALSE; + + /*................................................ Is this a init call */ + + if(FileHandle == NULL) + { + WaitCommEventOutStanding = FALSE; + return(TRUE); //Init successful + } + + /*......................... Do we need to issue a new WaitComm ioctl ? */ + + if(!WaitCommEventOutStanding) + { + + /*...................................... Issue WaitCommEvent ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, + CommsCPUWaitEvents[CommsEventInx], + NULL, + NULL, + &ioStatusBlock, + IOCTL_SERIAL_WAIT_ON_MASK, + NULL, + 0, + EvtMask, + sizeof(ULONG))) ) + { + // Should display an error here +#ifndef PROD + fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__); + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); +#endif + SETUPLASTERROR(rtn); + return(FALSE); + } + else + WaitCommEventOutStanding = TRUE; + } + else + rtn = STATUS_PENDING; // Already pending WaitCommEvent ioctl + + /*.......................... Wait for communication or CPU thread event */ + + if(rtn == STATUS_PENDING) + { + *SignalledObj = NtWaitForMultipleObjects(2, + CommsCPUWaitEvents, + WaitAny, + FALSE, + NULL + ); + + /*........... Did wait complete because of a communications event ? */ + + if(*SignalledObj == (ULONG)CommsEventInx) + { + // Get result from WaitCommEvent ioctl + + WaitCommEventOutStanding = FALSE; + if(ioStatusBlock.Status != STATUS_SUCCESS) + { + SETUPLASTERROR(ioStatusBlock.Status); + return(FALSE); + } + } + } + else + { + //WaitCommEvent completed instantly + *SignalledObj = CommsEventInx; + WaitCommEventOutStanding = FALSE; + } + + return(TRUE); +} + + + +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ +/*::::::::::::::::: Turn on MSR,LSR, RX streaming mode :::::::::::::::::::::*/ +/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/ + + +BOOL EnableMSRLSRRXmode( + +HANDLE FileHandle, // Handle of comms port to send ioctl to +HANDLE Event, // Event to signal completion of ioctl on +unsigned char EscapeChar) +{ + NTSTATUS rtn; + IO_STATUS_BLOCK ioStatusBlock; + + /*........................................................ issue ioctl */ + + if(!NT_SUCCESS(rtn = NtDeviceIoControlFile(FileHandle, Event, NULL, NULL, + &ioStatusBlock, + IOCTL_SERIAL_LSRMST_INSERT, + &EscapeChar, sizeof(unsigned char),NULL,0))) + { +#ifndef PROD + fprintf(trace_file, "%s (%d) ",__FILE__,__LINE__); + fprintf(trace_file, "NtDeviceIoControlFile failed %x\n",rtn); +#endif + return(FALSE); + } + + /*......................................... Wait for IOCTL to complete */ + + if (rtn == STATUS_PENDING) + NtWaitForSingleObject(Event, FALSE, NULL); + + + /*............................................ Check completion status */ + +#ifndef PROD + if(ioStatusBlock.Status != STATUS_SUCCESS) + fprintf(trace_file,"IOCTL_SERIAL_LSRMST_INSERT ioctl failed (%x)\n", + ioStatusBlock.Status); +#endif + + return(ioStatusBlock.Status == STATUS_SUCCESS ? TRUE : FALSE); +} + + +/* Function to set a new baudrate for the comm device. + * Input: FileHandle -- file handle to the comm device + * BaudRate -- new baudrate to be set for the comm device + * output: TRUE if the function succeed + * FALSE if the function failed +**/ + + +BOOL FastCommSetBaudRate(HANDLE FileHandle, int BaudRate) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE SyncEvent; + SERIAL_BAUD_RATE LocalBaud; + + SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (SyncEvent == NULL) + return FALSE; + + LocalBaud.BaudRate = (ULONG)BaudRate; + + Status = NtDeviceIoControlFile(FileHandle, + SyncEvent, + NULL, + NULL, + &IoStatusBlock, + IOCTL_SERIAL_SET_BAUD_RATE, + &LocalBaud, + sizeof(LocalBaud), + NULL, + 0 + ); + if (Status == STATUS_PENDING) + NtWaitForSingleObject(SyncEvent, FALSE, NULL); + CloseHandle(SyncEvent); + return(NT_SUCCESS(IoStatusBlock.Status)); +} + +/* Function to set the new line control to the given comm device + * Input: FileHanlde -- file handle to the comm device + * StopBits -- new Stopbits + * Parity -- new parity + * DataBits -- new databits + * Output: + * TRUE if the function succeed. + * FALSE if the function failed. +**/ +BOOL FastCommSetLineControl(HANDLE FileHandle, UCHAR StopBits, UCHAR Parity, + UCHAR DataBits) +{ + NTSTATUS Status; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE SyncEvent; + SERIAL_LINE_CONTROL LocalLC; + + + /* make sure Windows and NT has the same definiation because + * the caller only deal with WINDOWS value while we will be returning + * NT values(NO_PARITY, STOP_BIT_1 and etc). + */ + ASSERT(NOPARITY == NO_PARITY && ODDPARITY == ODD_PARITY && + EVENPARITY == EVEN_PARITY && MARKPARITY == MARK_PARITY && + SPACEPARITY == SPACE_PARITY); + ASSERT(ONESTOPBIT == STOP_BIT_1 && ONE5STOPBITS == STOP_BITS_1_5 && + TWOSTOPBITS == STOP_BITS_2); + + /* Create an event to wait for the NT call */ + SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (SyncEvent == NULL) + return FALSE; + + LocalLC.StopBits = StopBits; + LocalLC.Parity = Parity; + LocalLC.WordLength = DataBits; + + Status = NtDeviceIoControlFile(FileHandle, + SyncEvent, + NULL, + NULL, + &IoStatusBlock, + IOCTL_SERIAL_SET_LINE_CONTROL, + &LocalLC, + sizeof(LocalLC), + NULL, + 0 + ); + if (Status == STATUS_PENDING) + NtWaitForSingleObject(SyncEvent, FALSE, NULL); + + CloseHandle(SyncEvent); + return(NT_SUCCESS(IoStatusBlock.Status)); +} + +/* Function to retrieve the given comm device current line control setting + * Input: FileHandle -- file handle to the comm device + * StopBits, Parity and DataBits are pointers to the placeholders + * to receive Stop bits, Parity and Data bits repectively. + * Output: + * TRUE if the function succeed + * FALSE if the function failed. +**/ + +BOOL FastCommGetLineControl(HANDLE FileHandle, UCHAR *StopBits, UCHAR *Parity, + UCHAR *DataBits) +{ + NTSTATUS Status; + SERIAL_LINE_CONTROL LocalLC; + IO_STATUS_BLOCK IoStatusBlock; + HANDLE SyncEvent; + + /* make sure Windows and NT has the same definiation because + * the parameters we received from the caller are WINDOWS value + * while we will be calling NT API using NT values + */ + ASSERT(NOPARITY == NO_PARITY && ODDPARITY == ODD_PARITY && + EVENPARITY == EVEN_PARITY && MARKPARITY == MARK_PARITY && + SPACEPARITY == SPACE_PARITY); + ASSERT(ONESTOPBIT == STOP_BIT_1 && ONE5STOPBITS == STOP_BITS_1_5 && + TWOSTOPBITS == STOP_BITS_2); + + ASSERT(StopBits != NULL && Parity != NULL && DataBits != NULL); + + SyncEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (SyncEvent == NULL) + return FALSE; + Status = NtDeviceIoControlFile(FileHandle, + SyncEvent, + NULL, + NULL, + &IoStatusBlock, + IOCTL_SERIAL_GET_LINE_CONTROL, + NULL, + 0, + &LocalLC, + sizeof(LocalLC) + ); + if (Status == STATUS_PENDING) + NtWaitForSingleObject(SyncEvent, FALSE, NULL); + + CloseHandle(SyncEvent); + + if (NT_SUCCESS(IoStatusBlock.Status)) { + *StopBits = LocalLC.StopBits; + *Parity = LocalLC.Parity; + *DataBits = LocalLC.WordLength; + return TRUE; + } + return FALSE; +} |