xref: /original-bsd/sys/luna68k/stand/sio.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * OMRON Corporation.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)sio.c	8.1 (Berkeley) 06/10/93
12  */
13 
14 /* sio.c   NOV-25-1991 */
15 
16 #define NSIO 2
17 
18 #include <sys/param.h>
19 #include <luna68k/stand/sioreg.h>
20 #include <luna68k/stand/rcvbuf.h>
21 #include <luna68k/stand/kbdreg.h>
22 
23 struct rcvbuf	rcvbuf[NSIO];
24 
25 int	sioconsole = -1;
26 struct	siodevice *sio_addr[2];
27 int	cur_unit;
28 
29 
30 #define	siounit(x)	( x & 0xffff )
31 #define isprint(c)      ((c >= 0x20) && (c < 0x7F) ? 1 : 0)
32 
33 
34 void
35 _siointr()
36 {
37 	register int unit;
38 
39 	for (unit = 0; unit < NSIO; unit++)
40 		siointr(unit);
41 }
42 
43 siointr(unit)
44 	register int unit;
45 {
46 	register struct	siodevice *sio = sio_addr[unit];
47 	register int rr0 = sioreg(REG(unit, RR0), 0);
48 	register int rr1 = sioreg(REG(unit, RR1), 0);
49 
50 	if (rr0 & RR0_RXAVAIL) {
51 		if (rr1 & RR1_FRAMING)
52 			return;
53 
54 		if (rr1 & (RR1_PARITY | RR1_OVERRUN))
55 		    sioreg(REG(unit, WR0), WR0_ERRRST); /* Channel-A Error Reset */
56 
57 		if (unit == 1) {
58 			register int c = kbd_decode(sio_addr[unit]->sio_data);
59 
60 			if ((c & KC_TYPE) == KC_CODE)
61 				PUSH_RBUF(unit, c);
62 		} else {
63 			PUSH_RBUF(unit, sio_addr[unit]->sio_data);
64 		}
65 	}
66 }
67 
68 /*
69  * Following are all routines needed for SIO to act as console
70  */
71 #include <luna68k/luna68k/cons.h>
72 #include "romvec.h"
73 
74 siocnprobe(cp)
75 	struct consdev *cp;
76 {
77 	sio_addr[0] = (struct siodevice *) 0x51000000;
78 	sio_addr[1] = (struct siodevice *) 0x51000004;
79 
80 	/* make sure hardware exists */
81 	if (badaddr((short *)sio_addr[0])) {
82 		cp->cn_pri = CN_DEAD;
83 		return;
84 	}
85 
86 	/* locate the major number */
87 
88 	/* initialize required fields */
89 	cp->cn_dev = cur_unit = 0;
90 	cp->cn_tp  = 0;
91 	cp->cn_pri = CN_NORMAL;
92 }
93 
94 siocninit(cp)
95 	struct consdev *cp;
96 {
97 	int unit = siounit(cp->cn_dev);
98 
99 	sioinit();
100 	sioconsole = unit;
101 }
102 
103 siocngetc(dev)
104 	dev_t dev;
105 {
106 	register int c, unit = siounit(dev);
107 
108 	while (RBUF_EMPTY(unit)) {
109 		DELAY(10);
110 	}
111 
112 	POP_RBUF(unit, c);
113 
114 	return(c);
115 }
116 
117 siocnputc(dev, c)
118 	dev_t dev;
119 	int c;
120 {
121 	int unit = siounit(dev);
122 	int s;
123 
124 	if (sioconsole == -1) {
125 		(void) sioinit();
126 		sioconsole = unit;
127 	}
128 
129 	s = splsio();
130 
131 	/* wait for any pending transmission to finish */
132 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
133 
134 	sio_addr[unit]->sio_data = (c & 0xFF);
135 
136 	/* wait for any pending transmission to finish */
137 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
138 
139 	splx(s);
140 }
141 
142 /* SIO misc routines */
143 
144 sioinit()
145 {
146 	int s;
147 
148 	RBUF_INIT(0);
149 	RBUF_INIT(1);
150 
151 	s = splsio();
152 
153 	sioreg(REG(0, WR0), WR0_CHANRST);		/* Channel-A Reset */
154 
155 	sioreg(WR2A, WR2_VEC86  | WR2_INTR_1);		/* Set CPU BUS Interface Mode */
156 	sioreg(WR2B, 0);				/* Set Interrupt Vector */
157 
158 	sioreg(REG(0, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
159 	sioreg(REG(0, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
160 	sioreg(REG(0, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
161 	sioreg(REG(0, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
162 	sioreg(REG(0, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
163 	sioreg(REG(0, WR1), WR1_RXALLS);		/* Interrupted All Char. */
164 
165 	sioreg(REG(1, WR0), WR0_CHANRST);		/* Channel-A Reset */
166 
167 	sioreg(REG(1, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
168 	sioreg(REG(1, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
169 	sioreg(REG(1, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
170 	sioreg(REG(1, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
171 	sioreg(REG(1, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
172 	sioreg(REG(1, WR1), WR1_RXALLS);		/* Interrupted All Char. */
173 
174 	splx(s);
175 }
176 
177 int
178 sioreg(reg, val)
179 	register int reg, val;
180 {
181 	register int chan;
182 
183 	chan = CHANNEL(reg);
184 
185 	if (isStatusReg(reg)) {
186 		if (REGNO(reg) != 0)
187 		    sio_addr[chan]->sio_cmd = REGNO(reg);
188 		return(sio_addr[chan]->sio_stat);
189 	} else {
190 		if (REGNO(reg) != 0)
191 		    sio_addr[chan]->sio_cmd = REGNO(reg);
192 		sio_addr[chan]->sio_cmd = val;
193 		return(val);
194 	}
195 }
196