xref: /csrg-svn/sys/luna68k/stand/sio.c (revision 57100)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * 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	7.1 (Berkeley) 12/13/92
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) == 0) {
61 				if (isprint(c))
62 					PUSH_RBUF(unit, c);
63 				else
64 					PUSH_RBUF(unit, ' ');
65 			}
66 		} else {
67 			PUSH_RBUF(unit, sio_addr[unit]->sio_data);
68 		}
69 	}
70 }
71 
72 /*
73  * Following are all routines needed for SIO to act as console
74  */
75 #include <luna68k/luna68k/cons.h>
76 #include "romvec.h"
77 
78 siocnprobe(cp)
79 	struct consdev *cp;
80 {
81 	sio_addr[0] = (struct siodevice *) 0x51000000;
82 	sio_addr[1] = (struct siodevice *) 0x51000004;
83 
84 	/* make sure hardware exists */
85 	if (badaddr((short *)sio_addr[0])) {
86 		cp->cn_pri = CN_DEAD;
87 		return;
88 	}
89 
90 	/* locate the major number */
91 
92 	/* initialize required fields */
93 	cp->cn_dev = cur_unit = 0;
94 	cp->cn_tp  = 0;
95 	cp->cn_pri = CN_NORMAL;
96 }
97 
98 siocninit(cp)
99 	struct consdev *cp;
100 {
101 	int unit = siounit(cp->cn_dev);
102 
103 	sioinit();
104 	sioconsole = unit;
105 }
106 
107 siocngetc(dev)
108 	dev_t dev;
109 {
110 	register int c, unit = siounit(dev);
111 
112 	while (RBUF_EMPTY(unit)) {
113 		DELAY(10);
114 	}
115 
116 	POP_RBUF(unit, c);
117 
118 	return(c);
119 }
120 
121 siocnputc(dev, c)
122 	dev_t dev;
123 	int c;
124 {
125 	int unit = siounit(dev);
126 	int s;
127 
128 	if (sioconsole == -1) {
129 		(void) sioinit();
130 		sioconsole = unit;
131 	}
132 
133 	s = splsio();
134 
135 	/* wait for any pending transmission to finish */
136 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
137 
138 	sio_addr[unit]->sio_data = (c & 0xFF);
139 
140 	/* wait for any pending transmission to finish */
141 	while ((sioreg(REG(unit, RR0), 0) & RR0_TXEMPTY) == 0);
142 
143 	splx(s);
144 }
145 
146 /* SIO misc routines */
147 
148 sioinit()
149 {
150 	int s;
151 
152 	RBUF_INIT(0);
153 	RBUF_INIT(1);
154 
155 	s = splsio();
156 
157 	sioreg(REG(0, WR0), WR0_CHANRST);		/* Channel-A Reset */
158 
159 	sioreg(WR2A, WR2_VEC86  | WR2_INTR_1);		/* Set CPU BUS Interface Mode */
160 	sioreg(WR2B, 0);				/* Set Interrupt Vector */
161 
162 	sioreg(REG(0, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
163 	sioreg(REG(0, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
164 	sioreg(REG(0, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
165 	sioreg(REG(0, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
166 	sioreg(REG(0, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
167 	sioreg(REG(0, WR1), WR1_RXALLS);		/* Interrupted All Char. */
168 
169 	sioreg(REG(1, WR0), WR0_CHANRST);		/* Channel-A Reset */
170 
171 	sioreg(REG(1, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
172 	sioreg(REG(1, WR4), WR4_BAUD96 | WR4_STOP1 | WR4_NPARITY);	/* Tx/Rx */
173 	sioreg(REG(1, WR3), WR3_RX8BIT | WR3_RXENBL);		/* Rx */
174 	sioreg(REG(1, WR5), WR5_TX8BIT | WR5_TXENBL);		/* Tx */
175 	sioreg(REG(1, WR0), WR0_RSTINT);		/* Reset E/S Interrupt */
176 	sioreg(REG(1, WR1), WR1_RXALLS);		/* Interrupted All Char. */
177 
178 	splx(s);
179 }
180 
181 int
182 sioreg(reg, val)
183 	register int reg, val;
184 {
185 	register int chan;
186 
187 	chan = CHANNEL(reg);
188 
189 	if (isStatusReg(reg)) {
190 		if (REGNO(reg) != 0)
191 		    sio_addr[chan]->sio_cmd = REGNO(reg);
192 		return(sio_addr[chan]->sio_stat);
193 	} else {
194 		if (REGNO(reg) != 0)
195 		    sio_addr[chan]->sio_cmd = REGNO(reg);
196 		sio_addr[chan]->sio_cmd = val;
197 		return(val);
198 	}
199 }
200