⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nt_com.c

📁 DD sample implements serial port support for the Virtual DOS Machine (VDM). Driver for windows. Tool
💻 C
📖 第 1 页 / 共 3 页
字号:
/*::::::::::::::::::: Leave critical section for adapter :::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void host_com_unlock( tAdapter adapter )
{
    register pHostCom current = & host_com[adapter];

    if(current->host_adapter_status != HOST_ADAPTER_OPEN)
        return; /* Exit, NULL adapter */

    if (current->AdapterLockCnt != 0)
    {
        current->AdapterLockCnt--;
        LeaveCriticalSection(&current->AdapterLock);
    }
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::: Interrupt detection thread, one per comm port ::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
static DWORD monitor_comms( DWORD adapter )
{
    register pHostCom current = & host_com[adapter];       // Set ptr to current adapter
    BOOL com_locked = FALSE;                                // not locked!

#define EV_LS_MS_TX (EV_ERR | EV_BREAK | EV_CTS | EV_DSR | EV_RING | EV_RLSD | EV_TXEMPTY)
    /* Set up event mask (without RX event) */
    SetCommMask( current->handle, EV_LS_MS_TX );

    forever
    {
        if (com_locked)
        {
            host_com_unlock( adapter );
            com_locked = FALSE;
        }

        wait_comm( current );

        if (current->TerminateRXThread)
        {
            return 0;                                       // Terminate thread
        }
                                                                 
        if (current->EvtMask & (EV_ERR | EV_BREAK))
        {
            if (!com_locked)
            {
                host_com_lock( adapter );
                com_locked = TRUE;
            }
            raise_rls_interrupt( &host_com[adapter].uart );
        }
        if (current->EvtMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD))
        {
            if (!com_locked)
            {
                host_com_lock( adapter );
                com_locked = TRUE;
            }
            raise_ms_interrupt( &host_com[adapter].uart );
        }
        if (current->EvtMask & (EV_RXCHAR))
        {
            if (!com_locked)
            {
                host_com_lock( adapter );
                com_locked = TRUE;
            }
            if (check_rda_interrupt( &host_com[adapter].uart ))
            {
                // reset event mask (without RX event)
                // to reduce overhead from this thread.
                SetCommMask( current->handle, EV_LS_MS_TX );
                current->rx_waiting = FALSE;
            }
            else
            {
                raise_rda_interrupt( &host_com[adapter].uart );
            }
        }
        if (current->EvtMask & (EV_TXEMPTY))
        {
            if (!com_locked)
            {
                host_com_lock( adapter );
                com_locked = TRUE;
            }
            clear_tbr_flag( & host_com[adapter].uart );
        }
    }
}

void host_com_rx_wait( tAdapter adapter )
{
    register pHostCom current = & host_com[adapter];     // Set ptr to current adapter

    if (!current->rx_waiting)
    {
        SetCommMask( current->handle, EV_LS_MS_TX | EV_RXCHAR );// reset event mask with RX event
        current->rx_waiting = TRUE;
    }
}


