summaryrefslogtreecommitdiffstats
path: root/private/mvdm/softpc.new/host/src/nt_ntfun.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/mvdm/softpc.new/host/src/nt_ntfun.c')
-rw-r--r--private/mvdm/softpc.new/host/src/nt_ntfun.c592
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;
+}