Annotation of ntddk/src/vdd/com_vdd/nt_com.c, revision 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.