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