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