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

📄 nt_com.c

📁 DD sample implements serial port support for the Virtual DOS Machine (VDM). Driver for windows. Tool
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * NT_com.c - Windows NT serial interface
 *
 * This module handles serial input and output to Windows NT.
 *
 * copyright 1992, 1993 by Microsoft Corporation
 * portions copyright 1991 by Insignia Solutions Ltd., used by permission.
 *
 * revision history:
 *  24-Dec-1992 John Morgan:  written
 *              based (in part) on serial driver support from Windows NT VDM.
 *   4-Jan-1993 John Morgan:  added support for transmit buffering
 */

//
//    useful utility macros
//
#include "util_def.h"

//
//    standard library include files
//
#include <windows.h>

#include <math.h>
#include <malloc.h>
#include <stdlib.h>

//
//    COM_VDD specific include files
//
#include "com_vdd.h"
#include "pc_com.h"
#include "nt_com.h"
#include "vddsvc.h"


//
// Serial driver magic numbers
//
#define INPUT_QUEUE_SIZE    (4*1024)
#define OUTPUT_QUEUE_SIZE   100

#define  XON_CHARACTER   (17)           /* XON character, Cntrl-Q */
#define  XOFF_CHARACTER  (19)           /* XOFF character, Cntrl-S */

#define  REOPEN_DELAY    (36)           /* Reopen delay in 55ms (2 secs) */

//
// Serial status structure
//  this incorporates the UART status as a substucture
//
tHostCom host_com[NUM_SERIAL_PORTS];    /* 4 comm ports - the insignia MAX */


/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::: Wait for Comm Event ::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
static BOOL wait_comm( pHostCom current )
{
    ResetEvent( current->WaitOverlap.hEvent );

    if (WaitCommEvent( current->handle, &current->EvtMask, &current->WaitOverlap ))
        return TRUE;

    if (GetLastError() == ERROR_IO_PENDING)
        return GetOverlappedResult( current->handle, &current->WaitOverlap, NULL, TRUE );

    return FALSE;
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::: Read Comm Port :::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
static BOOL read_comm( pHostCom current, DWORD *bytesread )
{

    ResetEvent( current->WaitOverlap.hEvent );

    if (ReadFile( current->handle, current->rx_buffer, RX_BUFFER_SIZE, bytesread, &current->RXOverlap ))
        return TRUE;

    if (GetLastError() == ERROR_IO_PENDING)
        return GetOverlappedResult( current->handle, &current->RXOverlap, NULL, TRUE );

    return FALSE;
}

#if (!XMIT_BUFFER)

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::: Write Comm Port ::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
static BOOL write_comm( pHostCom current, BYTE *buffer, DWORD length )
{
    DWORD byteswritten;

    ResetEvent( current->WaitOverlap.hEvent );

    if (WriteFile( current->handle, buffer, length, &byteswritten, &current->TXOverlap ))
        return TRUE;

    if (GetLastError() == ERROR_IO_PENDING)
        return GetOverlappedResult( current->handle, &current->TXOverlap, NULL, TRUE );

    return FALSE;
}

#else

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::: TX buffer pool :::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
// the number of transmit buffers available
#define NUM_TX_BUFFERS 4

typedef struct tTX_qitem
{
    struct tTX_qitem *next;      // pointer to next buffer (for queues)
    tTX_buffer buffer;
} tTX_qitem, *pTX_qitem;

static tTX_qitem  TX_q_buff[NUM_TX_BUFFERS];


/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::: TX transmit queues :::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
// queue selector type
typedef DWORD tQueueSel;

// the queue number for the free pool
#define NUM_TX_QUEUES (NUM_SERIAL_PORTS+1)
#define TX_FREE_QUEUE (NUM_TX_QUEUES-1)

typedef struct tTX_queue
{
    HANDLE wait[2];              // mutal exclusion & buffer available
    pTX_qitem head;
    pTX_qitem tail;
} tTX_queue, *pTX_queue;

static tTX_queue  TX_queue[NUM_TX_QUEUES];

static pTX_qitem TX_dequeue( tQueueSel queue_sel )
{
    pTX_queue queue = &TX_queue[queue_sel];
    pTX_qitem item;

    // wait until buffer available
    WaitForMultipleObjects( 2, queue -> wait, TRUE, INFINITE );
    if ((item = queue -> tail) != NULL)
    {
        if ((queue -> tail = item -> next) == NULL)
            queue -> head = NULL;
        item -> next = NULL;
    }
    ReleaseMutex( queue -> wait[0] );

    return item;
}

static void TX_enqueue( tQueueSel queue_sel, pTX_qitem item )
{
    pTX_queue queue = &TX_queue[queue_sel];

    WaitForSingleObject( queue -> wait[0], INFINITE );
    item -> next = NULL;
    if (queue -> head == NULL)
        queue -> tail = item;
    else
        queue -> head -> next = item;
    queue -> head = item;
    ReleaseSemaphore( queue -> wait[1], 1, NULL );
    ReleaseMutex( queue -> wait[0] );
}

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*:::::::::::::::::::::::::::: transmit buffers ::::::::::::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

// the maximum wait time before writing a buffer even if it isn't full
#define TX_BUFF_DELAY 130

static DWORD transmit_buffers( DWORD adapter )
{
    DWORD byteswritten;
    pTX_qitem item;

    while ((item = TX_dequeue( adapter )) != NULL)      // Get next buffer to transmit
    {
        // wait until full, or timeout
        if (WaitForMultipleObjects( 2, item -> buffer.wait, TRUE, TX_BUFF_DELAY ) == WAIT_TIMEOUT)
        {
            // must have mutual exclusion regardless
            WaitForSingleObject( item -> buffer.wait[0], INFINITE );
        }

        // signal that buffer has been written
        item -> buffer.adapter = TX_FREE_QUEUE;         // not a legal port number

        // OK to release now (WE DON'T HAVE TO WAIT FOR ACTUAL WRITE!)
        ReleaseMutex( item -> buffer.wait[0] );

        // Wait for previous write (if any to complete)
        WaitForSingleObject( item -> buffer.Overlap.hEvent, INFINITE);
        ResetEvent( item -> buffer.Overlap.hEvent );

        // write buffer to com port
        WriteFile( host_com[adapter].handle, item -> buffer.bytes, item -> buffer.byte_count,
            &byteswritten, &item -> buffer.Overlap );

        // now buffer should be moved to free pool
        TX_enqueue( TX_FREE_QUEUE, item );

    }

    // close buffer queue
    CloseHandle( TX_queue[adapter].wait[0] );
    CloseHandle( TX_queue[adapter].wait[1] );

    return TRUE;
}

static void post_transmit( tAdapter adapter, BYTE data )
{
    register pHostCom current = & host_com[adapter];
    pTX_buffer buffer;
    pTX_qitem item;

    // check to see if buffer available
    if ((buffer = current -> tx_buffer) != NULL && buffer -> adapter == adapter)
    {
        // get mutual exclusion on buffer
        WaitForSingleObject( buffer -> wait[0], INFINITE );

        // check for buffer written before we could get MX
        if (buffer -> adapter == adapter)
        {
            // add another byte
            buffer -> bytes[(buffer -> byte_count)++] = data;

            // signal if buffer full
            if ((int)(buffer -> byte_count) >= current -> TX_full_length)
            {
                SetEvent( buffer -> wait[1] );
                current -> tx_buffer = NULL;
            }

            // release buffer MX
            ReleaseMutex( buffer -> wait[0] );

            return;
        }

        // Oops buffer written, but no harm done.
        ReleaseMutex( buffer -> wait[0] );
    }

    // expand buffer size by one character
    if (++(current -> TX_full_length) > TX_BUFFER_SIZE)
        current -> TX_full_length = TX_BUFFER_SIZE;

    // buffer written or unavailable.
    item = TX_dequeue( TX_FREE_QUEUE );
    item -> buffer.adapter = adapter;
    item -> buffer.bytes[0] = data;
    if ((int)(item -> buffer.byte_count = 1) >= current -> TX_full_length)
    {
        SetEvent( item -> buffer.wait[1] );        // signal buffer full
        current -> tx_buffer = NULL;
    }
    else
    {
        ResetEvent( item -> buffer.wait[1] );      // buffer not full
        current -> tx_buffer = &(item -> buffer);
    }
    TX_enqueue( adapter, item );
}

static void shrink_TX_buffer( tAdapter adapter )
{
    // collapse buffer by one character
    if (--(host_com[adapter].TX_full_length) < 0)
        host_com[adapter].TX_full_length = 0;
}

#endif //(XMIT_BUFFER)


/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::::::::::::::::::: Enter critical section for adapter :::::::::::::::::::*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void host_com_lock( tAdapter adapter )
{
    register pHostCom current = & host_com[adapter];
    if (current->host_adapter_status != HOST_ADAPTER_OPEN)
        return;  /* Exit, NULL adapter */

    EnterCriticalSection(&current->AdapterLock);
    current->AdapterLockCnt++;
}

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

⌨️ 快捷键说明

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