|
|
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.