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