1 /*
2  * scc.cpp - SCC 85C30 emulation code
3  *
4  * Adaptions to Hatari:
5  *
6  * Copyright 2018 Thomas Huth
7  *
8  * Original code taken from Aranym:
9  *
10  * Copyright (c) 2001-2004 Petr Stehlik of ARAnyM dev team
11  *               2010 Jean Conter
12  *
13  * This code is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This code 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
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with ARAnyM; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  */
27 
28 #include "main.h"
29 
30 #if HAVE_TERMIOS_H
31 # include <termios.h>
32 # include <unistd.h>
33 #endif
34 #if HAVE_SYS_IOCTL_H
35 # include <sys/ioctl.h>
36 #endif
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <errno.h>
41 
42 #include "configuration.h"
43 #include "ioMem.h"
44 #include "log.h"
45 #include "memorySnapShot.h"
46 #include "scc.h"
47 
48 #if 0
49 #define bug printf
50 #define D(x) x
51 #else
52 #define bug(...)
53 #define D(x)
54 #endif
55 
56 #ifndef O_NONBLOCK
57 # ifdef O_NDELAY
58 #  define O_NONBLOCK O_NDELAY
59 # else
60 #  define O_NONBLOCK 0
61 # endif
62 #endif
63 
64 #define RCA 0
65 #define TBE 2
66 #define CTS 5
67 
68 struct SCC {
69 	uint8_t regs[16];
70 	int charcount;
71 	int rd_handle, wr_handle;
72 	uint16_t oldTBE;
73 	uint16_t oldStatus;
74 	bool bFileHandleIsATTY;
75 };
76 
77 static struct SCC scc[2];
78 
79 static int active_reg;
80 static uint8_t RR3, RR3M;    // common to channel A & B
81 
SCC_IsAvailable(CNF_PARAMS * cnf)82 bool SCC_IsAvailable(CNF_PARAMS *cnf)
83 {
84 	return ConfigureParams.System.nMachineType == MACHINE_MEGA_STE
85 	       || ConfigureParams.System.nMachineType == MACHINE_TT
86 	       || ConfigureParams.System.nMachineType == MACHINE_FALCON;
87 }
88 
SCC_Init(void)89 void SCC_Init(void)
90 {
91 	SCC_Reset();
92 
93 	scc[0].oldTBE = scc[1].oldTBE = 0;
94 	scc[0].oldStatus = scc[1].oldStatus = 0;
95 
96 	scc[0].rd_handle = scc[0].wr_handle = -1;
97 	scc[1].rd_handle = scc[1].wr_handle = -1;
98 
99 	D(bug("SCC: interface initialized\n"));
100 
101 	if (!ConfigureParams.RS232.bEnableSccB || !SCC_IsAvailable(&ConfigureParams))
102 		return;
103 
104 	if (ConfigureParams.RS232.sSccBInFileName[0] &&
105 	    strcmp(ConfigureParams.RS232.sSccBInFileName, ConfigureParams.RS232.sSccBOutFileName) == 0)
106 	{
107 #if HAVE_TERMIOS_H
108 		scc[1].rd_handle = open(ConfigureParams.RS232.sSccBInFileName, O_RDWR | O_NONBLOCK);
109 		if (scc[1].rd_handle >= 0)
110 		{
111 			if (isatty(scc[1].rd_handle))
112 			{
113 				scc[1].wr_handle = scc[1].rd_handle;
114 			}
115 			else
116 			{
117 				Log_Printf(LOG_ERROR, "SCC_Init: Setting SCC-B input and output "
118 				           "to the same file only works with tty devices.\n");
119 				close(scc[1].rd_handle);
120 				scc[1].rd_handle = -1;
121 			}
122 		}
123 		else
124 		{
125 			Log_Printf(LOG_ERROR, "SCC_Init: Can not open device '%s'\n",
126 			           ConfigureParams.RS232.sSccBInFileName);
127 		}
128 #else
129 		Log_Printf(LOG_ERROR, "SCC_Init: Setting SCC-B input and output "
130 		           "to the same file is not supported on this system.\n");
131 #endif
132 	}
133 	else
134 	{
135 		if (ConfigureParams.RS232.sSccBInFileName[0])
136 		{
137 			scc[1].rd_handle = open(ConfigureParams.RS232.sSccBInFileName, O_RDONLY | O_NONBLOCK);
138 			if (scc[1].rd_handle < 0)
139 			{
140 				Log_Printf(LOG_ERROR, "SCC_Init: Can not open input file '%s'\n",
141 					   ConfigureParams.RS232.sSccBInFileName);
142 			}
143 		}
144 		if (ConfigureParams.RS232.sSccBOutFileName[0])
145 		{
146 			scc[1].wr_handle = open(ConfigureParams.RS232.sSccBOutFileName,
147 						O_CREAT | O_WRONLY | O_NONBLOCK, S_IRUSR | S_IWUSR);
148 			if (scc[1].wr_handle < 0)
149 			{
150 				Log_Printf(LOG_ERROR, "SCC_Init: Can not open output file '%s'\n",
151 					   ConfigureParams.RS232.sSccBOutFileName);
152 			}
153 		}
154 	}
155 	if (scc[1].rd_handle == -1 && scc[1].wr_handle == -1)
156 	{
157 		ConfigureParams.RS232.bEnableSccB = false;
158 	}
159 }
160 
SCC_UnInit(void)161 void SCC_UnInit(void)
162 {
163 	D(bug("SCC: interface destroyed\n"));
164 	if (scc[1].rd_handle >= 0)
165 	{
166 		if (scc[1].wr_handle == scc[1].rd_handle)
167 			scc[1].wr_handle = -1;
168 		close(scc[1].rd_handle);
169 		scc[1].rd_handle = -1;
170 	}
171 	if (scc[1].wr_handle >= 0)
172 	{
173 		close(scc[1].wr_handle);
174 		scc[1].wr_handle = -1;
175 	}
176 }
177 
SCC_MemorySnapShot_Capture(bool bSave)178 void SCC_MemorySnapShot_Capture(bool bSave)
179 {
180 	MemorySnapShot_Store(&active_reg, sizeof(active_reg));
181 	MemorySnapShot_Store(&RR3, sizeof(RR3));
182 	MemorySnapShot_Store(&RR3M, sizeof(RR3M));
183 	for (int c = 0; c < 2; c++)
184 	{
185 		MemorySnapShot_Store(scc[c].regs, sizeof(scc[c].regs));
186 		MemorySnapShot_Store(&scc[c].charcount, sizeof(scc[c].charcount));
187 		MemorySnapShot_Store(&scc[c].oldTBE, sizeof(scc[c].oldTBE));
188 		MemorySnapShot_Store(&scc[c].oldStatus, sizeof(scc[c].oldStatus));
189 	}
190 }
191 
SCC_channelAreset(void)192 static void SCC_channelAreset(void)
193 {
194 	scc[0].regs[15] = 0xF8;
195 	scc[0].regs[14] = 0xA0;
196 	scc[0].regs[11] = 0x08;
197 	scc[0].regs[9] = 0;
198 	RR3 &= ~0x38;
199 	RR3M &= ~0x38;
200 	scc[0].regs[0] = 1 << TBE;  // RR0A
201 }
202 
SCC_channelBreset(void)203 static void SCC_channelBreset(void)
204 {
205 	scc[1].regs[15] = 0xF8;
206 	scc[1].regs[14] = 0xA0;
207 	scc[1].regs[11] = 0x08;
208 	scc[0].regs[9] = 0;         // single WR9
209 	RR3 &= ~7;
210 	RR3M &= ~7;
211 	scc[1].regs[0] = 1 << TBE;  // RR0B
212 }
213 
SCC_Reset()214 void SCC_Reset()
215 {
216 	active_reg = 0;
217 	memset(scc[0].regs, 0, sizeof(scc[0].regs));
218 	memset(scc[1].regs, 0, sizeof(scc[1].regs));
219 	SCC_channelAreset();
220 	SCC_channelBreset();
221 	RR3 = 0;
222 	RR3M = 0;
223 	scc[0].charcount = scc[1].charcount = 0;
224 }
225 
TriggerSCC(bool enable)226 static void TriggerSCC(bool enable)
227 {
228 	if (enable)
229 	{
230 		Log_Printf(LOG_TODO, "TriggerSCC\n");
231 	}
232 }
233 
SCC_serial_getData(int channel)234 static uint8_t SCC_serial_getData(int channel)
235 {
236 	uint8_t value = 0;
237 	int nb;
238 
239 	D(bug("SCC: getData\n"));
240 	if (scc[channel].rd_handle >= 0)
241 	{
242 		nb = read(scc[channel].rd_handle, &value, 1);
243 		if (nb < 0)
244 		{
245 			D(bug("SCC: impossible to get data\n"));
246 		}
247 	}
248 	return value;
249 }
250 
SCC_serial_setData(int channel,uint8_t value)251 static void SCC_serial_setData(int channel, uint8_t value)
252 {
253 	int nb;
254 
255 	D(bug("SCC: setData\n"));
256 	if (scc[channel].wr_handle >= 0)
257 	{
258 		do
259 		{
260 			nb = write(scc[channel].wr_handle, &value, 1);
261 		} while (nb < 0 && (errno == EAGAIN || errno == EINTR));
262 	}
263 }
264 
265 #if HAVE_TERMIOS_H
SCC_serial_setBaudAttr(int handle,speed_t new_speed)266 static void SCC_serial_setBaudAttr(int handle, speed_t new_speed)
267 {
268 	struct termios options;
269 
270 	if (handle < 0)
271 		return;
272 
273 	tcgetattr(handle, &options);
274 
275 	cfsetispeed(&options, new_speed);
276 	cfsetospeed(&options, new_speed);
277 
278 	options.c_cflag |= (CLOCAL | CREAD);
279 	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // raw input
280 	options.c_iflag &= ~(ICRNL); // CR is not CR+LF
281 
282 	tcsetattr(handle, TCSANOW, &options);
283 }
284 #endif
285 
SCC_serial_setBaud(int channel,int value)286 static void SCC_serial_setBaud(int channel, int value)
287 {
288 #if HAVE_TERMIOS_H
289 	speed_t new_speed = B0;
290 
291 	D(bug("SCC: setBaud %i\n", value));
292 
293 	switch (value)
294 	{
295 	 case 230400:	new_speed = B230400;	break;
296 	 case 115200:	new_speed = B115200;	break;
297 	 case 57600:	new_speed = B57600;	break;
298 	 case 38400:	new_speed = B38400;	break;
299 	 case 19200:	new_speed = B19200;	break;
300 	 case 9600:	new_speed = B9600;	break;
301 	 case 4800:	new_speed = B4800;	break;
302 	 case 2400:	new_speed = B2400;	break;
303 	 case 1800:	new_speed = B1800;	break;
304 	 case 1200:	new_speed = B1200;	break;
305 	 case 600:	new_speed = B600;	break;
306 	 case 300:	new_speed = B300;	break;
307 	 case 200:	new_speed = B200;	break;
308 	 case 150:	new_speed = B150;	break;
309 	 case 134:	new_speed = B134;	break;
310 	 case 110:	new_speed = B110;	break;
311 	 case 75:	new_speed = B75;	break;
312 	 case 50:	new_speed = B50;	break;
313 	 default:	D(bug("SCC: unsupported baud rate %i\n", value)); break;
314 	}
315 
316 	if (new_speed == B0)
317 		return;
318 
319 	SCC_serial_setBaudAttr(scc[channel].rd_handle, new_speed);
320 	if (scc[channel].rd_handle != scc[channel].wr_handle)
321 		SCC_serial_setBaudAttr(scc[channel].wr_handle, new_speed);
322 #endif
323 }
324 
SCC_getTBE(int chn)325 static inline uint16_t SCC_getTBE(int chn)
326 {
327 	uint16_t value = 0;
328 
329 #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCSERGETLSR) && defined(TIOCSER_TEMT)
330 	int status = 0;
331 	if (ioctl(scc[chn].wr_handle, TIOCSERGETLSR, &status) < 0)  // OK with ttyS0, not OK with ttyUSB0
332 	{
333 		// D(bug("SCC: Can't get LSR"));
334 		value |= (1<<TBE);   // only for serial USB
335 	}
336 	else if (status & TIOCSER_TEMT)
337 	{
338 		value = (1 << TBE);  // this is a real TBE for ttyS0
339 		if ((scc[chn].oldTBE & (1 << TBE)) == 0)
340 		{
341 			value |= 0x200;
342 		} // TBE rise=>TxIP (based on real TBE)
343 	}
344 #endif
345 
346 	scc[chn].oldTBE = value;
347 	return value;
348 }
349 
SCC_serial_getStatus(int chn)350 static uint16_t SCC_serial_getStatus(int chn)
351 {
352 	uint16_t value = 0;
353 	uint16_t diff;
354 
355 #if defined(HAVE_SYS_IOCTL_H) && defined(FIONREAD)
356 	if (scc[chn].rd_handle >= 0)
357 	{
358 		int nbchar = 0;
359 
360 		if (ioctl(scc[chn].rd_handle, FIONREAD, &nbchar) < 0)
361 		{
362 			D(bug("SCC: Can't get input fifo count\n"));
363 		}
364 		scc[chn].charcount = nbchar; // to optimize input (see UGLY in handleWrite)
365 		if (nbchar > 0)
366 			value = 0x0401;  // RxIC+RBF
367 	}
368 #endif
369 #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCMGET)
370 	if (scc[chn].wr_handle >= 0 && scc[chn].bFileHandleIsATTY)
371 	{
372 		int status = 0;
373 
374 		value |= SCC_getTBE(chn); // TxIC
375 		value |= (1 << TBE);  // fake TBE to optimize output (for ttyS0)
376 		if (ioctl(scc[chn].wr_handle, TIOCMGET, &status) < 0)
377 		{
378 			D(bug("SCC: Can't get status\n"));
379 		}
380 		if (status & TIOCM_CTS)
381 			value |= (1 << CTS);
382 	}
383 #endif
384 
385 	if (scc[chn].wr_handle >= 0 && !scc[chn].bFileHandleIsATTY)
386 	{
387 		/* Output is a normal file, thus always set Clear-To-Send
388 		 * and Transmit-Buffer-Empty: */
389 		value |= (1 << CTS) | (1 << TBE);
390 	}
391 	else if (scc[chn].wr_handle < 0)
392 	{
393 		/* If not connected, signal transmit-buffer-empty anyway to
394 		 * avoid that the program blocks while polling this bit */
395 		value |= (1 << TBE);
396 	}
397 
398 	diff = scc[chn].oldStatus ^ value;
399 	if (diff & (1 << CTS))
400 		value |= 0x100;  // ext status IC on CTS change
401 
402 	D(bug("SCC: getStatus 0x%04x\n", value));
403 
404 	scc[chn].oldStatus = value;
405 	return value;
406 }
407 
SCC_serial_setRTS(int chn,bool value)408 static void SCC_serial_setRTS(int chn, bool value)
409 {
410 #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCMGET)
411 	int status = 0;
412 
413 	if (scc[chn].wr_handle >= 0 && scc[chn].bFileHandleIsATTY)
414 	{
415 		if (ioctl(scc[chn].wr_handle, TIOCMGET, &status) < 0)
416 		{
417 			D(bug("SCC: Can't get status for RTS\n"));
418 		}
419 		if (value)
420 			status |= TIOCM_RTS;
421 		else
422 			status &= ~TIOCM_RTS;
423 		ioctl(scc[chn].wr_handle, TIOCMSET, &status);
424 	}
425 #endif
426 }
427 
SCC_serial_setDTR(int chn,bool value)428 static void SCC_serial_setDTR(int chn, bool value)
429 {
430 #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCMGET)
431 	int status = 0;
432 
433 	if (scc[chn].wr_handle >= 0 && scc[chn].bFileHandleIsATTY)
434 	{
435 		if (ioctl(scc[chn].wr_handle, TIOCMGET, &status) < 0)
436 		{
437 			D(bug("SCC: Can't get status for DTR\n"));
438 		}
439 		if (value)
440 			status |= TIOCM_DTR;
441 		else
442 			status &= ~TIOCM_DTR;
443 		ioctl(scc[chn].wr_handle, TIOCMSET, &status);
444 	}
445 #endif
446 }
447 
SCC_ReadControl(int chn)448 static uint8_t SCC_ReadControl(int chn)
449 {
450 	uint8_t value = 0;
451 	uint16_t temp;
452 
453 	switch (active_reg)
454 	{
455 	 case 0:	// RR0
456 		temp = SCC_serial_getStatus(chn);
457 		scc[chn].regs[0] = temp & 0xFF;		// define CTS(5), TBE(2) and RBF=RCA(0)
458 		if (chn)
459 			RR3 = RR3M & (temp >> 8);	// define RxIP(2), TxIP(1) and ExtIP(0)
460 		else if (scc[0].regs[9] == 0x20)
461 			RR3 |= 0x8;
462 		value = scc[chn].regs[0];
463 		break;
464 	 case 2:	// not really useful (RR2 seems unaccessed...)
465 		value = scc[0].regs[2];
466 		if (chn == 0)	// vector base only for RR2A
467 			break;
468 		if ((scc[0].regs[9] & 1) == 0)	// no status bit added
469 			break;
470 		// status bit added to vector
471 		if (scc[0].regs[9] & 0x10) // modify high bits
472 		{
473 			if (RR3 == 0)
474 			{
475 				value |= 0x60;
476 				break;
477 			}
478 			if (RR3 & 32)
479 			{
480 				value |= 0x30;        // A RxIP
481 				break;
482 			}
483 			if (RR3 & 16)
484 			{
485 				value |= 0x10;        // A TxIP
486 				break;
487 			}
488 			if (RR3 & 8)
489 			{
490 				value |= 0x50;        // A Ext IP
491 				break;
492 			}
493 			if (RR3 & 4)
494 			{
495 				value |= 0x20;        // B RBF
496 				break;
497 			}
498 			if (RR3 & 2)
499 				break;                // B TBE
500 			if (RR3 & 1)
501 				value |= 0x40;        // B Ext Status
502 		}
503 		else // modify low bits
504 		{
505 			if (RR3 == 0)
506 			{
507 				value |= 6;           // no one
508 				break;
509 			}
510 			if (RR3 & 32)
511 			{
512 				value |= 0xC;         // A RxIP
513 				break;
514 			}
515 			if (RR3 & 16)
516 			{
517 				value |= 0x8;         // A TxIP
518 				break;
519 			}
520 			if (RR3 & 8)
521 			{
522 				value |= 0xA;         // A Ext IP
523 				break;
524 			}
525 			if (RR3 & 4)
526 			{
527 				value |= 4;           // B RBF
528 				break;
529 			}
530 			if (RR3 & 2)
531 				break;                // B TBE
532 			if (RR3 & 1)
533 				value |= 2;           // B Ext Status (CTS)
534 		}
535 		break;
536 	 case 3:
537 		value = chn ? 0 : RR3;     // access on A channel only
538 		break;
539 	 case 4: // RR0
540 		value = scc[chn].regs[0];
541 		break;
542 	 case 8: // DATA reg
543 		scc[chn].regs[8] = SCC_serial_getData(chn);
544 		value = scc[chn].regs[8];
545 		break;
546 	 case 9: // WR13
547 		value = scc[chn].regs[13];
548 		break;
549 	 case 11: // WR15
550 	 case 15: // EXT/STATUS IT Ctrl
551 		value = scc[chn].regs[15] &= 0xFA; // mask out D2 and D0
552 		break;
553 	 case 12: // BRG LSB
554 	 case 13: // BRG MSB
555 		value = scc[chn].regs[active_reg];
556 		break;
557 
558 	 default: // RR5,RR6,RR7,RR10,RR14 not processed
559 		D(bug("scc : unprocessed read address=$%x *********\n", active_reg));
560 		value = 0;
561 		break;
562 	}
563 
564 	return value;
565 }
566 
SCC_handleRead(uint32_t addr)567 static uint8_t SCC_handleRead(uint32_t addr)
568 {
569 	uint8_t value = 0;
570 	int channel;
571 
572 	addr &= 0x6;
573 	channel = (addr >= 4) ? 1 : 0;  // 0 = channel A, 1 = channel B
574 	switch (addr)
575 	{
576 	 case 0: // channel A
577 	 case 4: // channel B
578 		value = SCC_ReadControl(channel);
579 		break;
580 	 case 2: // channel A
581 	 case 6: // channel B
582 		scc[channel].regs[8] = SCC_serial_getData(channel);
583 		value = scc[channel].regs[8];
584 		break;
585 	 default:
586 		D(bug("scc : illegal read address=$%x\n", addr));
587 		break;
588 	}
589 
590 	active_reg = 0; // next access for RR0 or WR0
591 
592 	return value;
593 }
594 
SCC_WriteControl(int chn,uint8_t value)595 static void SCC_WriteControl(int chn, uint8_t value)
596 {
597 	uint32_t BaudRate;
598 	int i;
599 
600 	if (active_reg == 0)
601 	{
602 
603 		if (value <= 15)
604 		{
605 			active_reg = value & 0x0f;
606 		}
607 		else
608 		{
609 			if ((value & 0x38) == 0x38) // Reset Highest IUS (last operation in IT service routine)
610 			{
611 				for (i = 0x20; i; i >>= 1)
612 				{
613 					if (RR3 & i)
614 						break;
615 				}
616 #define UGLY
617 #ifdef UGLY
618 				// tricky & ugly speed improvement for input
619 				if (i == 4) // RxIP
620 				{
621 					scc[chn].charcount--;
622 					if (scc[chn].charcount <= 0)
623 						RR3 &= ~4; // optimize input; don't reset RxIP when chars are buffered
624 				}
625 				else
626 				{
627 					RR3 &= ~i;
628 				}
629 #else
630 				RR3 &= ~i;
631 #endif
632 			}
633 			else if ((value & 0x38) == 0x28) // Reset Tx int pending
634 			{
635 				if (chn)
636 					RR3 &= ~2;       // channel B
637 				else
638 					RR3 &= ~0x10;    // channel A
639 			}
640 			else if ((value & 0x38) == 0x10) // Reset Ext/Status ints
641 			{
642 				if (chn)
643 					RR3 &= ~1;       // channel B
644 				else
645 					RR3 &= ~8;       // channel A
646 			}
647 			// Clear SCC flag if no pending IT or no properly
648 			// configured WR9. Must be done here to avoid
649 			// scc_do_Interrupt call without pending IT
650 			TriggerSCC((RR3 & RR3M) && ((0xB & scc[0].regs[9]) == 9));
651 		}
652 		return;
653 	}
654 
655 	// active_reg > 0:
656 	scc[chn].regs[active_reg] = value;
657 	if (active_reg == 2)
658 	{
659 		scc[0].regs[active_reg] = value; // single WR2 on SCC
660 	}
661 	else if (active_reg == 8)
662 	{
663 		SCC_serial_setData(chn, value);
664 	}
665 	else if (active_reg == 1) // Tx/Rx interrupt enable
666 	{
667 		if (chn == 0)
668 		{
669 			// channel A
670 			if (value & 1)
671 				RR3M |= 8;
672 			else
673 				RR3 &= ~8; // no IP(RR3) if not enabled(RR3M)
674 			if (value & 2)
675 				RR3M |= 16;
676 			else
677 				RR3 &= ~16;
678 			if (value & 0x18)
679 				RR3M |= 32;
680 			else
681 				RR3 &= ~32;
682 		}
683 		else
684 		{
685 			// channel B
686 			if (value & 1)
687 				RR3M |= 1;
688 			else
689 				RR3 &= ~1;
690 			if (value & 2)
691 				RR3M |= 2;
692 			else
693 				RR3 &= ~2;
694 			if (value & 0x18)
695 				RR3M |= 4;
696 			else
697 				RR3 &= ~4;
698 			// set or clear SCC flag if necessary (see later)
699 		}
700 	}
701 	else if (active_reg == 5) // Transmit parameter and control
702 	{
703 		SCC_serial_setRTS(chn, value & 2);
704 		SCC_serial_setDTR(chn, value & 128);
705 		// Tx character format & Tx CRC would be selected also here (8 bits/char and no CRC assumed)
706 	}
707 	else if (active_reg == 9) // Master interrupt control (common for both channels)
708 	{
709 		scc[0].regs[9] = value; // single WR9 (accessible by both channels)
710 		if (value & 0x40)
711 		{
712 			SCC_channelBreset();
713 		}
714 		if (value & 0x80)
715 		{
716 			SCC_channelAreset();
717 		}
718 		//  set or clear SCC flag accordingly (see later)
719 	}
720 	else if (active_reg == 13) // set baud rate according to WR13 and WR12
721 	{
722 		// Normally we have to set the baud rate according
723 		// to clock source (WR11) and clock mode (WR4)
724 		// In fact, we choose the baud rate from the value stored in WR12 & WR13
725 		// Note: we assume that WR13 is always written last (after WR12)
726 		// we tried to be more or less compatible with HSMODEM (see below)
727 		// 75 and 50 bauds are preserved because 153600 and 76800 were not available
728 		// 3600 and 2000 were also unavailable and are remapped to 57600 and 38400 respectively
729 		BaudRate = 0;
730 		switch (value)
731 		{
732 		 case 0:
733 			switch (scc[chn].regs[12])
734 			{
735 			 case 0: // HSMODEM for 200 mapped to 230400
736 				BaudRate = 230400;
737 				break;
738 			 case 2: // HSMODEM for 150 mapped to 115200
739 				BaudRate = 115200;
740 				break;
741 			 case 6:    // HSMODEM for 134 mapped to 57600
742 			 case 0x7e: // HSMODEM for 3600 remapped to 57600
743 			 case 0x44: // normal for 3600 remapped to 57600
744 				BaudRate = 57600;
745 				break;
746 			 case 0xa:  // HSMODEM for 110 mapped to 38400
747 			 case 0xe4: // HSMODEM for 2000 remapped to 38400
748 			 case 0x7c: // normal for 2000 remapped to 38400
749 				BaudRate = 38400;
750 				break;
751 			 case 0x16: // HSMODEM for 19200
752 			 case 0xb:  // normal for 19200
753 				BaudRate = 19200;
754 				break;
755 			 case 0x2e: // HSMODEM for 9600
756 			 case 0x18: // normal for 9600
757 				BaudRate = 9600;
758 				break;
759 			 case 0x5e: // HSMODEM for 4800
760 			 case 0x32: // normal for 4800
761 				BaudRate = 4800;
762 				break;
763 			 case 0xbe: // HSMODEM for 2400
764 			 case 0x67: // normal
765 				BaudRate = 2400;
766 				break;
767 			 case 0xfe: // HSMODEM for 1800
768 			 case 0x8a: // normal for 1800
769 				BaudRate = 1800;
770 				break;
771 			 case 0xd0: // normal for 1200
772 				BaudRate = 1200;
773 				break;
774 			 case 1: // HSMODEM for 75 kept to 75
775 				BaudRate = 75;
776 				break;
777 			 case 4: // HSMODEM for 50 kept to 50
778 				BaudRate = 50;
779 				break;
780 			 default:
781 				D(bug("SCC: unexpected LSB constant for baud rate\n"));
782 				break;
783 			}
784 			break;
785 		 case 1:
786 			switch (scc[chn].regs[12])
787 			{
788 			 case 0xa1: // normal for 600
789 				BaudRate = 600;
790 				break;
791 			 case 0x7e: // HSMODEM for 1200
792 				BaudRate = 1200;
793 				break;
794 			}
795 			break;
796 		 case 2:
797 			if (scc[chn].regs[12] == 0xfe)
798 				BaudRate = 600; //HSMODEM
799 			break;
800 		 case 3:
801 			if (scc[chn].regs[12] == 0x45)
802 				BaudRate = 300; //normal
803 			break;
804 		 case 4:
805 			if (scc[chn].regs[12] == 0xe8)
806 				BaudRate = 200; //normal
807 			break;
808 		 case 5:
809 			if (scc[chn].regs[12] == 0xfe)
810 				BaudRate = 300; //HSMODEM
811 			break;
812 		 case 6:
813 			if (scc[chn].regs[12] == 0x8c)
814 				BaudRate = 150; //normal
815 			break;
816 		 case 7:
817 			if (scc[chn].regs[12] == 0x4d)
818 				BaudRate = 134; //normal
819 			break;
820 		 case 8:
821 			if (scc[chn].regs[12] == 0xee)
822 				BaudRate = 110; //normal
823 			break;
824 		 case 0xd:
825 			if (scc[chn].regs[12] == 0x1a)
826 				BaudRate = 75; //normal
827 			break;
828 		 case 0x13:
829 			if (scc[chn].regs[12] == 0xa8)
830 				BaudRate = 50; //normal
831 			break;
832 		 case 0xff: // HSMODEM dummy value->silently ignored
833 			break;
834 		 default:
835 			D(bug("SCC: unexpected MSB constant for baud rate\n"));
836 			break;
837 		}
838 		if (BaudRate)  // set only if defined
839 			SCC_serial_setBaud(chn, BaudRate);
840 
841 		/* summary of baud rates:
842 		   Rsconf   Falcon     Falcon(+HSMODEM)   Hatari    Hatari(+HSMODEM)
843 		   0        19200         19200            19200       19200
844 		   1         9600          9600             9600        9600
845 		   2         4800          4800             4800        4800
846 		   3         3600          3600            57600       57600
847 		   4         2400          2400             2400        2400
848 		   5         2000          2000            38400       38400
849 		   6         1800          1800             1800        1800
850 		   7         1200          1200             1200        1200
851 		   8          600           600              600         600
852 		   9          300           300              300         300
853 		   10         200        230400              200      230400
854 		   11         150        115200              150      115200
855 		   12         134         57600              134       57600
856 		   13         110         38400              110       38400
857 		   14          75        153600               75          75
858 		   15          50         76800               50          50
859 		*/
860 	}
861 	else if (active_reg == 15) // external status int control
862 	{
863 		if (value & 1)
864 		{
865 			D(bug("SCC WR7 prime not yet processed\n"));
866 		}
867 	}
868 
869 	// set or clear SCC flag accordingly. Yes it's ugly but avoids unnecessary useless calls
870 	if (active_reg == 1 || active_reg == 2 || active_reg == 9)
871 		TriggerSCC((RR3 & RR3M) && ((0xB & scc[0].regs[9]) == 9));
872 
873 	active_reg = 0; // next access for RR0 or WR0
874 }
875 
SCC_handleWrite(uint32_t addr,uint8_t value)876 static void SCC_handleWrite(uint32_t addr, uint8_t value)
877 {
878 	int channel;
879 
880 	addr &= 0x6;
881 	channel = (addr >= 4) ? 1 : 0;  // 0 = channel A, 1 = channel B
882 	switch (addr)
883 	{
884 	 case 0:
885 	 case 4:
886 		SCC_WriteControl(channel, value);
887 		break;
888 	 case 2: // channel A
889 	 case 6: // channel B
890 		SCC_serial_setData(channel, value);
891 		break;
892 	 default:
893 		D(bug( "scc : illegal write address =$%x\n", addr));
894 		break;
895 	}
896 }
897 
SCC_IRQ(void)898 void SCC_IRQ(void)
899 {
900 	uint16_t temp;
901 	temp = SCC_serial_getStatus(0);
902 	if (scc[0].regs[9] == 0x20)
903 		temp |= 0x800; // fake ExtStatusChange for HSMODEM install
904 	scc[1].regs[0] = temp & 0xFF; // RR0B
905 	RR3 = RR3M & (temp >> 8);
906 	if (RR3 && (scc[0].regs[9] & 0xB) == 9)
907 		TriggerSCC(true);
908 }
909 
910 
911 // return : vector number, or zero if no interrupt
SCC_doInterrupt()912 int SCC_doInterrupt()
913 {
914 	int vector;
915 	uint8_t i;
916 	for (i = 0x20 ; i ; i >>= 1) // highest priority first
917 	{
918 		if (RR3 & i & RR3M)
919 			break ;
920 	}
921 	vector = scc[0].regs[2]; // WR2 = base of vectored interrupts for SCC
922 	if ((scc[0].regs[9] & 3) == 0)
923 		return vector; // no status included in vector
924 	if ((scc[0].regs[9] & 0x32) != 0)  // shouldn't happen with TOS, (to be completed if needed)
925 	{
926 		D(bug( "unexpected WR9 contents \n"));
927 		// no Soft IACK, Status Low control bit expected, no NV
928 		return 0;
929 	}
930 	switch (i)
931 	{
932 	 case 0: /* this shouldn't happen :-) */
933 		D(bug( "scc_do_interrupt called with no pending interrupt\n"));
934 		vector = 0; // cancel
935 		break;
936 	 case 1:
937 		vector |= 2; // Ch B Ext/status change
938 		break;
939 	 case 2:
940 		break;// Ch B Transmit buffer Empty
941 	 case 4:
942 		vector |= 4; // Ch B Receive Char available
943 		break;
944 	 case 8:
945 		vector |= 0xA; // Ch A Ext/status change
946 		break;
947 	 case 16:
948 		vector |= 8; // Ch A Transmit Buffer Empty
949 		break;
950 	 case 32:
951 		vector |= 0xC; // Ch A Receive Char available
952 		break;
953 		// special receive condition not yet processed
954 	}
955 #if 0
956 	D(bug( "SCC_doInterrupt : vector %d\n", vector));
957 #endif
958 	return vector ;
959 }
960 
961 
SCC_IoMem_ReadByte(void)962 void SCC_IoMem_ReadByte(void)
963 {
964 	int i;
965 
966 	for (i = 0; i < nIoMemAccessSize; i++)
967 	{
968 		uint32_t addr = IoAccessBaseAddress + i;
969 		if (addr & 1)
970 			IoMem[addr] = SCC_handleRead(addr);
971 		else
972 			IoMem[addr] = 0xff;
973 	}
974 }
975 
SCC_IoMem_WriteByte(void)976 void SCC_IoMem_WriteByte(void)
977 {
978 	int i;
979 
980 	for (i = 0; i < nIoMemAccessSize; i++)
981 	{
982 		uint32_t addr = IoAccessBaseAddress + i;
983 		if (addr & 1)
984 			SCC_handleWrite(addr, IoMem[addr]);
985 	}
986 }
987