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
_siointr()35 _siointr()
36 {
37 register int unit;
38
39 for (unit = 0; unit < NSIO; unit++)
40 siointr(unit);
41 }
42
siointr(unit)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
siocngetc(dev)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
siocnputc(dev,c)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
sioinit()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
sioreg(reg,val)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