|
|
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, ¤t->EvtMask, ¤t->WaitOverlap ))
64: return TRUE;
65:
66: if (GetLastError() == ERROR_IO_PENDING)
67: return GetOverlappedResult( current->handle, ¤t->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, ¤t->RXOverlap ))
81: return TRUE;
82:
83: if (GetLastError() == ERROR_IO_PENDING)
84: return GetOverlappedResult( current->handle, ¤t->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, ¤t->TXOverlap ))
101: return TRUE;
102:
103: if (GetLastError() == ERROR_IO_PENDING)
104: return GetOverlappedResult( current->handle, ¤t->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(¤t->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(¤t->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: ¤t->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: ¤t->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(¤t->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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.