ser.c revision 1.48 1 1.48 is /* $NetBSD: ser.c,v 1.48 1998/07/18 20:19:33 is Exp $ */
2 1.23 cgd
3 1.1 mw /*
4 1.1 mw * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
5 1.1 mw * All rights reserved.
6 1.1 mw *
7 1.1 mw * Redistribution and use in source and binary forms, with or without
8 1.1 mw * modification, are permitted provided that the following conditions
9 1.1 mw * are met:
10 1.1 mw * 1. Redistributions of source code must retain the above copyright
11 1.1 mw * notice, this list of conditions and the following disclaimer.
12 1.1 mw * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 mw * notice, this list of conditions and the following disclaimer in the
14 1.1 mw * documentation and/or other materials provided with the distribution.
15 1.1 mw * 3. All advertising materials mentioning features or use of this software
16 1.1 mw * must display the following acknowledgement:
17 1.1 mw * This product includes software developed by the University of
18 1.1 mw * California, Berkeley and its contributors.
19 1.1 mw * 4. Neither the name of the University nor the names of its contributors
20 1.1 mw * may be used to endorse or promote products derived from this software
21 1.1 mw * without specific prior written permission.
22 1.1 mw *
23 1.1 mw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.1 mw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.1 mw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.1 mw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.1 mw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.1 mw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.1 mw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.1 mw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.1 mw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.1 mw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.1 mw * SUCH DAMAGE.
34 1.1 mw *
35 1.4 mw * @(#)ser.c 7.12 (Berkeley) 6/27/91
36 1.15 chopps */
37 1.15 chopps /*
38 1.32 is * XXX This file needs major cleanup it will never service more than one
39 1.15 chopps * XXX unit.
40 1.1 mw */
41 1.1 mw
42 1.10 chopps #include <sys/param.h>
43 1.10 chopps #include <sys/systm.h>
44 1.10 chopps #include <sys/ioctl.h>
45 1.15 chopps #include <sys/device.h>
46 1.10 chopps #include <sys/tty.h>
47 1.10 chopps #include <sys/proc.h>
48 1.10 chopps #include <sys/file.h>
49 1.10 chopps #include <sys/malloc.h>
50 1.10 chopps #include <sys/uio.h>
51 1.10 chopps #include <sys/kernel.h>
52 1.10 chopps #include <sys/syslog.h>
53 1.13 chopps #include <sys/queue.h>
54 1.15 chopps #include <machine/cpu.h>
55 1.15 chopps #include <amiga/amiga/device.h>
56 1.10 chopps #include <amiga/dev/serreg.h>
57 1.10 chopps #include <amiga/amiga/custom.h>
58 1.10 chopps #include <amiga/amiga/cia.h>
59 1.10 chopps #include <amiga/amiga/cc.h>
60 1.1 mw
61 1.14 chopps #include <dev/cons.h>
62 1.14 chopps
63 1.31 veego #include <sys/conf.h>
64 1.31 veego #include <machine/conf.h>
65 1.31 veego
66 1.15 chopps #include "ser.h"
67 1.15 chopps #if NSER > 0
68 1.14 chopps
69 1.15 chopps void serattach __P((struct device *, struct device *, void *));
70 1.39 veego int sermatch __P((struct device *, struct cfdata *, void *));
71 1.15 chopps
72 1.28 jtc struct ser_softc {
73 1.28 jtc struct device dev;
74 1.28 jtc struct tty *ser_tty;
75 1.28 jtc };
76 1.28 jtc
77 1.29 thorpej struct cfattach ser_ca = {
78 1.30 mhitch sizeof(struct ser_softc), sermatch, serattach
79 1.29 thorpej };
80 1.29 thorpej
81 1.43 thorpej extern struct cfdriver ser_cd;
82 1.15 chopps
83 1.26 chopps #ifndef SEROBUF_SIZE
84 1.15 chopps #define SEROBUF_SIZE 32
85 1.26 chopps #endif
86 1.26 chopps #ifndef SERIBUF_SIZE
87 1.15 chopps #define SERIBUF_SIZE 512
88 1.26 chopps #endif
89 1.26 chopps
90 1.26 chopps #define splser() spl5()
91 1.1 mw
92 1.31 veego void serstart __P((struct tty *));
93 1.44 is void ser_shutdown __P((struct ser_softc *));
94 1.31 veego int serparam __P((struct tty *, struct termios *));
95 1.44 is void serintr __P((void));
96 1.31 veego int serhwiflow __P((struct tty *, int));
97 1.31 veego int sermctl __P((dev_t dev, int, int));
98 1.31 veego void ser_fastint __P((void));
99 1.44 is void sereint __P((int));
100 1.31 veego static void ser_putchar __P((struct tty *, u_short));
101 1.31 veego void ser_outintr __P((void));
102 1.31 veego void sercnprobe __P((struct consdev *));
103 1.31 veego void sercninit __P((struct consdev *));
104 1.44 is void serinit __P((int));
105 1.31 veego int sercngetc __P((dev_t dev));
106 1.31 veego void sercnputc __P((dev_t, int));
107 1.31 veego void sercnpollc __P((dev_t, int));
108 1.31 veego
109 1.1 mw int nser = NSER;
110 1.1 mw #ifdef SERCONSOLE
111 1.1 mw int serconsole = SERCONSOLE;
112 1.1 mw #else
113 1.1 mw int serconsole = -1;
114 1.1 mw #endif
115 1.1 mw int serconsinit;
116 1.1 mw int serdefaultrate = TTYDEF_SPEED;
117 1.1 mw int sermajor;
118 1.14 chopps int serswflags;
119 1.14 chopps
120 1.44 is struct vbl_node ser_vbl_node;
121 1.1 mw struct tty ser_cons;
122 1.44 is struct tty *ser_tty;
123 1.44 is
124 1.44 is static u_short serbuf[SERIBUF_SIZE];
125 1.44 is static u_short *sbrpt = serbuf;
126 1.44 is static u_short *sbwpt = serbuf;
127 1.44 is static u_short sbcnt;
128 1.44 is static u_short sbovfl;
129 1.44 is static u_char serdcd;
130 1.48 is static u_short sercharmask, serparmask, serparoddmask, serstopmask,
131 1.48 is sercharwidth;
132 1.1 mw
133 1.14 chopps /*
134 1.14 chopps * Since this UART is not particularly bright (to put it nicely), we'll
135 1.14 chopps * have to do parity stuff on our own. This table contains the 8th bit
136 1.14 chopps * in 7bit character mode, for even parity. If you want odd parity,
137 1.14 chopps * flip the bit. (for generation of the table, see genpar.c)
138 1.14 chopps */
139 1.14 chopps
140 1.14 chopps u_char even_parity[] = {
141 1.14 chopps 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
142 1.14 chopps 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
143 1.14 chopps 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
144 1.14 chopps 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
145 1.14 chopps 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
146 1.14 chopps 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
147 1.14 chopps 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
148 1.14 chopps 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
149 1.1 mw };
150 1.1 mw
151 1.14 chopps /*
152 1.14 chopps * Since we don't get interrupts for changes on the modem control line,
153 1.14 chopps * we'll have to fake them by comparing current settings to the settings
154 1.14 chopps * we remembered on last invocation.
155 1.14 chopps */
156 1.14 chopps
157 1.14 chopps u_char last_ciab_pra;
158 1.14 chopps
159 1.14 chopps extern struct tty *constty;
160 1.1 mw
161 1.42 mhitch extern int ser_open_speed; /* current speed of open serial device */
162 1.42 mhitch
163 1.1 mw #ifdef KGDB
164 1.10 chopps #include <machine/remote-sl.h>
165 1.1 mw
166 1.1 mw extern dev_t kgdb_dev;
167 1.1 mw extern int kgdb_rate;
168 1.1 mw extern int kgdb_debug_init;
169 1.1 mw #endif
170 1.1 mw
171 1.1 mw #ifdef DEBUG
172 1.1 mw long fifoin[17];
173 1.1 mw long fifoout[17];
174 1.1 mw long serintrcount[16];
175 1.1 mw long sermintcount[16];
176 1.1 mw #endif
177 1.1 mw
178 1.14 chopps void sermint __P((register int unit));
179 1.5 mw
180 1.5 mw int
181 1.39 veego sermatch(pdp, cfp, auxp)
182 1.15 chopps struct device *pdp;
183 1.39 veego struct cfdata *cfp;
184 1.39 veego void *auxp;
185 1.15 chopps {
186 1.29 thorpej
187 1.15 chopps if (matchname("ser", (char *)auxp) == 0 || cfp->cf_unit != 0)
188 1.15 chopps return(0);
189 1.15 chopps if (serconsole != 0 && amiga_realconfig == 0)
190 1.15 chopps return(0);
191 1.15 chopps return(1);
192 1.15 chopps }
193 1.15 chopps
194 1.15 chopps
195 1.15 chopps void
196 1.15 chopps serattach(pdp, dp, auxp)
197 1.15 chopps struct device *pdp, *dp;
198 1.15 chopps void *auxp;
199 1.1 mw {
200 1.44 is struct ser_softc *sc;
201 1.44 is struct tty *tp;
202 1.15 chopps u_short ir;
203 1.14 chopps
204 1.44 is sc = (struct ser_softc *)dp;
205 1.44 is
206 1.14 chopps ir = custom.intenar;
207 1.15 chopps if (serconsole == 0)
208 1.14 chopps DELAY(100000);
209 1.14 chopps
210 1.44 is ser_vbl_node.function = (void (*) (void *)) sermint;
211 1.44 is add_vbl_function(&ser_vbl_node, SER_VBL_PRIORITY, (void *) 0);
212 1.1 mw #ifdef KGDB
213 1.15 chopps if (kgdb_dev == makedev(sermajor, 0)) {
214 1.15 chopps if (serconsole == 0)
215 1.14 chopps kgdb_dev = NODEV; /* can't debug over console port */
216 1.14 chopps else {
217 1.44 is (void) serinit(kgdb_rate);
218 1.14 chopps serconsinit = 1; /* don't re-init in serputc */
219 1.14 chopps if (kgdb_debug_init == 0)
220 1.38 christos printf(" kgdb enabled\n");
221 1.14 chopps else {
222 1.14 chopps /*
223 1.14 chopps * Print prefix of device name,
224 1.14 chopps * let kgdb_connect print the rest.
225 1.14 chopps */
226 1.38 christos printf("ser0: ");
227 1.14 chopps kgdb_connect(1);
228 1.14 chopps }
229 1.14 chopps }
230 1.14 chopps }
231 1.5 mw #endif
232 1.14 chopps /*
233 1.14 chopps * Need to reset baud rate, etc. of next print so reset serconsinit.
234 1.14 chopps */
235 1.15 chopps if (0 == serconsole)
236 1.14 chopps serconsinit = 0;
237 1.44 is
238 1.44 is tp = ttymalloc();
239 1.44 is tp->t_oproc = (void (*) (struct tty *)) serstart;
240 1.44 is tp->t_param = serparam;
241 1.44 is tp->t_hwiflow = serhwiflow;
242 1.44 is tty_attach(tp);
243 1.44 is sc->ser_tty = ser_tty = tp;
244 1.44 is
245 1.15 chopps if (dp)
246 1.38 christos printf(": input fifo %d output fifo %d\n", SERIBUF_SIZE,
247 1.15 chopps SEROBUF_SIZE);
248 1.1 mw }
249 1.1 mw
250 1.14 chopps
251 1.1 mw /* ARGSUSED */
252 1.5 mw int
253 1.1 mw seropen(dev, flag, mode, p)
254 1.14 chopps dev_t dev;
255 1.14 chopps int flag, mode;
256 1.14 chopps struct proc *p;
257 1.1 mw {
258 1.44 is struct ser_softc *sc;
259 1.14 chopps struct tty *tp;
260 1.44 is int unit, error, s, s2;
261 1.14 chopps
262 1.14 chopps error = 0;
263 1.14 chopps unit = SERUNIT(dev);
264 1.14 chopps
265 1.44 is if (unit >= ser_cd.cd_ndevs)
266 1.44 is return (ENXIO);
267 1.44 is
268 1.44 is sc = ser_cd.cd_devs[unit];
269 1.44 is if (sc == 0)
270 1.14 chopps return (ENXIO);
271 1.14 chopps
272 1.44 is /* XXX com.c: insert KGDB check here */
273 1.44 is
274 1.44 is /* XXX ser.c had: s = spltty(); */
275 1.44 is
276 1.44 is tp = sc->ser_tty;
277 1.44 is
278 1.44 is if ((tp->t_state & TS_ISOPEN) &&
279 1.44 is (tp->t_state & TS_XCLUDE) &&
280 1.44 is p->p_ucred->cr_uid != 0)
281 1.44 is return (EBUSY);
282 1.44 is
283 1.14 chopps s = spltty();
284 1.14 chopps
285 1.44 is /*
286 1.44 is * If this is a first open...
287 1.44 is */
288 1.44 is
289 1.44 is if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
290 1.44 is struct termios t;
291 1.14 chopps
292 1.44 is tp->t_dev = dev;
293 1.14 chopps
294 1.44 is s2 = splser();
295 1.14 chopps /*
296 1.44 is * XXX here: hw enable,
297 1.14 chopps */
298 1.46 is last_ciab_pra = ciab.pra;
299 1.44 is
300 1.44 is splx(s2);
301 1.44 is t.c_ispeed = 0;
302 1.44 is
303 1.44 is /* XXX serconsolerate? */
304 1.44 is t.c_ospeed = TTYDEF_SPEED;
305 1.44 is t.c_cflag = TTYDEF_CFLAG;
306 1.44 is
307 1.14 chopps if (serswflags & TIOCFLAG_CLOCAL)
308 1.44 is t.c_cflag |= CLOCAL;
309 1.14 chopps if (serswflags & TIOCFLAG_CRTSCTS)
310 1.44 is t.c_cflag |= CRTSCTS;
311 1.14 chopps if (serswflags & TIOCFLAG_MDMBUF)
312 1.44 is t.c_cflag |= MDMBUF;
313 1.44 is
314 1.44 is /* Make sure serparam() will do something. */
315 1.44 is tp->t_ospeed = 0;
316 1.44 is serparam(tp, &t);
317 1.44 is tp->t_iflag = TTYDEF_IFLAG;
318 1.44 is tp->t_oflag = TTYDEF_OFLAG;
319 1.44 is tp->t_lflag = TTYDEF_LFLAG;
320 1.44 is ttychars(tp);
321 1.14 chopps ttsetwater(tp);
322 1.44 is
323 1.44 is s2 = splser();
324 1.45 is (void)sermctl(dev, TIOCM_DTR, DMSET);
325 1.44 is /* clear input ring */
326 1.44 is sbrpt = sbwpt = serbuf;
327 1.44 is sbcnt = 0;
328 1.44 is splx(s2);
329 1.14 chopps }
330 1.14 chopps
331 1.44 is splx(s);
332 1.44 is
333 1.44 is error = ttyopen(tp, DIALOUT(dev), flag & O_NONBLOCK);
334 1.44 is if (error)
335 1.44 is goto bad;
336 1.44 is
337 1.44 is error = (*linesw[tp->t_line].l_open)(dev, tp);
338 1.44 is if (error)
339 1.44 is goto bad;
340 1.44 is
341 1.44 is return (0);
342 1.14 chopps
343 1.44 is bad:
344 1.44 is if (!(tp->t_state & TS_ISOPEN) && tp->t_wopen == 0) {
345 1.44 is ser_shutdown(sc);
346 1.22 chopps }
347 1.22 chopps
348 1.44 is return (error);
349 1.1 mw }
350 1.14 chopps
351 1.1 mw /*ARGSUSED*/
352 1.5 mw int
353 1.1 mw serclose(dev, flag, mode, p)
354 1.14 chopps dev_t dev;
355 1.14 chopps int flag, mode;
356 1.14 chopps struct proc *p;
357 1.14 chopps {
358 1.44 is struct ser_softc *sc;
359 1.14 chopps struct tty *tp;
360 1.14 chopps
361 1.44 is sc = ser_cd.cd_devs[0];
362 1.44 is tp = ser_tty;
363 1.44 is
364 1.44 is /* XXX This is for cons.c, according to com.c */
365 1.44 is if (!(tp->t_state & TS_ISOPEN))
366 1.44 is return (0);
367 1.14 chopps
368 1.14 chopps (*linesw[tp->t_line].l_close)(tp, flag);
369 1.44 is ttyclose(tp);
370 1.44 is
371 1.44 is if (!(tp->t_state & TS_ISOPEN) && tp->t_wopen == 0) {
372 1.44 is ser_shutdown(sc);
373 1.44 is }
374 1.44 is return (0);
375 1.44 is }
376 1.44 is
377 1.44 is void
378 1.44 is ser_shutdown(sc)
379 1.44 is struct ser_softc *sc;
380 1.44 is {
381 1.44 is struct tty *tp = sc->ser_tty;
382 1.44 is int s;
383 1.44 is
384 1.44 is s = splser();
385 1.44 is
386 1.14 chopps custom.adkcon = ADKCONF_UARTBRK; /* clear break */
387 1.44 is #if 0 /* XXX fix: #ifdef KGDB */
388 1.14 chopps /*
389 1.14 chopps * do not disable interrupts if debugging
390 1.14 chopps */
391 1.14 chopps if (dev != kgdb_dev)
392 1.1 mw #endif
393 1.44 is custom.intena = INTF_RBF | INTF_TBE; /* disable interrupts */
394 1.14 chopps custom.intreq = INTF_RBF | INTF_TBE; /* clear intr request */
395 1.14 chopps
396 1.14 chopps /*
397 1.41 is * If HUPCL is not set, leave DTR unchanged.
398 1.14 chopps */
399 1.44 is if (tp->t_cflag & HUPCL) {
400 1.44 is (void)sermctl(tp->t_dev, TIOCM_DTR, DMBIC);
401 1.44 is /*
402 1.44 is * Idea from dev/ic/com.c:
403 1.44 is * sleep a bit so that other side will notice, even if we
404 1.44 is * reopen immediately.
405 1.44 is */
406 1.44 is (void) tsleep(tp, TTIPRI, ttclos, hz);
407 1.44 is }
408 1.41 is
409 1.14 chopps #if not_yet
410 1.14 chopps if (tp != &ser_cons) {
411 1.44 is remove_vbl_function(&ser_vbl_node);
412 1.14 chopps ttyfree(tp);
413 1.44 is ser_tty = (struct tty *) NULL;
414 1.14 chopps }
415 1.3 mw #endif
416 1.42 mhitch ser_open_speed = tp->t_ispeed;
417 1.44 is return;
418 1.1 mw }
419 1.14 chopps
420 1.5 mw int
421 1.1 mw serread(dev, uio, flag)
422 1.14 chopps dev_t dev;
423 1.14 chopps struct uio *uio;
424 1.14 chopps int flag;
425 1.1 mw {
426 1.44 is /* ARGSUSED */
427 1.44 is
428 1.44 is return((*linesw[ser_tty->t_line].l_read)(ser_tty, uio, flag));
429 1.14 chopps }
430 1.1 mw
431 1.5 mw int
432 1.1 mw serwrite(dev, uio, flag)
433 1.14 chopps dev_t dev;
434 1.14 chopps struct uio *uio;
435 1.14 chopps int flag;
436 1.1 mw {
437 1.44 is /* ARGSUSED */
438 1.14 chopps
439 1.44 is return((*linesw[ser_tty->t_line].l_write)(ser_tty, uio, flag));
440 1.1 mw }
441 1.3 mw
442 1.27 chopps struct tty *
443 1.27 chopps sertty(dev)
444 1.27 chopps dev_t dev;
445 1.27 chopps {
446 1.44 is /* ARGSUSED */
447 1.44 is
448 1.44 is return (ser_tty);
449 1.27 chopps }
450 1.3 mw
451 1.14 chopps /*
452 1.14 chopps * We don't do any processing of data here, so we store the raw code
453 1.14 chopps * obtained from the uart register. In theory, 110kBaud gives you
454 1.14 chopps * 11kcps, so 16k buffer should be more than enough, interrupt
455 1.14 chopps * latency of 1s should never happen, or something is seriously
456 1.14 chopps * wrong..
457 1.44 is * buffers moved to above seropen() -is
458 1.14 chopps */
459 1.14 chopps
460 1.14 chopps /*
461 1.14 chopps * This is a replacement for the lack of a hardware fifo. 32k should be
462 1.14 chopps * enough (there's only one unit anyway, so this is not going to
463 1.14 chopps * accumulate).
464 1.14 chopps */
465 1.3 mw void
466 1.14 chopps ser_fastint()
467 1.3 mw {
468 1.14 chopps /*
469 1.14 chopps * We're at RBE-level, which is higher than VBL-level which is used
470 1.14 chopps * to periodically transmit contents of this buffer up one layer,
471 1.14 chopps * so no spl-raising is necessary.
472 1.14 chopps */
473 1.47 is u_short code;
474 1.14 chopps
475 1.47 is /*
476 1.47 is * This register contains both data and status bits!
477 1.47 is */
478 1.47 is code = custom.serdatr;
479 1.14 chopps
480 1.40 mhitch /*
481 1.47 is * Use SERDATF_RBF instead of INTF_RBF; they're equivalent, but
482 1.47 is * we save one (slow) custom chip access.
483 1.40 mhitch */
484 1.47 is if ((code & SERDATRF_RBF) == 0)
485 1.47 is return;
486 1.40 mhitch
487 1.14 chopps /*
488 1.14 chopps * clear interrupt
489 1.14 chopps */
490 1.44 is custom.intreq = INTF_RBF;
491 1.14 chopps
492 1.14 chopps /*
493 1.14 chopps * check for buffer overflow.
494 1.14 chopps */
495 1.22 chopps if (sbcnt == SERIBUF_SIZE) {
496 1.18 chopps ++sbovfl;
497 1.14 chopps return;
498 1.14 chopps }
499 1.14 chopps /*
500 1.14 chopps * store in buffer
501 1.14 chopps */
502 1.14 chopps *sbwpt++ = code;
503 1.14 chopps if (sbwpt == serbuf + SERIBUF_SIZE)
504 1.14 chopps sbwpt = serbuf;
505 1.22 chopps ++sbcnt;
506 1.26 chopps if (sbcnt > SERIBUF_SIZE - 20)
507 1.22 chopps CLRRTS(ciab.pra); /* drop RTS if buffer almost full */
508 1.3 mw }
509 1.3 mw
510 1.3 mw
511 1.31 veego void
512 1.44 is serintr()
513 1.1 mw {
514 1.18 chopps int s1, s2, ovfl;
515 1.44 is struct tty *tp = ser_tty;
516 1.1 mw
517 1.14 chopps /*
518 1.14 chopps * Make sure we're not interrupted by another
519 1.14 chopps * vbl, but allow level5 ints
520 1.14 chopps */
521 1.14 chopps s1 = spltty();
522 1.1 mw
523 1.14 chopps /*
524 1.14 chopps * pass along any acumulated information
525 1.14 chopps */
526 1.22 chopps while (sbcnt > 0 && (tp->t_state & TS_TBLOCK) == 0) {
527 1.14 chopps /*
528 1.14 chopps * no collision with ser_fastint()
529 1.14 chopps */
530 1.44 is sereint(*sbrpt++);
531 1.14 chopps
532 1.18 chopps ovfl = 0;
533 1.14 chopps /* lock against ser_fastint() */
534 1.26 chopps s2 = splser();
535 1.22 chopps sbcnt--;
536 1.14 chopps if (sbrpt == serbuf + SERIBUF_SIZE)
537 1.14 chopps sbrpt = serbuf;
538 1.18 chopps if (sbovfl != 0) {
539 1.18 chopps ovfl = sbovfl;
540 1.18 chopps sbovfl = 0;
541 1.18 chopps }
542 1.14 chopps splx(s2);
543 1.18 chopps if (ovfl != 0)
544 1.21 chopps log(LOG_WARNING, "ser0: %d ring buffer overflows.\n",
545 1.21 chopps ovfl);
546 1.14 chopps }
547 1.33 is s2 = splser();
548 1.22 chopps if (sbcnt == 0 && (tp->t_state & TS_TBLOCK) == 0)
549 1.22 chopps SETRTS(ciab.pra); /* start accepting data again */
550 1.33 is splx(s2);
551 1.14 chopps splx(s1);
552 1.1 mw }
553 1.1 mw
554 1.31 veego void
555 1.44 is sereint(stat)
556 1.44 is int stat;
557 1.1 mw {
558 1.14 chopps struct tty *tp;
559 1.14 chopps u_char ch;
560 1.14 chopps int c;
561 1.14 chopps
562 1.44 is tp = ser_tty;
563 1.48 is ch = stat & (sercharmask | serparmask);
564 1.14 chopps c = ch;
565 1.14 chopps
566 1.14 chopps if ((tp->t_state & TS_ISOPEN) == 0) {
567 1.1 mw #ifdef KGDB
568 1.14 chopps /* we don't care about parity errors */
569 1.44 is if (kgdb_dev == makedev(sermajor, 0) && c == FRAME_END)
570 1.14 chopps kgdb_connect(0); /* trap into kgdb */
571 1.1 mw #endif
572 1.14 chopps return;
573 1.14 chopps }
574 1.14 chopps
575 1.14 chopps /*
576 1.14 chopps * Check for break and (if enabled) parity error.
577 1.14 chopps */
578 1.14 chopps if ((stat & 0x1ff) == 0)
579 1.14 chopps c |= TTY_FE;
580 1.48 is else if (serparmask &&
581 1.48 is (ch & serparmask) ^ serparoddmask ^
582 1.48 is even_parity[ch & sercharmask] << sercharwidth)
583 1.14 chopps c |= TTY_PE;
584 1.14 chopps
585 1.14 chopps if (stat & SERDATRF_OVRUN)
586 1.15 chopps log(LOG_WARNING, "ser0: silo overflow\n");
587 1.1 mw
588 1.14 chopps (*linesw[tp->t_line].l_rint)(c, tp);
589 1.14 chopps }
590 1.14 chopps
591 1.14 chopps /*
592 1.14 chopps * This interrupt is periodically invoked in the vertical blank
593 1.14 chopps * interrupt. It's used to keep track of the modem control lines
594 1.14 chopps * and (new with the fast_int code) to move accumulated data
595 1.14 chopps * up into the tty layer.
596 1.14 chopps */
597 1.3 mw void
598 1.14 chopps sermint(unit)
599 1.14 chopps int unit;
600 1.1 mw {
601 1.14 chopps struct tty *tp;
602 1.14 chopps u_char stat, last, istat;
603 1.14 chopps
604 1.44 is tp = ser_tty;
605 1.14 chopps if (!tp)
606 1.14 chopps return;
607 1.14 chopps
608 1.44 is /*
609 1.44 is if ((tp->t_state & TS_ISOPEN) == 0 || tp->t_wopen == 0) {
610 1.14 chopps sbrpt = sbwpt = serbuf;
611 1.14 chopps return;
612 1.14 chopps }
613 1.44 is */
614 1.14 chopps /*
615 1.14 chopps * empty buffer
616 1.14 chopps */
617 1.44 is serintr();
618 1.14 chopps
619 1.14 chopps stat = ciab.pra;
620 1.14 chopps last = last_ciab_pra;
621 1.14 chopps last_ciab_pra = stat;
622 1.14 chopps
623 1.14 chopps /*
624 1.14 chopps * check whether any interesting signal changed state
625 1.14 chopps */
626 1.14 chopps istat = stat ^ last;
627 1.1 mw
628 1.44 is if (istat & serdcd) {
629 1.44 is (*linesw[tp->t_line].l_modem)(tp, ISDCD(stat));
630 1.14 chopps }
631 1.44 is
632 1.14 chopps if ((istat & CIAB_PRA_CTS) && (tp->t_state & TS_ISOPEN) &&
633 1.14 chopps (tp->t_cflag & CRTSCTS)) {
634 1.5 mw #if 0
635 1.14 chopps /* the line is up and we want to do rts/cts flow control */
636 1.14 chopps if (ISCTS(stat)) {
637 1.14 chopps tp->t_state &= ~TS_TTSTOP;
638 1.14 chopps ttstart(tp);
639 1.14 chopps /* cause tbe-int if we were stuck there */
640 1.14 chopps custom.intreq = INTF_SETCLR | INTF_TBE;
641 1.14 chopps } else
642 1.14 chopps tp->t_state |= TS_TTSTOP;
643 1.5 mw #else
644 1.14 chopps /* do this on hardware level, not with tty driver */
645 1.14 chopps if (ISCTS(stat)) {
646 1.14 chopps tp->t_state &= ~TS_TTSTOP;
647 1.14 chopps /* cause TBE interrupt */
648 1.14 chopps custom.intreq = INTF_SETCLR | INTF_TBE;
649 1.14 chopps }
650 1.14 chopps #endif
651 1.5 mw }
652 1.1 mw }
653 1.1 mw
654 1.5 mw int
655 1.8 chopps serioctl(dev, cmd, data, flag, p)
656 1.24 chopps dev_t dev;
657 1.24 chopps u_long cmd;
658 1.8 chopps caddr_t data;
659 1.24 chopps int flag;
660 1.8 chopps struct proc *p;
661 1.1 mw {
662 1.14 chopps register struct tty *tp;
663 1.14 chopps register int error;
664 1.14 chopps
665 1.44 is tp = ser_tty;
666 1.14 chopps if (!tp)
667 1.14 chopps return ENXIO;
668 1.14 chopps
669 1.14 chopps error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
670 1.14 chopps if (error >= 0)
671 1.14 chopps return(error);
672 1.14 chopps
673 1.14 chopps error = ttioctl(tp, cmd, data, flag, p);
674 1.14 chopps if (error >= 0)
675 1.14 chopps return(error);
676 1.14 chopps
677 1.14 chopps switch (cmd) {
678 1.14 chopps case TIOCSBRK:
679 1.14 chopps custom.adkcon = ADKCONF_SETCLR | ADKCONF_UARTBRK;
680 1.14 chopps break;
681 1.14 chopps
682 1.14 chopps case TIOCCBRK:
683 1.14 chopps custom.adkcon = ADKCONF_UARTBRK;
684 1.14 chopps break;
685 1.14 chopps
686 1.14 chopps case TIOCSDTR:
687 1.44 is (void) sermctl(dev, TIOCM_DTR, DMBIS);
688 1.14 chopps break;
689 1.14 chopps
690 1.14 chopps case TIOCCDTR:
691 1.44 is (void) sermctl(dev, TIOCM_DTR, DMBIC);
692 1.14 chopps break;
693 1.14 chopps
694 1.14 chopps case TIOCMSET:
695 1.14 chopps (void) sermctl(dev, *(int *) data, DMSET);
696 1.14 chopps break;
697 1.14 chopps
698 1.14 chopps case TIOCMBIS:
699 1.14 chopps (void) sermctl(dev, *(int *) data, DMBIS);
700 1.14 chopps break;
701 1.14 chopps
702 1.14 chopps case TIOCMBIC:
703 1.14 chopps (void) sermctl(dev, *(int *) data, DMBIC);
704 1.14 chopps break;
705 1.14 chopps
706 1.14 chopps case TIOCMGET:
707 1.14 chopps *(int *)data = sermctl(dev, 0, DMGET);
708 1.14 chopps break;
709 1.14 chopps case TIOCGFLAGS:
710 1.44 is *(int *)data = serswflags;
711 1.14 chopps break;
712 1.14 chopps case TIOCSFLAGS:
713 1.14 chopps error = suser(p->p_ucred, &p->p_acflag);
714 1.14 chopps if (error != 0)
715 1.14 chopps return(EPERM);
716 1.14 chopps
717 1.14 chopps serswflags = *(int *)data;
718 1.14 chopps serswflags &= /* only allow valid flags */
719 1.14 chopps (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
720 1.14 chopps break;
721 1.14 chopps default:
722 1.14 chopps return(ENOTTY);
723 1.14 chopps }
724 1.1 mw
725 1.14 chopps return(0);
726 1.1 mw }
727 1.1 mw
728 1.5 mw int
729 1.1 mw serparam(tp, t)
730 1.14 chopps struct tty *tp;
731 1.14 chopps struct termios *t;
732 1.1 mw {
733 1.44 is int cflag, ospeed = 0;
734 1.14 chopps
735 1.32 is if (t->c_ospeed > 0) {
736 1.32 is if (t->c_ospeed < 110)
737 1.32 is return(EINVAL);
738 1.32 is ospeed = SERBRD(t->c_ospeed);
739 1.32 is }
740 1.32 is
741 1.32 is if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
742 1.14 chopps return(EINVAL);
743 1.14 chopps
744 1.44 is /* XXX missing here: console test */
745 1.44 is if (serswflags & TIOCFLAG_SOFTCAR) {
746 1.44 is t->c_cflag = (t->c_cflag & ~HUPCL) | CLOCAL;
747 1.44 is }
748 1.44 is
749 1.44 is /* if no changes, dont do anything. com.c explains why. */
750 1.44 is if (tp->t_ospeed == t->c_ospeed &&
751 1.44 is tp->t_cflag == t->c_cflag)
752 1.44 is return (0);
753 1.44 is
754 1.44 is cflag = t->c_cflag;
755 1.44 is
756 1.48 is /* todo: 8[EO][12] */
757 1.48 is
758 1.48 is if ((cflag & CSIZE) == CS8 && (cflag & PARENB))
759 1.48 is return (EINVAL); /* XXX TODO: 8bit + parity */
760 1.48 is
761 1.48 is /*
762 1.48 is * We need 8 bits: either 8N or 7E or 7O.
763 1.48 is * 7N, 6x and 5x are invalid.
764 1.48 is */
765 1.48 is
766 1.48 is if ((cflag & CSIZE) == CS7 && !(cflag & PARENB))
767 1.48 is return (EINVAL);
768 1.48 is
769 1.48 is if ((cflag & CSIZE) == CS6)
770 1.48 is return (EINVAL);
771 1.48 is
772 1.48 is if ((cflag & CSIZE) == CS5)
773 1.48 is return (EINVAL);
774 1.48 is
775 1.44 is if (cflag & (CLOCAL | MDMBUF))
776 1.44 is serdcd = 0;
777 1.44 is else
778 1.44 is serdcd = CIAB_PRA_CD;
779 1.44 is
780 1.44 is /* TODO: support multiple flow control protocols like com.c */
781 1.44 is
782 1.14 chopps /*
783 1.14 chopps * copy to tty
784 1.14 chopps */
785 1.14 chopps tp->t_ispeed = t->c_ispeed;
786 1.14 chopps tp->t_ospeed = t->c_ospeed;
787 1.14 chopps tp->t_cflag = cflag;
788 1.42 mhitch ser_open_speed = tp->t_ispeed;
789 1.14 chopps
790 1.48 is if ((tp->t_cflag & CSIZE) == CS7)
791 1.48 is sercharwidth = 7;
792 1.48 is else if ((tp->t_cflag & CSIZE) == CS8)
793 1.48 is sercharwidth = 8;
794 1.48 is
795 1.48 is if (cflag & CSTOPB)
796 1.48 is serstopmask = 3;
797 1.48 is else
798 1.48 is serstopmask = 1;
799 1.48 is
800 1.48 is serstopmask <<= sercharwidth;
801 1.48 is sercharmask = ~((~0) << sercharwidth);
802 1.48 is
803 1.48 is if (cflag & PARENB) {
804 1.48 is serparmask = 1 << sercharwidth;
805 1.48 is serstopmask <<= 1;
806 1.48 is sercharmask <<= 1;
807 1.48 is } else
808 1.48 is serparmask = 0;
809 1.48 is
810 1.48 is if (cflag & PARODD)
811 1.48 is serparoddmask = serparmask;
812 1.48 is else
813 1.48 is serparoddmask = 0;
814 1.48 is
815 1.48 is
816 1.14 chopps /*
817 1.14 chopps * enable interrupts
818 1.14 chopps */
819 1.14 chopps custom.intena = INTF_SETCLR | INTF_RBF | INTF_TBE;
820 1.14 chopps last_ciab_pra = ciab.pra;
821 1.14 chopps
822 1.32 is if (t->c_ospeed == 0)
823 1.14 chopps (void)sermctl(tp->t_dev, 0, DMSET); /* hang up line */
824 1.14 chopps else {
825 1.14 chopps /*
826 1.14 chopps * (re)enable DTR
827 1.14 chopps * and set baud rate. (8 bit mode)
828 1.14 chopps */
829 1.45 is (void)sermctl(tp->t_dev, TIOCM_DTR, DMSET);
830 1.14 chopps custom.serper = (0 << 15) | ospeed;
831 1.14 chopps }
832 1.45 is (void)(*linesw[tp->t_line].l_modem)(tp, ISDCD(last_ciab_pra));
833 1.45 is
834 1.14 chopps return(0);
835 1.1 mw }
836 1.3 mw
837 1.22 chopps int serhwiflow(tp, flag)
838 1.22 chopps struct tty *tp;
839 1.22 chopps int flag;
840 1.22 chopps {
841 1.22 chopps #if 0
842 1.38 christos printf ("serhwiflow %d\n", flag);
843 1.22 chopps #endif
844 1.22 chopps if (flag)
845 1.22 chopps CLRRTS(ciab.pra);
846 1.22 chopps else
847 1.22 chopps SETRTS(ciab.pra);
848 1.22 chopps return 1;
849 1.22 chopps }
850 1.3 mw
851 1.3 mw static void
852 1.14 chopps ser_putchar(tp, c)
853 1.14 chopps struct tty *tp;
854 1.14 chopps u_short c;
855 1.14 chopps {
856 1.48 is c &= sercharmask;
857 1.14 chopps
858 1.14 chopps /*
859 1.14 chopps * handle parity if necessary
860 1.14 chopps */
861 1.48 is if (serparmask) {
862 1.14 chopps if (even_parity[c])
863 1.48 is c |= serparmask;
864 1.48 is c ^= serparoddmask;
865 1.14 chopps }
866 1.14 chopps /*
867 1.14 chopps * add stop bit(s)
868 1.14 chopps */
869 1.48 is c |= serstopmask;
870 1.14 chopps
871 1.14 chopps custom.serdat = c;
872 1.3 mw }
873 1.3 mw
874 1.3 mw
875 1.3 mw static u_char ser_outbuf[SEROBUF_SIZE];
876 1.14 chopps static u_char *sob_ptr = ser_outbuf, *sob_end = ser_outbuf;
877 1.14 chopps
878 1.3 mw void
879 1.14 chopps ser_outintr()
880 1.3 mw {
881 1.44 is struct tty *tp;
882 1.14 chopps int s;
883 1.14 chopps
884 1.44 is tp = ser_tty;
885 1.14 chopps s = spltty();
886 1.14 chopps
887 1.14 chopps if (tp == 0)
888 1.14 chopps goto out;
889 1.14 chopps
890 1.14 chopps if ((custom.intreqr & INTF_TBE) == 0)
891 1.14 chopps goto out;
892 1.14 chopps
893 1.14 chopps /*
894 1.14 chopps * clear interrupt
895 1.14 chopps */
896 1.14 chopps custom.intreq = INTF_TBE;
897 1.14 chopps
898 1.14 chopps if (sob_ptr == sob_end) {
899 1.14 chopps tp->t_state &= ~(TS_BUSY | TS_FLUSH);
900 1.14 chopps if (tp->t_line)
901 1.14 chopps (*linesw[tp->t_line].l_start)(tp);
902 1.14 chopps else
903 1.14 chopps serstart(tp);
904 1.14 chopps goto out;
905 1.14 chopps }
906 1.14 chopps
907 1.14 chopps /*
908 1.14 chopps * Do hardware flow control here. if the CTS line goes down, don't
909 1.14 chopps * transmit anything. That way, we'll be restarted by the periodic
910 1.14 chopps * interrupt when CTS comes back up.
911 1.14 chopps */
912 1.14 chopps if (ISCTS(ciab.pra))
913 1.14 chopps ser_putchar(tp, *sob_ptr++);
914 1.22 chopps else
915 1.22 chopps CLRCTS(last_ciab_pra); /* Remember that CTS is off */
916 1.5 mw out:
917 1.14 chopps splx(s);
918 1.3 mw }
919 1.14 chopps
920 1.31 veego void
921 1.1 mw serstart(tp)
922 1.14 chopps struct tty *tp;
923 1.1 mw {
924 1.44 is int cc, s, hiwat;
925 1.44 is #ifdef DIAGNOSTIC
926 1.44 is int unit;
927 1.44 is #endif
928 1.14 chopps
929 1.14 chopps hiwat = 0;
930 1.14 chopps
931 1.14 chopps if ((tp->t_state & TS_ISOPEN) == 0)
932 1.14 chopps return;
933 1.14 chopps
934 1.44 is #ifdef DIAGNOSTIC
935 1.14 chopps unit = SERUNIT(tp->t_dev);
936 1.44 is if (unit)
937 1.44 is panic("serstart: unit is %d\n", unit);
938 1.44 is #endif
939 1.1 mw
940 1.14 chopps s = spltty();
941 1.14 chopps if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
942 1.14 chopps goto out;
943 1.14 chopps
944 1.14 chopps cc = tp->t_outq.c_cc;
945 1.14 chopps if (cc <= tp->t_lowat) {
946 1.14 chopps if (tp->t_state & TS_ASLEEP) {
947 1.14 chopps tp->t_state &= ~TS_ASLEEP;
948 1.14 chopps wakeup((caddr_t) & tp->t_outq);
949 1.14 chopps }
950 1.14 chopps selwakeup(&tp->t_wsel);
951 1.14 chopps }
952 1.14 chopps if (cc == 0 || (tp->t_state & TS_BUSY))
953 1.14 chopps goto out;
954 1.14 chopps
955 1.14 chopps /*
956 1.14 chopps * We only do bulk transfers if using CTSRTS flow control, not for
957 1.14 chopps * (probably sloooow) ixon/ixoff devices.
958 1.14 chopps */
959 1.14 chopps if ((tp->t_cflag & CRTSCTS) == 0)
960 1.14 chopps cc = 1;
961 1.14 chopps
962 1.14 chopps /*
963 1.14 chopps * Limit the amount of output we do in one burst
964 1.14 chopps * to prevent hogging the CPU.
965 1.14 chopps */
966 1.14 chopps if (cc > SEROBUF_SIZE) {
967 1.14 chopps hiwat++;
968 1.14 chopps cc = SEROBUF_SIZE;
969 1.14 chopps }
970 1.14 chopps cc = q_to_b(&tp->t_outq, ser_outbuf, cc);
971 1.14 chopps if (cc > 0) {
972 1.14 chopps tp->t_state |= TS_BUSY;
973 1.14 chopps
974 1.14 chopps sob_ptr = ser_outbuf;
975 1.14 chopps sob_end = ser_outbuf + cc;
976 1.14 chopps
977 1.14 chopps /*
978 1.14 chopps * Get first character out, then have TBE-interrupts blow out
979 1.14 chopps * further characters, until buffer is empty, and TS_BUSY gets
980 1.14 chopps * cleared.
981 1.14 chopps */
982 1.14 chopps ser_putchar(tp, *sob_ptr++);
983 1.14 chopps }
984 1.14 chopps out:
985 1.14 chopps splx(s);
986 1.1 mw }
987 1.14 chopps
988 1.1 mw /*
989 1.1 mw * Stop output on a line.
990 1.1 mw */
991 1.1 mw /*ARGSUSED*/
992 1.36 mycroft void
993 1.1 mw serstop(tp, flag)
994 1.14 chopps struct tty *tp;
995 1.31 veego int flag;
996 1.1 mw {
997 1.14 chopps int s;
998 1.1 mw
999 1.14 chopps s = spltty();
1000 1.14 chopps if (tp->t_state & TS_BUSY) {
1001 1.14 chopps if ((tp->t_state & TS_TTSTOP) == 0)
1002 1.14 chopps tp->t_state |= TS_FLUSH;
1003 1.14 chopps }
1004 1.14 chopps splx(s);
1005 1.1 mw }
1006 1.14 chopps
1007 1.5 mw int
1008 1.1 mw sermctl(dev, bits, how)
1009 1.14 chopps dev_t dev;
1010 1.14 chopps int bits, how;
1011 1.1 mw {
1012 1.44 is int s;
1013 1.31 veego u_char ub = 0;
1014 1.14 chopps
1015 1.14 chopps /*
1016 1.14 chopps * convert TIOCM* mask into CIA mask
1017 1.14 chopps * which is active low
1018 1.14 chopps */
1019 1.14 chopps if (how != DMGET) {
1020 1.14 chopps ub = 0;
1021 1.14 chopps if (bits & TIOCM_DTR)
1022 1.14 chopps ub |= CIAB_PRA_DTR;
1023 1.14 chopps if (bits & TIOCM_RTS)
1024 1.14 chopps ub |= CIAB_PRA_RTS;
1025 1.14 chopps if (bits & TIOCM_CTS)
1026 1.14 chopps ub |= CIAB_PRA_CTS;
1027 1.14 chopps if (bits & TIOCM_CD)
1028 1.14 chopps ub |= CIAB_PRA_CD;
1029 1.14 chopps if (bits & TIOCM_RI)
1030 1.14 chopps ub |= CIAB_PRA_SEL; /* collision with /dev/par ! */
1031 1.14 chopps if (bits & TIOCM_DSR)
1032 1.14 chopps ub |= CIAB_PRA_DSR;
1033 1.14 chopps }
1034 1.14 chopps s = spltty();
1035 1.14 chopps switch (how) {
1036 1.14 chopps case DMSET:
1037 1.14 chopps /* invert and set */
1038 1.14 chopps ciab.pra = ~ub;
1039 1.14 chopps break;
1040 1.14 chopps
1041 1.14 chopps case DMBIC:
1042 1.14 chopps ciab.pra |= ub;
1043 1.14 chopps ub = ~ciab.pra;
1044 1.14 chopps break;
1045 1.14 chopps
1046 1.14 chopps case DMBIS:
1047 1.14 chopps ciab.pra &= ~ub;
1048 1.14 chopps ub = ~ciab.pra;
1049 1.14 chopps break;
1050 1.14 chopps
1051 1.14 chopps case DMGET:
1052 1.14 chopps ub = ~ciab.pra;
1053 1.14 chopps break;
1054 1.14 chopps }
1055 1.14 chopps (void)splx(s);
1056 1.14 chopps
1057 1.14 chopps bits = 0;
1058 1.14 chopps if (ub & CIAB_PRA_DTR)
1059 1.14 chopps bits |= TIOCM_DTR;
1060 1.14 chopps if (ub & CIAB_PRA_RTS)
1061 1.14 chopps bits |= TIOCM_RTS;
1062 1.14 chopps if (ub & CIAB_PRA_CTS)
1063 1.14 chopps bits |= TIOCM_CTS;
1064 1.14 chopps if (ub & CIAB_PRA_CD)
1065 1.14 chopps bits |= TIOCM_CD;
1066 1.14 chopps if (ub & CIAB_PRA_SEL)
1067 1.14 chopps bits |= TIOCM_RI;
1068 1.14 chopps if (ub & CIAB_PRA_DSR)
1069 1.14 chopps bits |= TIOCM_DSR;
1070 1.14 chopps
1071 1.14 chopps return(bits);
1072 1.1 mw }
1073 1.1 mw
1074 1.1 mw /*
1075 1.1 mw * Following are all routines needed for SER to act as console
1076 1.1 mw */
1077 1.31 veego void
1078 1.1 mw sercnprobe(cp)
1079 1.1 mw struct consdev *cp;
1080 1.1 mw {
1081 1.44 is int unit;
1082 1.14 chopps
1083 1.14 chopps /* locate the major number */
1084 1.14 chopps for (sermajor = 0; sermajor < nchrdev; sermajor++)
1085 1.14 chopps if (cdevsw[sermajor].d_open == (void *)seropen)
1086 1.14 chopps break;
1087 1.14 chopps
1088 1.14 chopps
1089 1.14 chopps unit = CONUNIT; /* XXX: ick */
1090 1.14 chopps
1091 1.14 chopps /*
1092 1.14 chopps * initialize required fields
1093 1.14 chopps */
1094 1.14 chopps cp->cn_dev = makedev(sermajor, unit);
1095 1.14 chopps if (serconsole == unit)
1096 1.14 chopps cp->cn_pri = CN_REMOTE;
1097 1.14 chopps else
1098 1.14 chopps cp->cn_pri = CN_NORMAL;
1099 1.1 mw #ifdef KGDB
1100 1.14 chopps if (major(kgdb_dev) == 1) /* XXX */
1101 1.14 chopps kgdb_dev = makedev(sermajor, minor(kgdb_dev));
1102 1.1 mw #endif
1103 1.1 mw }
1104 1.1 mw
1105 1.31 veego void
1106 1.1 mw sercninit(cp)
1107 1.1 mw struct consdev *cp;
1108 1.1 mw {
1109 1.14 chopps int unit;
1110 1.1 mw
1111 1.14 chopps unit = SERUNIT(cp->cn_dev);
1112 1.14 chopps
1113 1.44 is serinit(serdefaultrate);
1114 1.14 chopps serconsole = unit;
1115 1.14 chopps serconsinit = 1;
1116 1.1 mw }
1117 1.1 mw
1118 1.31 veego void
1119 1.44 is serinit(rate)
1120 1.44 is int rate;
1121 1.1 mw {
1122 1.14 chopps int s;
1123 1.1 mw
1124 1.26 chopps s = splser();
1125 1.14 chopps /*
1126 1.14 chopps * might want to fiddle with the CIA later ???
1127 1.14 chopps */
1128 1.32 is custom.serper = (rate>=110 ? SERBRD(rate) : 0);
1129 1.14 chopps splx(s);
1130 1.1 mw }
1131 1.1 mw
1132 1.31 veego int
1133 1.1 mw sercngetc(dev)
1134 1.31 veego dev_t dev;
1135 1.1 mw {
1136 1.14 chopps u_short stat;
1137 1.14 chopps int c, s;
1138 1.1 mw
1139 1.26 chopps s = splser();
1140 1.14 chopps /*
1141 1.14 chopps * poll
1142 1.14 chopps */
1143 1.14 chopps while (((stat = custom.serdatr & 0xffff) & SERDATRF_RBF) == 0)
1144 1.14 chopps ;
1145 1.14 chopps c = stat & 0xff;
1146 1.14 chopps /*
1147 1.14 chopps * clear interrupt
1148 1.14 chopps */
1149 1.14 chopps custom.intreq = INTF_RBF;
1150 1.14 chopps splx(s);
1151 1.14 chopps return(c);
1152 1.1 mw }
1153 1.1 mw
1154 1.1 mw /*
1155 1.1 mw * Console kernel output character routine.
1156 1.1 mw */
1157 1.31 veego void
1158 1.1 mw sercnputc(dev, c)
1159 1.14 chopps dev_t dev;
1160 1.14 chopps int c;
1161 1.1 mw {
1162 1.14 chopps register int timo;
1163 1.14 chopps int s;
1164 1.14 chopps
1165 1.14 chopps s = splhigh();
1166 1.1 mw
1167 1.14 chopps if (serconsinit == 0) {
1168 1.44 is (void)serinit(serdefaultrate);
1169 1.14 chopps serconsinit = 1;
1170 1.14 chopps }
1171 1.14 chopps
1172 1.14 chopps /*
1173 1.14 chopps * wait for any pending transmission to finish
1174 1.14 chopps */
1175 1.14 chopps timo = 50000;
1176 1.14 chopps while (!(custom.serdatr & SERDATRF_TBE) && --timo);
1177 1.14 chopps
1178 1.14 chopps /*
1179 1.14 chopps * transmit char.
1180 1.14 chopps */
1181 1.14 chopps custom.serdat = (c & 0xff) | 0x100;
1182 1.14 chopps
1183 1.14 chopps /*
1184 1.14 chopps * wait for this transmission to complete
1185 1.14 chopps */
1186 1.14 chopps timo = 1500000;
1187 1.14 chopps while (!(custom.serdatr & SERDATRF_TBE) && --timo)
1188 1.14 chopps ;
1189 1.14 chopps
1190 1.14 chopps /*
1191 1.14 chopps * Wait for the device (my vt100..) to process the data, since we
1192 1.14 chopps * don't do flow-control with cnputc
1193 1.14 chopps */
1194 1.14 chopps for (timo = 0; timo < 30000; timo++)
1195 1.14 chopps ;
1196 1.14 chopps
1197 1.14 chopps /*
1198 1.14 chopps * clear any interrupts generated by this transmission
1199 1.14 chopps */
1200 1.14 chopps custom.intreq = INTF_TBE;
1201 1.14 chopps splx(s);
1202 1.25 chopps }
1203 1.25 chopps
1204 1.25 chopps void
1205 1.25 chopps sercnpollc(dev, on)
1206 1.25 chopps dev_t dev;
1207 1.25 chopps int on;
1208 1.25 chopps {
1209 1.1 mw }
1210 1.1 mw #endif
1211