siotty.c revision 1.8.8.5 1 1.8.8.5 nathanw /* $NetBSD: siotty.c,v 1.8.8.5 2002/11/11 21:59:28 nathanw Exp $ */
2 1.8.8.2 nathanw
3 1.8.8.2 nathanw /*-
4 1.8.8.2 nathanw * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 1.8.8.2 nathanw * All rights reserved.
6 1.8.8.2 nathanw *
7 1.8.8.2 nathanw * This code is derived from software contributed to The NetBSD Foundation
8 1.8.8.2 nathanw * by Tohru Nishimura.
9 1.8.8.2 nathanw *
10 1.8.8.2 nathanw * Redistribution and use in source and binary forms, with or without
11 1.8.8.2 nathanw * modification, are permitted provided that the following conditions
12 1.8.8.2 nathanw * are met:
13 1.8.8.2 nathanw * 1. Redistributions of source code must retain the above copyright
14 1.8.8.2 nathanw * notice, this list of conditions and the following disclaimer.
15 1.8.8.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
16 1.8.8.2 nathanw * notice, this list of conditions and the following disclaimer in the
17 1.8.8.2 nathanw * documentation and/or other materials provided with the distribution.
18 1.8.8.2 nathanw * 3. All advertising materials mentioning features or use of this software
19 1.8.8.2 nathanw * must display the following acknowledgement:
20 1.8.8.2 nathanw * This product includes software developed by the NetBSD
21 1.8.8.2 nathanw * Foundation, Inc. and its contributors.
22 1.8.8.2 nathanw * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.8.8.2 nathanw * contributors may be used to endorse or promote products derived
24 1.8.8.2 nathanw * from this software without specific prior written permission.
25 1.8.8.2 nathanw *
26 1.8.8.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.8.8.2 nathanw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.8.8.2 nathanw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.8.8.2 nathanw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.8.8.2 nathanw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.8.8.2 nathanw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.8.8.2 nathanw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.8.8.2 nathanw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.8.8.2 nathanw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.8.8.2 nathanw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.8.8.2 nathanw * POSSIBILITY OF SUCH DAMAGE.
37 1.8.8.2 nathanw */
38 1.8.8.2 nathanw
39 1.8.8.2 nathanw #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
40 1.8.8.2 nathanw
41 1.8.8.5 nathanw __KERNEL_RCSID(0, "$NetBSD: siotty.c,v 1.8.8.5 2002/11/11 21:59:28 nathanw Exp $");
42 1.8.8.2 nathanw
43 1.8.8.2 nathanw #include "opt_ddb.h"
44 1.8.8.2 nathanw
45 1.8.8.2 nathanw #include <sys/param.h>
46 1.8.8.2 nathanw #include <sys/systm.h>
47 1.8.8.2 nathanw #include <sys/device.h>
48 1.8.8.2 nathanw #include <sys/conf.h>
49 1.8.8.2 nathanw #include <sys/ioctl.h>
50 1.8.8.2 nathanw #include <sys/proc.h>
51 1.8.8.2 nathanw #include <sys/user.h>
52 1.8.8.2 nathanw #include <sys/tty.h>
53 1.8.8.2 nathanw #include <sys/uio.h>
54 1.8.8.2 nathanw #include <sys/callout.h>
55 1.8.8.2 nathanw #include <sys/fcntl.h>
56 1.8.8.2 nathanw #include <dev/cons.h>
57 1.8.8.2 nathanw
58 1.8.8.2 nathanw #include <machine/cpu.h>
59 1.8.8.2 nathanw
60 1.8.8.2 nathanw #include <luna68k/dev/sioreg.h>
61 1.8.8.2 nathanw #include <luna68k/dev/siovar.h>
62 1.8.8.2 nathanw
63 1.8.8.2 nathanw #define TIOCM_BREAK 01000 /* non standard use */
64 1.8.8.2 nathanw
65 1.8.8.2 nathanw static const u_int8_t ch0_regs[6] = {
66 1.8.8.2 nathanw WR0_RSTINT, /* reset E/S interrupt */
67 1.8.8.2 nathanw WR1_RXALLS | WR1_TXENBL, /* Rx per char, Tx */
68 1.8.8.2 nathanw 0, /* */
69 1.8.8.2 nathanw WR3_RX8BIT | WR3_RXENBL, /* Rx */
70 1.8.8.2 nathanw WR4_BAUD96 | WR4_STOP1, /* Tx/Rx */
71 1.8.8.2 nathanw WR5_TX8BIT | WR5_TXENBL | WR5_DTR | WR5_RTS, /* Tx */
72 1.8.8.2 nathanw };
73 1.8.8.2 nathanw
74 1.8.8.2 nathanw static struct speedtab siospeedtab[] = {
75 1.8.8.2 nathanw { 2400, WR4_BAUD24, },
76 1.8.8.2 nathanw { 4800, WR4_BAUD48, },
77 1.8.8.2 nathanw { 9600, WR4_BAUD96, },
78 1.8.8.2 nathanw { -1, 0, },
79 1.8.8.2 nathanw };
80 1.8.8.2 nathanw
81 1.8.8.2 nathanw struct siotty_softc {
82 1.8.8.2 nathanw struct device sc_dev;
83 1.8.8.2 nathanw struct tty *sc_tty;
84 1.8.8.2 nathanw struct sioreg *sc_ctl;
85 1.8.8.2 nathanw u_int sc_flags;
86 1.8.8.2 nathanw u_int8_t sc_wr[6];
87 1.8.8.2 nathanw };
88 1.8.8.2 nathanw
89 1.8.8.2 nathanw #include "siotty.h"
90 1.8.8.2 nathanw static void siostart __P((struct tty *));
91 1.8.8.2 nathanw static int sioparam __P((struct tty *, struct termios *));
92 1.8.8.2 nathanw static void siottyintr __P((int));
93 1.8.8.2 nathanw static int siomctl __P((struct siotty_softc *, int, int));
94 1.8.8.2 nathanw
95 1.8.8.2 nathanw static int siotty_match __P((struct device *, struct cfdata *, void *));
96 1.8.8.2 nathanw static void siotty_attach __P((struct device *, struct device *, void *));
97 1.8.8.2 nathanw
98 1.8.8.4 nathanw CFATTACH_DECL(siotty, sizeof(struct siotty_softc),
99 1.8.8.4 nathanw siotty_match, siotty_attach, NULL, NULL);
100 1.8.8.2 nathanw extern struct cfdriver siotty_cd;
101 1.8.8.2 nathanw
102 1.8.8.3 nathanw dev_type_open(sioopen);
103 1.8.8.3 nathanw dev_type_close(sioclose);
104 1.8.8.3 nathanw dev_type_read(sioread);
105 1.8.8.3 nathanw dev_type_write(siowrite);
106 1.8.8.3 nathanw dev_type_ioctl(sioioctl);
107 1.8.8.3 nathanw dev_type_stop(siostop);
108 1.8.8.3 nathanw dev_type_tty(siotty);
109 1.8.8.3 nathanw dev_type_poll(siopoll);
110 1.8.8.3 nathanw
111 1.8.8.3 nathanw const struct cdevsw siotty_cdevsw = {
112 1.8.8.3 nathanw sioopen, sioclose, sioread, siowrite, sioioctl,
113 1.8.8.5 nathanw siostop, siotty, siopoll, nommap, ttykqfilter, D_TTY
114 1.8.8.3 nathanw };
115 1.8.8.3 nathanw
116 1.8.8.2 nathanw static int
117 1.8.8.2 nathanw siotty_match(parent, cf, aux)
118 1.8.8.2 nathanw struct device *parent;
119 1.8.8.2 nathanw struct cfdata *cf;
120 1.8.8.2 nathanw void *aux;
121 1.8.8.2 nathanw {
122 1.8.8.2 nathanw struct sio_attach_args *args = aux;
123 1.8.8.2 nathanw
124 1.8.8.2 nathanw if (args->channel != 0) /* XXX allow tty on Ch.B XXX */
125 1.8.8.2 nathanw return 0;
126 1.8.8.2 nathanw return 1;
127 1.8.8.2 nathanw }
128 1.8.8.2 nathanw
129 1.8.8.2 nathanw static void
130 1.8.8.2 nathanw siotty_attach(parent, self, aux)
131 1.8.8.2 nathanw struct device *parent, *self;
132 1.8.8.2 nathanw void *aux;
133 1.8.8.2 nathanw {
134 1.8.8.2 nathanw struct sio_softc *scp = (void *)parent;
135 1.8.8.2 nathanw struct siotty_softc *sc = (void *)self;
136 1.8.8.2 nathanw struct sio_attach_args *args = aux;
137 1.8.8.2 nathanw
138 1.8.8.2 nathanw sc->sc_ctl = (struct sioreg *)scp->scp_ctl + args->channel;
139 1.8.8.2 nathanw bcopy(ch0_regs, sc->sc_wr, sizeof(ch0_regs));
140 1.8.8.2 nathanw scp->scp_intr[args->channel] = siottyintr;
141 1.8.8.2 nathanw
142 1.8.8.2 nathanw if (args->hwflags == 1) {
143 1.8.8.2 nathanw printf(" (console)");
144 1.8.8.2 nathanw sc->sc_flags = TIOCFLAG_SOFTCAR;
145 1.8.8.2 nathanw }
146 1.8.8.2 nathanw else {
147 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR0, WR0_CHANRST);
148 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR2A, WR2_VEC86 | WR2_INTR_1);
149 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR2B, 0);
150 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
151 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
152 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
153 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
154 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR0, sc->sc_wr[WR0]);
155 1.8.8.2 nathanw }
156 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR1, sc->sc_wr[WR1]); /* now interrupt driven */
157 1.8.8.2 nathanw
158 1.8.8.2 nathanw printf("\n");
159 1.8.8.2 nathanw }
160 1.8.8.2 nathanw
161 1.8.8.2 nathanw /*-------------------- low level routine --------------------*/
162 1.8.8.2 nathanw
163 1.8.8.2 nathanw static void
164 1.8.8.2 nathanw siottyintr(chan)
165 1.8.8.2 nathanw int chan;
166 1.8.8.2 nathanw {
167 1.8.8.2 nathanw struct siotty_softc *sc;
168 1.8.8.2 nathanw struct sioreg *sio;
169 1.8.8.2 nathanw struct tty *tp;
170 1.8.8.2 nathanw unsigned int code;
171 1.8.8.2 nathanw int rr;
172 1.8.8.2 nathanw
173 1.8.8.2 nathanw if (chan >= siotty_cd.cd_ndevs)
174 1.8.8.2 nathanw return;
175 1.8.8.2 nathanw sc = siotty_cd.cd_devs[chan];
176 1.8.8.2 nathanw tp = sc->sc_tty;
177 1.8.8.2 nathanw sio = sc->sc_ctl;
178 1.8.8.2 nathanw rr = getsiocsr(sio);
179 1.8.8.2 nathanw if (rr & RR_RXRDY) {
180 1.8.8.2 nathanw do {
181 1.8.8.2 nathanw code = sio->sio_data;
182 1.8.8.2 nathanw if (rr & (RR_FRAMING | RR_OVERRUN | RR_PARITY)) {
183 1.8.8.2 nathanw sio->sio_cmd = WR0_ERRRST;
184 1.8.8.2 nathanw if (sio->sio_stat & RR_FRAMING)
185 1.8.8.2 nathanw code |= TTY_FE;
186 1.8.8.2 nathanw else if (sio->sio_stat & RR_PARITY)
187 1.8.8.2 nathanw code |= TTY_PE;
188 1.8.8.2 nathanw }
189 1.8.8.2 nathanw if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
190 1.8.8.2 nathanw continue;
191 1.8.8.2 nathanw #if 0 && defined(DDB) /* ?!?! fails to resume ?!?! */
192 1.8.8.2 nathanw if ((rr & RR_BREAK) && tp->t_dev == cn_tab->cn_dev) {
193 1.8.8.2 nathanw cpu_Debugger();
194 1.8.8.2 nathanw return;
195 1.8.8.2 nathanw }
196 1.8.8.2 nathanw #endif
197 1.8.8.2 nathanw (*tp->t_linesw->l_rint)(code, tp);
198 1.8.8.2 nathanw } while ((rr = getsiocsr(sio)) & RR_RXRDY);
199 1.8.8.2 nathanw }
200 1.8.8.2 nathanw if (rr & RR_TXRDY) {
201 1.8.8.2 nathanw sio->sio_cmd = WR0_RSTPEND;
202 1.8.8.2 nathanw if (tp != NULL) {
203 1.8.8.2 nathanw tp->t_state &= ~(TS_BUSY|TS_FLUSH);
204 1.8.8.2 nathanw (*tp->t_linesw->l_start)(tp);
205 1.8.8.2 nathanw }
206 1.8.8.2 nathanw }
207 1.8.8.2 nathanw }
208 1.8.8.2 nathanw
209 1.8.8.2 nathanw static void
210 1.8.8.2 nathanw siostart(tp)
211 1.8.8.2 nathanw struct tty *tp;
212 1.8.8.2 nathanw {
213 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
214 1.8.8.2 nathanw int s, c;
215 1.8.8.2 nathanw
216 1.8.8.2 nathanw s = spltty();
217 1.8.8.2 nathanw if (tp->t_state & (TS_BUSY|TS_TIMEOUT|TS_TTSTOP))
218 1.8.8.2 nathanw goto out;
219 1.8.8.2 nathanw if (tp->t_outq.c_cc <= tp->t_lowat) {
220 1.8.8.2 nathanw if (tp->t_state & TS_ASLEEP) {
221 1.8.8.2 nathanw tp->t_state &= ~TS_ASLEEP;
222 1.8.8.2 nathanw wakeup((caddr_t)&tp->t_outq);
223 1.8.8.2 nathanw }
224 1.8.8.2 nathanw selwakeup(&tp->t_wsel);
225 1.8.8.2 nathanw }
226 1.8.8.2 nathanw if (tp->t_outq.c_cc == 0)
227 1.8.8.2 nathanw goto out;
228 1.8.8.2 nathanw
229 1.8.8.2 nathanw tp->t_state |= TS_BUSY;
230 1.8.8.2 nathanw while (getsiocsr(sc->sc_ctl) & RR_TXRDY) {
231 1.8.8.2 nathanw if ((c = getc(&tp->t_outq)) == -1)
232 1.8.8.2 nathanw break;
233 1.8.8.2 nathanw sc->sc_ctl->sio_data = c;
234 1.8.8.2 nathanw }
235 1.8.8.2 nathanw out:
236 1.8.8.2 nathanw splx(s);
237 1.8.8.2 nathanw }
238 1.8.8.2 nathanw
239 1.8.8.2 nathanw void
240 1.8.8.2 nathanw siostop(tp, flag)
241 1.8.8.2 nathanw struct tty *tp;
242 1.8.8.2 nathanw int flag;
243 1.8.8.2 nathanw {
244 1.8.8.2 nathanw int s;
245 1.8.8.2 nathanw
246 1.8.8.2 nathanw s = spltty();
247 1.8.8.2 nathanw if (TS_BUSY == (tp->t_state & (TS_BUSY|TS_TTSTOP))) {
248 1.8.8.2 nathanw /*
249 1.8.8.2 nathanw * Device is transmitting; must stop it.
250 1.8.8.2 nathanw */
251 1.8.8.2 nathanw tp->t_state |= TS_FLUSH;
252 1.8.8.2 nathanw }
253 1.8.8.2 nathanw splx(s);
254 1.8.8.2 nathanw }
255 1.8.8.2 nathanw
256 1.8.8.2 nathanw static int
257 1.8.8.2 nathanw sioparam(tp, t)
258 1.8.8.2 nathanw struct tty *tp;
259 1.8.8.2 nathanw struct termios *t;
260 1.8.8.2 nathanw {
261 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(tp->t_dev)];
262 1.8.8.2 nathanw int wr4, s;
263 1.8.8.2 nathanw
264 1.8.8.2 nathanw if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
265 1.8.8.2 nathanw return EINVAL;
266 1.8.8.2 nathanw wr4 = ttspeedtab(t->c_ospeed, siospeedtab);
267 1.8.8.2 nathanw if (wr4 < 0)
268 1.8.8.2 nathanw return EINVAL;
269 1.8.8.2 nathanw
270 1.8.8.2 nathanw if (sc->sc_flags & TIOCFLAG_SOFTCAR) {
271 1.8.8.2 nathanw t->c_cflag |= CLOCAL;
272 1.8.8.2 nathanw t->c_cflag &= ~HUPCL;
273 1.8.8.2 nathanw }
274 1.8.8.2 nathanw if (sc->sc_flags & TIOCFLAG_CLOCAL)
275 1.8.8.2 nathanw t->c_cflag |= CLOCAL;
276 1.8.8.2 nathanw
277 1.8.8.2 nathanw /*
278 1.8.8.2 nathanw * If there were no changes, don't do anything. This avoids dropping
279 1.8.8.2 nathanw * input and improves performance when all we did was frob things like
280 1.8.8.2 nathanw * VMIN and VTIME.
281 1.8.8.2 nathanw */
282 1.8.8.2 nathanw if (tp->t_ospeed == t->c_ospeed && tp->t_cflag == t->c_cflag)
283 1.8.8.2 nathanw return 0;
284 1.8.8.2 nathanw
285 1.8.8.2 nathanw tp->t_ispeed = t->c_ispeed;
286 1.8.8.2 nathanw tp->t_ospeed = t->c_ospeed;
287 1.8.8.2 nathanw tp->t_cflag = t->c_cflag;
288 1.8.8.2 nathanw
289 1.8.8.2 nathanw sc->sc_wr[WR3] &= 0x3f;
290 1.8.8.2 nathanw sc->sc_wr[WR5] &= 0x9f;
291 1.8.8.2 nathanw switch (tp->t_cflag & CSIZE) {
292 1.8.8.2 nathanw case CS7:
293 1.8.8.2 nathanw sc->sc_wr[WR3] |= WR3_RX7BIT; sc->sc_wr[WR5] |= WR5_TX7BIT;
294 1.8.8.2 nathanw break;
295 1.8.8.2 nathanw case CS8:
296 1.8.8.2 nathanw sc->sc_wr[WR3] |= WR3_RX8BIT; sc->sc_wr[WR5] |= WR5_TX8BIT;
297 1.8.8.2 nathanw break;
298 1.8.8.2 nathanw }
299 1.8.8.2 nathanw if (tp->t_cflag & PARENB) {
300 1.8.8.2 nathanw wr4 |= WR4_PARENAB;
301 1.8.8.2 nathanw if ((tp->t_cflag & PARODD) == 0)
302 1.8.8.2 nathanw wr4 |= WR4_EPARITY;
303 1.8.8.2 nathanw }
304 1.8.8.2 nathanw wr4 |= (tp->t_cflag & CSTOPB) ? WR4_STOP2 : WR4_STOP1;
305 1.8.8.2 nathanw sc->sc_wr[WR4] = wr4;
306 1.8.8.2 nathanw
307 1.8.8.2 nathanw s = spltty();
308 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR4, sc->sc_wr[WR4]);
309 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR3, sc->sc_wr[WR3]);
310 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR5, sc->sc_wr[WR5]);
311 1.8.8.2 nathanw splx(s);
312 1.8.8.2 nathanw
313 1.8.8.2 nathanw return 0;
314 1.8.8.2 nathanw }
315 1.8.8.2 nathanw
316 1.8.8.2 nathanw static int
317 1.8.8.2 nathanw siomctl(sc, control, op)
318 1.8.8.2 nathanw struct siotty_softc *sc;
319 1.8.8.2 nathanw int control, op;
320 1.8.8.2 nathanw {
321 1.8.8.2 nathanw int val, s, wr5, rr;
322 1.8.8.2 nathanw
323 1.8.8.2 nathanw val = 0;
324 1.8.8.2 nathanw if (control & TIOCM_BREAK)
325 1.8.8.2 nathanw val |= WR5_BREAK;
326 1.8.8.2 nathanw if (control & TIOCM_DTR)
327 1.8.8.2 nathanw val |= WR5_DTR;
328 1.8.8.2 nathanw if (control & TIOCM_RTS)
329 1.8.8.2 nathanw val |= WR5_RTS;
330 1.8.8.2 nathanw s = spltty();
331 1.8.8.2 nathanw wr5 = sc->sc_wr[WR5];
332 1.8.8.2 nathanw switch (op) {
333 1.8.8.2 nathanw case DMSET:
334 1.8.8.2 nathanw wr5 &= ~(WR5_BREAK|WR5_DTR|WR5_RTS);
335 1.8.8.2 nathanw /* FALLTHRU */
336 1.8.8.2 nathanw case DMBIS:
337 1.8.8.2 nathanw wr5 |= val;
338 1.8.8.2 nathanw break;
339 1.8.8.2 nathanw case DMBIC:
340 1.8.8.2 nathanw wr5 &= ~val;
341 1.8.8.2 nathanw break;
342 1.8.8.2 nathanw case DMGET:
343 1.8.8.2 nathanw val = 0;
344 1.8.8.2 nathanw rr = getsiocsr(sc->sc_ctl);
345 1.8.8.2 nathanw if (wr5 & WR5_DTR)
346 1.8.8.2 nathanw val |= TIOCM_DTR;
347 1.8.8.2 nathanw if (wr5 & WR5_RTS)
348 1.8.8.2 nathanw val |= TIOCM_RTS;
349 1.8.8.2 nathanw if (rr & RR_CTS)
350 1.8.8.2 nathanw val |= TIOCM_CTS;
351 1.8.8.2 nathanw if (rr & RR_DCD)
352 1.8.8.2 nathanw val |= TIOCM_CD;
353 1.8.8.2 nathanw goto done;
354 1.8.8.2 nathanw }
355 1.8.8.2 nathanw sc->sc_wr[WR5] = wr5;
356 1.8.8.2 nathanw setsioreg(sc->sc_ctl, WR5, wr5);
357 1.8.8.2 nathanw val = 0;
358 1.8.8.2 nathanw done:
359 1.8.8.2 nathanw splx(s);
360 1.8.8.2 nathanw return val;
361 1.8.8.2 nathanw }
362 1.8.8.2 nathanw
363 1.8.8.2 nathanw /*-------------------- cdevsw[] interface --------------------*/
364 1.8.8.2 nathanw
365 1.8.8.2 nathanw int
366 1.8.8.2 nathanw sioopen(dev, flag, mode, p)
367 1.8.8.2 nathanw dev_t dev;
368 1.8.8.2 nathanw int flag, mode;
369 1.8.8.2 nathanw struct proc *p;
370 1.8.8.2 nathanw {
371 1.8.8.2 nathanw struct siotty_softc *sc;
372 1.8.8.2 nathanw struct tty *tp;
373 1.8.8.2 nathanw int error;
374 1.8.8.2 nathanw
375 1.8.8.2 nathanw if ((sc = siotty_cd.cd_devs[minor(dev)]) == NULL)
376 1.8.8.2 nathanw return ENXIO;
377 1.8.8.2 nathanw if ((tp = sc->sc_tty) == NULL) {
378 1.8.8.2 nathanw tp = sc->sc_tty = ttymalloc();
379 1.8.8.2 nathanw tty_attach(tp);
380 1.8.8.2 nathanw }
381 1.8.8.2 nathanw else if ((tp->t_state & TS_ISOPEN) && (tp->t_state & TS_XCLUDE)
382 1.8.8.2 nathanw && p->p_ucred->cr_uid != 0)
383 1.8.8.2 nathanw return EBUSY;
384 1.8.8.2 nathanw
385 1.8.8.2 nathanw tp->t_oproc = siostart;
386 1.8.8.2 nathanw tp->t_param = sioparam;
387 1.8.8.2 nathanw tp->t_hwiflow = NULL /* XXX siohwiflow XXX */;
388 1.8.8.2 nathanw tp->t_dev = dev;
389 1.8.8.2 nathanw if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
390 1.8.8.2 nathanw struct termios t;
391 1.8.8.2 nathanw
392 1.8.8.2 nathanw t.c_ispeed = t.c_ospeed = TTYDEF_SPEED;
393 1.8.8.2 nathanw t.c_cflag = TTYDEF_CFLAG;
394 1.8.8.2 nathanw tp->t_ospeed = 0; /* force register update */
395 1.8.8.2 nathanw (void)sioparam(tp, &t);
396 1.8.8.2 nathanw tp->t_iflag = TTYDEF_IFLAG;
397 1.8.8.2 nathanw tp->t_oflag = TTYDEF_OFLAG;
398 1.8.8.2 nathanw tp->t_lflag = TTYDEF_LFLAG;
399 1.8.8.2 nathanw ttychars(tp);
400 1.8.8.2 nathanw ttsetwater(tp);
401 1.8.8.2 nathanw /* raise RTS and DTR here; but, DTR lead is not wired */
402 1.8.8.2 nathanw /* then check DCD condition; but, DCD lead is not wired */
403 1.8.8.2 nathanw tp->t_state |= TS_CARR_ON; /* assume detected all the time */
404 1.8.8.2 nathanw #if 0
405 1.8.8.2 nathanw if ((sc->sc_flags & TIOCFLAG_SOFTCAR)
406 1.8.8.2 nathanw || (tp->t_cflag & MDMBUF)
407 1.8.8.2 nathanw || (getsiocsr(sc->sc_ctl) & RR_DCD))
408 1.8.8.2 nathanw tp->t_state |= TS_CARR_ON;
409 1.8.8.2 nathanw else
410 1.8.8.2 nathanw tp->t_state &= ~TS_CARR_ON;
411 1.8.8.2 nathanw #endif
412 1.8.8.2 nathanw }
413 1.8.8.2 nathanw
414 1.8.8.2 nathanw error = ttyopen(tp, 0, (flag & O_NONBLOCK));
415 1.8.8.2 nathanw if (error > 0)
416 1.8.8.2 nathanw return error;
417 1.8.8.2 nathanw return (*tp->t_linesw->l_open)(dev, tp);
418 1.8.8.2 nathanw }
419 1.8.8.2 nathanw
420 1.8.8.2 nathanw int
421 1.8.8.2 nathanw sioclose(dev, flag, mode, p)
422 1.8.8.2 nathanw dev_t dev;
423 1.8.8.2 nathanw int flag, mode;
424 1.8.8.2 nathanw struct proc *p;
425 1.8.8.2 nathanw {
426 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
427 1.8.8.2 nathanw struct tty *tp = sc->sc_tty;
428 1.8.8.2 nathanw int s;
429 1.8.8.2 nathanw
430 1.8.8.2 nathanw (*tp->t_linesw->l_close)(tp, flag);
431 1.8.8.2 nathanw
432 1.8.8.2 nathanw s = spltty();
433 1.8.8.2 nathanw siomctl(sc, TIOCM_BREAK, DMBIC);
434 1.8.8.2 nathanw #if 0 /* because unable to feed DTR signal */
435 1.8.8.2 nathanw if ((tp->t_cflag & HUPCL)
436 1.8.8.2 nathanw || tp->t_wopen || (tp->t_state & TS_ISOPEN) == 0) {
437 1.8.8.2 nathanw siomctl(sc, TIOCM_DTR, DMBIC);
438 1.8.8.2 nathanw /* Yield CPU time to others for 1 second, then ... */
439 1.8.8.2 nathanw siomctl(sc, TIOCM_DTR, DMBIS);
440 1.8.8.2 nathanw }
441 1.8.8.2 nathanw #endif
442 1.8.8.2 nathanw splx(s);
443 1.8.8.2 nathanw return ttyclose(tp);
444 1.8.8.2 nathanw }
445 1.8.8.2 nathanw
446 1.8.8.2 nathanw int
447 1.8.8.2 nathanw sioread(dev, uio, flag)
448 1.8.8.2 nathanw dev_t dev;
449 1.8.8.2 nathanw struct uio *uio;
450 1.8.8.2 nathanw int flag;
451 1.8.8.2 nathanw {
452 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
453 1.8.8.2 nathanw struct tty *tp = sc->sc_tty;
454 1.8.8.2 nathanw
455 1.8.8.2 nathanw return (*tp->t_linesw->l_read)(tp, uio, flag);
456 1.8.8.2 nathanw }
457 1.8.8.2 nathanw
458 1.8.8.2 nathanw int
459 1.8.8.2 nathanw siowrite(dev, uio, flag)
460 1.8.8.2 nathanw dev_t dev;
461 1.8.8.2 nathanw struct uio *uio;
462 1.8.8.2 nathanw int flag;
463 1.8.8.2 nathanw {
464 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
465 1.8.8.2 nathanw struct tty *tp = sc->sc_tty;
466 1.8.8.2 nathanw
467 1.8.8.2 nathanw return (*tp->t_linesw->l_write)(tp, uio, flag);
468 1.8.8.2 nathanw }
469 1.8.8.2 nathanw
470 1.8.8.2 nathanw int
471 1.8.8.2 nathanw siopoll(dev, events, p)
472 1.8.8.2 nathanw dev_t dev;
473 1.8.8.2 nathanw int events;
474 1.8.8.2 nathanw struct proc *p;
475 1.8.8.2 nathanw {
476 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
477 1.8.8.2 nathanw struct tty *tp = sc->sc_tty;
478 1.8.8.2 nathanw
479 1.8.8.2 nathanw return ((*tp->t_linesw->l_poll)(tp, events, p));
480 1.8.8.2 nathanw }
481 1.8.8.2 nathanw
482 1.8.8.2 nathanw int
483 1.8.8.2 nathanw sioioctl(dev, cmd, data, flag, p)
484 1.8.8.2 nathanw dev_t dev;
485 1.8.8.2 nathanw u_long cmd;
486 1.8.8.2 nathanw caddr_t data;
487 1.8.8.2 nathanw int flag;
488 1.8.8.2 nathanw struct proc *p;
489 1.8.8.2 nathanw {
490 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
491 1.8.8.2 nathanw struct tty *tp = sc->sc_tty;
492 1.8.8.2 nathanw int error;
493 1.8.8.2 nathanw
494 1.8.8.2 nathanw error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p);
495 1.8.8.2 nathanw if (error != EPASSTHROUGH)
496 1.8.8.2 nathanw return error;
497 1.8.8.2 nathanw
498 1.8.8.2 nathanw error = ttioctl(tp, cmd, data, flag, p);
499 1.8.8.2 nathanw if (error != EPASSTHROUGH)
500 1.8.8.2 nathanw return error;
501 1.8.8.2 nathanw
502 1.8.8.2 nathanw /* the last resort for TIOC ioctl tranversing */
503 1.8.8.2 nathanw switch (cmd) {
504 1.8.8.2 nathanw case TIOCSBRK: /* Set the hardware into BREAK condition */
505 1.8.8.2 nathanw siomctl(sc, TIOCM_BREAK, DMBIS);
506 1.8.8.2 nathanw break;
507 1.8.8.2 nathanw case TIOCCBRK: /* Clear the hardware BREAK condition */
508 1.8.8.2 nathanw siomctl(sc, TIOCM_BREAK, DMBIC);
509 1.8.8.2 nathanw break;
510 1.8.8.2 nathanw case TIOCSDTR: /* Assert DTR signal */
511 1.8.8.2 nathanw siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIS);
512 1.8.8.2 nathanw break;
513 1.8.8.2 nathanw case TIOCCDTR: /* Clear DTR signal */
514 1.8.8.2 nathanw siomctl(sc, TIOCM_DTR|TIOCM_RTS, DMBIC);
515 1.8.8.2 nathanw break;
516 1.8.8.2 nathanw case TIOCMSET: /* Set modem state replacing current one */
517 1.8.8.2 nathanw siomctl(sc, *(int *)data, DMSET);
518 1.8.8.2 nathanw break;
519 1.8.8.2 nathanw case TIOCMGET: /* Return current modem state */
520 1.8.8.2 nathanw *(int *)data = siomctl(sc, 0, DMGET);
521 1.8.8.2 nathanw break;
522 1.8.8.2 nathanw case TIOCMBIS: /* Set individual bits of modem state */
523 1.8.8.2 nathanw siomctl(sc, *(int *)data, DMBIS);
524 1.8.8.2 nathanw break;
525 1.8.8.2 nathanw case TIOCMBIC: /* Clear individual bits of modem state */
526 1.8.8.2 nathanw siomctl(sc, *(int *)data, DMBIC);
527 1.8.8.2 nathanw break;
528 1.8.8.2 nathanw case TIOCSFLAGS: /* Instruct how serial port behaves */
529 1.8.8.2 nathanw sc->sc_flags = *(int *)data;
530 1.8.8.2 nathanw break;
531 1.8.8.2 nathanw case TIOCGFLAGS: /* Return current serial port state */
532 1.8.8.2 nathanw *(int *)data = sc->sc_flags;
533 1.8.8.2 nathanw break;
534 1.8.8.2 nathanw default:
535 1.8.8.2 nathanw return EPASSTHROUGH;
536 1.8.8.2 nathanw }
537 1.8.8.2 nathanw return 0;
538 1.8.8.2 nathanw }
539 1.8.8.2 nathanw
540 1.8.8.2 nathanw /* ARSGUSED */
541 1.8.8.2 nathanw struct tty *
542 1.8.8.2 nathanw siotty(dev)
543 1.8.8.2 nathanw dev_t dev;
544 1.8.8.2 nathanw {
545 1.8.8.2 nathanw struct siotty_softc *sc = siotty_cd.cd_devs[minor(dev)];
546 1.8.8.2 nathanw
547 1.8.8.2 nathanw return sc->sc_tty;
548 1.8.8.2 nathanw }
549 1.8.8.2 nathanw
550 1.8.8.2 nathanw /*-------------------- miscelleneous routine --------------------*/
551 1.8.8.2 nathanw
552 1.8.8.2 nathanw /* EXPORT */ void
553 1.8.8.2 nathanw setsioreg(sio, regno, val)
554 1.8.8.2 nathanw struct sioreg *sio;
555 1.8.8.2 nathanw int regno, val;
556 1.8.8.2 nathanw {
557 1.8.8.2 nathanw if (regno != 0)
558 1.8.8.2 nathanw sio->sio_cmd = regno; /* DELAY(); */
559 1.8.8.2 nathanw sio->sio_cmd = val; /* DELAY(); */
560 1.8.8.2 nathanw }
561 1.8.8.2 nathanw
562 1.8.8.2 nathanw /* EXPORT */ int
563 1.8.8.2 nathanw getsiocsr(sio)
564 1.8.8.2 nathanw struct sioreg *sio;
565 1.8.8.2 nathanw {
566 1.8.8.2 nathanw int val;
567 1.8.8.2 nathanw
568 1.8.8.2 nathanw val = sio->sio_stat << 8; /* DELAY(); */
569 1.8.8.2 nathanw sio->sio_cmd = 1; /* DELAY(); */
570 1.8.8.2 nathanw val |= sio->sio_stat; /* DELAY(); */
571 1.8.8.2 nathanw return val;
572 1.8.8.2 nathanw }
573 1.8.8.2 nathanw
574 1.8.8.2 nathanw /*--------------------- console interface ----------------------*/
575 1.8.8.2 nathanw
576 1.8.8.2 nathanw void syscnattach __P((int));
577 1.8.8.2 nathanw int syscngetc __P((dev_t));
578 1.8.8.2 nathanw void syscnputc __P((dev_t, int));
579 1.8.8.2 nathanw
580 1.8.8.2 nathanw struct consdev syscons = {
581 1.8.8.2 nathanw NULL,
582 1.8.8.2 nathanw NULL,
583 1.8.8.2 nathanw syscngetc,
584 1.8.8.2 nathanw syscnputc,
585 1.8.8.2 nathanw nullcnpollc,
586 1.8.8.2 nathanw NULL,
587 1.8.8.2 nathanw NODEV,
588 1.8.8.2 nathanw CN_REMOTE,
589 1.8.8.2 nathanw };
590 1.8.8.2 nathanw
591 1.8.8.2 nathanw /* EXPORT */ void
592 1.8.8.2 nathanw syscnattach(channel)
593 1.8.8.2 nathanw int channel;
594 1.8.8.2 nathanw {
595 1.8.8.2 nathanw /*
596 1.8.8.2 nathanw * Channel A is immediately initialized with 9600N1 right after cold
597 1.8.8.2 nathanw * boot/reset/poweron. ROM monitor emits one line message on CH.A.
598 1.8.8.2 nathanw */
599 1.8.8.2 nathanw struct sioreg *sio;
600 1.8.8.2 nathanw sio = (struct sioreg *)0x51000000 + channel;
601 1.8.8.2 nathanw
602 1.8.8.3 nathanw syscons.cn_dev = makedev(cdevsw_lookup_major(&siotty_cdevsw),
603 1.8.8.3 nathanw channel);
604 1.8.8.2 nathanw cn_tab = &syscons;
605 1.8.8.2 nathanw
606 1.8.8.2 nathanw setsioreg(sio, WR0, WR0_CHANRST);
607 1.8.8.2 nathanw setsioreg(sio, WR2A, WR2_VEC86 | WR2_INTR_1);
608 1.8.8.2 nathanw setsioreg(sio, WR2B, 0);
609 1.8.8.2 nathanw setsioreg(sio, WR0, ch0_regs[WR0]);
610 1.8.8.2 nathanw setsioreg(sio, WR4, ch0_regs[WR4]);
611 1.8.8.2 nathanw setsioreg(sio, WR3, ch0_regs[WR3]);
612 1.8.8.2 nathanw setsioreg(sio, WR5, ch0_regs[WR5]);
613 1.8.8.2 nathanw setsioreg(sio, WR0, ch0_regs[WR0]);
614 1.8.8.2 nathanw }
615 1.8.8.2 nathanw
616 1.8.8.2 nathanw /* EXPORT */ int
617 1.8.8.2 nathanw syscngetc(dev)
618 1.8.8.2 nathanw dev_t dev;
619 1.8.8.2 nathanw {
620 1.8.8.2 nathanw struct sioreg *sio;
621 1.8.8.2 nathanw int s, c;
622 1.8.8.2 nathanw
623 1.8.8.2 nathanw sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
624 1.8.8.2 nathanw s = splhigh();
625 1.8.8.2 nathanw while ((getsiocsr(sio) & RR_RXRDY) == 0)
626 1.8.8.2 nathanw ;
627 1.8.8.2 nathanw c = sio->sio_data;
628 1.8.8.2 nathanw splx(s);
629 1.8.8.2 nathanw
630 1.8.8.2 nathanw return c;
631 1.8.8.2 nathanw }
632 1.8.8.2 nathanw
633 1.8.8.2 nathanw /* EXPORT */ void
634 1.8.8.2 nathanw syscnputc(dev, c)
635 1.8.8.2 nathanw dev_t dev;
636 1.8.8.2 nathanw int c;
637 1.8.8.2 nathanw {
638 1.8.8.2 nathanw struct sioreg *sio;
639 1.8.8.2 nathanw int s;
640 1.8.8.2 nathanw
641 1.8.8.2 nathanw sio = (struct sioreg *)0x51000000 + ((int)dev & 0x1);
642 1.8.8.2 nathanw s = splhigh();
643 1.8.8.2 nathanw while ((getsiocsr(sio) & RR_TXRDY) == 0)
644 1.8.8.2 nathanw ;
645 1.8.8.2 nathanw sio->sio_cmd = WR0_RSTPEND;
646 1.8.8.2 nathanw sio->sio_data = c;
647 1.8.8.2 nathanw splx(s);
648 1.8.8.2 nathanw }
649