1 /*
2  *  Copyright (C) 2003-2018  Anders Gavare.  All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions are met:
6  *
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. The name of the author may not be used to endorse or promote products
13  *     derived from this software without specific prior written permission.
14  *
15  *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  *  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  *  SUCH DAMAGE.
26  *
27  *
28  *  COMMENT: Serial controller used in some DECsystem and SGI machines
29  *
30  *  Hm... Same as Z8530? Most of the code in here is written for DECsystem
31  *  emulation, though.
32  *
33  *  NOTE:
34  *	Each scc device is responsible for two lines; the first scc device
35  *	controls mouse (0) and keyboard (1), and the second device controls
36  *	serial ports (2 and 3).
37  *
38  *  TODO:
39  *	Mouse support!!!  (scc0 and scc1 need to cooperate, in order to
40  *		emulate the same lk201 behaviour as when using the dc device)
41  *	DMA
42  *	More correct interrupt support.
43  *
44  ******************************************************************************
45  *	 _____ ___  ____   ___  _
46  *	|_   _/ _ \|  _ \ / _ \| |
47  *	  | || | | | | | | | | | |
48  *	  | || |_| | |_| | |_| |_|
49  *	  |_| \___/|____/ \___/(_)
50  *
51  *	Since this is actually a Z8530, it should be merged with dev_z8530.c!
52  */
53 
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 
58 #include "console.h"
59 #include "cpu.h"
60 #include "devices.h"
61 #include "machine.h"
62 #include "memory.h"
63 #include "misc.h"
64 
65 #include "thirdparty/sccreg.h"
66 
67 
68 #define	SCC_TICK_SHIFT		14
69 
70 #define	N_SCC_PORTS		2
71 #define	N_SCC_REGS		16
72 #define	MAX_QUEUE_LEN		1024
73 
74 /*  #define SCC_DEBUG  */
75 
76 
77 struct scc_data {
78 	struct interrupt	irq;
79 
80 	int		use_fb;
81 	int		console_handle;
82 
83 	int		scc_nr;
84 	int		addrmul;
85 
86 	int		register_select_in_progress[N_SCC_PORTS];
87 	int		register_selected[N_SCC_PORTS];
88 
89 	unsigned char	scc_register_r[N_SCC_PORTS * N_SCC_REGS];
90 	unsigned char	scc_register_w[N_SCC_PORTS * N_SCC_REGS];
91 
92 	unsigned char	rx_queue_char[N_SCC_PORTS * MAX_QUEUE_LEN];
93 	int		cur_rx_queue_pos_write[N_SCC_PORTS];
94 	int		cur_rx_queue_pos_read[N_SCC_PORTS];
95 
96 	struct lk201_data lk201;
97 };
98 
99 
100 /*
101  *  dev_scc_add_to_rx_queue():
102  *
103  *  Add a character to the receive queue.
104  */
dev_scc_add_to_rx_queue(void * e,int ch,int portnr)105 void dev_scc_add_to_rx_queue(void *e, int ch, int portnr)
106 {
107 	struct scc_data *d = (struct scc_data *) e;
108 	int scc_nr;
109 
110 	/*  DC's keyboard port ==> SCC keyboard port  */
111 	if (portnr == 0)
112 		portnr = 3;
113 
114 	scc_nr = portnr / N_SCC_PORTS;
115 	if (scc_nr != d->scc_nr)
116 		return;
117 
118 	portnr &= (N_SCC_PORTS - 1);
119 
120         d->rx_queue_char[portnr * MAX_QUEUE_LEN +
121 	    d->cur_rx_queue_pos_write[portnr]] = ch;
122         d->cur_rx_queue_pos_write[portnr] ++;
123         if (d->cur_rx_queue_pos_write[portnr] == MAX_QUEUE_LEN)
124                 d->cur_rx_queue_pos_write[portnr] = 0;
125 
126         if (d->cur_rx_queue_pos_write[portnr] ==
127 	    d->cur_rx_queue_pos_read[portnr])
128                 fatal("warning: add_to_rx_queue(): rx_queue overrun!\n");
129 }
130 
131 
rx_avail(struct scc_data * d,int portnr)132 static int rx_avail(struct scc_data *d, int portnr)
133 {
134 	return d->cur_rx_queue_pos_write[portnr] !=
135 	    d->cur_rx_queue_pos_read[portnr];
136 }
137 
138 
rx_nextchar(struct scc_data * d,int portnr)139 static unsigned char rx_nextchar(struct scc_data *d, int portnr)
140 {
141 	unsigned char ch;
142 	ch = d->rx_queue_char[portnr * MAX_QUEUE_LEN +
143 	    d->cur_rx_queue_pos_read[portnr]];
144 	d->cur_rx_queue_pos_read[portnr]++;
145 	if (d->cur_rx_queue_pos_read[portnr] == MAX_QUEUE_LEN)
146 		d->cur_rx_queue_pos_read[portnr] = 0;
147 	return ch;
148 }
149 
150 
DEVICE_TICK(scc)151 DEVICE_TICK(scc)
152 {
153 	struct scc_data *d = (struct scc_data *) extra;
154 	int i;
155 
156 	/*  Add keystrokes to the rx queue:  */
157 	if (d->scc_nr == 1) {
158 		if (d->use_fb == 0) {
159 			if (console_charavail(d->console_handle))
160 				dev_scc_add_to_rx_queue(extra, console_readchar(
161 			    d->console_handle), 2);
162 		} else if (d->use_fb == 1)
163 			lk201_tick(cpu->machine, &d->lk201);
164 	}
165 
166 	for (i=0; i<N_SCC_PORTS; i++) {
167 		d->scc_register_r[i * N_SCC_REGS + SCC_RR0] |= SCC_RR0_TX_EMPTY;
168 		d->scc_register_r[i * N_SCC_REGS + SCC_RR1] = 0;
169 		    /*  No receive errors  */
170 
171 		d->scc_register_r[i * N_SCC_REGS + SCC_RR0] &=
172 		    ~SCC_RR0_RX_AVAIL;
173 		if (rx_avail(d, i))
174 			d->scc_register_r[i * N_SCC_REGS + SCC_RR0] |=
175 			    SCC_RR0_RX_AVAIL;
176 
177 		/*
178 		 *  Interrupts:
179 		 *  (NOTE: Interrupt enables are always at channel A)
180 		 */
181 		if (d->scc_register_w[N_SCC_REGS + SCC_WR9] &
182 		    SCC_WR9_MASTER_IE) {
183 			/*  TX interrupts?  */
184 			if (d->scc_register_w[i * N_SCC_REGS + SCC_WR1] &
185 			    SCC_WR1_TX_IE) {
186 				if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
187 				    & SCC_RR3_TX_IP_A ||
188 				    d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
189 				    & SCC_RR3_TX_IP_B) {
190 					INTERRUPT_ASSERT(d->irq);
191 				}
192 			}
193 
194 			/*  RX interrupts?  */
195 			if (d->scc_register_w[N_SCC_REGS + SCC_WR1] &
196 			    (SCC_WR1_RXI_FIRST_CHAR | SCC_WR1_RXI_ALL_CHAR)) {
197 				if (d->scc_register_r[i * N_SCC_REGS + SCC_RR0]
198 				    & SCC_RR0_RX_AVAIL) {
199 					if (i == SCC_CHANNEL_A)
200 						d->scc_register_r[N_SCC_REGS +
201 						    SCC_RR3] |= SCC_RR3_RX_IP_A;
202 					else
203 						d->scc_register_r[N_SCC_REGS +
204 						    SCC_RR3] |= SCC_RR3_RX_IP_B;
205 				}
206 
207 				if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
208 				    & SCC_RR3_RX_IP_A ||
209 				    d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
210 				    & SCC_RR3_RX_IP_B) {
211 					INTERRUPT_ASSERT(d->irq);
212 				}
213 			}
214 
215 			if (d->scc_register_w[N_SCC_REGS + SCC_WR1] &
216 			    SCC_WR1_DMA_MODE) {
217 				if (d->scc_register_r[i * N_SCC_REGS + SCC_RR0]
218 				    & SCC_RR0_RX_AVAIL) {
219 					if (i == SCC_CHANNEL_A)
220 						d->scc_register_r[N_SCC_REGS +
221 						    SCC_RR3] |=
222 						    SCC_RR3_EXT_IP_A;
223 					else
224 						d->scc_register_r[N_SCC_REGS +
225 						    SCC_RR3] |=
226 						    SCC_RR3_EXT_IP_B;
227 				}
228 
229 				if (d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
230 				    & SCC_RR3_EXT_IP_A ||
231 				    d->scc_register_r[i * N_SCC_REGS + SCC_RR3]
232 				    & SCC_RR3_EXT_IP_B) {
233 					INTERRUPT_ASSERT(d->irq);
234 				}
235 			}
236 		}
237 	}
238 }
239 
240 
241 /*
242  *  dev_scc_dma_func():
243  */
dev_scc_dma_func(struct cpu * cpu,void * extra,uint64_t addr,size_t dma_len,int tx)244 int dev_scc_dma_func(struct cpu *cpu, void *extra, uint64_t addr,
245 	size_t dma_len, int tx)
246 {
247 	/*  printf("dev_scc_dma_func(): addr = %08x, len = %i\n",
248 	    (int)addr, (int)dma_len);  */
249 	unsigned char word[4];
250 	struct scc_data *d = (struct scc_data *) extra;
251 	int n;
252 
253 	int port = SCC_CHANNEL_A;	/*  TODO  */
254 
255 	if (tx) {
256 		do {
257 			cpu->memory_rw(cpu, cpu->mem, addr, &word[0],
258 			    sizeof(word), MEM_READ, NO_EXCEPTIONS | PHYSICAL);
259 
260 			lk201_tx_data(&d->lk201, d->scc_nr * 2 + port, word[1]);
261 			/*  Loopback:  */
262 			if (d->scc_register_w[port * N_SCC_REGS + SCC_WR14]
263 			    & SCC_WR14_LOCAL_LOOPB)
264 				dev_scc_add_to_rx_queue(d, word[1],
265 				    d->scc_nr * 2 + port);
266 
267 			addr += sizeof(word);
268 		} while ((addr & 0xffc) != 0);
269 
270 		dev_scc_tick(cpu, extra);
271 		return 1;
272 	} else {
273 		printf("dev_scc_dma_func(): addr = %08x, len = %i\n",
274 		    (int)addr, (int)dma_len);
275 
276 
277 /*  TODO: all this is just nonsense  */
278 
279 		n = 0;
280 		while (rx_avail(d, port)) {
281 			word[0] = word[1] = word[2] = word[3] = 0;
282 			word[0] = word[1] = word[2] = word[3] =
283 			    rx_nextchar(d, port);
284 			n++;
285 			cpu->memory_rw(cpu, cpu->mem, addr, &word[0],
286 			    sizeof(word), MEM_WRITE, NO_EXCEPTIONS | PHYSICAL);
287 
288 			addr += sizeof(word);
289 			/*  Half-page?  */
290 			if ((addr & 0x7fc) == 0)
291 				break;
292 		}
293 		dev_scc_tick(cpu, extra);
294 		return n*4;
295 	}
296 }
297 
298 
DEVICE_ACCESS(scc)299 DEVICE_ACCESS(scc)
300 {
301 	struct scc_data *d = (struct scc_data *) extra;
302 	uint64_t idata = 0, odata = 0;
303 	int port;
304 	int ultrix_mode = 0;
305 
306 	if (writeflag == MEM_WRITE)
307 		idata = memory_readmax64(cpu, data, len);
308 
309 	/*  relative_addr /= d->addrmul;  */
310 		/*  See SGI comment below instead.  */
311 	/*
312 	 *  SGI writes command to 0x0f, and data to 0x1f.
313 	 *  (TODO: This works for port nr 0, how about port nr 1?)
314 	 */
315 	if ((relative_addr & 0x0f) == 0xf) {
316 		if (relative_addr == 0x0f)
317 			relative_addr = 1;
318 		else
319 			relative_addr = 5;
320 	}
321 
322 	port = relative_addr / 8;
323 	relative_addr &= 7;
324 
325 	dev_scc_tick(cpu, extra);
326 
327 	/*
328 	 *  Ultrix writes words such as 0x1200 to relative address 0,
329 	 *  instead of writing the byte 0x12 directly to address 1.
330 	 */
331 	if ((relative_addr == 0 || relative_addr == 4) && (idata & 0xff) == 0) {
332 		ultrix_mode = 1;
333 		relative_addr ++;
334 		idata >>= 8;
335 	}
336 
337 	switch (relative_addr) {
338 	case 1:		/*  command  */
339 		if (writeflag==MEM_READ) {
340 			odata = d->scc_register_r[port * N_SCC_REGS +
341 			    d->register_selected[port]];
342 
343 			if (d->register_selected[port] == SCC_RR3) {
344 				if (port == SCC_CHANNEL_B)
345 					fatal("WARNING! scc channel B has "
346 					    "no RR3\n");
347 
348 				d->scc_register_r[port * N_SCC_REGS +
349 				    SCC_RR3] = 0;
350 
351 				INTERRUPT_DEASSERT(d->irq);
352 			}
353 
354 #ifdef SCC_DEBUG
355 			fatal("[ scc: port %i, register %i, read value "
356 			    "0x%02x ]\n", port, d->register_selected[port],
357 			    (int)odata);
358 #endif
359 			d->register_select_in_progress[port] = 0;
360 			d->register_selected[port] = 0;
361 			/*  debug("[ scc: (port %i) read from 0x%08lx ]\n",
362 			    port, (long)relative_addr);  */
363 		} else {
364 			/*  If no register is selected, then select one.
365 			    Otherwise, write to the selected register.  */
366 			if (d->register_select_in_progress[port] == 0) {
367 				d->register_select_in_progress[port] = 1;
368 				d->register_selected[port] = idata;
369 				d->register_selected[port] &= (N_SCC_REGS-1);
370 			} else {
371 				d->scc_register_w[port * N_SCC_REGS +
372 				    d->register_selected[port]] = idata;
373 #ifdef SCC_DEBUG
374 				fatal("[ scc: port %i, register %i, write "
375 				    "value 0x%02x ]\n", port,
376 				    d->register_selected[port], idata);
377 #endif
378 
379 				d->scc_register_r[port * N_SCC_REGS +
380 				    SCC_RR12] = d->scc_register_w[port *
381 				    N_SCC_REGS + SCC_WR12];
382 				d->scc_register_r[port * N_SCC_REGS +
383 				    SCC_RR13] = d->scc_register_w[port *
384 				    N_SCC_REGS + SCC_WR13];
385 
386 				d->register_select_in_progress[port] = 0;
387 				d->register_selected[port] = 0;
388 			}
389 		}
390 		break;
391 	case 5:		/*  data  */
392 		if (writeflag==MEM_READ) {
393 			if (rx_avail(d, port))
394 				odata = rx_nextchar(d, port);
395 
396 			/*  TODO:  perhaps only clear the RX part of RR3?  */
397 			d->scc_register_r[N_SCC_REGS + SCC_RR3] = 0;
398 
399 			INTERRUPT_DEASSERT(d->irq);
400 
401 //			debug("[ scc: (port %i) read from 0x%08lx: 0x%02x ]\n",
402 //			    port, (long)relative_addr, (int)odata);
403 		} else {
404 			/*  debug("[ scc: (port %i) write to  0x%08lx: "
405 			    "0x%08x ]\n", port, (long)relative_addr,
406 			    (int)idata);  */
407 
408 			/*  Send the character:  */
409 			lk201_tx_data(&d->lk201, d->scc_nr * 2 + port, idata);
410 
411 			/*  Loopback:  */
412 			if (d->scc_register_w[port * N_SCC_REGS + SCC_WR14]
413 			    & SCC_WR14_LOCAL_LOOPB)
414 				dev_scc_add_to_rx_queue(d, idata, d->scc_nr
415 				    * 2 + port);
416 
417 			/*  TX interrupt:  */
418 			if (d->scc_register_w[port * N_SCC_REGS + SCC_WR9] &
419 			    SCC_WR9_MASTER_IE &&
420 			    d->scc_register_w[port * N_SCC_REGS + SCC_WR1] &
421 			    SCC_WR1_TX_IE) {
422 				if (port == SCC_CHANNEL_A)
423 					d->scc_register_r[N_SCC_REGS + SCC_RR3]
424 					    |= SCC_RR3_TX_IP_A;
425 				else
426 					d->scc_register_r[N_SCC_REGS + SCC_RR3]
427 					    |= SCC_RR3_TX_IP_B;
428 			}
429 
430 			dev_scc_tick(cpu, extra);
431 		}
432 		break;
433 	default:
434 		if (writeflag==MEM_READ) {
435 			debug("[ scc: (port %i) read from 0x%08lx ]\n",
436 			    port, (long)relative_addr);
437 		} else {
438 			debug("[ scc: (port %i) write to  0x%08lx: 0x%08x ]\n",
439 			    port, (long)relative_addr, (int)idata);
440 		}
441 	}
442 
443 	if (ultrix_mode && writeflag == MEM_READ) {
444 		odata <<= 8;
445 	}
446 
447 	if (writeflag == MEM_READ)
448 		memory_writemax64(cpu, data, len, odata);
449 
450 	return 1;
451 }
452 
453 
454 /*
455  *  dev_scc_init():
456  *
457  *	use_fb = non-zero when using graphical console + keyboard
458  *	scc_nr = 0 or 1
459  *	addmul = 1 in most cases, 8 on SGI?
460  */
dev_scc_init(struct machine * machine,struct memory * mem,uint64_t baseaddr,char * irq_path,int use_fb,int scc_nr,int addrmul)461 void *dev_scc_init(struct machine *machine, struct memory *mem,
462 	uint64_t baseaddr, char* irq_path, int use_fb, int scc_nr, int addrmul)
463 {
464 	struct scc_data *d;
465 
466 	CHECK_ALLOCATION(d = (struct scc_data *) malloc(sizeof(struct scc_data)));
467 	memset(d, 0, sizeof(struct scc_data));
468 
469 	INTERRUPT_CONNECT(irq_path, d->irq);
470 	d->scc_nr  = scc_nr;
471 	d->use_fb  = use_fb;
472 	d->addrmul = addrmul;
473 	d->console_handle = console_start_slave(machine, "SCC", 1);
474 
475 	d->scc_register_r[SCC_RR0] |= SCC_RR0_TX_UNDERRUN;
476 
477 	lk201_init(&d->lk201, use_fb, dev_scc_add_to_rx_queue,
478 	    d->console_handle, d);
479 
480 	memory_device_register(mem, "scc", baseaddr, DEV_SCC_LENGTH,
481 	    dev_scc_access, d, DM_DEFAULT, NULL);
482 	machine_add_tickfunction(machine, dev_scc_tick, d, SCC_TICK_SHIFT);
483 
484 	return (void *) d;
485 }
486 
487