Fixed compilation error
[bochs-mirror.git] / iodev / serial_raw.cc
blob67bf438f9369c3bd32f71f6a59549c67fbf820a7
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: serial_raw.cc,v 1.22 2008/01/26 22:24:02 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2004 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
29 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
30 // is used to know when we are exporting symbols and when we are importing.
31 #define BX_PLUGGABLE
33 #define NO_DEVICE_INCLUDES
34 #include "iodev.h"
36 #if USE_RAW_SERIAL
38 #include "serial_raw.h"
40 #define LOG_THIS
42 #ifdef WIN32_RECEIVE_RAW
43 DWORD WINAPI RawSerialThread(VOID *this_ptr);
44 #endif
46 serial_raw::serial_raw(const char *devname)
48 #ifdef WIN32
49 char portstr[MAX_PATH];
50 #ifdef WIN32_RECEIVE_RAW
51 DWORD threadID;
52 #endif
53 #endif
55 put ("SERR");
56 settype (SERRLOG);
57 #ifdef WIN32
58 memset(&dcb, 0, sizeof(DCB));
59 dcb.DCBlength = sizeof(DCB);
60 dcb.fBinary = 1;
61 dcb.fDtrControl = DTR_CONTROL_ENABLE;
62 dcb.fRtsControl = RTS_CONTROL_ENABLE;
63 dcb.Parity = NOPARITY;
64 dcb.ByteSize = 8;
65 dcb.StopBits = ONESTOPBIT;
66 dcb.BaudRate = CBR_115200;
67 DCBchanged = FALSE;
68 if (lstrlen(devname) > 0) {
69 wsprintf(portstr, "\\\\.\\%s", devname);
70 hCOM = CreateFile(portstr, GENERIC_READ|GENERIC_WRITE, 0, NULL,
71 OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
72 if (hCOM != INVALID_HANDLE_VALUE) {
73 present = 1;
74 GetCommModemStatus(hCOM, &MSR_value);
75 SetupComm(hCOM, 8192, 2048);
76 PurgeComm(hCOM, PURGE_TXABORT | PURGE_RXABORT |
77 PURGE_TXCLEAR | PURGE_RXCLEAR);
78 #ifdef WIN32_RECEIVE_RAW
79 SetCommMask(hCOM, EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR);
80 memset(&rx_ovl, 0, sizeof(OVERLAPPED));
81 rx_ovl.hEvent = CreateEvent(NULL,TRUE,FALSE,"receive");
82 hRawSerialThread = CreateThread(NULL, 0, RawSerialThread, this, 0, &threadID);
83 #endif
84 } else {
85 present = 0;
86 BX_ERROR(("Raw device '%s' not present", devname));
88 } else {
89 present = 0;
91 #else
92 present = 0;
93 #endif
94 set_modem_control(0x00);
95 set_break(0);
96 rxdata_count = 0;
99 serial_raw::~serial_raw(void)
101 if (present) {
102 #ifdef WIN32
103 #ifdef WIN32_RECEIVE_RAW
104 thread_quit = TRUE;
105 SetCommMask(hCOM, 0);
106 while (thread_active) Sleep(10);
107 CloseHandle(thread_ovl.hEvent);
108 CloseHandle(rx_ovl.hEvent);
109 CloseHandle(hRawSerialThread);
110 #endif
111 CloseHandle(hCOM);
112 #endif
116 void serial_raw::set_baudrate(int rate)
118 BX_DEBUG (("set_baudrate %d", rate));
119 #ifdef WIN32
120 switch (rate) {
121 case 110: dcb.BaudRate = CBR_110; break;
122 case 300: dcb.BaudRate = CBR_300; break;
123 case 600: dcb.BaudRate = CBR_600; break;
124 case 1200: dcb.BaudRate = CBR_1200; break;
125 case 2400: dcb.BaudRate = CBR_2400; break;
126 case 4800: dcb.BaudRate = CBR_4800; break;
127 case 9600: dcb.BaudRate = CBR_9600; break;
128 case 19200: dcb.BaudRate = CBR_19200; break;
129 case 38400: dcb.BaudRate = CBR_38400; break;
130 case 57600: dcb.BaudRate = CBR_57600; break;
131 case 115200: dcb.BaudRate = CBR_115200; break;
132 default: BX_ERROR(("set_baudrate(): unsupported value %d", rate));
134 DCBchanged = TRUE;
135 #endif
138 void serial_raw::set_data_bits(int val)
140 BX_DEBUG (("set data bits (%d)", val));
141 #ifdef WIN32
142 dcb.ByteSize = val;
143 DCBchanged = TRUE;
144 #endif
147 void serial_raw::set_stop_bits(int val)
149 BX_DEBUG (("set stop bits (%d)", val));
150 #ifdef WIN32
151 if (val == 1) {
152 dcb.StopBits = ONESTOPBIT;
153 } if (dcb.ByteSize == 5) {
154 dcb.StopBits = ONE5STOPBITS;
155 } else {
156 dcb.StopBits = TWOSTOPBITS;
158 DCBchanged = TRUE;
159 #endif
162 void serial_raw::set_parity_mode(int mode)
164 BX_DEBUG (("set parity mode %d", mode));
165 #ifdef WIN32
166 switch (mode) {
167 case 0:
168 dcb.fParity = FALSE;
169 dcb.Parity = NOPARITY;
170 break;
171 case 1:
172 dcb.fParity = TRUE;
173 dcb.Parity = ODDPARITY;
174 break;
175 case 2:
176 dcb.fParity = TRUE;
177 dcb.Parity = EVENPARITY;
178 break;
179 case 3:
180 dcb.fParity = TRUE;
181 dcb.Parity = MARKPARITY;
182 break;
183 case 4:
184 dcb.fParity = TRUE;
185 dcb.Parity = SPACEPARITY;
186 break;
188 DCBchanged = TRUE;
189 #endif
192 void serial_raw::set_break(int mode)
194 BX_DEBUG (("set break %s", mode?"on":"off"));
195 #ifdef WIN32
196 if (mode) {
197 SetCommBreak(hCOM);
198 } else {
199 ClearCommBreak(hCOM);
201 #endif
204 void serial_raw::set_modem_control(int ctrl)
206 BX_DEBUG (("set modem control 0x%02x", ctrl));
207 #ifdef WIN32
208 EscapeCommFunction(hCOM, (ctrl & 0x01)?SETDTR:CLRDTR);
209 EscapeCommFunction(hCOM, (ctrl & 0x02)?SETRTS:CLRRTS);
210 #endif
213 int serial_raw::get_modem_status()
215 int status = 0;
217 #ifdef WIN32
218 status = MSR_value;
219 #endif
220 BX_DEBUG (("get modem status returns 0x%02x", status));
221 return status;
224 void serial_raw::setup_port()
226 #ifdef WIN32
227 DWORD DErr;
228 COMMTIMEOUTS ctmo;
230 ClearCommError(hCOM, &DErr, NULL);
231 PurgeComm(hCOM, PURGE_TXABORT | PURGE_RXABORT |
232 PURGE_TXCLEAR | PURGE_RXCLEAR);
233 memset(&ctmo, 0, sizeof(ctmo));
234 SetCommTimeouts(hCOM, &ctmo);
235 SetCommState(hCOM, &dcb);
236 rxdata_count = 0;
237 #ifdef WIN32_RECEIVE_RAW
238 thread_rxdata_count = 0;
239 #endif
240 #endif
243 void serial_raw::transmit(Bit8u byte)
245 #ifdef WIN32
246 DWORD DErr, Len2;
247 OVERLAPPED tx_ovl;
248 #endif
250 BX_DEBUG (("transmit %d", byte));
251 if (present) {
252 #ifdef WIN32
253 if (DCBchanged) {
254 setup_port();
255 } else {
256 ClearCommError(hCOM, &DErr, NULL);
258 memset(&tx_ovl, 0, sizeof(OVERLAPPED));
259 tx_ovl.hEvent = CreateEvent(NULL,TRUE,TRUE,"transmit");
260 if (!WriteFile(hCOM, &byte, 1, &Len2, &tx_ovl)) {
261 if (GetLastError() == ERROR_IO_PENDING) {
262 if (WaitForSingleObject(tx_ovl.hEvent, 100) == WAIT_OBJECT_0) {
263 GetOverlappedResult(hCOM, &tx_ovl, &Len2, FALSE);
267 if (Len2 != 1) BX_ERROR(("transmit failed: len = %d", Len2));
268 ClearCommError(hCOM, &DErr, NULL);
269 CloseHandle(tx_ovl.hEvent);
270 #endif
274 bx_bool serial_raw::ready_transmit()
276 BX_DEBUG (("ready_transmit returning %d", present));
277 return present;
280 bx_bool serial_raw::ready_receive()
282 #ifdef WIN32_RECEIVE_RAW
283 if ((rxdata_count == 0) && (thread_rxdata_count > 0)) {
284 SetEvent(thread_ovl.hEvent);
285 SetEvent(rx_ovl.hEvent);
287 #endif
288 BX_DEBUG (("ready_receive returning %d", (rxdata_count > 0)));
289 return (rxdata_count > 0);
292 int serial_raw::receive()
294 #ifdef WIN32
295 int data;
296 #endif
298 if (present) {
299 #ifdef WIN32
300 if (DCBchanged) {
301 setup_port();
303 data = rxdata_buffer[0];
304 if (rxdata_count > 0) {
305 memcpy(&rxdata_buffer[0], &rxdata_buffer[1], sizeof(Bit16s)*(RX_BUFSIZE-1));
306 rxdata_count--;
308 if (data < 0) {
309 switch (data) {
310 case RAW_EVENT_CTS_ON:
311 MSR_value |= 0x10;
312 break;
313 case RAW_EVENT_CTS_OFF:
314 MSR_value &= ~0x10;
315 break;
316 case RAW_EVENT_DSR_ON:
317 MSR_value |= 0x20;
318 break;
319 case RAW_EVENT_DSR_OFF:
320 MSR_value &= ~0x20;
321 break;
322 case RAW_EVENT_RING_ON:
323 MSR_value |= 0x40;
324 break;
325 case RAW_EVENT_RING_OFF:
326 MSR_value &= ~0x40;
327 break;
328 case RAW_EVENT_RLSD_ON:
329 MSR_value |= 0x80;
330 break;
331 case RAW_EVENT_RLSD_OFF:
332 MSR_value &= ~0x80;
333 break;
336 return data;
337 #else
338 BX_DEBUG (("receive returning 'A'"));
339 return (int)'A';
340 #endif
341 } else {
342 BX_DEBUG (("receive returning 'A'"));
343 return (int)'A';
347 #ifdef WIN32_RECEIVE_RAW
349 DWORD WINAPI RawSerialThread(VOID *this_ptr)
351 serial_raw *class_ptr = (serial_raw *) this_ptr;
352 class_ptr->serial_thread();
353 return 0;
356 void serial_raw::serial_thread()
358 DWORD DErr, Len2;
359 DWORD EvtMask, MSR, Temp;
360 char s1[2];
362 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
363 thread_active = TRUE;
364 thread_quit = FALSE;
365 memset(&thread_ovl, 0, sizeof(OVERLAPPED));
366 thread_ovl.hEvent = CreateEvent(NULL,TRUE,TRUE,"thread");
367 thread_rxdata_count = 0;
368 while (!thread_quit) {
369 if ((rxdata_count == 0) && (thread_rxdata_count > 0)) {
370 if (thread_rxdata_count > RX_BUFSIZE) {
371 memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*RX_BUFSIZE);
372 memcpy(&thread_rxdata_buffer[0], &thread_rxdata_buffer[RX_BUFSIZE], sizeof(Bit16s)*(thread_rxdata_count-RX_BUFSIZE));
373 rxdata_count = RX_BUFSIZE;
374 thread_rxdata_count -= RX_BUFSIZE;
375 } else {
376 memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*thread_rxdata_count);
377 rxdata_count = thread_rxdata_count;
378 thread_rxdata_count = 0;
381 ClearCommError(hCOM, &DErr, NULL);
382 EvtMask = 0;
383 if (!WaitCommEvent(hCOM, &EvtMask, &thread_ovl)) {
384 if (GetLastError() == ERROR_IO_PENDING) {
385 if (WaitForSingleObject(thread_ovl.hEvent, INFINITE) == WAIT_OBJECT_0) {
386 GetOverlappedResult(hCOM, &thread_ovl, &Temp, FALSE);
390 if (EvtMask & EV_RXCHAR) {
391 if (thread_rxdata_count < THREAD_RX_BUFSIZE) {
392 do {
393 ClearCommError(hCOM, &DErr, NULL);
394 if (!ReadFile(hCOM, s1, 1, &Len2, &rx_ovl)) {
395 if (GetLastError() == ERROR_IO_PENDING) {
396 if (WaitForSingleObject(rx_ovl.hEvent, INFINITE) != WAIT_OBJECT_0) {
397 Len2 = 0;
398 } else {
399 GetOverlappedResult(hCOM, &rx_ovl, &Len2, FALSE);
401 } else {
402 Len2 = 0;
405 if (Len2 > 0) {
406 enq_event(s1[0]);
408 if ((rxdata_count == 0) && (thread_rxdata_count > 0)) {
409 if (thread_rxdata_count > RX_BUFSIZE) {
410 memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*RX_BUFSIZE);
411 memcpy(&thread_rxdata_buffer[0], &thread_rxdata_buffer[RX_BUFSIZE], sizeof(Bit16s)*(thread_rxdata_count-RX_BUFSIZE));
412 rxdata_count = RX_BUFSIZE;
413 thread_rxdata_count -= RX_BUFSIZE;
414 } else {
415 memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*thread_rxdata_count);
416 rxdata_count = thread_rxdata_count;
417 thread_rxdata_count = 0;
420 } while ((Len2 != 0) && (thread_rxdata_count < THREAD_RX_BUFSIZE));
421 ClearCommError(hCOM, &DErr, NULL);
424 if (EvtMask & EV_BREAK) {
425 enq_event(RAW_EVENT_BREAK);
427 if (EvtMask & EV_ERR) {
428 ClearCommError(hCOM, &DErr, NULL);
429 if (DErr & CE_FRAME) {
430 enq_event(RAW_EVENT_FRAME);
432 if (DErr & CE_OVERRUN) {
433 enq_event(RAW_EVENT_OVERRUN);
435 if (DErr & CE_RXPARITY) {
436 enq_event(RAW_EVENT_PARITY);
439 if (EvtMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD)) {
440 GetCommModemStatus(hCOM, &MSR);
442 if (EvtMask & EV_CTS) {
443 if (MSR & MS_CTS_ON) {
444 enq_event(RAW_EVENT_CTS_ON);
445 } else {
446 enq_event(RAW_EVENT_CTS_OFF);
449 if (EvtMask & EV_DSR) {
450 if (MSR & MS_DSR_ON) {
451 enq_event(RAW_EVENT_DSR_ON);
452 } else {
453 enq_event(RAW_EVENT_DSR_OFF);
456 if (EvtMask & EV_RING) {
457 if (MSR & MS_RING_ON) {
458 enq_event(RAW_EVENT_RING_ON);
459 } else {
460 enq_event(RAW_EVENT_RING_OFF);
463 if (EvtMask & EV_RLSD) {
464 if (MSR & MS_RLSD_ON) {
465 enq_event(RAW_EVENT_RLSD_ON);
466 } else {
467 enq_event(RAW_EVENT_RLSD_OFF);
471 CloseHandle(thread_ovl.hEvent);
472 thread_active = FALSE;
475 void serial_raw::enq_event(Bit16s event)
477 if (thread_rxdata_count < THREAD_RX_BUFSIZE) {
478 thread_rxdata_buffer[thread_rxdata_count++] = event;
479 } else {
480 fprintf(stderr, "receive buffer overflow\n");
483 #endif
485 #endif