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