com.c revision 1.79 1 /* $NetBSD: com.c,v 1.79 1996/04/15 18:54:31 cgd Exp $ */
2
3 /*-
4 * Copyright (c) 1993, 1994, 1995, 1996
5 * Charles M. Hannum. All rights reserved.
6 * Copyright (c) 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)com.c 7.5 (Berkeley) 5/16/91
38 */
39
40 /*
41 * COM driver, based on HP dca driver
42 * uses National Semiconductor NS16450/NS16550AF UART
43 */
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/ioctl.h>
47 #include <sys/select.h>
48 #include <sys/tty.h>
49 #include <sys/proc.h>
50 #include <sys/user.h>
51 #include <sys/conf.h>
52 #include <sys/file.h>
53 #include <sys/uio.h>
54 #include <sys/kernel.h>
55 #include <sys/syslog.h>
56 #include <sys/types.h>
57 #include <sys/device.h>
58
59 #ifdef i386 /* XXX */
60 #include <machine/cpu.h> /* XXX */
61 #else /* XXX */
62 #include <machine/intr.h>
63 #endif /* XXX */
64 #include <machine/bus.h>
65
66 #include <dev/isa/isavar.h>
67 #include <dev/isa/comreg.h>
68 #include <dev/isa/comvar.h>
69 #include <dev/ic/ns16550reg.h>
70 #ifdef COM_HAYESP
71 #include <dev/ic/hayespreg.h>
72 #endif
73 #define com_lcr com_cfcr
74
75 #include "com.h"
76
77 #define COM_IBUFSIZE (2 * 512)
78 #define COM_IHIGHWATER ((3 * COM_IBUFSIZE) / 4)
79
80 struct com_softc {
81 struct device sc_dev;
82 void *sc_ih;
83 struct tty *sc_tty;
84
85 int sc_overflows;
86 int sc_floods;
87 int sc_errors;
88
89 int sc_halt;
90
91 int sc_iobase;
92 #ifdef COM_HAYESP
93 int sc_hayespbase;
94 #endif
95
96 bus_chipset_tag_t sc_bc;
97 bus_io_handle_t sc_ioh;
98 bus_io_handle_t sc_hayespioh;
99
100 u_char sc_hwflags;
101 #define COM_HW_NOIEN 0x01
102 #define COM_HW_FIFO 0x02
103 #define COM_HW_HAYESP 0x04
104 #define COM_HW_CONSOLE 0x40
105 u_char sc_swflags;
106 #define COM_SW_SOFTCAR 0x01
107 #define COM_SW_CLOCAL 0x02
108 #define COM_SW_CRTSCTS 0x04
109 #define COM_SW_MDMBUF 0x08
110 u_char sc_msr, sc_mcr, sc_lcr, sc_ier;
111 u_char sc_dtr;
112
113 u_char *sc_ibuf, *sc_ibufp, *sc_ibufhigh, *sc_ibufend;
114 u_char sc_ibufs[2][COM_IBUFSIZE];
115 };
116
117 #ifdef COM_HAYESP
118 int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
119 #endif
120 int comopen __P((dev_t, int, int, struct proc *));
121 int comclose __P((dev_t, int, int, struct proc *));
122 void comdiag __P((void *));
123 int comintr __P((void *));
124 void compoll __P((void *));
125 int comparam __P((struct tty *, struct termios *));
126 void comstart __P((struct tty *));
127
128 /*
129 * XXX the following two cfattach structs should be different, and possibly
130 * XXX elsewhere.
131 */
132 int comprobe __P((struct device *, void *, void *));
133 void comattach __P((struct device *, struct device *, void *));
134
135 #if NCOM_ISA
136 struct cfattach com_isa_ca = {
137 sizeof(struct com_softc), comprobe, comattach
138 };
139 #endif
140
141 #if NCOM_COMMULTI
142 struct cfattach com_commulti_ca = {
143 sizeof(struct com_softc), comprobe, comattach
144 };
145 #endif
146
147 struct cfdriver com_cd = {
148 NULL, "com", DV_TTY
149 };
150
151 int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
152
153 #ifdef COMCONSOLE
154 int comdefaultrate = CONSPEED; /* XXX why set default? */
155 #else
156 int comdefaultrate = TTYDEF_SPEED;
157 #endif
158 int comconsaddr;
159 int comconsinit;
160 int comconsattached;
161 bus_chipset_tag_t comconsbc;
162 bus_io_handle_t comconsioh;
163 tcflag_t comconscflag = TTYDEF_CFLAG;
164
165 int commajor;
166 int comsopen = 0;
167 int comevents = 0;
168
169 #ifdef KGDB
170 #include <machine/remote-sl.h>
171 extern int kgdb_dev;
172 extern int kgdb_rate;
173 extern int kgdb_debug_init;
174 #endif
175
176 #define COMUNIT(x) (minor(x))
177
178 /* Macros to clear/set/test flags. */
179 #define SET(t, f) (t) |= (f)
180 #define CLR(t, f) (t) &= ~(f)
181 #define ISSET(t, f) ((t) & (f))
182
183 int
184 comspeed(speed)
185 long speed;
186 {
187 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
188
189 int x, err;
190
191 if (speed == 0)
192 return 0;
193 if (speed < 0)
194 return -1;
195 x = divrnd((COM_FREQ / 16), speed);
196 if (x <= 0)
197 return -1;
198 err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
199 if (err < 0)
200 err = -err;
201 if (err > COM_TOLERANCE)
202 return -1;
203 return x;
204
205 #undef divrnd(n, q)
206 }
207
208 int
209 comprobe1(bc, ioh, iobase)
210 bus_chipset_tag_t bc;
211 bus_io_handle_t ioh;
212 int iobase;
213 {
214
215 /* force access to id reg */
216 bus_io_write_1(bc, ioh, com_lcr, 0);
217 bus_io_write_1(bc, ioh, com_iir, 0);
218 if (bus_io_read_1(bc, ioh, com_iir) & 0x38)
219 return 0;
220
221 return 1;
222 }
223
224 #ifdef COM_HAYESP
225 int
226 comprobeHAYESP(hayespioh, sc)
227 bus_io_handle_t hayespioh;
228 struct com_softc *sc;
229 {
230 char val, dips;
231 int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
232 bus_chipset_tag_t bc = sc->sc_bc;
233
234 /*
235 * Hayes ESP cards have two iobases. One is for compatibility with
236 * 16550 serial chips, and at the same ISA PC base addresses. The
237 * other is for ESP-specific enhanced features, and lies at a
238 * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
239 */
240
241 /* Test for ESP signature */
242 if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
243 return 0;
244
245 /*
246 * ESP is present at ESP enhanced base address; unknown com port
247 */
248
249 /* Get the dip-switch configurations */
250 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
251 dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
252
253 /* Determine which com port this ESP card services: bits 0,1 of */
254 /* dips is the port # (0-3); combaselist[val] is the com_iobase */
255 if (sc->sc_iobase != combaselist[dips & 0x03])
256 return 0;
257
258 printf(": ESP");
259
260 /* Check ESP Self Test bits. */
261 /* Check for ESP version 2.0: bits 4,5,6 == 010 */
262 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
263 val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
264 val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
265 if ((val & 0x70) < 0x20) {
266 printf("-old (%o)", val & 0x70);
267 /* we do not support the necessary features */
268 return 0;
269 }
270
271 /* Check for ability to emulate 16550: bit 8 == 1 */
272 if ((dips & 0x80) == 0) {
273 printf(" slave");
274 /* XXX Does slave really mean no 16550 support?? */
275 return 0;
276 }
277
278 /*
279 * If we made it this far, we are a full-featured ESP v2.0 (or
280 * better), at the correct com port address.
281 */
282
283 SET(sc->sc_hwflags, COM_HW_HAYESP);
284 printf(", 1024 byte fifo\n");
285 return 1;
286 }
287 #endif
288
289 int
290 comprobe(parent, match, aux)
291 struct device *parent;
292 void *match, *aux;
293 {
294 struct cfdata *cf = match;
295 bus_chipset_tag_t bc;
296 bus_io_handle_t ioh;
297 int iobase, needioh;
298 int rv = 1;
299
300 /*
301 * XXX should be broken out into functions for isa probe and
302 * XXX for commulti probe, with a helper function that contains
303 * XXX most of the interesting stuff.
304 */
305 #if NCOM_ISA
306 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
307 struct isa_attach_args *ia = aux;
308
309 bc = ia->ia_bc;
310 iobase = ia->ia_iobase;
311 needioh = 1;
312 } else
313 #endif
314 #if NCOM_COMMULTI
315 if (1) {
316 struct commulti_attach_args *ca = aux;
317
318 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
319 return (0);
320
321 bc = ca->ca_bc;
322 iobase = ca->ca_iobase;
323 ioh = ca->ca_ioh;
324 needioh = 0;
325 } else
326 #endif
327 return(0); /* This cannot happen */
328
329 /* if it's in use as console, it's there. */
330 if (iobase == comconsaddr && !comconsattached)
331 goto out;
332
333 if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
334 rv = 0;
335 goto out;
336 }
337 rv = comprobe1(bc, ioh, iobase);
338 if (needioh)
339 bus_io_unmap(bc, ioh, COM_NPORTS);
340
341 out:
342 #if NCOM_ISA
343 if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
344 struct isa_attach_args *ia = aux;
345
346 ia->ia_iosize = COM_NPORTS;
347 ia->ia_msize = 0;
348 }
349 #endif
350 return (rv);
351 }
352
353 void
354 comattach(parent, self, aux)
355 struct device *parent, *self;
356 void *aux;
357 {
358 struct com_softc *sc = (void *)self;
359 struct cfdata *cf = sc->sc_dev.dv_cfdata;
360 int iobase, irq;
361 bus_chipset_tag_t bc;
362 bus_io_handle_t ioh;
363 struct tty *tp;
364 #ifdef COM_HAYESP
365 int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
366 int *hayespp;
367 #endif
368
369 /*
370 * XXX should be broken out into functions for isa attach and
371 * XXX for commulti attach, with a helper function that contains
372 * XXX most of the interesting stuff.
373 */
374 sc->sc_hwflags = 0;
375 sc->sc_swflags = 0;
376 #if NCOM_ISA
377 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
378 struct isa_attach_args *ia = aux;
379
380 /*
381 * We're living on an isa.
382 */
383 iobase = ia->ia_iobase;
384 bc = ia->ia_bc;
385 if (iobase != comconsaddr) {
386 if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
387 panic("comattach: io mapping failed");
388 } else
389 ioh = comconsioh;
390 irq = ia->ia_irq;
391 } else
392 #endif
393 #if NCOM_COMMULTI
394 if (1) {
395 struct commulti_attach_args *ca = aux;
396
397 /*
398 * We're living on a commulti.
399 */
400 iobase = ca->ca_iobase;
401 bc = ca->ca_bc;
402 ioh = ca->ca_ioh;
403 irq = IRQUNK;
404
405 if (ca->ca_noien)
406 sc->sc_hwflags |= COM_HW_NOIEN;
407 } else
408 #endif
409 panic("comattach: impossible");
410
411 sc->sc_bc = bc;
412 sc->sc_ioh = ioh;
413 sc->sc_iobase = iobase;
414
415 if (iobase == comconsaddr) {
416 comconsattached = 1;
417
418 /*
419 * Need to reset baud rate, etc. of next print so reset
420 * comconsinit. Also make sure console is always "hardwired".
421 */
422 delay(1000); /* wait for output to finish */
423 comconsinit = 0;
424 SET(sc->sc_hwflags, COM_HW_CONSOLE);
425 SET(sc->sc_swflags, COM_SW_SOFTCAR);
426 }
427
428 #ifdef COM_HAYESP
429 /* Look for a Hayes ESP board. */
430 for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
431 bus_io_handle_t hayespioh;
432
433 #define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */
434 if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
435 continue;
436 if (comprobeHAYESP(hayespioh, sc)) {
437 sc->sc_hayespbase = *hayespp;
438 sc->sc_hayespioh = hayespioh;
439 break;
440 }
441 bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
442 }
443 /* No ESP; look for other things. */
444 if (*hayespp == 0) {
445 #endif
446
447 /* look for a NS 16550AF UART with FIFOs */
448 bus_io_write_1(bc, ioh, com_fifo,
449 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
450 delay(100);
451 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
452 if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
453 SET(sc->sc_hwflags, COM_HW_FIFO);
454 printf(": ns16550a, working fifo\n");
455 } else
456 printf(": ns16550, broken fifo\n");
457 else
458 printf(": ns8250 or ns16450, no fifo\n");
459 bus_io_write_1(bc, ioh, com_fifo, 0);
460 #ifdef COM_HAYESP
461 }
462 #endif
463
464 /* disable interrupts */
465 bus_io_write_1(bc, ioh, com_ier, 0);
466 bus_io_write_1(bc, ioh, com_mcr, 0);
467
468 if (irq != IRQUNK) {
469 #if NCOM_ISA
470 if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
471 struct isa_attach_args *ia = aux;
472
473 sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
474 IST_EDGE, IPL_TTY, comintr, sc);
475 } else
476 #endif
477 panic("comattach: IRQ but can't have one");
478 }
479
480 #ifdef KGDB
481 if (kgdb_dev == makedev(commajor, unit)) {
482 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
483 kgdb_dev = -1; /* can't debug over console port */
484 else {
485 (void) cominit(bc, ioh, kgdb_rate);
486 if (kgdb_debug_init) {
487 /*
488 * Print prefix of device name,
489 * let kgdb_connect print the rest.
490 */
491 printf("%s: ", sc->sc_dev.dv_xname);
492 kgdb_connect(1);
493 } else
494 printf("%s: kgdb enabled\n",
495 sc->sc_dev.dv_xname);
496 }
497 }
498 #endif
499
500 /* XXX maybe move up some? */
501 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
502 printf("%s: console\n", sc->sc_dev.dv_xname);
503 }
504
505 int
506 comopen(dev, flag, mode, p)
507 dev_t dev;
508 int flag, mode;
509 struct proc *p;
510 {
511 int unit = COMUNIT(dev);
512 struct com_softc *sc;
513 bus_chipset_tag_t bc;
514 bus_io_handle_t ioh;
515 struct tty *tp;
516 int s;
517 int error = 0;
518
519 if (unit >= com_cd.cd_ndevs)
520 return ENXIO;
521 sc = com_cd.cd_devs[unit];
522 if (!sc)
523 return ENXIO;
524
525 if (!sc->sc_tty)
526 tp = sc->sc_tty = ttymalloc();
527 else
528 tp = sc->sc_tty;
529
530 tp->t_oproc = comstart;
531 tp->t_param = comparam;
532 tp->t_dev = dev;
533 if (!ISSET(tp->t_state, TS_ISOPEN)) {
534 SET(tp->t_state, TS_WOPEN);
535 ttychars(tp);
536 tp->t_iflag = TTYDEF_IFLAG;
537 tp->t_oflag = TTYDEF_OFLAG;
538 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
539 tp->t_cflag = comconscflag;
540 else
541 tp->t_cflag = TTYDEF_CFLAG;
542 if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
543 SET(tp->t_cflag, CLOCAL);
544 if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
545 SET(tp->t_cflag, CRTSCTS);
546 if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
547 SET(tp->t_cflag, MDMBUF);
548 tp->t_lflag = TTYDEF_LFLAG;
549 tp->t_ispeed = tp->t_ospeed = comdefaultrate;
550
551 s = spltty();
552
553 comparam(tp, &tp->t_termios);
554 ttsetwater(tp);
555
556 if (comsopen++ == 0)
557 timeout(compoll, NULL, 1);
558
559 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
560 sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
561 sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
562
563 bc = sc->sc_bc;
564 ioh = sc->sc_ioh;
565 #ifdef COM_HAYESP
566 /* Setup the ESP board */
567 if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
568 bus_io_handle_t hayespioh = sc->sc_hayespioh;
569
570 bus_io_write_1(bc, ioh, com_fifo,
571 FIFO_DMA_MODE|FIFO_ENABLE|
572 FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
573
574 /* Set 16550 compatibility mode */
575 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
576 bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
577 HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
578 HAYESP_MODE_SCALE);
579
580 /* Set RTS/CTS flow control */
581 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
582 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
583 bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
584
585 /* Set flow control levels */
586 bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
587 bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
588 HAYESP_HIBYTE(HAYESP_RXHIWMARK));
589 bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
590 HAYESP_LOBYTE(HAYESP_RXHIWMARK));
591 bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
592 HAYESP_HIBYTE(HAYESP_RXLOWMARK));
593 bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
594 HAYESP_LOBYTE(HAYESP_RXLOWMARK));
595 } else
596 #endif
597 if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
598 /* Set the FIFO threshold based on the receive speed. */
599 bus_io_write_1(bc, ioh, com_fifo,
600 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
601 (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
602 /* flush any pending I/O */
603 while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
604 (void) bus_io_read_1(bc, ioh, com_data);
605 /* you turn me on, baby */
606 sc->sc_mcr = MCR_DTR | MCR_RTS;
607 if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
608 SET(sc->sc_mcr, MCR_IENABLE);
609 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
610 sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
611 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
612
613 sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
614 if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
615 ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
616 SET(tp->t_state, TS_CARR_ON);
617 else
618 CLR(tp->t_state, TS_CARR_ON);
619 } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
620 return EBUSY;
621 else
622 s = spltty();
623
624 /* wait for carrier if necessary */
625 if (!ISSET(flag, O_NONBLOCK))
626 while (!ISSET(tp->t_cflag, CLOCAL) &&
627 !ISSET(tp->t_state, TS_CARR_ON)) {
628 SET(tp->t_state, TS_WOPEN);
629 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
630 ttopen, 0);
631 if (error) {
632 /* XXX should turn off chip if we're the
633 only waiter */
634 splx(s);
635 return error;
636 }
637 }
638 splx(s);
639
640 return (*linesw[tp->t_line].l_open)(dev, tp);
641 }
642
643 int
644 comclose(dev, flag, mode, p)
645 dev_t dev;
646 int flag, mode;
647 struct proc *p;
648 {
649 int unit = COMUNIT(dev);
650 struct com_softc *sc = com_cd.cd_devs[unit];
651 struct tty *tp = sc->sc_tty;
652 bus_chipset_tag_t bc = sc->sc_bc;
653 bus_io_handle_t ioh = sc->sc_ioh;
654 int s;
655
656 /* XXX This is for cons.c. */
657 if (!ISSET(tp->t_state, TS_ISOPEN))
658 return 0;
659
660 (*linesw[tp->t_line].l_close)(tp, flag);
661 s = spltty();
662 CLR(sc->sc_lcr, LCR_SBREAK);
663 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
664 bus_io_write_1(bc, ioh, com_ier, 0);
665 if (ISSET(tp->t_cflag, HUPCL) &&
666 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
667 /* XXX perhaps only clear DTR */
668 bus_io_write_1(bc, ioh, com_mcr, 0);
669 }
670 CLR(tp->t_state, TS_BUSY | TS_FLUSH);
671 if (--comsopen == 0)
672 untimeout(compoll, NULL);
673 splx(s);
674 ttyclose(tp);
675 #ifdef notyet /* XXXX */
676 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
677 ttyfree(tp);
678 sc->sc_tty = 0;
679 }
680 #endif
681 return 0;
682 }
683
684 int
685 comread(dev, uio, flag)
686 dev_t dev;
687 struct uio *uio;
688 int flag;
689 {
690 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
691 struct tty *tp = sc->sc_tty;
692
693 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
694 }
695
696 int
697 comwrite(dev, uio, flag)
698 dev_t dev;
699 struct uio *uio;
700 int flag;
701 {
702 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
703 struct tty *tp = sc->sc_tty;
704
705 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
706 }
707
708 struct tty *
709 comtty(dev)
710 dev_t dev;
711 {
712 struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
713 struct tty *tp = sc->sc_tty;
714
715 return (tp);
716 }
717
718 static u_char
719 tiocm_xxx2mcr(data)
720 int data;
721 {
722 u_char m = 0;
723
724 if (ISSET(data, TIOCM_DTR))
725 SET(m, MCR_DTR);
726 if (ISSET(data, TIOCM_RTS))
727 SET(m, MCR_RTS);
728 return m;
729 }
730
731 int
732 comioctl(dev, cmd, data, flag, p)
733 dev_t dev;
734 u_long cmd;
735 caddr_t data;
736 int flag;
737 struct proc *p;
738 {
739 int unit = COMUNIT(dev);
740 struct com_softc *sc = com_cd.cd_devs[unit];
741 struct tty *tp = sc->sc_tty;
742 bus_chipset_tag_t bc = sc->sc_bc;
743 bus_io_handle_t ioh = sc->sc_ioh;
744 int error;
745
746 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
747 if (error >= 0)
748 return error;
749 error = ttioctl(tp, cmd, data, flag, p);
750 if (error >= 0)
751 return error;
752
753 switch (cmd) {
754 case TIOCSBRK:
755 SET(sc->sc_lcr, LCR_SBREAK);
756 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
757 break;
758 case TIOCCBRK:
759 CLR(sc->sc_lcr, LCR_SBREAK);
760 bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
761 break;
762 case TIOCSDTR:
763 SET(sc->sc_mcr, sc->sc_dtr);
764 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
765 break;
766 case TIOCCDTR:
767 CLR(sc->sc_mcr, sc->sc_dtr);
768 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
769 break;
770 case TIOCMSET:
771 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
772 case TIOCMBIS:
773 SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
774 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
775 break;
776 case TIOCMBIC:
777 CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
778 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
779 break;
780 case TIOCMGET: {
781 u_char m;
782 int bits = 0;
783
784 m = sc->sc_mcr;
785 if (ISSET(m, MCR_DTR))
786 SET(bits, TIOCM_DTR);
787 if (ISSET(m, MCR_RTS))
788 SET(bits, TIOCM_RTS);
789 m = sc->sc_msr;
790 if (ISSET(m, MSR_DCD))
791 SET(bits, TIOCM_CD);
792 if (ISSET(m, MSR_CTS))
793 SET(bits, TIOCM_CTS);
794 if (ISSET(m, MSR_DSR))
795 SET(bits, TIOCM_DSR);
796 if (ISSET(m, MSR_RI | MSR_TERI))
797 SET(bits, TIOCM_RI);
798 if (bus_io_read_1(bc, ioh, com_ier))
799 SET(bits, TIOCM_LE);
800 *(int *)data = bits;
801 break;
802 }
803 case TIOCGFLAGS: {
804 int driverbits, userbits = 0;
805
806 driverbits = sc->sc_swflags;
807 if (ISSET(driverbits, COM_SW_SOFTCAR))
808 SET(userbits, TIOCFLAG_SOFTCAR);
809 if (ISSET(driverbits, COM_SW_CLOCAL))
810 SET(userbits, TIOCFLAG_CLOCAL);
811 if (ISSET(driverbits, COM_SW_CRTSCTS))
812 SET(userbits, TIOCFLAG_CRTSCTS);
813 if (ISSET(driverbits, COM_SW_MDMBUF))
814 SET(userbits, TIOCFLAG_MDMBUF);
815
816 *(int *)data = userbits;
817 break;
818 }
819 case TIOCSFLAGS: {
820 int userbits, driverbits = 0;
821
822 error = suser(p->p_ucred, &p->p_acflag);
823 if (error != 0)
824 return(EPERM);
825
826 userbits = *(int *)data;
827 if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
828 ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
829 SET(driverbits, COM_SW_SOFTCAR);
830 if (ISSET(userbits, TIOCFLAG_CLOCAL))
831 SET(driverbits, COM_SW_CLOCAL);
832 if (ISSET(userbits, TIOCFLAG_CRTSCTS))
833 SET(driverbits, COM_SW_CRTSCTS);
834 if (ISSET(userbits, TIOCFLAG_MDMBUF))
835 SET(driverbits, COM_SW_MDMBUF);
836
837 sc->sc_swflags = driverbits;
838 break;
839 }
840 default:
841 return ENOTTY;
842 }
843
844 return 0;
845 }
846
847 int
848 comparam(tp, t)
849 struct tty *tp;
850 struct termios *t;
851 {
852 struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
853 bus_chipset_tag_t bc = sc->sc_bc;
854 bus_io_handle_t ioh = sc->sc_ioh;
855 int ospeed = comspeed(t->c_ospeed);
856 u_char lcr;
857 tcflag_t oldcflag;
858 int s;
859
860 /* check requested parameters */
861 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
862 return EINVAL;
863
864 lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
865
866 switch (ISSET(t->c_cflag, CSIZE)) {
867 case CS5:
868 SET(lcr, LCR_5BITS);
869 break;
870 case CS6:
871 SET(lcr, LCR_6BITS);
872 break;
873 case CS7:
874 SET(lcr, LCR_7BITS);
875 break;
876 case CS8:
877 SET(lcr, LCR_8BITS);
878 break;
879 }
880 if (ISSET(t->c_cflag, PARENB)) {
881 SET(lcr, LCR_PENAB);
882 if (!ISSET(t->c_cflag, PARODD))
883 SET(lcr, LCR_PEVEN);
884 }
885 if (ISSET(t->c_cflag, CSTOPB))
886 SET(lcr, LCR_STOPB);
887
888 sc->sc_lcr = lcr;
889
890 s = spltty();
891
892 if (ospeed == 0) {
893 CLR(sc->sc_mcr, MCR_DTR);
894 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
895 }
896
897 /*
898 * Set the FIFO threshold based on the receive speed, if we are
899 * changing it.
900 */
901 #if 1
902 if (tp->t_ispeed != t->c_ispeed) {
903 #else
904 if (1) {
905 #endif
906 if (ospeed != 0) {
907 /*
908 * Make sure the transmit FIFO is empty before
909 * proceeding. If we don't do this, some revisions
910 * of the UART will hang. Interestingly enough,
911 * even if we do this will the last character is
912 * still being pushed out, they don't hang. This
913 * seems good enough.
914 */
915 while (ISSET(tp->t_state, TS_BUSY)) {
916 int error;
917
918 ++sc->sc_halt;
919 error = ttysleep(tp, &tp->t_outq,
920 TTOPRI | PCATCH, "comprm", 0);
921 --sc->sc_halt;
922 if (error) {
923 splx(s);
924 comstart(tp);
925 return (error);
926 }
927 }
928
929 bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
930 bus_io_write_1(bc, ioh, com_dlbl, ospeed);
931 bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
932 bus_io_write_1(bc, ioh, com_lcr, lcr);
933 SET(sc->sc_mcr, MCR_DTR);
934 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
935 } else
936 bus_io_write_1(bc, ioh, com_lcr, lcr);
937
938 if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
939 ISSET(sc->sc_hwflags, COM_HW_FIFO))
940 bus_io_write_1(bc, ioh, com_fifo,
941 FIFO_ENABLE |
942 (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
943 } else
944 bus_io_write_1(bc, ioh, com_lcr, lcr);
945
946 /* When not using CRTSCTS, RTS follows DTR. */
947 if (!ISSET(t->c_cflag, CRTSCTS)) {
948 if (ISSET(sc->sc_mcr, MCR_DTR)) {
949 if (!ISSET(sc->sc_mcr, MCR_RTS)) {
950 SET(sc->sc_mcr, MCR_RTS);
951 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
952 }
953 } else {
954 if (ISSET(sc->sc_mcr, MCR_RTS)) {
955 CLR(sc->sc_mcr, MCR_RTS);
956 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
957 }
958 }
959 sc->sc_dtr = MCR_DTR | MCR_RTS;
960 } else
961 sc->sc_dtr = MCR_DTR;
962
963 /* and copy to tty */
964 tp->t_ispeed = t->c_ispeed;
965 tp->t_ospeed = t->c_ospeed;
966 oldcflag = tp->t_cflag;
967 tp->t_cflag = t->c_cflag;
968
969 /*
970 * If DCD is off and MDMBUF is changed, ask the tty layer if we should
971 * stop the device.
972 */
973 if (!ISSET(sc->sc_msr, MSR_DCD) &&
974 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
975 ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
976 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
977 CLR(sc->sc_mcr, sc->sc_dtr);
978 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
979 }
980
981 /* Just to be sure... */
982 splx(s);
983 comstart(tp);
984 return 0;
985 }
986
987 void
988 comstart(tp)
989 struct tty *tp;
990 {
991 struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
992 bus_chipset_tag_t bc = sc->sc_bc;
993 bus_io_handle_t ioh = sc->sc_ioh;
994 int s;
995
996 s = spltty();
997 if (ISSET(tp->t_state, TS_BUSY))
998 goto out;
999 if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) ||
1000 sc->sc_halt > 0)
1001 goto stopped;
1002 if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
1003 goto stopped;
1004 if (tp->t_outq.c_cc <= tp->t_lowat) {
1005 if (ISSET(tp->t_state, TS_ASLEEP)) {
1006 CLR(tp->t_state, TS_ASLEEP);
1007 wakeup(&tp->t_outq);
1008 }
1009 if (tp->t_outq.c_cc == 0)
1010 goto stopped;
1011 selwakeup(&tp->t_wsel);
1012 }
1013 SET(tp->t_state, TS_BUSY);
1014
1015 if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
1016 SET(sc->sc_ier, IER_ETXRDY);
1017 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
1018 }
1019 #ifdef COM_HAYESP
1020 if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
1021 u_char buffer[1024], *cp = buffer;
1022 int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
1023 do
1024 bus_io_write_1(bc, ioh, com_data, *cp++);
1025 while (--n);
1026 }
1027 else
1028 #endif
1029 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
1030 u_char buffer[16], *cp = buffer;
1031 int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
1032 do {
1033 bus_io_write_1(bc, ioh, com_data, *cp++);
1034 } while (--n);
1035 } else
1036 bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
1037 out:
1038 splx(s);
1039 return;
1040 stopped:
1041 if (ISSET(sc->sc_ier, IER_ETXRDY)) {
1042 CLR(sc->sc_ier, IER_ETXRDY);
1043 bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
1044 }
1045 splx(s);
1046 }
1047
1048 /*
1049 * Stop output on a line.
1050 */
1051 void
1052 comstop(tp, flag)
1053 struct tty *tp;
1054 {
1055 int s;
1056
1057 s = spltty();
1058 if (ISSET(tp->t_state, TS_BUSY))
1059 if (!ISSET(tp->t_state, TS_TTSTOP))
1060 SET(tp->t_state, TS_FLUSH);
1061 splx(s);
1062 }
1063
1064 void
1065 comdiag(arg)
1066 void *arg;
1067 {
1068 struct com_softc *sc = arg;
1069 int overflows, floods;
1070 int s;
1071
1072 s = spltty();
1073 sc->sc_errors = 0;
1074 overflows = sc->sc_overflows;
1075 sc->sc_overflows = 0;
1076 floods = sc->sc_floods;
1077 sc->sc_floods = 0;
1078 splx(s);
1079
1080 log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
1081 sc->sc_dev.dv_xname,
1082 overflows, overflows == 1 ? "" : "s",
1083 floods, floods == 1 ? "" : "s");
1084 }
1085
1086 void
1087 compoll(arg)
1088 void *arg;
1089 {
1090 int unit;
1091 struct com_softc *sc;
1092 struct tty *tp;
1093 register u_char *ibufp;
1094 u_char *ibufend;
1095 register int c;
1096 int s;
1097 static int lsrmap[8] = {
1098 0, TTY_PE,
1099 TTY_FE, TTY_PE|TTY_FE,
1100 TTY_FE, TTY_PE|TTY_FE,
1101 TTY_FE, TTY_PE|TTY_FE
1102 };
1103
1104 s = spltty();
1105 if (comevents == 0) {
1106 splx(s);
1107 goto out;
1108 }
1109 comevents = 0;
1110 splx(s);
1111
1112 for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
1113 sc = com_cd.cd_devs[unit];
1114 if (sc == 0 || sc->sc_ibufp == sc->sc_ibuf)
1115 continue;
1116
1117 tp = sc->sc_tty;
1118
1119 s = spltty();
1120
1121 ibufp = sc->sc_ibuf;
1122 ibufend = sc->sc_ibufp;
1123
1124 if (ibufp == ibufend) {
1125 splx(s);
1126 continue;
1127 }
1128
1129 sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
1130 sc->sc_ibufs[1] : sc->sc_ibufs[0];
1131 sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
1132 sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
1133
1134 if (tp == 0 || !ISSET(tp->t_state, TS_ISOPEN)) {
1135 splx(s);
1136 continue;
1137 }
1138
1139 if (ISSET(tp->t_cflag, CRTSCTS) &&
1140 !ISSET(sc->sc_mcr, MCR_RTS)) {
1141 /* XXX */
1142 SET(sc->sc_mcr, MCR_RTS);
1143 bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
1144 sc->sc_mcr);
1145 }
1146
1147 splx(s);
1148
1149 while (ibufp < ibufend) {
1150 c = *ibufp++;
1151 if (*ibufp & LSR_OE) {
1152 sc->sc_overflows++;
1153 if (sc->sc_errors++ == 0)
1154 timeout(comdiag, sc, 60 * hz);
1155 }
1156 /* This is ugly, but fast. */
1157 c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
1158 (*linesw[tp->t_line].l_rint)(c, tp);
1159 }
1160 }
1161
1162 out:
1163 timeout(compoll, NULL, 1);
1164 }
1165
1166 int
1167 comintr(arg)
1168 void *arg;
1169 {
1170 struct com_softc *sc = arg;
1171 bus_chipset_tag_t bc = sc->sc_bc;
1172 bus_io_handle_t ioh = sc->sc_ioh;
1173 struct tty *tp;
1174 u_char lsr, data, msr, delta;
1175 #ifdef COM_DEBUG
1176 int n;
1177 struct {
1178 u_char iir, lsr, msr;
1179 } iter[32];
1180 #endif
1181
1182 #ifdef COM_DEBUG
1183 n = 0;
1184 if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
1185 return (0);
1186 #else
1187 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
1188 return (0);
1189 #endif
1190
1191 tp = sc->sc_tty;
1192
1193 for (;;) {
1194 #ifdef COM_DEBUG
1195 iter[n].lsr =
1196 #endif
1197 lsr = bus_io_read_1(bc, ioh, com_lsr);
1198
1199 if (ISSET(lsr, LSR_RXRDY)) {
1200 register u_char *p = sc->sc_ibufp;
1201
1202 comevents = 1;
1203 do {
1204 data = bus_io_read_1(bc, ioh, com_data);
1205 if (ISSET(lsr, LSR_BI)) {
1206 #ifdef notdef
1207 printf("break %02x %02x %02x %02x\n",
1208 sc->sc_msr, sc->sc_mcr, sc->sc_lcr,
1209 sc->sc_dtr);
1210 #endif
1211 #ifdef DDB
1212 if (ISSET(sc->sc_hwflags,
1213 COM_HW_CONSOLE)) {
1214 Debugger();
1215 goto next;
1216 }
1217 #endif
1218 }
1219 if (p >= sc->sc_ibufend) {
1220 sc->sc_floods++;
1221 if (sc->sc_errors++ == 0)
1222 timeout(comdiag, sc, 60 * hz);
1223 } else {
1224 *p++ = data;
1225 *p++ = lsr;
1226 if (p == sc->sc_ibufhigh &&
1227 ISSET(tp->t_cflag, CRTSCTS)) {
1228 /* XXX */
1229 CLR(sc->sc_mcr, MCR_RTS);
1230 bus_io_write_1(bc, ioh, com_mcr,
1231 sc->sc_mcr);
1232 }
1233 }
1234 next:
1235 #ifdef COM_DEBUG
1236 if (++n >= 32)
1237 goto ohfudge;
1238 iter[n].lsr =
1239 #endif
1240 lsr = bus_io_read_1(bc, ioh, com_lsr);
1241 } while (ISSET(lsr, LSR_RXRDY));
1242
1243 sc->sc_ibufp = p;
1244 }
1245 #ifdef COM_DEBUG
1246 else if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
1247 printf("weird lsr %02x\n", lsr);
1248 #endif
1249
1250 #ifdef COM_DEBUG
1251 iter[n].msr =
1252 #endif
1253 msr = bus_io_read_1(bc, ioh, com_msr);
1254
1255 if (msr != sc->sc_msr) {
1256 delta = msr ^ sc->sc_msr;
1257 sc->sc_msr = msr;
1258 if (ISSET(delta, MSR_DCD) &&
1259 !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
1260 (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
1261 CLR(sc->sc_mcr, sc->sc_dtr);
1262 bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
1263 }
1264 if (ISSET(delta & msr, MSR_CTS) &&
1265 ISSET(tp->t_cflag, CRTSCTS)) {
1266 /* the line is up and we want to do rts/cts flow control */
1267 (*linesw[tp->t_line].l_start)(tp);
1268 }
1269 }
1270
1271 if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
1272 CLR(tp->t_state, TS_BUSY | TS_FLUSH);
1273 if (sc->sc_halt > 0)
1274 wakeup(&tp->t_outq);
1275 (*linesw[tp->t_line].l_start)(tp);
1276 }
1277
1278 #ifdef COM_DEBUG
1279 if (++n >= 32)
1280 goto ohfudge;
1281 if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
1282 return (1);
1283 #else
1284 if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
1285 return (1);
1286 #endif
1287 }
1288 #ifdef COM_DEBUG
1289 ohfudge:
1290 printf("comintr: too many iterations");
1291 for (n = 0; n < 32; n++) {
1292 if ((n % 4) == 0)
1293 printf("\ncomintr: iter[%02d]", n);
1294 printf(" %02x %02x %02x", iter[n].iir, iter[n].lsr, iter[n].msr);
1295 }
1296 printf("\n");
1297 printf("comintr: msr %02x mcr %02x lcr %02x ier %02x\n",
1298 sc->sc_msr, sc->sc_mcr, sc->sc_lcr, sc->sc_ier);
1299 printf("comintr: state %08x cc %d\n", sc->sc_tty->t_state,
1300 sc->sc_tty->t_outq.c_cc);
1301 #endif
1302 }
1303
1304 /*
1305 * Following are all routines needed for COM to act as console
1306 */
1307 #include <dev/cons.h>
1308
1309 void
1310 comcnprobe(cp)
1311 struct consdev *cp;
1312 {
1313 bus_chipset_tag_t bc;
1314 bus_io_handle_t ioh;
1315 int found;
1316
1317 #if 0
1318 XXX NEEDS TO BE FIXED XXX
1319 bc = ???;
1320 #endif
1321 if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
1322 cp->cn_pri = CN_DEAD;
1323 return;
1324 }
1325 found = comprobe1(bc, ioh, CONADDR);
1326 bus_io_unmap(bc, ioh, COM_NPORTS);
1327 if (!found) {
1328 cp->cn_pri = CN_DEAD;
1329 return;
1330 }
1331
1332 /* locate the major number */
1333 for (commajor = 0; commajor < nchrdev; commajor++)
1334 if (cdevsw[commajor].d_open == comopen)
1335 break;
1336
1337 /* initialize required fields */
1338 cp->cn_dev = makedev(commajor, CONUNIT);
1339 #ifdef COMCONSOLE
1340 cp->cn_pri = CN_REMOTE; /* Force a serial port console */
1341 #else
1342 cp->cn_pri = CN_NORMAL;
1343 #endif
1344 }
1345
1346 void
1347 comcninit(cp)
1348 struct consdev *cp;
1349 {
1350
1351 #if 0
1352 XXX NEEDS TO BE FIXED XXX
1353 comconsbc = ???;
1354 #endif
1355 if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
1356 panic("comcninit: mapping failed");
1357
1358 cominit(comconsbc, comconsioh, comdefaultrate);
1359 comconsaddr = CONADDR;
1360 comconsinit = 0;
1361 }
1362
1363 cominit(bc, ioh, rate)
1364 bus_chipset_tag_t bc;
1365 bus_io_handle_t ioh;
1366 int rate;
1367 {
1368 int s = splhigh();
1369 u_char stat;
1370
1371 bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
1372 rate = comspeed(comdefaultrate);
1373 bus_io_write_1(bc, ioh, com_dlbl, rate);
1374 bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
1375 bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
1376 bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
1377 bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
1378 stat = bus_io_read_1(bc, ioh, com_iir);
1379 splx(s);
1380 }
1381
1382 comcngetc(dev)
1383 dev_t dev;
1384 {
1385 int s = splhigh();
1386 bus_chipset_tag_t bc = comconsbc;
1387 bus_io_handle_t ioh = comconsioh;
1388 u_char stat, c;
1389
1390 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
1391 ;
1392 c = bus_io_read_1(bc, ioh, com_data);
1393 stat = bus_io_read_1(bc, ioh, com_iir);
1394 splx(s);
1395 return c;
1396 }
1397
1398 /*
1399 * Console kernel output character routine.
1400 */
1401 void
1402 comcnputc(dev, c)
1403 dev_t dev;
1404 int c;
1405 {
1406 int s = splhigh();
1407 bus_chipset_tag_t bc = comconsbc;
1408 bus_io_handle_t ioh = comconsioh;
1409 u_char stat;
1410 register int timo;
1411
1412 #ifdef KGDB
1413 if (dev != kgdb_dev)
1414 #endif
1415 if (comconsinit == 0) {
1416 (void) cominit(bc, ioh, comdefaultrate);
1417 comconsinit = 1;
1418 }
1419 /* wait for any pending transmission to finish */
1420 timo = 50000;
1421 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
1422 ;
1423 bus_io_write_1(bc, ioh, com_data, c);
1424 /* wait for this transmission to complete */
1425 timo = 1500000;
1426 while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
1427 ;
1428 /* clear any interrupts generated by this transmission */
1429 stat = bus_io_read_1(bc, ioh, com_iir);
1430 splx(s);
1431 }
1432
1433 void
1434 comcnpollc(dev, on)
1435 dev_t dev;
1436 int on;
1437 {
1438
1439 }
1440