1 /**********************************************************************
2 
3     Motorola 6821 PIA interface and emulation
4 
5     This function emulates all the functionality of up to 8 M6821
6     peripheral interface adapters.
7 
8     MAME sources by Nathan Woods
9 
10 **********************************************************************/
11 
12 #include <string.h>
13 #include <stdio.h>
14 #include <stddef.h>
15 #include "burnint.h"
16 #include "6821pia.h"
17 
18 #define VERBOSE 0
19 
20 #if VERBOSE
21 #define LOG(x)	logerror x
22 #else
23 #define LOG(x)
24 #endif
25 
26 
27 /******************* internal PIA data structure *******************/
28 
29 struct pia6821
30 {
31 	UINT8 addr;
32 
33 	UINT8 in_a;
34 	UINT8 in_ca1;
35 	UINT8 in_ca2;
36 	UINT8 out_a;
37 	UINT8 out_ca2;
38 	UINT8 ddr_a;
39 	UINT8 ctl_a;
40 	UINT8 irq_a1;
41 	UINT8 irq_a2;
42 	UINT8 irq_a_state;
43 
44 	UINT8 in_b;
45 	UINT8 in_cb1;
46 	UINT8 in_cb2;
47 	UINT8 out_b;
48 	UINT8 out_cb2;
49 	UINT8 ddr_b;
50 	UINT8 ctl_b;
51 	UINT8 irq_b1;
52 	UINT8 irq_b2;
53 	UINT8 irq_b_state;
54 	UINT8 in_set; // which input ports are set
55 
56 	const struct pia6821_interface *intf;
57 };
58 
59 
60 /******************* convenince macros and defines *******************/
61 
62 #define PIA_IRQ1				0x80
63 #define PIA_IRQ2				0x40
64 
65 #define IRQ1_ENABLED(c)			(c & 0x01)
66 #define IRQ1_DISABLED(c)		(!(c & 0x01))
67 #define C1_LOW_TO_HIGH(c)		(c & 0x02)
68 #define C1_HIGH_TO_LOW(c)		(!(c & 0x02))
69 #define OUTPUT_SELECTED(c)		(c & 0x04)
70 #define DDR_SELECTED(c)			(!(c & 0x04))
71 #define IRQ2_ENABLED(c)			(c & 0x08)
72 #define IRQ2_DISABLED(c)		(!(c & 0x08))
73 #define STROBE_E_RESET(c)		(c & 0x08)
74 #define STROBE_C1_RESET(c)		(!(c & 0x08))
75 #define SET_C2(c)				(c & 0x08)
76 #define RESET_C2(c)				(!(c & 0x08))
77 #define C2_LOW_TO_HIGH(c)		(c & 0x10)
78 #define C2_HIGH_TO_LOW(c)		(!(c & 0x10))
79 #define C2_SET_MODE(c)			(c & 0x10)
80 #define C2_STROBE_MODE(c)		(!(c & 0x10))
81 #define C2_OUTPUT(c)			(c & 0x20)
82 #define C2_INPUT(c)				(!(c & 0x20))
83 
84 #define PIA_IN_SET_A   0x01
85 #define PIA_IN_SET_CA1 0x02
86 #define PIA_IN_SET_CA2 0x04
87 #define PIA_IN_SET_B   0x08
88 #define PIA_IN_SET_CB1 0x10
89 #define PIA_IN_SET_CB2 0x20
90 
91 /******************* static variables *******************/
92 
93 static struct pia6821 pia[MAX_PIA];
94 
95 static const UINT8 swizzle_address[4] = { 0, 2, 1, 3 };
96 
97 
98 
99 /******************* stave state *******************/
100 
pia_scan(INT32 nAction,INT32 *)101 void pia_scan(INT32 nAction, INT32 *)
102 {
103 	for (INT32 i = 0; i < MAX_PIA; i++) {
104 		ScanVar(&pia[i], STRUCT_SIZE_HELPER(struct pia6821, in_set), "pia-6821 chip");
105 	}
106 }
107 
108 /******************* un-configuration *******************/
109 
pia_init(void)110 void pia_init(void) // was pia_unconfig
111 {
112 	memset(&pia, 0, sizeof(pia));
113 }
114 
pia_exit(void)115 void pia_exit(void)
116 {
117 	pia_init();
118 }
119 
120 /******************* configuration *******************/
121 
pia_config(int which,int addressing,const struct pia6821_interface * intf)122 void pia_config(int which, int addressing, const struct pia6821_interface *intf)
123 {
124 	if (which >= MAX_PIA) return;
125 	memset(&pia[which], 0, sizeof(pia[0]));
126 	if (!intf) return;
127 	pia[which].intf = intf;
128 	pia[which].addr = addressing;
129 	// set default read values.
130 	// Ports A,CA1,CA2 default to 1
131 	// Ports B,CB1,CB2 are three-state and undefined (set to 0)
132 	pia[which].in_a = pia[which].in_ca1 = pia[which].in_ca2 = 0xff;
133 }
134 
135 
136 /******************* reset *******************/
137 
pia_reset(void)138 void pia_reset(void)
139 {
140 	int i;
141 
142 	/* zap each structure, preserving the interface and swizzle */
143 	for (i = 0; i < MAX_PIA; i++) pia_config(i, pia[i].addr, pia[i].intf);
144 }
145 
146 
147 /******************* wire-OR for all interrupt handlers *******************/
148 
update_shared_irq_handler(void (* irq_func)(int state))149 static void update_shared_irq_handler(void (*irq_func)(int state))
150 {
151 	int i;
152 
153 	/* search all PIAs for this same IRQ function */
154 	for (i = 0; i < MAX_PIA; i++)
155 		if (pia[i].intf)
156 		{
157 			/* check IRQ A */
158 			if (pia[i].intf->irq_a_func == irq_func && pia[i].irq_a_state)
159 			{
160 				(*irq_func)(1);
161 				return;
162 			}
163 
164 			/* check IRQ B */
165 			if (pia[i].intf->irq_b_func == irq_func && pia[i].irq_b_state)
166 			{
167 				(*irq_func)(1);
168 				return;
169 			}
170 		}
171 
172 	/* if we found nothing, the state is off */
173 	(*irq_func)(0);
174 }
175 
176 
177 /******************* external interrupt check *******************/
178 
update_6821_interrupts(struct pia6821 * p)179 static void update_6821_interrupts(struct pia6821 *p)
180 {
181 	int new_state;
182 
183 	/* start with IRQ A */
184 	new_state = 0;
185 	if ((p->irq_a1 && IRQ1_ENABLED(p->ctl_a)) || (p->irq_a2 && IRQ2_ENABLED(p->ctl_a))) new_state = 1;
186 	if (new_state != p->irq_a_state)
187 	{
188 		p->irq_a_state = new_state;
189 		if (p->intf->irq_a_func) update_shared_irq_handler(p->intf->irq_a_func);
190 	}
191 
192 	/* then do IRQ B */
193 	new_state = 0;
194 	if ((p->irq_b1 && IRQ1_ENABLED(p->ctl_b)) || (p->irq_b2 && IRQ2_ENABLED(p->ctl_b))) new_state = 1;
195 	if (new_state != p->irq_b_state)
196 	{
197 		p->irq_b_state = new_state;
198 		if (p->intf->irq_b_func) update_shared_irq_handler(p->intf->irq_b_func);
199 	}
200 }
201 
202 
203 /******************* CPU interface for PIA read *******************/
204 
pia_read(int which,int offset)205 int pia_read(int which, int offset)
206 {
207 	struct pia6821 *p = pia + which;
208 	int val = 0;
209 
210 	/* adjust offset for 16-bit and ordering */
211 	offset &= 3;
212 	if (p->addr & PIA_ALTERNATE_ORDERING) offset = swizzle_address[offset];
213 
214 	switch (offset)
215 	{
216 		/******************* port A output/DDR read *******************/
217 		case PIA_DDRA:
218 
219 			/* read output register */
220 			if (OUTPUT_SELECTED(p->ctl_a))
221 			{
222 				/* update the input */
223 				if (p->intf->in_a_func)
224 					p->in_a = p->intf->in_a_func(0);
225 #ifdef MAME_DEBUG
226 				else if ((p->ddr_a ^ 0xff) && !(p->in_set & PIA_IN_SET_A)) {
227 					logerror("PIA%d: Warning! no port A read handler. Assuming pins %02x not connected\n",
228 					         which, p->ddr_a ^ 0xff);
229 					p->in_set |= PIA_IN_SET_A; // disable logging
230 				}
231 #endif // MAME_DEBUG
232 
233 				/* combine input and output values */
234 				val = (p->out_a & p->ddr_a) + (p->in_a & ~p->ddr_a);
235 
236 				/* IRQ flags implicitly cleared by a read */
237 				p->irq_a1 = p->irq_a2 = 0;
238 				update_6821_interrupts(p);
239 
240 				/* CA2 is configured as output and in read strobe mode */
241 				if (C2_OUTPUT(p->ctl_a) && C2_STROBE_MODE(p->ctl_a))
242 				{
243 					/* this will cause a transition low; call the output function if we're currently high */
244 					if (p->out_ca2)
245 						if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 0);
246 					p->out_ca2 = 0;
247 
248 					/* if the CA2 strobe is cleared by the E, reset it right away */
249 					if (STROBE_E_RESET(p->ctl_a))
250 					{
251 						if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 1);
252 						p->out_ca2 = 1;
253 					}
254 				}
255 
256 				LOG(("%04x: PIA%d read port A = %02X\n", activecpu_get_previouspc(),  which, val));
257 			}
258 
259 			/* read DDR register */
260 			else
261 			{
262 				val = p->ddr_a;
263 				LOG(("%04x: PIA%d read DDR A = %02X\n", activecpu_get_previouspc(), which, val));
264 			}
265 			break;
266 
267 		/******************* port B output/DDR read *******************/
268 		case PIA_DDRB:
269 
270 			/* read output register */
271 			if (OUTPUT_SELECTED(p->ctl_b))
272 			{
273 				/* update the input */
274 				if (p->intf->in_b_func)
275 					p->in_b = p->intf->in_b_func(0);
276 #ifdef MAME_DEBUG
277 				else if ((p->ddr_b ^ 0xff) && !(p->in_set & PIA_IN_SET_B)) {
278 					logerror("PIA%d: Error! no port B read handler. Three-state pins %02x are undefined\n",
279 					         which, p->ddr_b ^ 0xff);
280 					p->in_set |= PIA_IN_SET_B; // disable logging
281 				}
282 #endif // MAME_DEBUG
283 
284 				/* combine input and output values */
285 				val = (p->out_b & p->ddr_b) + (p->in_b & ~p->ddr_b);
286 
287 				/* This read will implicitly clear the IRQ B1 flag.  If CB2 is in write-strobe
288                    output mode with CB1 restore, and a CB1 active transition set the flag,
289                    clearing it will cause CB2 to go high again.  Note that this is different
290                    from what happens with port A. */
291 				if (p->irq_b1 && C2_OUTPUT(p->ctl_b) && C2_STROBE_MODE(p->ctl_b) && STROBE_C1_RESET(p->ctl_b))
292 				{
293 					/* call the CB2 output function */
294 					if (!p->out_cb2)
295 						if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 1);
296 
297 					/* clear CB2 */
298 					p->out_cb2 = 1;
299 				}
300 
301 				/* IRQ flags implicitly cleared by a read */
302 				p->irq_b1 = p->irq_b2 = 0;
303 				update_6821_interrupts(p);
304 
305 				LOG(("%04x: PIA%d read port B = %02X\n", activecpu_get_previouspc(), which, val));
306 			}
307 
308 			/* read DDR register */
309 			else
310 			{
311 				val = p->ddr_b;
312 				LOG(("%04x: PIA%d read DDR B = %02X\n", activecpu_get_previouspc(), which, val));
313 			}
314 			break;
315 
316 		/******************* port A control read *******************/
317 		case PIA_CTLA:
318 
319 			/* Update CA1 & CA2 if callback exists, these in turn may update IRQ's */
320 			if (p->intf->in_ca1_func)
321 				pia_set_input_ca1(which, p->intf->in_ca1_func(0));
322 #ifdef MAME_DEBUG
323 			else if (!(p->in_set & PIA_IN_SET_CA1)) {
324 				logerror("PIA%d: Warning! no CA1 read handler. Assuming pin not connected\n",which);
325 				p->in_set |= PIA_IN_SET_CA1; // disable logging
326 			}
327 #endif // MAME_DEBUG
328 			if (p->intf->in_ca2_func)
329 				pia_set_input_ca2(which, p->intf->in_ca2_func(0));
330 #ifdef MAME_DEBUG
331 			else if (C2_INPUT(p->ctl_a) && !(p->in_set & PIA_IN_SET_CA2)) {
332 				logerror("PIA%d: Warning! no CA2 read handler. Assuming pin not connected\n",which);
333 				p->in_set |= PIA_IN_SET_CA2; // disable logging
334 			}
335 #endif // MAME_DEBUG
336 
337 			/* read control register */
338 			val = p->ctl_a;
339 
340 			/* set the IRQ flags if we have pending IRQs */
341 			if (p->irq_a1) val |= PIA_IRQ1;
342 			if (p->irq_a2 && C2_INPUT(p->ctl_a)) val |= PIA_IRQ2;
343 
344 			LOG(("%04x: PIA%d read control A = %02X\n", activecpu_get_previouspc(), which, val));
345 			break;
346 
347 		/******************* port B control read *******************/
348 		case PIA_CTLB:
349 
350 			/* Update CB1 & CB2 if callback exists, these in turn may update IRQ's */
351 			if (p->intf->in_cb1_func)
352 				pia_set_input_cb1(which, p->intf->in_cb1_func(0));
353 #ifdef MAME_DEBUG
354 			else if (!(p->in_set & PIA_IN_SET_CB1)) {
355 				logerror("PIA%d: Error! no CB1 read handler. Three-state pin is undefined\n",which);
356 				p->in_set |= PIA_IN_SET_CB1; // disable logging
357 			}
358 #endif // MAME_DEBUG
359 			if (p->intf->in_cb2_func)
360 				pia_set_input_cb2(which, p->intf->in_cb2_func(0));
361 #ifdef MAME_DEBUG
362 			else if (C2_INPUT(p->ctl_b) && !(p->in_set & PIA_IN_SET_CB2)) {
363 				logerror("PIA%d: Error! no CB2 read handler. Three-state pin is undefined\n",which);
364 				p->in_set |= PIA_IN_SET_CB2; // disable logging
365 			}
366 #endif // MAME_DEBUG
367 
368 			/* read control register */
369 			val = p->ctl_b;
370 
371 			/* set the IRQ flags if we have pending IRQs */
372 			if (p->irq_b1) val |= PIA_IRQ1;
373 			if (p->irq_b2 && C2_INPUT(p->ctl_b)) val |= PIA_IRQ2;
374 
375 			LOG(("%04x: PIA%d read control B = %02X\n", activecpu_get_previouspc(), which, val));
376 			break;
377 	}
378 
379 	return val;
380 }
381 
382 
383 /******************* CPU interface for PIA write *******************/
384 
pia_write(int which,int offset,int data)385 void pia_write(int which, int offset, int data)
386 {
387 	struct pia6821 *p = pia + which;
388 
389 	/* adjust offset for 16-bit and ordering */
390 	offset &= 3;
391 	if (p->addr & PIA_ALTERNATE_ORDERING) offset = swizzle_address[offset];
392 
393 	switch (offset)
394 	{
395 		/******************* port A output/DDR write *******************/
396 		case PIA_DDRA:
397 
398 			/* write output register */
399 			if (OUTPUT_SELECTED(p->ctl_a))
400 			{
401 				LOG(("%04x: PIA%d port A write = %02X\n", activecpu_get_previouspc(), which, data));
402 
403 				/* update the output value */
404 				p->out_a = data;/* & p->ddr_a; */	/* NS990130 - don't mask now, DDR could change later */
405 
406 				/* send it to the output function */
407 				if (p->intf->out_a_func && p->ddr_a) p->intf->out_a_func(0, p->out_a & p->ddr_a);	/* NS990130 */
408 			}
409 
410 			/* write DDR register */
411 			else
412 			{
413 				LOG(("%04x: PIA%d DDR A write = %02X\n", activecpu_get_previouspc(), which, data));
414 
415 				if (p->ddr_a != data)
416 				{
417 					/* NS990130 - if DDR changed, call the callback again */
418 					p->ddr_a = data;
419 
420 					/* send it to the output function */
421 					if (p->intf->out_a_func && p->ddr_a) p->intf->out_a_func(0, p->out_a & p->ddr_a);
422 				}
423 			}
424 			break;
425 
426 		/******************* port B output/DDR write *******************/
427 		case PIA_DDRB:
428 
429 			/* write output register */
430 			if (OUTPUT_SELECTED(p->ctl_b))
431 			{
432 				LOG(("%04x: PIA%d port B write = %02X\n", activecpu_get_previouspc(), which, data));
433 
434 				/* update the output value */
435 				p->out_b = data;/* & p->ddr_b */	/* NS990130 - don't mask now, DDR could change later */
436 
437 				/* send it to the output function */
438 				if (p->intf->out_b_func && p->ddr_b) p->intf->out_b_func(0, p->out_b & p->ddr_b);	/* NS990130 */
439 
440 				/* CB2 is configured as output and in write strobe mode */
441 				if (C2_OUTPUT(p->ctl_b) && C2_STROBE_MODE(p->ctl_b))
442 				{
443 					/* this will cause a transition low; call the output function if we're currently high */
444 					if (p->out_cb2)
445 						if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 0);
446 					p->out_cb2 = 0;
447 
448 					/* if the CB2 strobe is cleared by the E, reset it right away */
449 					if (STROBE_E_RESET(p->ctl_b))
450 					{
451 						if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, 1);
452 						p->out_cb2 = 1;
453 					}
454 				}
455 			}
456 
457 			/* write DDR register */
458 			else
459 			{
460 				LOG(("%04x: PIA%d DDR B write = %02X\n", activecpu_get_previouspc(), which, data));
461 
462 				if (p->ddr_b != data)
463 				{
464 					/* NS990130 - if DDR changed, call the callback again */
465 					p->ddr_b = data;
466 
467 					/* send it to the output function */
468 					if (p->intf->out_b_func && p->ddr_b) p->intf->out_b_func(0, p->out_b & p->ddr_b);
469 				}
470 			}
471 			break;
472 
473 		/******************* port A control write *******************/
474 		case PIA_CTLA:
475 
476 			/* Bit 7 and 6 read only - PD 16/01/00 */
477 
478 			data &= 0x3f;
479 
480 
481 			LOG(("%04x: PIA%d control A write = %02X\n", activecpu_get_previouspc(), which, data));
482 
483 			/* CA2 is configured as output */
484 			if (C2_OUTPUT(data))
485 			{
486 				int temp;
487 
488 				if (C2_SET_MODE(data))
489 				{
490 					/* set/reset mode--bit value determines the new output */
491 					temp = SET_C2(data) ? 1 : 0;
492 				}
493 				else {
494 					/* strobe mode--output is always high unless strobed. */
495 					temp = 1;
496 				}
497 
498 				/* if we're going from input to output mode, or we're already in output mode
499                    and this change creates a transition, call the CA2 output function */
500 				if (C2_INPUT(p->ctl_a) || (C2_OUTPUT(p->ctl_a) && (p->out_ca2 ^ temp)))
501 					if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, temp);
502 
503 				/* set the new value */
504 				p->out_ca2 = temp;
505 			}
506 
507 			/* update the control register */
508 			p->ctl_a = data;
509 
510 			/* update externals */
511 			update_6821_interrupts(p);
512 			break;
513 
514 		/******************* port B control write *******************/
515 		case PIA_CTLB:
516 
517 			/* Bit 7 and 6 read only - PD 16/01/00 */
518 
519 			data &= 0x3f;
520 
521 			LOG(("%04x: PIA%d control B write = %02X\n", activecpu_get_previouspc(), which, data));
522 
523 			/* CB2 is configured as output */
524 			if (C2_OUTPUT(data))
525 			{
526 				int temp;
527 
528 				if (C2_SET_MODE(data))
529 				{
530 					/* set/reset mode--bit value determines the new output */
531 					temp = SET_C2(data) ? 1 : 0;
532 				}
533 				else {
534 					/* strobe mode--output is always high unless strobed. */
535 					temp = 1;
536 				}
537 
538 				/* if we're going from input to output mode, or we're already in output mode
539                    and this change creates a transition, call the CB2 output function */
540 				if (C2_INPUT(p->ctl_b) || (C2_OUTPUT(p->ctl_b) && (p->out_cb2 ^ temp)))
541 					if (p->intf->out_cb2_func) p->intf->out_cb2_func(0, temp);
542 
543 				/* set the new value */
544 				p->out_cb2 = temp;
545 			}
546 
547 			/* update the control register */
548 			p->ctl_b = data;
549 
550 			/* update externals */
551 			update_6821_interrupts(p);
552 			break;
553 	}
554 }
555 
556 
557 /******************* interface setting PIA port A input *******************/
558 
pia_set_input_a(int which,int data)559 void pia_set_input_a(int which, int data)
560 {
561 	struct pia6821 *p = pia + which;
562 
563 	/* set the input, what could be easier? */
564 	p->in_a = data;
565 	p->in_set |= PIA_IN_SET_A;
566 }
567 
568 
569 
570 /******************* interface setting PIA port CA1 input *******************/
571 
pia_set_input_ca1(int which,int data)572 void pia_set_input_ca1(int which, int data)
573 {
574 	struct pia6821 *p = pia + which;
575 
576 	/* limit the data to 0 or 1 */
577 	data = data ? 1 : 0;
578 
579 	/* the new state has caused a transition */
580 	if (p->in_ca1 ^ data)
581 	{
582 		/* handle the active transition */
583 		if ((data && C1_LOW_TO_HIGH(p->ctl_a)) || (!data && C1_HIGH_TO_LOW(p->ctl_a)))
584 		{
585 			/* mark the IRQ */
586 			p->irq_a1 = 1;
587 
588 			/* update externals */
589 			update_6821_interrupts(p);
590 
591 			/* CA2 is configured as output and in read strobe mode and cleared by a CA1 transition */
592 			if (C2_OUTPUT(p->ctl_a) && C2_STROBE_MODE(p->ctl_a) && STROBE_C1_RESET(p->ctl_a))
593 			{
594 				/* call the CA2 output function */
595 				if (!p->out_ca2)
596 					if (p->intf->out_ca2_func) p->intf->out_ca2_func(0, 1);
597 
598 				/* clear CA2 */
599 				p->out_ca2 = 1;
600 			}
601 		}
602 	}
603 
604 	/* set the new value for CA1 */
605 	p->in_ca1 = data;
606 	p->in_set |= PIA_IN_SET_CA1;
607 }
608 
609 
610 
611 /******************* interface setting PIA port CA2 input *******************/
612 
pia_set_input_ca2(int which,int data)613 void pia_set_input_ca2(int which, int data)
614 {
615 	struct pia6821 *p = pia + which;
616 
617 	/* limit the data to 0 or 1 */
618 	data = data ? 1 : 0;
619 
620 	/* CA2 is in input mode */
621 	if (C2_INPUT(p->ctl_a))
622 	{
623 		/* the new state has caused a transition */
624 		if (p->in_ca2 ^ data)
625 		{
626 			/* handle the active transition */
627 			if ((data && C2_LOW_TO_HIGH(p->ctl_a)) || (!data && C2_HIGH_TO_LOW(p->ctl_a)))
628 			{
629 				/* mark the IRQ */
630 				p->irq_a2 = 1;
631 
632 				/* update externals */
633 				update_6821_interrupts(p);
634 			}
635 		}
636 	}
637 
638 	/* set the new value for CA2 */
639 	p->in_ca2 = data;
640 	p->in_set |= PIA_IN_SET_CA2;
641 }
642 
643 
644 
645 /******************* interface setting PIA port B input *******************/
646 
pia_set_input_b(int which,int data)647 void pia_set_input_b(int which, int data)
648 {
649 	struct pia6821 *p = pia + which;
650 
651 	/* set the input, what could be easier? */
652 	p->in_b = data;
653     p->in_set |= PIA_IN_SET_B;
654 }
655 
656 
657 
658 /******************* interface setting PIA port CB1 input *******************/
659 
pia_set_input_cb1(int which,int data)660 void pia_set_input_cb1(int which, int data)
661 {
662 	struct pia6821 *p = pia + which;
663 
664 	/* limit the data to 0 or 1 */
665 	data = data ? 1 : 0;
666 
667 	/* the new state has caused a transition */
668 	if (p->in_cb1 ^ data)
669 	{
670 		/* handle the active transition */
671 		if ((data && C1_LOW_TO_HIGH(p->ctl_b)) || (!data && C1_HIGH_TO_LOW(p->ctl_b)))
672 		{
673 			/* mark the IRQ */
674 			p->irq_b1 = 1;
675 
676 			/* update externals */
677 			update_6821_interrupts(p);
678 
679 			/* If CB2 is configured as a write-strobe output which is reset by a CB1
680                transition, this reset will only happen when a read from port B implicitly
681                clears the IRQ B1 flag.  So we handle the CB2 reset there.  Note that this
682                is different from what happens with port A. */
683 		}
684 	}
685 
686 	/* set the new value for CB1 */
687 	p->in_cb1 = data;
688 	p->in_set |= PIA_IN_SET_CB1;
689 }
690 
691 
692 
693 /******************* interface setting PIA port CB2 input *******************/
694 
pia_set_input_cb2(int which,int data)695 void pia_set_input_cb2(int which, int data)
696 {
697 	struct pia6821 *p = pia + which;
698 
699 	/* limit the data to 0 or 1 */
700 	data = data ? 1 : 0;
701 
702 	/* CB2 is in input mode */
703 	if (C2_INPUT(p->ctl_b))
704 	{
705 		/* the new state has caused a transition */
706 		if (p->in_cb2 ^ data)
707 		{
708 			/* handle the active transition */
709 			if ((data && C2_LOW_TO_HIGH(p->ctl_b)) || (!data && C2_HIGH_TO_LOW(p->ctl_b)))
710 			{
711 				/* mark the IRQ */
712 				p->irq_b2 = 1;
713 
714 				/* update externals */
715 				update_6821_interrupts(p);
716 			}
717 		}
718 	}
719 
720 	/* set the new value for CA2 */
721 	p->in_cb2 = data;
722 	p->in_set |= PIA_IN_SET_CB2;
723 }
724 
725 
726 
727 /******************* interface retrieving DDR *******************/
728 
pia_get_ddr_a(int which)729 UINT8 pia_get_ddr_a(int which)
730 {
731 	struct pia6821 *p = pia + which;
732 	return p->ddr_a;
733 }
734 
735 
736 
pia_get_ddr_b(int which)737 UINT8 pia_get_ddr_b(int which)
738 {
739 	struct pia6821 *p = pia + which;
740 	return p->ddr_b;
741 }
742 
pia_get_irq_a_state(int which)743 UINT8 pia_get_irq_a_state(int which)
744 {
745 	struct pia6821 *p = pia + which;
746 	return p->irq_a_state;
747 }
748 
pia_get_irq_b_state(int which)749 UINT8 pia_get_irq_b_state(int which)
750 {
751 	struct pia6821 *p = pia + which;
752 	return p->irq_b_state;
753 }
754 
755 /******************* Interface retrieving port Data *************************/
756 
pia_read_porta(int which)757 UINT8 pia_read_porta(int which)
758 {
759 	return pia[which].in_a;
760 }
761 
pia_read_portb(int which)762 UINT8 pia_read_portb(int which)
763 {
764 	return pia[which].in_b;
765 }
766 
767 
768 #if 0
769 /******************* Standard 8-bit CPU interfaces, D0-D7 *******************/
770 
771 READ8_HANDLER( pia_0_r ) { return pia_read(0, offset); }
772 READ8_HANDLER( pia_1_r ) { return pia_read(1, offset); }
773 READ8_HANDLER( pia_2_r ) { return pia_read(2, offset); }
774 READ8_HANDLER( pia_3_r ) { return pia_read(3, offset); }
775 READ8_HANDLER( pia_4_r ) { return pia_read(4, offset); }
776 READ8_HANDLER( pia_5_r ) { return pia_read(5, offset); }
777 READ8_HANDLER( pia_6_r ) { return pia_read(6, offset); }
778 READ8_HANDLER( pia_7_r ) { return pia_read(7, offset); }
779 
780 WRITE8_HANDLER( pia_0_w ) { pia_write(0, offset, data); }
781 WRITE8_HANDLER( pia_1_w ) { pia_write(1, offset, data); }
782 WRITE8_HANDLER( pia_2_w ) { pia_write(2, offset, data); }
783 WRITE8_HANDLER( pia_3_w ) { pia_write(3, offset, data); }
784 WRITE8_HANDLER( pia_4_w ) { pia_write(4, offset, data); }
785 WRITE8_HANDLER( pia_5_w ) { pia_write(5, offset, data); }
786 WRITE8_HANDLER( pia_6_w ) { pia_write(6, offset, data); }
787 WRITE8_HANDLER( pia_7_w ) { pia_write(7, offset, data); }
788 
789 /******************* Standard 16-bit CPU interfaces, D0-D7 *******************/
790 
791 READ16_HANDLER( pia_0_lsb_r ) { return pia_read(0, offset); }
792 READ16_HANDLER( pia_1_lsb_r ) { return pia_read(1, offset); }
793 READ16_HANDLER( pia_2_lsb_r ) { return pia_read(2, offset); }
794 READ16_HANDLER( pia_3_lsb_r ) { return pia_read(3, offset); }
795 READ16_HANDLER( pia_4_lsb_r ) { return pia_read(4, offset); }
796 READ16_HANDLER( pia_5_lsb_r ) { return pia_read(5, offset); }
797 READ16_HANDLER( pia_6_lsb_r ) { return pia_read(6, offset); }
798 READ16_HANDLER( pia_7_lsb_r ) { return pia_read(7, offset); }
799 
800 WRITE16_HANDLER( pia_0_lsb_w ) { if (ACCESSING_LSB) pia_write(0, offset, data & 0xff); }
801 WRITE16_HANDLER( pia_1_lsb_w ) { if (ACCESSING_LSB) pia_write(1, offset, data & 0xff); }
802 WRITE16_HANDLER( pia_2_lsb_w ) { if (ACCESSING_LSB) pia_write(2, offset, data & 0xff); }
803 WRITE16_HANDLER( pia_3_lsb_w ) { if (ACCESSING_LSB) pia_write(3, offset, data & 0xff); }
804 WRITE16_HANDLER( pia_4_lsb_w ) { if (ACCESSING_LSB) pia_write(4, offset, data & 0xff); }
805 WRITE16_HANDLER( pia_5_lsb_w ) { if (ACCESSING_LSB) pia_write(5, offset, data & 0xff); }
806 WRITE16_HANDLER( pia_6_lsb_w ) { if (ACCESSING_LSB) pia_write(6, offset, data & 0xff); }
807 WRITE16_HANDLER( pia_7_lsb_w ) { if (ACCESSING_LSB) pia_write(7, offset, data & 0xff); }
808 
809 /******************* Standard 16-bit CPU interfaces, D8-D15 *******************/
810 
811 READ16_HANDLER( pia_0_msb_r ) { return pia_read(0, offset) << 8; }
812 READ16_HANDLER( pia_1_msb_r ) { return pia_read(1, offset) << 8; }
813 READ16_HANDLER( pia_2_msb_r ) { return pia_read(2, offset) << 8; }
814 READ16_HANDLER( pia_3_msb_r ) { return pia_read(3, offset) << 8; }
815 READ16_HANDLER( pia_4_msb_r ) { return pia_read(4, offset) << 8; }
816 READ16_HANDLER( pia_5_msb_r ) { return pia_read(5, offset) << 8; }
817 READ16_HANDLER( pia_6_msb_r ) { return pia_read(6, offset) << 8; }
818 READ16_HANDLER( pia_7_msb_r ) { return pia_read(7, offset) << 8; }
819 
820 WRITE16_HANDLER( pia_0_msb_w ) { if (ACCESSING_MSB) pia_write(0, offset, data >> 8); }
821 WRITE16_HANDLER( pia_1_msb_w ) { if (ACCESSING_MSB) pia_write(1, offset, data >> 8); }
822 WRITE16_HANDLER( pia_2_msb_w ) { if (ACCESSING_MSB) pia_write(2, offset, data >> 8); }
823 WRITE16_HANDLER( pia_3_msb_w ) { if (ACCESSING_MSB) pia_write(3, offset, data >> 8); }
824 WRITE16_HANDLER( pia_4_msb_w ) { if (ACCESSING_MSB) pia_write(4, offset, data >> 8); }
825 WRITE16_HANDLER( pia_5_msb_w ) { if (ACCESSING_MSB) pia_write(5, offset, data >> 8); }
826 WRITE16_HANDLER( pia_6_msb_w ) { if (ACCESSING_MSB) pia_write(6, offset, data >> 8); }
827 WRITE16_HANDLER( pia_7_msb_w ) { if (ACCESSING_MSB) pia_write(7, offset, data >> 8); }
828 
829 /******************* 8-bit A/B port interfaces *******************/
830 
831 WRITE8_HANDLER( pia_0_porta_w ) { pia_set_input_a(0, data); }
832 WRITE8_HANDLER( pia_1_porta_w ) { pia_set_input_a(1, data); }
833 WRITE8_HANDLER( pia_2_porta_w ) { pia_set_input_a(2, data); }
834 WRITE8_HANDLER( pia_3_porta_w ) { pia_set_input_a(3, data); }
835 WRITE8_HANDLER( pia_4_porta_w ) { pia_set_input_a(4, data); }
836 WRITE8_HANDLER( pia_5_porta_w ) { pia_set_input_a(5, data); }
837 WRITE8_HANDLER( pia_6_porta_w ) { pia_set_input_a(6, data); }
838 WRITE8_HANDLER( pia_7_porta_w ) { pia_set_input_a(7, data); }
839 
840 WRITE8_HANDLER( pia_0_portb_w ) { pia_set_input_b(0, data); }
841 WRITE8_HANDLER( pia_1_portb_w ) { pia_set_input_b(1, data); }
842 WRITE8_HANDLER( pia_2_portb_w ) { pia_set_input_b(2, data); }
843 WRITE8_HANDLER( pia_3_portb_w ) { pia_set_input_b(3, data); }
844 WRITE8_HANDLER( pia_4_portb_w ) { pia_set_input_b(4, data); }
845 WRITE8_HANDLER( pia_5_portb_w ) { pia_set_input_b(5, data); }
846 WRITE8_HANDLER( pia_6_portb_w ) { pia_set_input_b(6, data); }
847 WRITE8_HANDLER( pia_7_portb_w ) { pia_set_input_b(7, data); }
848 
849 READ8_HANDLER( pia_0_porta_r ) { return pia[0].in_a; }
850 READ8_HANDLER( pia_1_porta_r ) { return pia[1].in_a; }
851 READ8_HANDLER( pia_2_porta_r ) { return pia[2].in_a; }
852 READ8_HANDLER( pia_3_porta_r ) { return pia[3].in_a; }
853 READ8_HANDLER( pia_4_porta_r ) { return pia[4].in_a; }
854 READ8_HANDLER( pia_5_porta_r ) { return pia[5].in_a; }
855 READ8_HANDLER( pia_6_porta_r ) { return pia[6].in_a; }
856 READ8_HANDLER( pia_7_porta_r ) { return pia[7].in_a; }
857 
858 READ8_HANDLER( pia_0_portb_r ) { return pia[0].in_b; }
859 READ8_HANDLER( pia_1_portb_r ) { return pia[1].in_b; }
860 READ8_HANDLER( pia_2_portb_r ) { return pia[2].in_b; }
861 READ8_HANDLER( pia_3_portb_r ) { return pia[3].in_b; }
862 READ8_HANDLER( pia_4_portb_r ) { return pia[4].in_b; }
863 READ8_HANDLER( pia_5_portb_r ) { return pia[5].in_b; }
864 READ8_HANDLER( pia_6_portb_r ) { return pia[6].in_b; }
865 READ8_HANDLER( pia_7_portb_r ) { return pia[7].in_b; }
866 
867 /******************* 1-bit CA1/CA2/CB1/CB2 port interfaces *******************/
868 
869 WRITE8_HANDLER( pia_0_ca1_w ) { pia_set_input_ca1(0, data); }
870 WRITE8_HANDLER( pia_1_ca1_w ) { pia_set_input_ca1(1, data); }
871 WRITE8_HANDLER( pia_2_ca1_w ) { pia_set_input_ca1(2, data); }
872 WRITE8_HANDLER( pia_3_ca1_w ) { pia_set_input_ca1(3, data); }
873 WRITE8_HANDLER( pia_4_ca1_w ) { pia_set_input_ca1(4, data); }
874 WRITE8_HANDLER( pia_5_ca1_w ) { pia_set_input_ca1(5, data); }
875 WRITE8_HANDLER( pia_6_ca1_w ) { pia_set_input_ca1(6, data); }
876 WRITE8_HANDLER( pia_7_ca1_w ) { pia_set_input_ca1(7, data); }
877 WRITE8_HANDLER( pia_0_ca2_w ) { pia_set_input_ca2(0, data); }
878 WRITE8_HANDLER( pia_1_ca2_w ) { pia_set_input_ca2(1, data); }
879 WRITE8_HANDLER( pia_2_ca2_w ) { pia_set_input_ca2(2, data); }
880 WRITE8_HANDLER( pia_3_ca2_w ) { pia_set_input_ca2(3, data); }
881 WRITE8_HANDLER( pia_4_ca2_w ) { pia_set_input_ca2(4, data); }
882 WRITE8_HANDLER( pia_5_ca2_w ) { pia_set_input_ca2(5, data); }
883 WRITE8_HANDLER( pia_6_ca2_w ) { pia_set_input_ca2(6, data); }
884 WRITE8_HANDLER( pia_7_ca2_w ) { pia_set_input_ca2(7, data); }
885 
886 WRITE8_HANDLER( pia_0_cb1_w ) { pia_set_input_cb1(0, data); }
887 WRITE8_HANDLER( pia_1_cb1_w ) { pia_set_input_cb1(1, data); }
888 WRITE8_HANDLER( pia_2_cb1_w ) { pia_set_input_cb1(2, data); }
889 WRITE8_HANDLER( pia_3_cb1_w ) { pia_set_input_cb1(3, data); }
890 WRITE8_HANDLER( pia_4_cb1_w ) { pia_set_input_cb1(4, data); }
891 WRITE8_HANDLER( pia_5_cb1_w ) { pia_set_input_cb1(5, data); }
892 WRITE8_HANDLER( pia_6_cb1_w ) { pia_set_input_cb1(6, data); }
893 WRITE8_HANDLER( pia_7_cb1_w ) { pia_set_input_cb1(7, data); }
894 WRITE8_HANDLER( pia_0_cb2_w ) { pia_set_input_cb2(0, data); }
895 WRITE8_HANDLER( pia_1_cb2_w ) { pia_set_input_cb2(1, data); }
896 WRITE8_HANDLER( pia_2_cb2_w ) { pia_set_input_cb2(2, data); }
897 WRITE8_HANDLER( pia_3_cb2_w ) { pia_set_input_cb2(3, data); }
898 WRITE8_HANDLER( pia_4_cb2_w ) { pia_set_input_cb2(4, data); }
899 WRITE8_HANDLER( pia_5_cb2_w ) { pia_set_input_cb2(5, data); }
900 WRITE8_HANDLER( pia_6_cb2_w ) { pia_set_input_cb2(6, data); }
901 WRITE8_HANDLER( pia_7_cb2_w ) { pia_set_input_cb2(7, data); }
902 
903 READ8_HANDLER( pia_0_ca1_r ) { return pia[0].in_ca1; }
904 READ8_HANDLER( pia_1_ca1_r ) { return pia[1].in_ca1; }
905 READ8_HANDLER( pia_2_ca1_r ) { return pia[2].in_ca1; }
906 READ8_HANDLER( pia_3_ca1_r ) { return pia[3].in_ca1; }
907 READ8_HANDLER( pia_4_ca1_r ) { return pia[4].in_ca1; }
908 READ8_HANDLER( pia_5_ca1_r ) { return pia[5].in_ca1; }
909 READ8_HANDLER( pia_6_ca1_r ) { return pia[6].in_ca1; }
910 READ8_HANDLER( pia_7_ca1_r ) { return pia[7].in_ca1; }
911 READ8_HANDLER( pia_0_ca2_r ) { return pia[0].in_ca2; }
912 READ8_HANDLER( pia_1_ca2_r ) { return pia[1].in_ca2; }
913 READ8_HANDLER( pia_2_ca2_r ) { return pia[2].in_ca2; }
914 READ8_HANDLER( pia_3_ca2_r ) { return pia[3].in_ca2; }
915 READ8_HANDLER( pia_4_ca2_r ) { return pia[4].in_ca2; }
916 READ8_HANDLER( pia_5_ca2_r ) { return pia[5].in_ca2; }
917 READ8_HANDLER( pia_6_ca2_r ) { return pia[6].in_ca2; }
918 READ8_HANDLER( pia_7_ca2_r ) { return pia[7].in_ca2; }
919 
920 READ8_HANDLER( pia_0_cb1_r ) { return pia[0].in_cb1; }
921 READ8_HANDLER( pia_1_cb1_r ) { return pia[1].in_cb1; }
922 READ8_HANDLER( pia_2_cb1_r ) { return pia[2].in_cb1; }
923 READ8_HANDLER( pia_3_cb1_r ) { return pia[3].in_cb1; }
924 READ8_HANDLER( pia_4_cb1_r ) { return pia[4].in_cb1; }
925 READ8_HANDLER( pia_5_cb1_r ) { return pia[5].in_cb1; }
926 READ8_HANDLER( pia_6_cb1_r ) { return pia[6].in_cb1; }
927 READ8_HANDLER( pia_7_cb1_r ) { return pia[7].in_cb1; }
928 READ8_HANDLER( pia_0_cb2_r ) { return pia[0].in_cb2; }
929 READ8_HANDLER( pia_1_cb2_r ) { return pia[1].in_cb2; }
930 READ8_HANDLER( pia_2_cb2_r ) { return pia[2].in_cb2; }
931 READ8_HANDLER( pia_3_cb2_r ) { return pia[3].in_cb2; }
932 READ8_HANDLER( pia_4_cb2_r ) { return pia[4].in_cb2; }
933 READ8_HANDLER( pia_5_cb2_r ) { return pia[5].in_cb2; }
934 READ8_HANDLER( pia_6_cb2_r ) { return pia[6].in_cb2; }
935 READ8_HANDLER( pia_7_cb2_r ) { return pia[7].in_cb2; }
936 #endif
937