/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:::::::::::::::::::::::: Close comms port ::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void host_com_close( tAdapter adapter )
{
    register pHostCom current;
    
    com_close( adapter );

    current = & host_com[adapter];

    /*:::::::::::::::::::::::::::::::::::::::: Dealing with NULL adapter ? */
    if (current->host_adapter_status == HOST_ADAPTER_OPEN)
    {
        /*................................................. Close RX thread */
        if (current->RXThreadHandle != NULL)
        {
            /*................................. Tell RX thread to terminate */

            current->TerminateRXThread = TRUE;  // Tell RX thread to terminate

            /*....................... Signal RX Thread to break out of Wait */
            SetCommMask(current->handle, 0 );

            /*..... Wait for RX thread to close itself, max wait 30 seconds */
            WaitForSingleObject(current->RXThreadHandle, 30000);
            CloseHandle(current->RXThreadHandle);

            current->RXThreadHandle = NULL;  // Mark thread as closed
        }

#if (XMIT_BUFFER)
        /*................................................. Close TX thread */
        if (current->TXThreadHandle != NULL)
        {
            /*................................. Tell TX thread to terminate */
            ReleaseSemaphore( TX_queue[adapter].wait[1], 1, NULL );

            /*..... Wait for RX thread to close itself, max wait 30 seconds */
            WaitForSingleObject(current->TXThreadHandle, 30000);
            CloseHandle(current->TXThreadHandle);

            current->TXThreadHandle = NULL;  // Mark thread as closed
        }
#endif //(XMIT_BUFFER)

        /*.............................................. Close Comms device */
        CloseHandle(current->handle);
        current->handle = NULL;

        /*. This makes sure that the next access to the port will reopen it */
        current->ReOpenCounter = 0;
        current->host_adapter_status = HOST_ADAPTER_NOT_OPEN;   /* Mark adapter as closed */
     }
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::: Open comms port ::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
static BOOL host_com_open( tAdapter adapter )
{
    COMMTIMEOUTS comout;            /* Comms time out settings */
    char adapter_name[] = "COM?";
    register const pHostCom current = & host_com[adapter];

    switch (current->host_adapter_status) {
    case HOST_ADAPTER_DISABLED:
        return FALSE;

    case HOST_ADAPTER_OPEN:
        return TRUE;

    case HOST_ADAPTER_NOT_OPEN:
        /*:::::::::: Attempting to open the port too soon after a failed open ? */
        if (current->ReOpenCounter != 0)
            return FALSE;              /* Yes */

        /*::::::::::::::::::::::::::: We have a vaild adapter so try to open it */
        adapter_name[3] = '1'+adapter;
        current->handle = CreateFile( adapter_name,
                                      GENERIC_READ | GENERIC_WRITE, 0, NULL,
                                      OPEN_EXISTING,
                                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                                      NULL
                                    );

        /*............................................... Validate open attempt */
        if (current->handle == (HANDLE) -1)
        {
            current->host_adapter_status = HOST_ADAPTER_DISABLED;       /* Unable to open adapter */
            return FALSE;
        }

        /*:::::::::::::::::::::::::::::::::::::::::::::::: adapter port is open */
        current->host_adapter_status = HOST_ADAPTER_OPEN;

        /*::::::::::::::::::::::::::::::::::::::: Set Comms port to binary mode */
        if (!GetCommState( current->handle, &(current->dcb) ))
        {
            host_com_close( adapter );    /* turn it into a NULL adapter */
            current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
            return FALSE;
        }
    
        /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Setup DCB */
        current->dcb.fBinary = 1;                   /* run in RAW mode */
        current->dcb.fOutxCtsFlow = FALSE;          /* Disable CTS */
        current->dcb.fOutxDsrFlow = FALSE;          /* Disable DSR */
        current->dcb.fDtrControl = DTR_CONTROL_DISABLE;
        current->dcb.fOutX = FALSE;                 /* Disable XON/XOFF */
        current->dcb.fInX = FALSE;
        current->dcb.fRtsControl = RTS_CONTROL_DISABLE;

        current->dcb.XonChar = XON_CHARACTER;       /* Define XON/XOFF chars */
        current->dcb.XoffChar = XOFF_CHARACTER;

        /* Turn off error char replacement */
        current->dcb.fErrorChar = FALSE;

        /*:::::::::::::::::::::::::::::::::::::::::::::::: Set Comms port state */
        if (!SetCommState( current->handle, &(current->dcb) ))
        {
            host_com_close( adapter );
            current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
            return FALSE;
        }

        /*::::::::::::::::::::::::::::::::::::::::::::: Setup comms queue sizes */
        if (!SetupComm( current->handle, INPUT_QUEUE_SIZE, OUTPUT_QUEUE_SIZE) )
        {
            host_com_close( adapter );
            current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
            return FALSE;
        }

        /*::::::::::::::::::::: Set communication port up for non-blocking read */
        GetCommTimeouts( current->handle, &comout );

        comout.ReadIntervalTimeout = MAXDWORD;
        comout.ReadTotalTimeoutMultiplier = 0;
        comout.ReadTotalTimeoutConstant = 0;

        SetCommTimeouts( current->handle, &comout );

        /*:::::::::::::::::::::::::::::::: reset baud rate, line & modem control */
        com_reset( adapter );

#if (XMIT_BUFFER)
        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: TX buffer */
        current -> TX_full_length = 0;

        /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: TX queue */
        TX_queue[adapter].head = NULL;
        TX_queue[adapter].tail = NULL;
        TX_queue[adapter].wait[0] = CreateMutex( NULL, FALSE, NULL);
        TX_queue[adapter].wait[1] = CreateSemaphore( NULL, 0, NUM_TX_BUFFERS, NULL);

        /*::::::::::::::::::::::::::::::::::::::::::::::: Create Comms TX thread */
        if (!(current->TXThreadHandle = CreateThread( NULL,
                                                      10*1024,
                                                      (LPTHREAD_START_ROUTINE)transmit_buffers,
                                                      (LPVOID)adapter,
                                                      0L,
                                                      &current->TXThreadID )))
        {
            host_com_close( adapter );        /* Unable to create TX thread */
            current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
            return FALSE;
        }
        SetThreadPriority( current -> TXThreadHandle, THREAD_PRIORITY_TIME_CRITICAL );
#endif //(XMIT_BUFFER)

        /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: RX buffer */
        current->rx_error = 0;              // no errors pending
        current->rx_curr = current->rx_end = current->rx_buffer;
                                            // buffer empty
        current->rx_waiting = FALSE;        // not waiting for RX interrupt

        /*::::::::::::::::::::::::::::::::::::::::::::::: Create Comms RX thread */
        current->TerminateRXThread = FALSE;
        if (!(current->RXThreadHandle = CreateThread( NULL,
                                                      10*1024,
                                                      (LPTHREAD_START_ROUTINE)monitor_comms,
                                                      (LPVOID)adapter,
                                                      0L,
                                                      &current->RXThreadID )))
        {
            host_com_close( adapter );        /* Unable to create RX thread */
            current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
            return FALSE;
        }

        return TRUE;

    default:
        return FALSE;
    }
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -