Annotation of ntddk/src/vdd/com_vdd/nt_com.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * NT_com.c - Windows NT serial interface
                      3:  *
                      4:  * This module handles serial input and output to Windows NT.
                      5:  *
                      6:  * copyright 1992, 1993 by Microsoft Corporation
                      7:  * portions copyright 1991 by Insignia Solutions Ltd., used by permission.
                      8:  *
                      9:  * revision history:
                     10:  *  24-Dec-1992 John Morgan:  written
                     11:  *              based (in part) on serial driver support from Windows NT VDM.
                     12:  *   4-Jan-1993 John Morgan:  added support for transmit buffering
                     13:  */
                     14: 
                     15: //
                     16: //    useful utility macros
                     17: //
                     18: #include "util_def.h"
                     19: 
                     20: //
                     21: //    standard library include files
                     22: //
                     23: #include <windows.h>
                     24: 
                     25: #include <math.h>
                     26: #include <malloc.h>
                     27: #include <stdlib.h>
                     28: 
                     29: //
                     30: //    COM_VDD specific include files
                     31: //
                     32: #include "com_vdd.h"
                     33: #include "pc_com.h"
                     34: #include "nt_com.h"
                     35: #include "vddsvc.h"
                     36: 
                     37: 
                     38: //
                     39: // Serial driver magic numbers
                     40: //
                     41: #define INPUT_QUEUE_SIZE    (4*1024)
                     42: #define OUTPUT_QUEUE_SIZE   100
                     43: 
                     44: #define  XON_CHARACTER   (17)           /* XON character, Cntrl-Q */
                     45: #define  XOFF_CHARACTER  (19)           /* XOFF character, Cntrl-S */
                     46: 
                     47: #define  REOPEN_DELAY    (36)           /* Reopen delay in 55ms (2 secs) */
                     48: 
                     49: //
                     50: // Serial status structure
                     51: //  this incorporates the UART status as a substucture
                     52: //
                     53: tHostCom host_com[NUM_SERIAL_PORTS];    /* 4 comm ports - the insignia MAX */
                     54: 
                     55: 
                     56: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     57: /*::::::::::::::::::::::::::: Wait for Comm Event ::::::::::::::::::::::::::*/
                     58: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     59: static BOOL wait_comm( pHostCom current )
                     60: {
                     61:     ResetEvent( current->WaitOverlap.hEvent );
                     62: 
                     63:     if (WaitCommEvent( current->handle, &current->EvtMask, &current->WaitOverlap ))
                     64:         return TRUE;
                     65: 
                     66:     if (GetLastError() == ERROR_IO_PENDING)
                     67:         return GetOverlappedResult( current->handle, &current->WaitOverlap, NULL, TRUE );
                     68: 
                     69:     return FALSE;
                     70: }
                     71: 
                     72: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     73: /*::::::::::::::::::::::::::::: Read Comm Port :::::::::::::::::::::::::::::*/
                     74: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     75: static BOOL read_comm( pHostCom current, DWORD *bytesread )
                     76: {
                     77: 
                     78:     ResetEvent( current->WaitOverlap.hEvent );
                     79: 
                     80:     if (ReadFile( current->handle, current->rx_buffer, RX_BUFFER_SIZE, bytesread, &current->RXOverlap ))
                     81:         return TRUE;
                     82: 
                     83:     if (GetLastError() == ERROR_IO_PENDING)
                     84:         return GetOverlappedResult( current->handle, &current->RXOverlap, NULL, TRUE );
                     85: 
                     86:     return FALSE;
                     87: }
                     88: 
                     89: #if (!XMIT_BUFFER)
                     90: 
                     91: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     92: /*::::::::::::::::::::::::::::: Write Comm Port ::::::::::::::::::::::::::::*/
                     93: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                     94: static BOOL write_comm( pHostCom current, BYTE *buffer, DWORD length )
                     95: {
                     96:     DWORD byteswritten;
                     97: 
                     98:     ResetEvent( current->WaitOverlap.hEvent );
                     99: 
                    100:     if (WriteFile( current->handle, buffer, length, &byteswritten, &current->TXOverlap ))
                    101:         return TRUE;
                    102: 
                    103:     if (GetLastError() == ERROR_IO_PENDING)
                    104:         return GetOverlappedResult( current->handle, &current->TXOverlap, NULL, TRUE );
                    105: 
                    106:     return FALSE;
                    107: }
                    108: 
                    109: #else
                    110: 
                    111: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    112: /*::::::::::::::::::::::::::::: TX buffer pool :::::::::::::::::::::::::::::*/
                    113: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    114: // the number of transmit buffers available
                    115: #define NUM_TX_BUFFERS 4
                    116: 
                    117: typedef struct tTX_qitem
                    118: {
                    119:     struct tTX_qitem *next;      // pointer to next buffer (for queues)
                    120:     tTX_buffer buffer;
                    121: } tTX_qitem, *pTX_qitem;
                    122: 
                    123: static tTX_qitem  TX_q_buff[NUM_TX_BUFFERS];
                    124: 
                    125: 
                    126: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    127: /*::::::::::::::::::::::::::: TX transmit queues :::::::::::::::::::::::::::*/
                    128: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    129: // queue selector type
                    130: typedef DWORD tQueueSel;
                    131: 
                    132: // the queue number for the free pool
                    133: #define NUM_TX_QUEUES (NUM_SERIAL_PORTS+1)
                    134: #define TX_FREE_QUEUE (NUM_TX_QUEUES-1)
                    135: 
                    136: typedef struct tTX_queue
                    137: {
                    138:     HANDLE wait[2];              // mutal exclusion & buffer available
                    139:     pTX_qitem head;
                    140:     pTX_qitem tail;
                    141: } tTX_queue, *pTX_queue;
                    142: 
                    143: static tTX_queue  TX_queue[NUM_TX_QUEUES];
                    144: 
                    145: static pTX_qitem TX_dequeue( tQueueSel queue_sel )
                    146: {
                    147:     pTX_queue queue = &TX_queue[queue_sel];
                    148:     pTX_qitem item;
                    149: 
                    150:     // wait until buffer available
                    151:     WaitForMultipleObjects( 2, queue -> wait, TRUE, INFINITE );
                    152:     if ((item = queue -> tail) != NULL)
                    153:     {
                    154:         if ((queue -> tail = item -> next) == NULL)
                    155:             queue -> head = NULL;
                    156:         item -> next = NULL;
                    157:     }
                    158:     ReleaseMutex( queue -> wait[0] );
                    159: 
                    160:     return item;
                    161: }
                    162: 
                    163: static void TX_enqueue( tQueueSel queue_sel, pTX_qitem item )
                    164: {
                    165:     pTX_queue queue = &TX_queue[queue_sel];
                    166: 
                    167:     WaitForSingleObject( queue -> wait[0], INFINITE );
                    168:     item -> next = NULL;
                    169:     if (queue -> head == NULL)
                    170:         queue -> tail = item;
                    171:     else
                    172:         queue -> head -> next = item;
                    173:     queue -> head = item;
                    174:     ReleaseSemaphore( queue -> wait[1], 1, NULL );
                    175:     ReleaseMutex( queue -> wait[0] );
                    176: }
                    177: 
                    178: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    179: /*:::::::::::::::::::::::::::: transmit buffers ::::::::::::::::::::::::::::*/
                    180: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    181: 
                    182: // the maximum wait time before writing a buffer even if it isn't full
                    183: #define TX_BUFF_DELAY 130
                    184: 
                    185: static DWORD transmit_buffers( DWORD adapter )
                    186: {
                    187:     DWORD byteswritten;
                    188:     pTX_qitem item;
                    189: 
                    190:     while ((item = TX_dequeue( adapter )) != NULL)      // Get next buffer to transmit
                    191:     {
                    192:         // wait until full, or timeout
                    193:         if (WaitForMultipleObjects( 2, item -> buffer.wait, TRUE, TX_BUFF_DELAY ) == WAIT_TIMEOUT)
                    194:         {
                    195:             // must have mutual exclusion regardless
                    196:             WaitForSingleObject( item -> buffer.wait[0], INFINITE );
                    197:         }
                    198: 
                    199:         // signal that buffer has been written
                    200:         item -> buffer.adapter = TX_FREE_QUEUE;         // not a legal port number
                    201: 
                    202:         // OK to release now (WE DON'T HAVE TO WAIT FOR ACTUAL WRITE!)
                    203:         ReleaseMutex( item -> buffer.wait[0] );
                    204: 
                    205:         // Wait for previous write (if any to complete)
                    206:         WaitForSingleObject( item -> buffer.Overlap.hEvent, INFINITE);
                    207:         ResetEvent( item -> buffer.Overlap.hEvent );
                    208: 
                    209:         // write buffer to com port
                    210:         WriteFile( host_com[adapter].handle, item -> buffer.bytes, item -> buffer.byte_count,
                    211:             &byteswritten, &item -> buffer.Overlap );
                    212: 
                    213:         // now buffer should be moved to free pool
                    214:         TX_enqueue( TX_FREE_QUEUE, item );
                    215: 
                    216:     }
                    217: 
                    218:     // close buffer queue
                    219:     CloseHandle( TX_queue[adapter].wait[0] );
                    220:     CloseHandle( TX_queue[adapter].wait[1] );
                    221: 
                    222:     return TRUE;
                    223: }
                    224: 
                    225: static void post_transmit( tAdapter adapter, BYTE data )
                    226: {
                    227:     register pHostCom current = & host_com[adapter];
                    228:     pTX_buffer buffer;
                    229:     pTX_qitem item;
                    230: 
                    231:     // check to see if buffer available
                    232:     if ((buffer = current -> tx_buffer) != NULL && buffer -> adapter == adapter)
                    233:     {
                    234:         // get mutual exclusion on buffer
                    235:         WaitForSingleObject( buffer -> wait[0], INFINITE );
                    236: 
                    237:         // check for buffer written before we could get MX
                    238:         if (buffer -> adapter == adapter)
                    239:         {
                    240:             // add another byte
                    241:             buffer -> bytes[(buffer -> byte_count)++] = data;
                    242: 
                    243:             // signal if buffer full
                    244:             if ((int)(buffer -> byte_count) >= current -> TX_full_length)
                    245:             {
                    246:                 SetEvent( buffer -> wait[1] );
                    247:                 current -> tx_buffer = NULL;
                    248:             }
                    249: 
                    250:             // release buffer MX
                    251:             ReleaseMutex( buffer -> wait[0] );
                    252: 
                    253:             return;
                    254:         }
                    255: 
                    256:         // Oops buffer written, but no harm done.
                    257:         ReleaseMutex( buffer -> wait[0] );
                    258:     }
                    259: 
                    260:     // expand buffer size by one character
                    261:     if (++(current -> TX_full_length) > TX_BUFFER_SIZE)
                    262:         current -> TX_full_length = TX_BUFFER_SIZE;
                    263: 
                    264:     // buffer written or unavailable.
                    265:     item = TX_dequeue( TX_FREE_QUEUE );
                    266:     item -> buffer.adapter = adapter;
                    267:     item -> buffer.bytes[0] = data;
                    268:     if ((int)(item -> buffer.byte_count = 1) >= current -> TX_full_length)
                    269:     {
                    270:         SetEvent( item -> buffer.wait[1] );        // signal buffer full
                    271:         current -> tx_buffer = NULL;
                    272:     }
                    273:     else
                    274:     {
                    275:         ResetEvent( item -> buffer.wait[1] );      // buffer not full
                    276:         current -> tx_buffer = &(item -> buffer);
                    277:     }
                    278:     TX_enqueue( adapter, item );
                    279: }
                    280: 
                    281: static void shrink_TX_buffer( tAdapter adapter )
                    282: {
                    283:     // collapse buffer by one character
                    284:     if (--(host_com[adapter].TX_full_length) < 0)
                    285:         host_com[adapter].TX_full_length = 0;
                    286: }
                    287: 
                    288: #endif //(XMIT_BUFFER)
                    289: 
                    290: 
                    291: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    292: /*::::::::::::::::::: Enter critical section for adapter :::::::::::::::::::*/
                    293: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    294: void host_com_lock( tAdapter adapter )
                    295: {
                    296:     register pHostCom current = & host_com[adapter];
                    297:     if (current->host_adapter_status != HOST_ADAPTER_OPEN)
                    298:         return;  /* Exit, NULL adapter */
                    299: 
                    300:     EnterCriticalSection(&current->AdapterLock);
                    301:     current->AdapterLockCnt++;
                    302: }
                    303: 
                    304: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    305: /*::::::::::::::::::: Leave critical section for adapter :::::::::::::::::::*/
                    306: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    307: void host_com_unlock( tAdapter adapter )
                    308: {
                    309:     register pHostCom current = & host_com[adapter];
                    310: 
                    311:     if(current->host_adapter_status != HOST_ADAPTER_OPEN)
                    312:         return; /* Exit, NULL adapter */
                    313: 
                    314:     if (current->AdapterLockCnt != 0)
                    315:     {
                    316:         current->AdapterLockCnt--;
                    317:         LeaveCriticalSection(&current->AdapterLock);
                    318:     }
                    319: }
                    320: 
                    321: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    322: /*::::::::::: Interrupt detection thread, one per comm port ::::::::::::::::*/
                    323: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    324: static DWORD monitor_comms( DWORD adapter )
                    325: {
                    326:     register pHostCom current = & host_com[adapter];       // Set ptr to current adapter
                    327:     BOOL com_locked = FALSE;                                // not locked!
                    328: 
                    329: #define EV_LS_MS_TX (EV_ERR | EV_BREAK | EV_CTS | EV_DSR | EV_RING | EV_RLSD | EV_TXEMPTY)
                    330:     /* Set up event mask (without RX event) */
                    331:     SetCommMask( current->handle, EV_LS_MS_TX );
                    332: 
                    333:     forever
                    334:     {
                    335:         if (com_locked)
                    336:         {
                    337:             host_com_unlock( adapter );
                    338:             com_locked = FALSE;
                    339:         }
                    340: 
                    341:         wait_comm( current );
                    342: 
                    343:         if (current->TerminateRXThread)
                    344:         {
                    345:             return 0;                                       // Terminate thread
                    346:         }
                    347:                                                                  
                    348:         if (current->EvtMask & (EV_ERR | EV_BREAK))
                    349:         {
                    350:             if (!com_locked)
                    351:             {
                    352:                 host_com_lock( adapter );
                    353:                 com_locked = TRUE;
                    354:             }
                    355:             raise_rls_interrupt( &host_com[adapter].uart );
                    356:         }
                    357:         if (current->EvtMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD))
                    358:         {
                    359:             if (!com_locked)
                    360:             {
                    361:                 host_com_lock( adapter );
                    362:                 com_locked = TRUE;
                    363:             }
                    364:             raise_ms_interrupt( &host_com[adapter].uart );
                    365:         }
                    366:         if (current->EvtMask & (EV_RXCHAR))
                    367:         {
                    368:             if (!com_locked)
                    369:             {
                    370:                 host_com_lock( adapter );
                    371:                 com_locked = TRUE;
                    372:             }
                    373:             if (check_rda_interrupt( &host_com[adapter].uart ))
                    374:             {
                    375:                 // reset event mask (without RX event)
                    376:                 // to reduce overhead from this thread.
                    377:                 SetCommMask( current->handle, EV_LS_MS_TX );
                    378:                 current->rx_waiting = FALSE;
                    379:             }
                    380:             else
                    381:             {
                    382:                 raise_rda_interrupt( &host_com[adapter].uart );
                    383:             }
                    384:         }
                    385:         if (current->EvtMask & (EV_TXEMPTY))
                    386:         {
                    387:             if (!com_locked)
                    388:             {
                    389:                 host_com_lock( adapter );
                    390:                 com_locked = TRUE;
                    391:             }
                    392:             clear_tbr_flag( & host_com[adapter].uart );
                    393:         }
                    394:     }
                    395: }
                    396: 
                    397: void host_com_rx_wait( tAdapter adapter )
                    398: {
                    399:     register pHostCom current = & host_com[adapter];     // Set ptr to current adapter
                    400: 
                    401:     if (!current->rx_waiting)
                    402:     {
                    403:         SetCommMask( current->handle, EV_LS_MS_TX | EV_RXCHAR );// reset event mask with RX event
                    404:         current->rx_waiting = TRUE;
                    405:     }
                    406: }
                    407: 
                    408: 
                    409: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    410: /*:::::::::::::::::::::::: Close comms port ::::::::::::::::::::::::::::::::*/
                    411: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    412: void host_com_close( tAdapter adapter )
                    413: {
                    414:     register pHostCom current;
                    415:     
                    416:     com_close( adapter );
                    417: 
                    418:     current = & host_com[adapter];
                    419: 
                    420:     /*:::::::::::::::::::::::::::::::::::::::: Dealing with NULL adapter ? */
                    421:     if (current->host_adapter_status == HOST_ADAPTER_OPEN)
                    422:     {
                    423:         /*................................................. Close RX thread */
                    424:         if (current->RXThreadHandle != NULL)
                    425:         {
                    426:             /*................................. Tell RX thread to terminate */
                    427: 
                    428:             current->TerminateRXThread = TRUE;  // Tell RX thread to terminate
                    429: 
                    430:             /*....................... Signal RX Thread to break out of Wait */
                    431:             SetCommMask(current->handle, 0 );
                    432: 
                    433:             /*..... Wait for RX thread to close itself, max wait 30 seconds */
                    434:             WaitForSingleObject(current->RXThreadHandle, 30000);
                    435:             CloseHandle(current->RXThreadHandle);
                    436: 
                    437:             current->RXThreadHandle = NULL;  // Mark thread as closed
                    438:         }
                    439: 
                    440: #if (XMIT_BUFFER)
                    441:         /*................................................. Close TX thread */
                    442:         if (current->TXThreadHandle != NULL)
                    443:         {
                    444:             /*................................. Tell TX thread to terminate */
                    445:             ReleaseSemaphore( TX_queue[adapter].wait[1], 1, NULL );
                    446: 
                    447:             /*..... Wait for RX thread to close itself, max wait 30 seconds */
                    448:             WaitForSingleObject(current->TXThreadHandle, 30000);
                    449:             CloseHandle(current->TXThreadHandle);
                    450: 
                    451:             current->TXThreadHandle = NULL;  // Mark thread as closed
                    452:         }
                    453: #endif //(XMIT_BUFFER)
                    454: 
                    455:         /*.............................................. Close Comms device */
                    456:         CloseHandle(current->handle);
                    457:         current->handle = NULL;
                    458: 
                    459:         /*. This makes sure that the next access to the port will reopen it */
                    460:         current->ReOpenCounter = 0;
                    461:         current->host_adapter_status = HOST_ADAPTER_NOT_OPEN;   /* Mark adapter as closed */
                    462:      }
                    463: }
                    464: 
                    465: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    466: /*::::::::::::::::::::::::: Open comms port ::::::::::::::::::::::::::::::::*/
                    467: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    468: static BOOL host_com_open( tAdapter adapter )
                    469: {
                    470:     COMMTIMEOUTS comout;            /* Comms time out settings */
                    471:     char adapter_name[] = "COM?";
                    472:     register const pHostCom current = & host_com[adapter];
                    473: 
                    474:     switch (current->host_adapter_status) {
                    475:     case HOST_ADAPTER_DISABLED:
                    476:         return FALSE;
                    477: 
                    478:     case HOST_ADAPTER_OPEN:
                    479:         return TRUE;
                    480: 
                    481:     case HOST_ADAPTER_NOT_OPEN:
                    482:         /*:::::::::: Attempting to open the port too soon after a failed open ? */
                    483:         if (current->ReOpenCounter != 0)
                    484:             return FALSE;              /* Yes */
                    485: 
                    486:         /*::::::::::::::::::::::::::: We have a vaild adapter so try to open it */
                    487:         adapter_name[3] = '1'+adapter;
                    488:         current->handle = CreateFile( adapter_name,
                    489:                                       GENERIC_READ | GENERIC_WRITE, 0, NULL,
                    490:                                       OPEN_EXISTING,
                    491:                                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
                    492:                                       NULL
                    493:                                     );
                    494: 
                    495:         /*............................................... Validate open attempt */
                    496:         if (current->handle == (HANDLE) -1)
                    497:         {
                    498:             current->host_adapter_status = HOST_ADAPTER_DISABLED;       /* Unable to open adapter */
                    499:             return FALSE;
                    500:         }
                    501: 
                    502:         /*:::::::::::::::::::::::::::::::::::::::::::::::: adapter port is open */
                    503:         current->host_adapter_status = HOST_ADAPTER_OPEN;
                    504: 
                    505:         /*::::::::::::::::::::::::::::::::::::::: Set Comms port to binary mode */
                    506:         if (!GetCommState( current->handle, &(current->dcb) ))
                    507:         {
                    508:             host_com_close( adapter );    /* turn it into a NULL adapter */
                    509:             current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
                    510:             return FALSE;
                    511:         }
                    512:     
                    513:         /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Setup DCB */
                    514:         current->dcb.fBinary = 1;                   /* run in RAW mode */
                    515:         current->dcb.fOutxCtsFlow = FALSE;          /* Disable CTS */
                    516:         current->dcb.fOutxDsrFlow = FALSE;          /* Disable DSR */
                    517:         current->dcb.fDtrControl = DTR_CONTROL_DISABLE;
                    518:         current->dcb.fOutX = FALSE;                 /* Disable XON/XOFF */
                    519:         current->dcb.fInX = FALSE;
                    520:         current->dcb.fRtsControl = RTS_CONTROL_DISABLE;
                    521: 
                    522:         current->dcb.XonChar = XON_CHARACTER;       /* Define XON/XOFF chars */
                    523:         current->dcb.XoffChar = XOFF_CHARACTER;
                    524: 
                    525:         /* Turn off error char replacement */
                    526:         current->dcb.fErrorChar = FALSE;
                    527: 
                    528:         /*:::::::::::::::::::::::::::::::::::::::::::::::: Set Comms port state */
                    529:         if (!SetCommState( current->handle, &(current->dcb) ))
                    530:         {
                    531:             host_com_close( adapter );
                    532:             current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
                    533:             return FALSE;
                    534:         }
                    535: 
                    536:         /*::::::::::::::::::::::::::::::::::::::::::::: Setup comms queue sizes */
                    537:         if (!SetupComm( current->handle, INPUT_QUEUE_SIZE, OUTPUT_QUEUE_SIZE) )
                    538:         {
                    539:             host_com_close( adapter );
                    540:             current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
                    541:             return FALSE;
                    542:         }
                    543: 
                    544:         /*::::::::::::::::::::: Set communication port up for non-blocking read */
                    545:         GetCommTimeouts( current->handle, &comout );
                    546: 
                    547:         comout.ReadIntervalTimeout = MAXDWORD;
                    548:         comout.ReadTotalTimeoutMultiplier = 0;
                    549:         comout.ReadTotalTimeoutConstant = 0;
                    550: 
                    551:         SetCommTimeouts( current->handle, &comout );
                    552: 
                    553:         /*:::::::::::::::::::::::::::::::: reset baud rate, line & modem control */
                    554:         com_reset( adapter );
                    555: 
                    556: #if (XMIT_BUFFER)
                    557:         /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: TX buffer */
                    558:         current -> TX_full_length = 0;
                    559: 
                    560:         /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: TX queue */
                    561:         TX_queue[adapter].head = NULL;
                    562:         TX_queue[adapter].tail = NULL;
                    563:         TX_queue[adapter].wait[0] = CreateMutex( NULL, FALSE, NULL);
                    564:         TX_queue[adapter].wait[1] = CreateSemaphore( NULL, 0, NUM_TX_BUFFERS, NULL);
                    565: 
                    566:         /*::::::::::::::::::::::::::::::::::::::::::::::: Create Comms TX thread */
                    567:         if (!(current->TXThreadHandle = CreateThread( NULL,
                    568:                                                       10*1024,
                    569:                                                       (LPTHREAD_START_ROUTINE)transmit_buffers,
                    570:                                                       (LPVOID)adapter,
                    571:                                                       0L,
                    572:                                                       &current->TXThreadID )))
                    573:         {
                    574:             host_com_close( adapter );        /* Unable to create TX thread */
                    575:             current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
                    576:             return FALSE;
                    577:         }
                    578:         SetThreadPriority( current -> TXThreadHandle, THREAD_PRIORITY_TIME_CRITICAL );
                    579: #endif //(XMIT_BUFFER)
                    580: 
                    581:         /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: RX buffer */
                    582:         current->rx_error = 0;              // no errors pending
                    583:         current->rx_curr = current->rx_end = current->rx_buffer;
                    584:                                             // buffer empty
                    585:         current->rx_waiting = FALSE;        // not waiting for RX interrupt
                    586: 
                    587:         /*::::::::::::::::::::::::::::::::::::::::::::::: Create Comms RX thread */
                    588:         current->TerminateRXThread = FALSE;
                    589:         if (!(current->RXThreadHandle = CreateThread( NULL,
                    590:                                                       10*1024,
                    591:                                                       (LPTHREAD_START_ROUTINE)monitor_comms,
                    592:                                                       (LPVOID)adapter,
                    593:                                                       0L,
                    594:                                                       &current->RXThreadID )))
                    595:         {
                    596:             host_com_close( adapter );        /* Unable to create RX thread */
                    597:             current->ReOpenCounter = REOPEN_DELAY;   /* Delay next open attempt */
                    598:             return FALSE;
                    599:         }
                    600: 
                    601:         return TRUE;
                    602: 
                    603:     default:
                    604:         return FALSE;
                    605:     }
                    606: }
                    607: 
                    608: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    609: /*::::::::::::::::::::::::::: RX routines ::::::::::::::::::::::::::::::::::*/
                    610: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    611: DWORD host_com_get_error( tAdapter adapter )
                    612: {
                    613:     register pHostCom current = & host_com[adapter];     // Set ptr to current adapter
                    614:     DWORD error;
                    615: 
                    616:     if (current->host_adapter_status == HOST_ADAPTER_NOT_OPEN && !host_com_open( adapter ))
                    617:         return FALSE;                             /* Exit, unable to open adapter */
                    618: 
                    619:     if (current->rx_curr == current->rx_end)
                    620:     {
                    621:         error = current->rx_error;
                    622:         current->rx_error = 0;
                    623:         return error;
                    624:     }
                    625:     else
                    626:         return 0;
                    627: }
                    628: 
                    629: BOOL host_com_rx_avail( tAdapter adapter )
                    630: {
                    631:     register pHostCom current = & host_com[adapter];     // Set ptr to current adapter
                    632:     DWORD bytesread = 0;
                    633:     DWORD error = 0;
                    634: 
                    635:     if (current->host_adapter_status != HOST_ADAPTER_OPEN && !host_com_open( adapter ))
                    636:         return FALSE;                             /* Exit, unable to open adapter */
                    637: 
                    638:     if (current->rx_curr != current->rx_end)
                    639:         return TRUE;
                    640: 
                    641:     read_comm( current, &bytesread );
                    642: 
                    643:     // get communication error status
                    644:     ClearCommError( current->handle, &(current->rx_error), NULL );
                    645: 
                    646:     current->rx_curr = current->rx_buffer;
                    647:     current->rx_end = current->rx_buffer + bytesread;
                    648: 
                    649:     return (current->rx_curr != current->rx_end);
                    650: }
                    651: 
                    652: BOOL host_com_read_rx( tAdapter adapter, BYTE *data )
                    653: {
                    654:     if (host_com_rx_avail( adapter ))
                    655:     {
                    656:         *data = *(host_com[adapter].rx_curr++);
                    657: #if (XMIT_BUFFER)
                    658:         shrink_TX_buffer( adapter );
                    659: #endif
                    660: 
                    661:         return TRUE;
                    662:     }
                    663:     else
                    664:     {
                    665:         return FALSE;
                    666:     }
                    667: }
                    668: 
                    669: 
                    670: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    671: /*:::::::::::::::::::::::: Write to comms port :::::::::::::::::::::::::::::*/
                    672: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    673: BOOL host_com_write_tx( tAdapter adapter, BYTE data )
                    674: {
                    675:     if (host_com[adapter].host_adapter_status == HOST_ADAPTER_NOT_OPEN && !host_com_open( adapter ))
                    676:         return FALSE;                             /* Exit, unable to open adapter */
                    677: 
                    678: #if (XMIT_BUFFER)
                    679:     post_transmit( adapter, data );
                    680: #else //(XMIT_BUFFER)
                    681:     write_comm( &host_com[adapter], &data, 1 );
                    682: #endif //(XMIT_BUFFER)
                    683:     return TRUE;
                    684: }
                    685: 
                    686: 
                    687: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    688: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    689: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    690: ULONG host_com_ioctl( tAdapter adapter, int request, long arg )
                    691: {
                    692:     DWORD ModemState;
                    693:     ULONG ReturnState = 0;
                    694:     register pHostCom current = & host_com[adapter];      /* Define and set 'current' adaptor pointer */
                    695: 
                    696:     /*:::::::::::::::::::::::::::::::::: Are we dealing with a null adapter */
                    697: 
                    698:     if (current->host_adapter_status != HOST_ADAPTER_OPEN)
                    699:     {
                    700:         // Attempt to open adapter !
                    701: 
                    702:         if (request == HOST_COM_MSTATUS || !host_com_open(adapter))
                    703:         {
                    704:             return ReturnState;
                    705:         }
                    706:     }
                    707: 
                    708:     /*:::::::::::::::::::::::::::::::::::::::::::::: Identify ioctl request */
                    709: 
                    710:     switch (request)
                    711:     {
                    712:         /*:::::::::::::::::::::::::::::::::::::::::: Process break requests */
                    713: 
                    714:         case HOST_COM_SBRK:         /* Set BREAK */
                    715:             SetCommBreak(current->handle);
                    716:             break;
                    717: 
                    718:         case HOST_COM_CBRK:        /* Clear BREAK */
                    719:             ClearCommBreak(current->handle);
                    720:             break;
                    721: 
                    722:         /*::::::::::::::::::::::::::::::::::::::::: Process baud rate change */
                    723:         case HOST_COM_BAUD:
                    724:             if (GetCommState( current->handle, &(current->dcb) ))
                    725:             {
                    726:                 current->dcb.BaudRate = arg;
                    727:                 SetCommState( current->handle, &(current->dcb) );
                    728:             }
                    729:             break;
                    730: 
                    731: 
                    732:         /*:::::::::::::::::::::::::::::::::: Process modem control requests */
                    733:         case HOST_COM_MODEM_CTRL:                 /* DTR & RTS lines */
                    734:             if (arg & HOST_MC_DTR)
                    735:                 EscapeCommFunction( current->handle, SETDTR );
                    736:             else
                    737:                 EscapeCommFunction( current->handle, CLRDTR );
                    738: 
                    739:             if (arg & HOST_MC_RTS)
                    740:                 EscapeCommFunction( current->handle, CLRRTS );
                    741:             else
                    742:                 EscapeCommFunction( current->handle, SETRTS );
                    743:             break;
                    744: 
                    745:         /*::::::::::::::::::::::::::::::::::::::::::::: Return modem status */
                    746: 
                    747:         case HOST_COM_MSTATUS:              /* Get modem state */
                    748:             GetCommModemStatus( current->handle, &ModemState );
                    749: 
                    750:             if (ModemState & MS_CTS_ON)  ReturnState |= HOST_MS_CTS;
                    751:             if (ModemState & MS_RING_ON) ReturnState |= HOST_MS_RI;
                    752:             if (ModemState & MS_DSR_ON)  ReturnState |= HOST_MS_DSR;
                    753:             if (ModemState & MS_RLSD_ON) ReturnState |= HOST_MS_RLSD;
                    754: 
                    755:             current->modem_status = ReturnState;
                    756: 
                    757:             break;
                    758: 
                    759:         /*:::::::::::::::::::::::::::::::::::::::::::::::: Set line control */
                    760:         case HOST_COM_LINE_CTRL:
                    761:             if (GetCommState( current->handle, &(current->dcb) ))
                    762:             {
                    763:                 current->dcb.ByteSize = arg & HOST_LC_DATABITS;
                    764: 
                    765:                 switch (arg & HOST_LC_STOPBITS)
                    766:                 {
                    767:                     case HOST_LC_STOP_1:
                    768:                         current->dcb.StopBits = ONESTOPBIT; 
                    769:                         break;
                    770:                     case HOST_LC_STOP_2:  
                    771:                         current->dcb.StopBits = TWOSTOPBITS;
                    772:                         break;
                    773:                     case HOST_LC_STOP_15:  
                    774:                         current->dcb.StopBits = ONE5STOPBITS;
                    775:                         break;
                    776:                     default:
                    777:                         break;
                    778:                 }
                    779: 
                    780:                 switch (arg & HOST_LC_PARITY)
                    781:                 {
                    782:                     case HOST_LC_PARITY_EVEN:
                    783:                         current->dcb.Parity=EVENPARITY;
                    784:                         current->dcb.fParity=1;   /* ensure parity enabled */
                    785:                         break;
                    786: 
                    787:                     case HOST_LC_PARITY_ODD:
                    788:                         current->dcb.Parity=ODDPARITY;
                    789:                         current->dcb.fParity=1;   /* ensure parity enabled */
                    790:                         break;
                    791: 
                    792:                     case HOST_LC_PARITY_MARK:
                    793:                         current->dcb.Parity=MARKPARITY;
                    794:                         current->dcb.fParity=1;   /* ensure parity enabled */
                    795:                         break;
                    796: 
                    797:                     case HOST_LC_PARITY_SPACE:
                    798:                         current->dcb.Parity=SPACEPARITY;
                    799:                         current->dcb.fParity=1;   /* ensure parity enabled */
                    800:                         break;
                    801: 
                    802:                     case HOST_LC_PARITY_NONE:
                    803:                         current->dcb.Parity=NOPARITY;
                    804:                         current->dcb.fParity=0;   /* disable parity */
                    805:                         break;
                    806:                 }
                    807: 
                    808:                 SetCommState( current->handle, &(current->dcb) );
                    809:             }
                    810:             break;
                    811: 
                    812:         /*::::::::::::::::::::::::::::::::::::::: Unrecognised host_com ioctl */
                    813: 
                    814:         default:
                    815:             break;
                    816:     }
                    817: 
                    818:     return ReturnState;
                    819: }
                    820: 
                    821: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    822: /*:::::::::::::::::::::: Initialize comms port :::::::::::::::::::::::::::::*/
                    823: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    824: void host_com_init()
                    825: {
                    826:     tAdapter adapter;
                    827:     register pHostCom current;
                    828: 
                    829: #if (XMIT_BUFFER)
                    830:     int buffer_num;
                    831:     // set up transmit buffer free pool
                    832:     TX_queue[TX_FREE_QUEUE].head = NULL;
                    833:     TX_queue[TX_FREE_QUEUE].tail = NULL;
                    834:     TX_queue[TX_FREE_QUEUE].wait[0] = CreateMutex( NULL, FALSE, NULL);
                    835:     TX_queue[TX_FREE_QUEUE].wait[1] = CreateSemaphore( NULL, 0, NUM_TX_BUFFERS, NULL);
                    836: 
                    837:     // set up transmit buffers
                    838:     for (buffer_num = 0; buffer_num < NUM_TX_BUFFERS; buffer_num++)
                    839:     {
                    840:         TX_q_buff[buffer_num].buffer.wait[0] = CreateMutex( NULL, FALSE, NULL);
                    841:         TX_q_buff[buffer_num].buffer.wait[1] = CreateEvent( NULL, TRUE, FALSE, NULL);
                    842:         TX_q_buff[buffer_num].buffer.adapter = TX_FREE_QUEUE;
                    843:         TX_q_buff[buffer_num].buffer.Overlap.hEvent = CreateEvent( NULL, TRUE, TRUE, NULL );
                    844:         TX_enqueue( TX_FREE_QUEUE, &TX_q_buff[buffer_num] );
                    845:     }
                    846: #endif //(XMIT_BUFFER)
                    847: 
                    848:     // set up ports
                    849:     for (adapter = 0; adapter < NUM_SERIAL_PORTS; adapter++)
                    850:     {
                    851:         current = & host_com[adapter];
                    852: 
                    853:         current->host_adapter_status = HOST_ADAPTER_NOT_OPEN;
                    854:         current->handle = (HANDLE) -1;
                    855:         current->ReOpenCounter = 0;
                    856:         current->RXThreadHandle = NULL;
                    857: 
                    858:         /* critical section used to lock access to adapter from the base */
                    859:         InitializeCriticalSection(&current->AdapterLock);
                    860:         current->AdapterLockCnt = 0;
                    861: 
                    862:         current->WaitOverlap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
                    863:         current->RXOverlap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
                    864: #if (!XMIT_BUFFER)
                    865:         current->TXOverlap.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
                    866: #endif
                    867: 
                    868:         com_init( adapter );
                    869:     }
                    870: }
                    871: 
                    872: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    873: /*::::::::::::::::::::: Deinitialize comms port ::::::::::::::::::::::::::::*/
                    874: /*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
                    875: void host_com_exit()
                    876: {
                    877:     tAdapter adapter;
                    878:     int buffer_num;
                    879: 
                    880:     // close ports
                    881:     for (adapter = 0; adapter < NUM_SERIAL_PORTS; adapter++)
                    882:     {
                    883:         com_close( adapter );
                    884:         host_com_close( adapter );
                    885: 
                    886:         CloseHandle( host_com[adapter].WaitOverlap.hEvent );
                    887:         CloseHandle( host_com[adapter].RXOverlap.hEvent );
                    888: #if (!XMIT_BUFFER)
                    889:         CloseHandle( host_com[adapter].TXOverlap.hEvent );
                    890: #endif
                    891: 
                    892:         /*............... Delete RX critical section and RX control objects */
                    893:         DeleteCriticalSection( &host_com[adapter].AdapterLock );
                    894:     }
                    895: 
                    896: #if (XMIT_BUFFER)
                    897:     // close transmit buffers
                    898:     for (buffer_num = 0; buffer_num < NUM_TX_BUFFERS; buffer_num++)
                    899:     {
                    900:         CloseHandle( TX_q_buff[buffer_num].buffer.wait[0] );
                    901:         CloseHandle( TX_q_buff[buffer_num].buffer.wait[1] );
                    902:     }
                    903: 
                    904:     // close transmit buffer free pool
                    905:     CloseHandle( TX_queue[TX_FREE_QUEUE].wait[0] );
                    906:     CloseHandle( TX_queue[TX_FREE_QUEUE].wait[1] );
                    907: #endif //(XMIT_BUFFER)
                    908: }
                    909: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.