|
|
1.1 root 1: /*
1.1.1.4 root 2: Hatari - rs232.c
1.1 root 3:
1.1.1.4 root 4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
1.1 root 6:
1.1.1.4 root 7: RS-232 Communications
1.1.1.3 root 8:
1.1.1.4 root 9: This is similar to the printing functions, we open a direct file
10: (e.g. /dev/ttyS0) and send bytes over it.
11: Using such method mimicks the ST exactly, and even allows us to connect
12: to an actual ST! To wait for incoming data, we create a thread which copies
13: the bytes into an input buffer. This method fits in with the internet code
14: which also reads data into a buffer.
15: */
1.1.1.13 root 16: const char RS232_fileid[] = "Hatari rs232.c : " __DATE__ " " __TIME__;
1.1.1.4 root 17:
1.1.1.9 root 18: #include <config.h>
1.1.1.4 root 19:
20: #if HAVE_TERMIOS_H
21: # include <termios.h>
22: # include <unistd.h>
23: #endif
24:
25: #include <SDL.h>
26: #include <SDL_thread.h>
27: #include <errno.h>
1.1.1.3 root 28:
1.1 root 29: #include "main.h"
1.1.1.4 root 30: #include "configuration.h"
1.1.1.10 root 31: #include "ioMem.h"
1.1.1.8 root 32: #include "m68000.h"
1.1.1.4 root 33: #include "mfp.h"
1.1 root 34: #include "rs232.h"
1.1.1.2 root 35:
1.1 root 36:
1.1.1.4 root 37: #define RS232_DEBUG 0
38:
39: #if RS232_DEBUG
40: #define Dprintf(a) printf a
41: #else
42: #define Dprintf(a)
43: #endif
44:
45:
1.1.1.13 root 46: bool bConnectedRS232 = false; /* Connection to RS232? */
1.1.1.8 root 47: static FILE *hComIn = NULL; /* Handle to file for reading */
48: static FILE *hComOut = NULL; /* Handle to file for writing */
1.1.1.4 root 49:
1.1.1.8 root 50: static unsigned char InputBuffer_RS232[MAX_RS232INPUT_BUFFER];
51: static int InputBuffer_Head=0, InputBuffer_Tail=0;
1.1.1.4 root 52:
1.1.1.8 root 53:
54: #if HAVE_TERMIOS_H
55:
56: #if !HAVE_CFMAKERAW
1.1.1.4 root 57: static inline void cfmakeraw(struct termios *termios_p)
58: {
59: termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
60: termios_p->c_oflag &= ~OPOST;
61: termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
62: termios_p->c_cflag &= ~(CSIZE|PARENB);
63: termios_p->c_cflag |= CS8;
64: }
65: #endif
66:
1.1.1.9 root 67:
68: #if defined(__AMIGAOS4__)
69:
70: // dummy functions. REMOVE THEM LATER
71:
72: int tcgetattr(int file_descriptor,struct termios *tios_p)
73: {
74: return -1;
75: }
76:
77: int tcsetattr(int file_descriptor,int action,struct termios *tios_p)
78: {
79: return -1;
80: }
81:
82: int cfsetospeed(struct termios *tios, speed_t ospeed)
83: {
84:
85: tios->c_ospeed = ospeed;
86:
87: return 0;
88: }
89:
90:
91: int cfsetispeed(struct termios *tios,speed_t ispeed)
92: {
93: tios->c_ispeed = ispeed;
94:
95: return 0;
96: }
97:
98: #endif /* __AMIGAOS4__ */
99:
100:
1.1.1.4 root 101: /*-----------------------------------------------------------------------*/
1.1.1.9 root 102: /**
103: * Set serial line parameters to "raw" mode.
104: */
1.1.1.11 root 105: static bool RS232_SetRawMode(FILE *fhndl)
1.1 root 106: {
1.1.1.8 root 107: struct termios termmode;
108: int fd;
1.1 root 109:
1.1.1.8 root 110: memset (&termmode, 0, sizeof(termmode)); /* Init with zeroes */
111: fd = fileno(fhndl); /* Get file descriptor */
1.1.1.4 root 112:
1.1.1.8 root 113: if (isatty(fd))
1.1.1.4 root 114: {
1.1.1.8 root 115: if (tcgetattr(fd, &termmode) != 0)
1.1.1.13 root 116: return false;
1.1.1.8 root 117:
118: /* Set "raw" mode: */
119: termmode.c_cc[VMIN] = 1;
120: termmode.c_cc[VTIME] = 0;
121: cfmakeraw(&termmode);
122: if (tcsetattr(fd, TCSADRAIN, &termmode) != 0)
1.1.1.13 root 123: return false;
1.1.1.4 root 124: }
125:
1.1.1.13 root 126: return true;
1.1.1.8 root 127: }
1.1.1.4 root 128:
129: /*-----------------------------------------------------------------------*/
1.1.1.9 root 130: /**
131: * Set hardware configuration of RS-232:
132: * - Bits per character
133: * - Parity
134: * - Start/stop bits
135: */
1.1.1.14 root 136: static bool RS232_SetBitsConfig(FILE *fhndl, int nCharSize, int nStopBits, bool bUseParity, bool bEvenParity)
1.1.1.4 root 137: {
138: struct termios termmode;
1.1.1.14 root 139: int fd;
1.1.1.4 root 140:
141: memset (&termmode, 0, sizeof(termmode)); /* Init with zeroes */
1.1.1.14 root 142: fd = fileno(fhndl);
1.1.1.4 root 143:
144: if (isatty(fd))
145: {
146: if (tcgetattr(fd, &termmode) != 0)
1.1.1.8 root 147: {
148: Dprintf(("RS232_SetBitsConfig: tcgetattr failed.\n"));
1.1.1.13 root 149: return false;
1.1.1.8 root 150: }
1.1.1.4 root 151:
1.1.1.8 root 152: /* Set the character size: */
153: termmode.c_cflag &= ~CSIZE;
154: switch (nCharSize)
155: {
156: case 8: termmode.c_cflag |= CS8; break;
157: case 7: termmode.c_cflag |= CS7; break;
158: case 6: termmode.c_cflag |= CS6; break;
159: case 5: termmode.c_cflag |= CS5; break;
160: }
161:
162: /* Set stop bits: */
163: if (nStopBits >= 2)
164: termmode.c_oflag |= CSTOPB;
165: else
166: termmode.c_oflag &= ~CSTOPB;
167:
168: /* Parity bit: */
169: if (bUseParity)
170: termmode.c_cflag |= PARENB;
171: else
172: termmode.c_cflag &= ~PARENB;
173:
174: if (bEvenParity)
175: termmode.c_cflag &= ~PARODD;
176: else
177: termmode.c_cflag |= PARODD;
178:
179: /* Now store the configuration: */
1.1.1.4 root 180: if (tcsetattr(fd, TCSADRAIN, &termmode) != 0)
1.1.1.8 root 181: {
182: Dprintf(("RS232_SetBitsConfig: tcsetattr failed.\n"));
1.1.1.13 root 183: return false;
1.1.1.8 root 184: }
1.1.1.4 root 185: }
186:
1.1.1.13 root 187: return true;
1.1 root 188: }
1.1.1.8 root 189:
1.1.1.4 root 190: #endif /* HAVE_TERMIOS_H */
1.1 root 191:
1.1.1.4 root 192:
193: /*-----------------------------------------------------------------------*/
1.1.1.9 root 194: /**
195: * Open file on COM port.
196: */
1.1.1.11 root 197: static bool RS232_OpenCOMPort(void)
1.1 root 198: {
1.1.1.15 root 199: if (bConnectedRS232)
200: return true;
1.1.1.3 root 201:
1.1.1.4 root 202: /* Create our COM file for output */
1.1.1.9 root 203: hComOut = fopen(ConfigureParams.RS232.szOutFileName, "wb");
1.1.1.4 root 204: if (hComOut == NULL)
205: {
1.1.1.14 root 206: Log_Printf(LOG_WARN, "RS232: Failed to open output file %s\n",
207: ConfigureParams.RS232.szOutFileName);
1.1.1.13 root 208: return false;
1.1.1.4 root 209: }
210: setvbuf(hComOut, NULL, _IONBF, 0);
211:
212: /* Create our COM file for input */
1.1.1.9 root 213: hComIn = fopen(ConfigureParams.RS232.szInFileName, "rb");
1.1.1.4 root 214: if (hComIn == NULL)
215: {
1.1.1.14 root 216: Log_Printf(LOG_WARN, "RS232: Failed to open input file %s\n",
217: ConfigureParams.RS232.szInFileName);
1.1.1.4 root 218: fclose(hComOut); hComOut = NULL;
1.1.1.13 root 219: return false;
1.1.1.4 root 220: }
221: setvbuf(hComIn, NULL, _IONBF, 0);
222:
223: #if HAVE_TERMIOS_H
224: /* First set the output parameters to "raw" mode */
225: if (!RS232_SetRawMode(hComOut))
226: {
1.1.1.14 root 227: Log_Printf(LOG_WARN, "Can't set raw mode for %s\n",
1.1.1.4 root 228: ConfigureParams.RS232.szOutFileName);
229: }
230:
231: /* Now set the input parameters to "raw" mode */
232: if (!RS232_SetRawMode(hComIn))
233: {
1.1.1.14 root 234: Log_Printf(LOG_WARN, "Can't set raw mode for %s\n",
1.1.1.4 root 235: ConfigureParams.RS232.szInFileName);
236: }
237: #endif
1.1 root 238:
1.1.1.4 root 239: /* Set all OK */
1.1.1.13 root 240: bConnectedRS232 = true;
1.1 root 241:
1.1.1.4 root 242: Dprintf(("Successfully opened RS232 files.\n"));
1.1 root 243:
1.1.1.13 root 244: return true;
1.1 root 245: }
246:
1.1.1.4 root 247:
248: /*-----------------------------------------------------------------------*/
1.1.1.9 root 249: /**
250: * Close file on COM port
251: */
1.1.1.8 root 252: static void RS232_CloseCOMPort(void)
1.1 root 253: {
1.1.1.4 root 254: /* Do have file open? */
255: if (bConnectedRS232)
256: {
1.1.1.13 root 257: bConnectedRS232 = false;
1.1.1.4 root 258:
259: /* Close */
260: fclose(hComIn);
261: hComIn = NULL;
1.1 root 262:
1.1.1.4 root 263: fclose(hComOut);
264: hComOut = NULL;
265:
266: Dprintf(("Closed RS232 files.\n"));
267: }
1.1 root 268: }
269:
1.1.1.4 root 270:
1.1.1.8 root 271: /* thread stuff */
272: static SDL_sem* pSemFreeBuf; /* Semaphore to sync free space in InputBuffer_RS232 */
273: static SDL_Thread *RS232Thread = NULL; /* Thread handle for reading incoming data */
274:
275:
1.1.1.4 root 276: /*-----------------------------------------------------------------------*/
1.1.1.9 root 277: /**
278: * Add incoming bytes from other machine into our input buffer
279: */
1.1.1.8 root 280: static void RS232_AddBytesToInputBuffer(unsigned char *pBytes, int nBytes)
1.1.1.4 root 281: {
1.1.1.8 root 282: int i;
1.1 root 283:
1.1.1.8 root 284: /* Copy bytes into input buffer */
285: for (i=0; i<nBytes; i++)
286: {
287: SDL_SemWait(pSemFreeBuf); /* Wait for free space in buffer */
288: InputBuffer_RS232[InputBuffer_Tail] = *pBytes++;
289: InputBuffer_Tail = (InputBuffer_Tail+1) % MAX_RS232INPUT_BUFFER;
290: }
291: }
1.1.1.4 root 292:
1.1.1.8 root 293:
294: /*-----------------------------------------------------------------------*/
1.1.1.9 root 295: /**
296: * Thread to read incoming RS-232 data, and pass to emulator input buffer
297: */
1.1.1.8 root 298: static int RS232_ThreadFunc(void *pData)
299: {
300: int iInChar;
301: unsigned char cInChar;
302:
303: /* Check for any RS-232 incoming data */
1.1.1.13 root 304: while (true)
1.1.1.4 root 305: {
1.1.1.8 root 306: if (hComIn)
1.1.1.4 root 307: {
1.1.1.8 root 308: /* Read the bytes in, if we have any */
309: iInChar = fgetc(hComIn);
310: if (iInChar != EOF)
311: {
312: /* Copy into our internal queue */
313: cInChar = iInChar;
314: RS232_AddBytesToInputBuffer(&cInChar, 1);
315: /* FIXME: Use semaphores to lock MFP variables? */
316: MFP_InputOnChannel(MFP_RCVBUFFULL_BIT, MFP_IERA, &MFP_IPRA);
317: Dprintf(("RS232: Read character $%x\n", iInChar));
1.1.1.15 root 318: /* Sleep for a while */
319: SDL_Delay(2);
1.1.1.8 root 320: }
321: else
322: {
323: /*Dprintf(("RS232: Reached end of input file!\n"));*/
1.1.1.15 root 324: /* potential data race on hComIn modification */
1.1.1.8 root 325: clearerr(hComIn);
326: SDL_Delay(20);
327: }
328: }
329: else
1.1.1.4 root 330: {
1.1.1.15 root 331: /* No RS-232 connection, sleep for 0.2s */
332: SDL_Delay(200);
1.1.1.4 root 333: }
1.1.1.8 root 334: }
1.1.1.4 root 335:
1.1.1.13 root 336: return true;
1.1.1.8 root 337: }
1.1.1.4 root 338:
339:
1.1.1.8 root 340: /*-----------------------------------------------------------------------*/
1.1.1.9 root 341: /**
342: * Initialize RS-232, start thread to wait for incoming data
1.1.1.15 root 343: * (we will open a connection when first bytes are sent even
344: * if RS-232 isn't initialized for reading).
1.1.1.9 root 345: */
1.1.1.8 root 346: void RS232_Init(void)
347: {
348: if (ConfigureParams.RS232.bEnableRS232)
349: {
350: /* Create semaphore */
351: if (pSemFreeBuf == NULL)
352: pSemFreeBuf = SDL_CreateSemaphore(MAX_RS232INPUT_BUFFER);
353: if (pSemFreeBuf == NULL)
354: {
1.1.1.14 root 355: Log_Printf(LOG_WARN, "RS232_Init: Can't create semaphore!\n");
1.1.1.8 root 356: return;
357: }
1.1.1.4 root 358:
1.1.1.15 root 359: RS232_OpenCOMPort();
1.1.1.8 root 360:
361: /* Create thread to wait for incoming bytes over RS-232 */
362: if (!RS232Thread)
1.1.1.4 root 363: {
1.1.1.8 root 364: RS232Thread = SDL_CreateThread(RS232_ThreadFunc, NULL);
365: Dprintf(("RS232 thread has been created.\n"));
1.1.1.4 root 366: }
367: }
1.1.1.8 root 368: }
1.1.1.4 root 369:
1.1.1.8 root 370:
371: /*-----------------------------------------------------------------------*/
1.1.1.9 root 372: /**
373: * Close RS-232 connection and stop checking for incoming data.
374: */
1.1.1.8 root 375: void RS232_UnInit(void)
376: {
377: /* Close, kill thread and free resource */
378: if (RS232Thread)
379: {
1.1.1.15 root 380: /* Instead of killing the thread directly, we should
381: * probably better inform it via IPC so that it can
382: * terminate gracefully... but then we would need to
383: * wait until it exits, otherwise there's a data race
384: * on accessing/modifying hComIn.
385: */
1.1.1.8 root 386: Dprintf(("Killing RS232 thread...\n"));
387: SDL_KillThread(RS232Thread);
388: RS232Thread = NULL;
389: }
390: RS232_CloseCOMPort();
1.1.1.9 root 391:
1.1.1.8 root 392: if (pSemFreeBuf)
393: {
394: SDL_DestroySemaphore(pSemFreeBuf);
395: pSemFreeBuf = NULL;
396: }
1.1.1.4 root 397: }
1.1 root 398:
1.1.1.4 root 399:
400: /*-----------------------------------------------------------------------*/
1.1.1.9 root 401: /**
402: * Set hardware configuration of RS-232 according to the USART control register.
403: *
404: * ucr: USART Control Register
405: * Bit 0: unused
406: * Bit 1: 0-Odd Parity, 1-Even Parity
407: * Bit 2: 0-No Parity, 1-Parity
408: * Bits 3,4: Start/Stop bits
409: * 0 0 : 0-Start, 0-Stop Synchronous
410: * 0 1 : 0-Start, 1-Stop Asynchronous
411: * 1 0 : 1-Start, 1.5-Stop Asynchronous
412: * 1 1 : 1-Start, 2-Stop Asynchronous
413: * Bits 5,6: 'WordLength'
414: * 0 0 : 8 Bits
415: * 0 1 : 7 Bits
416: * 1 0 : 6 Bits
417: * 1 1 : 5 Bits
418: * Bit 7: Frequency from TC and RC
419: */
1.1.1.14 root 420: void RS232_HandleUCR(Sint16 ucr)
1.1.1.4 root 421: {
422: #if HAVE_TERMIOS_H
423: int nCharSize; /* Bits per character: 5, 6, 7 or 8 */
424: int nStopBits; /* Stop bits: 0=0 bits, 1=1 bit, 2=1.5 bits, 3=2 bits */
425:
426: nCharSize = 8 - ((ucr >> 5) & 3);
427: nStopBits = (ucr >> 3) & 3;
428:
429: Dprintf(("RS232_HandleUCR(%i) : character size=%i , stop bits=%i\n",
430: ucr, nCharSize, nStopBits));
431:
432: if (hComOut != NULL)
433: {
1.1.1.14 root 434: if (!RS232_SetBitsConfig(hComOut, nCharSize, nStopBits, ucr&4, ucr&2))
435: Log_Printf(LOG_WARN, "RS232_HandleUCR: failed to set bits configuration for %s\n", ConfigureParams.RS232.szOutFileName);
1.1.1.4 root 436: }
437:
438: if (hComIn != NULL)
439: {
1.1.1.14 root 440: if (!RS232_SetBitsConfig(hComIn, nCharSize, nStopBits, ucr&4, ucr&2))
441: Log_Printf(LOG_WARN, "RS232_HandleUCR: failed to set bits configuration for %s\n", ConfigureParams.RS232.szInFileName);
1.1.1.4 root 442: }
1.1.1.5 root 443: #endif /* HAVE_TERMIOS_H */
1.1.1.4 root 444: }
445:
446:
447: /*-----------------------------------------------------------------------*/
1.1.1.9 root 448: /**
449: * Set baud rate configuration of RS-232.
450: */
1.1.1.11 root 451: bool RS232_SetBaudRate(int nBaud)
1.1.1.4 root 452: {
453: #if HAVE_TERMIOS_H
454: int i;
455: int fd;
456: speed_t baudtype;
457: struct termios termmode;
1.1.1.8 root 458: static const int baudtable[][2] =
1.1.1.4 root 459: {
460: { 50, B50 },
461: { 75, B75 },
462: { 110, B110 },
463: { 134, B134 },
464: { 150, B150 },
465: { 200, B200 },
466: { 300, B300 },
467: { 600, B600 },
468: { 1200, B1200 },
469: { 1800, B1800 },
470: { 2400, B2400 },
471: { 4800, B4800 },
472: { 9600, B9600 },
473: { 19200, B19200 },
474: { 38400, B38400 },
475: { 57600, B57600 },
476: { 115200, B115200 },
1.1.1.8 root 477: #ifdef B230400 /* B230400 is not defined on all systems */
1.1.1.4 root 478: { 230400, B230400 },
1.1.1.8 root 479: #endif
1.1.1.4 root 480: { -1, -1 }
481: };
482:
483: Dprintf(("RS232_SetBaudRate(%i)\n", nBaud));
484:
485: /* Convert baud number to baud termios constant: */
486: baudtype = -1;
487: for (i = 0; baudtable[i][0] != -1; i++)
488: {
489: if (baudtable[i][0] == nBaud)
490: {
491: baudtype = baudtable[i][1];
492: break;
493: }
494: }
495:
1.1.1.5 root 496: if (baudtype == (speed_t)-1)
1.1.1.4 root 497: {
498: Dprintf(("RS232_SetBaudRate: Unsupported baud rate %i.\n", nBaud));
1.1.1.13 root 499: return false;
1.1.1.4 root 500: }
501:
502: /* Set ouput speed: */
503: if (hComOut != NULL)
504: {
505: memset (&termmode, 0, sizeof(termmode)); /* Init with zeroes */
506: fd = fileno(hComOut);
507: if (isatty(fd))
508: {
509: if (tcgetattr(fd, &termmode) != 0)
1.1.1.13 root 510: return false;
1.1.1.4 root 511:
512: cfsetospeed(&termmode, baudtype);
513:
514: if (tcsetattr(fd, TCSADRAIN, &termmode) != 0)
1.1.1.13 root 515: return false;
1.1.1.4 root 516: }
517: }
518:
519: /* Set input speed: */
520: if (hComIn != NULL)
521: {
522: memset (&termmode, 0, sizeof(termmode)); /* Init with zeroes */
523: fd = fileno(hComIn);
524: if (isatty(fd))
525: {
526: if (tcgetattr(fd, &termmode) != 0)
1.1.1.13 root 527: return false;
1.1.1.4 root 528:
529: cfsetispeed(&termmode, baudtype);
530:
531: if (tcsetattr(fd, TCSADRAIN, &termmode) != 0)
1.1.1.13 root 532: return false;
1.1.1.4 root 533: }
534: }
535: #endif /* HAVE_TERMIOS_H */
536:
1.1.1.13 root 537: return true;
1.1.1.4 root 538: }
539:
540:
541: /*-----------------------------------------------------------------------*/
1.1.1.9 root 542: /**
543: * Set baud rate configuration of RS-232 according to the Timer-D hardware
544: * registers.
545: */
1.1.1.4 root 546: void RS232_SetBaudRateFromTimerD(void)
1.1 root 547: {
1.1.1.4 root 548: int nTimerD_CR, nTimerD_DR, nBaudRate;
549:
1.1.1.10 root 550: nTimerD_CR = IoMem[0xfffa1d] & 0x07;
551: nTimerD_DR = IoMem[0xfffa25];
1.1.1.4 root 552:
553: if (!nTimerD_CR)
554: return;
555:
1.1.1.13 root 556: if ( nTimerD_DR == 0 )
557: nTimerD_DR = 256; /* In MFP, a data register=0 is in fact 256 */
558:
1.1.1.4 root 559: /* Calculate baud rate: (MFP/Timer-D is supplied with 2.4576 MHz) */
560: nBaudRate = 2457600 / nTimerD_DR / 2;
1.1.1.11 root 561:
562: /*if (IoMem[0xfffa29] & 0x80)*/ /* We only support the by-16 prescaler */
563: nBaudRate /= 16;
564:
1.1.1.4 root 565: switch (nTimerD_CR)
566: {
567: case 1: nBaudRate /= 4; break;
568: case 2: nBaudRate /= 10; break;
569: case 3: nBaudRate /= 16; break;
570: case 4: nBaudRate /= 50; break;
571: case 5: nBaudRate /= 64; break;
572: case 6: nBaudRate /= 100; break;
573: case 7: nBaudRate /= 200; break;
574: }
575:
576: /* Adjust some ugly baud rates from TOS to more reasonable values: */
577: switch (nBaudRate)
578: {
579: case 80: nBaudRate = 75; break;
580: case 109: nBaudRate = 110; break;
581: case 120: nBaudRate = 110; break;
582: case 1745: nBaudRate = 1800; break;
583: case 1920: nBaudRate = 1800; break;
584: }
1.1 root 585:
1.1.1.4 root 586: RS232_SetBaudRate(nBaudRate);
587: }
588:
589:
590: /*-----------------------------------------------------------------------*/
1.1.1.9 root 591: /**
592: * Set flow control configuration of RS-232.
593: */
1.1.1.14 root 594: void RS232_SetFlowControl(Sint16 ctrl)
1.1.1.4 root 595: {
596: Dprintf(("RS232_SetFlowControl(%i)\n", ctrl));
597:
598: /* Not yet written */
1.1 root 599: }
600:
1.1.1.4 root 601:
602: /*----------------------------------------------------------------------- */
1.1.1.9 root 603: /**
604: * Pass bytes from emulator to RS-232
605: */
1.1.1.14 root 606: bool RS232_TransferBytesTo(Uint8 *pBytes, int nBytes)
1.1 root 607: {
1.1.1.15 root 608: /* Make sure there's a RS-232 connection if it's enabled */
609: if (ConfigureParams.RS232.bEnableRS232)
610: RS232_OpenCOMPort();
1.1.1.4 root 611:
612: /* Have we connected to the RS232? */
613: if (bConnectedRS232)
614: {
615: /* Send bytes directly to the COM file */
616: if (fwrite(pBytes, 1, nBytes, hComOut))
617: {
618: Dprintf(("RS232: Sent %i bytes ($%x ...)\n", nBytes, *pBytes));
619: MFP_InputOnChannel(MFP_TRNBUFEMPTY_BIT, MFP_IERA, &MFP_IPRA);
620:
1.1.1.13 root 621: return true; /* OK */
1.1.1.4 root 622: }
623: }
624:
1.1.1.13 root 625: return false; /* Failed */
1.1.1.4 root 626: }
627:
628:
629: /*-----------------------------------------------------------------------*/
1.1.1.9 root 630: /**
631: * Read characters from our internal input buffer (bytes from other machine)
632: */
1.1.1.14 root 633: bool RS232_ReadBytes(Uint8 *pBytes, int nBytes)
1.1.1.4 root 634: {
635: int i;
636:
637: /* Connected? */
638: if (bConnectedRS232 && InputBuffer_Head != InputBuffer_Tail)
639: {
640: /* Read bytes out of input buffer */
641: for (i=0; i<nBytes; i++)
642: {
643: *pBytes++ = InputBuffer_RS232[InputBuffer_Head];
644: InputBuffer_Head = (InputBuffer_Head+1) % MAX_RS232INPUT_BUFFER;
645: SDL_SemPost(pSemFreeBuf); /* Signal free space */
646: }
1.1.1.13 root 647: return true;
1.1.1.4 root 648: }
649:
1.1.1.13 root 650: return false;
1.1.1.4 root 651: }
652:
653:
654: /*-----------------------------------------------------------------------*/
1.1.1.9 root 655: /**
1.1.1.13 root 656: * Return true if bytes waiting!
1.1.1.9 root 657: */
1.1.1.11 root 658: bool RS232_GetStatus(void)
1.1.1.4 root 659: {
660: /* Connected? */
661: if (bConnectedRS232)
662: {
663: /* Do we have bytes in the input buffer? */
664: if (InputBuffer_Head != InputBuffer_Tail)
1.1.1.13 root 665: return true;
1.1.1.4 root 666: }
1.1 root 667:
1.1.1.4 root 668: /* No, none */
1.1.1.13 root 669: return false;
1.1.1.4 root 670: }
1.1 root 671:
672:
1.1.1.4 root 673: /*-----------------------------------------------------------------------*/
1.1.1.9 root 674: /**
675: * Read from the Syncronous Character Register.
676: */
1.1.1.4 root 677: void RS232_SCR_ReadByte(void)
1.1 root 678: {
1.1.1.8 root 679: M68000_WaitState(4);
680:
681: /* nothing */
1.1.1.4 root 682: }
683:
684: /*-----------------------------------------------------------------------*/
1.1.1.9 root 685: /**
686: * Write to the Syncronous Character Register.
687: */
1.1.1.4 root 688: void RS232_SCR_WriteByte(void)
689: {
1.1.1.8 root 690: M68000_WaitState(4);
691:
1.1.1.10 root 692: /*Dprintf(("RS232: Write to SCR: $%x\n", (int)IoMem[0xfffa27]));*/
1.1.1.4 root 693: }
1.1 root 694:
1.1.1.4 root 695:
696: /*-----------------------------------------------------------------------*/
1.1.1.9 root 697: /**
698: * Read from the USART Control Register.
699: */
1.1.1.4 root 700: void RS232_UCR_ReadByte(void)
701: {
1.1.1.8 root 702: M68000_WaitState(4);
703:
1.1.1.10 root 704: Dprintf(("RS232: Read from UCR: $%x\n", (int)IoMem[0xfffa29]));
1.1.1.4 root 705: }
1.1 root 706:
1.1.1.4 root 707: /*-----------------------------------------------------------------------*/
1.1.1.9 root 708: /**
709: * Write to the USART Control Register.
710: */
1.1.1.4 root 711: void RS232_UCR_WriteByte(void)
712: {
1.1.1.8 root 713: M68000_WaitState(4);
714:
1.1.1.10 root 715: Dprintf(("RS232: Write to UCR: $%x\n", (int)IoMem[0xfffa29]));
1.1.1.4 root 716:
717: if (bConnectedRS232)
1.1.1.10 root 718: RS232_HandleUCR(IoMem[0xfffa29]);
1.1 root 719: }
720:
1.1.1.4 root 721:
722: /*-----------------------------------------------------------------------*/
1.1.1.9 root 723: /**
724: * Read from the Receiver Status Register.
725: */
1.1.1.4 root 726: void RS232_RSR_ReadByte(void)
1.1 root 727: {
1.1.1.8 root 728: M68000_WaitState(4);
729:
1.1.1.4 root 730: if (RS232_GetStatus())
1.1.1.10 root 731: IoMem[0xfffa2b] |= 0x80; /* Buffer full */
1.1.1.4 root 732: else
1.1.1.10 root 733: IoMem[0xfffa2b] &= ~0x80; /* Buffer not full */
1.1.1.4 root 734:
1.1.1.10 root 735: Dprintf(("RS232: Read from RSR: $%x\n", (int)IoMem[0xfffa2b]));
1.1.1.4 root 736: }
737:
738: /*-----------------------------------------------------------------------*/
1.1.1.9 root 739: /**
740: * Write to the Receiver Status Register.
741: */
1.1.1.4 root 742: void RS232_RSR_WriteByte(void)
743: {
1.1.1.8 root 744: M68000_WaitState(4);
745:
1.1.1.10 root 746: Dprintf(("RS232: Write to RSR: $%x\n", (int)IoMem[0xfffa2b]));
1.1 root 747: }
748:
1.1.1.4 root 749:
750: /*-----------------------------------------------------------------------*/
1.1.1.9 root 751: /**
752: * Read from the Transmitter Status Register.
1.1.1.16! root 753: * When RS232 emulation is not enabled, we still return 0x80 to allow
! 754: * some games to work when they don't require send/receive on the RS232 port
! 755: * (eg : 'Treasure Trap', 'The Deep' write some debug informations to RS232)
1.1.1.9 root 756: */
1.1.1.4 root 757: void RS232_TSR_ReadByte(void)
1.1 root 758: {
1.1.1.8 root 759: M68000_WaitState(4);
760:
1.1.1.16! root 761: IoMem[0xfffa2d] |= 0x80; /* Buffer empty */
1.1 root 762:
1.1.1.10 root 763: Dprintf(("RS232: Read from TSR: $%x\n", (int)IoMem[0xfffa2d]));
1.1 root 764: }
765:
1.1.1.4 root 766: /*-----------------------------------------------------------------------*/
1.1.1.9 root 767: /**
768: * Write to the Transmitter Status Register.
769: */
1.1.1.4 root 770: void RS232_TSR_WriteByte(void)
771: {
1.1.1.8 root 772: M68000_WaitState(4);
773:
1.1.1.10 root 774: Dprintf(("RS232: Write to TSR: $%x\n", (int)IoMem[0xfffa2d]));
1.1.1.4 root 775: }
776:
777:
778: /*-----------------------------------------------------------------------*/
1.1.1.9 root 779: /**
780: * Read from the USART Data Register.
781: */
1.1.1.4 root 782: void RS232_UDR_ReadByte(void)
1.1 root 783: {
1.1.1.14 root 784: Uint8 InByte = 0;
1.1 root 785:
1.1.1.8 root 786: M68000_WaitState(4);
787:
1.1.1.4 root 788: RS232_ReadBytes(&InByte, 1);
1.1.1.10 root 789: IoMem[0xfffa2f] = InByte;
790: Dprintf(("RS232: Read from UDR: $%x\n", (int)IoMem[0xfffa2f]));
1.1.1.4 root 791:
792: if (RS232_GetStatus()) /* More data waiting? */
793: {
794: /* Yes, generate another interrupt. */
795: MFP_InputOnChannel(MFP_RCVBUFFULL_BIT, MFP_IERA, &MFP_IPRA);
796: }
1.1 root 797: }
1.1.1.4 root 798:
799: /*-----------------------------------------------------------------------*/
1.1.1.9 root 800: /**
801: * Write to the USART Data Register.
802: */
1.1.1.4 root 803: void RS232_UDR_WriteByte(void)
804: {
1.1.1.14 root 805: Uint8 OutByte;
1.1.1.4 root 806:
1.1.1.8 root 807: M68000_WaitState(4);
808:
1.1.1.10 root 809: OutByte = IoMem[0xfffa2f];
1.1.1.4 root 810: RS232_TransferBytesTo(&OutByte, 1);
1.1.1.10 root 811: Dprintf(("RS232: Write to UDR: $%x\n", (int)IoMem[0xfffa2f]));
1.1.1.4 root 812: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.