Deleted Added
full compact
sio.c (117167) sio.c (119419)
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/sio/sio.c 117167 2003-07-02 16:09:02Z jhb $
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * from: i386/isa sio.c,v 1.234
36 */
37
33 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
34 * from: i386/isa sio.c,v 1.234
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/dev/sio/sio.c 119419 2003-08-24 18:03:45Z obrien $");
39
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"
42
43/*
44 * Serial driver, based on 386BSD-0.1 com driver.
45 * Mostly rewritten to use pseudo-DMA.
46 * Works for National Semiconductor NS8250-NS16550AF UARTs.
47 * COM driver, based on HP dca driver.
48 *
49 * Changes for PC-Card integration:
50 * - Added PC-Card driver table and handlers
51 */
52#include <sys/param.h>
53#include <sys/systm.h>
54#include <sys/bus.h>
55#include <sys/conf.h>
56#include <sys/fcntl.h>
57#include <sys/interrupt.h>
58#include <sys/kernel.h>
59#include <sys/limits.h>
60#include <sys/lock.h>
61#include <sys/malloc.h>
62#include <sys/module.h>
63#include <sys/mutex.h>
64#include <sys/proc.h>
65#include <sys/reboot.h>
66#include <sys/sysctl.h>
67#include <sys/syslog.h>
68#include <sys/tty.h>
69#include <machine/bus_pio.h>
70#include <machine/bus.h>
71#include <sys/rman.h>
72#include <sys/timepps.h>
73#include <sys/uio.h>
74
75#include <isa/isavar.h>
76
77#include <machine/resource.h>
78
79#include <dev/sio/sioreg.h>
80#include <dev/sio/siovar.h>
81
82#ifdef COM_ESP
83#include <dev/ic/esp.h>
84#endif
85#include <dev/ic/ns16550.h>
86
87#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
88
89#define CALLOUT_MASK 0x80
90#define CONTROL_MASK 0x60
91#define CONTROL_INIT_STATE 0x20
92#define CONTROL_LOCK_STATE 0x40
93#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
94#define MINOR_TO_UNIT(mynor) ((((mynor) & ~0xffffU) >> (8 + 3)) \
95 | ((mynor) & 0x1f))
96#define UNIT_TO_MINOR(unit) ((((unit) & ~0x1fU) << (8 + 3)) \
97 | ((unit) & 0x1f))
98
99#ifdef COM_MULTIPORT
100/* checks in flags for multiport and which is multiport "master chip"
101 * for a given card
102 */
103#define COM_ISMULTIPORT(flags) ((flags) & 0x01)
104#define COM_MPMASTER(flags) (((flags) >> 8) & 0x0ff)
105#define COM_NOTAST4(flags) ((flags) & 0x04)
106#else
107#define COM_ISMULTIPORT(flags) (0)
108#endif /* COM_MULTIPORT */
109
110#define COM_CONSOLE(flags) ((flags) & 0x10)
111#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
112#define COM_LLCONSOLE(flags) ((flags) & 0x40)
113#define COM_DEBUGGER(flags) ((flags) & 0x80)
114#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
115#define COM_NOFIFO(flags) ((flags) & 0x02)
116#define COM_PPSCTS(flags) ((flags) & 0x10000)
117#define COM_ST16650A(flags) ((flags) & 0x20000)
118#define COM_C_NOPROBE (0x40000)
119#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE)
120#define COM_C_IIR_TXRDYBUG (0x80000)
121#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
122#define COM_NOSCR(flags) ((flags) & 0x100000)
123#define COM_TI16754(flags) ((flags) & 0x200000)
124#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
125
126#define sio_getreg(com, off) \
127 (bus_space_read_1((com)->bst, (com)->bsh, (off)))
128#define sio_setreg(com, off, value) \
129 (bus_space_write_1((com)->bst, (com)->bsh, (off), (value)))
130
131/*
132 * com state bits.
133 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
134 * than the other bits so that they can be tested as a group without masking
135 * off the low bits.
136 *
137 * The following com and tty flags correspond closely:
138 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
139 * comstop())
140 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart())
141 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam())
142 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam())
143 * TS_FLUSH is not used.
144 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
145 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
146 */
147#define CS_BUSY 0x80 /* output in progress */
148#define CS_TTGO 0x40 /* output not stopped by XOFF */
149#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */
150#define CS_CHECKMSR 1 /* check of MSR scheduled */
151#define CS_CTS_OFLOW 2 /* use CTS output flow control */
152#define CS_DTR_OFF 0x10 /* DTR held off */
153#define CS_ODONE 4 /* output completed */
154#define CS_RTS_IFLOW 8 /* use RTS input flow control */
155#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */
156
157static char const * const error_desc[] = {
158#define CE_OVERRUN 0
159 "silo overflow",
160#define CE_INTERRUPT_BUF_OVERFLOW 1
161 "interrupt-level buffer overflow",
162#define CE_TTY_BUF_OVERFLOW 2
163 "tty-level buffer overflow",
164};
165
166#define CE_NTYPES 3
167#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
168
169/* types. XXX - should be elsewhere */
170typedef u_int Port_t; /* hardware port */
171typedef u_char bool_t; /* boolean */
172
173/* queue of linear buffers */
174struct lbq {
175 u_char *l_head; /* next char to process */
176 u_char *l_tail; /* one past the last char to process */
177 struct lbq *l_next; /* next in queue */
178 bool_t l_queued; /* nonzero if queued */
179};
180
181/* com device structure */
182struct com_s {
183 u_int flags; /* Copy isa device flags */
184 u_char state; /* miscellaneous flag bits */
185 bool_t active_out; /* nonzero if the callout device is open */
186 u_char cfcr_image; /* copy of value written to CFCR */
187#ifdef COM_ESP
188 bool_t esp; /* is this unit a hayes esp board? */
189#endif
190 u_char extra_state; /* more flag bits, separate for order trick */
191 u_char fifo_image; /* copy of value written to FIFO */
192 bool_t hasfifo; /* nonzero for 16550 UARTs */
193 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */
194 bool_t loses_outints; /* nonzero if device loses output interrupts */
195 u_char mcr_image; /* copy of value written to MCR */
196#ifdef COM_MULTIPORT
197 bool_t multiport; /* is this unit part of a multiport device? */
198#endif /* COM_MULTIPORT */
199 bool_t no_irq; /* nonzero if irq is not attached */
200 bool_t gone; /* hardware disappeared */
201 bool_t poll; /* nonzero if polling is required */
202 bool_t poll_output; /* nonzero if polling for output is required */
203 int unit; /* unit number */
204 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */
205 u_int tx_fifo_size;
206 u_int wopeners; /* # processes waiting for DCD in open() */
207
208 /*
209 * The high level of the driver never reads status registers directly
210 * because there would be too many side effects to handle conveniently.
211 * Instead, it reads copies of the registers stored here by the
212 * interrupt handler.
213 */
214 u_char last_modem_status; /* last MSR read by intr handler */
215 u_char prev_modem_status; /* last MSR handled by high level */
216
217 u_char hotchar; /* ldisc-specific char to be handled ASAP */
218 u_char *ibuf; /* start of input buffer */
219 u_char *ibufend; /* end of input buffer */
220 u_char *ibufold; /* old input buffer, to be freed */
221 u_char *ihighwater; /* threshold in input buffer */
222 u_char *iptr; /* next free spot in input buffer */
223 int ibufsize; /* size of ibuf (not include error bytes) */
224 int ierroff; /* offset of error bytes in ibuf */
225
226 struct lbq obufq; /* head of queue of output buffers */
227 struct lbq obufs[2]; /* output buffers */
228
229 bus_space_tag_t bst;
230 bus_space_handle_t bsh;
231
232 Port_t data_port; /* i/o ports */
233#ifdef COM_ESP
234 Port_t esp_port;
235#endif
236 Port_t int_id_port;
237 Port_t modem_ctl_port;
238 Port_t line_status_port;
239 Port_t modem_status_port;
240 Port_t intr_ctl_port; /* Ports of IIR register */
241
242 struct tty *tp; /* cross reference */
243
244 /* Initial state. */
245 struct termios it_in; /* should be in struct tty */
246 struct termios it_out;
247
248 /* Lock state. */
249 struct termios lt_in; /* should be in struct tty */
250 struct termios lt_out;
251
252 bool_t do_timestamp;
253 bool_t do_dcd_timestamp;
254 struct timeval timestamp;
255 struct timeval dcd_timestamp;
256 struct pps_state pps;
257 int pps_bit;
258
259 u_long bytes_in; /* statistics */
260 u_long bytes_out;
261 u_int delta_error_counts[CE_NTYPES];
262 u_long error_counts[CE_NTYPES];
263
264 u_long rclk;
265
266 struct resource *irqres;
267 struct resource *ioportres;
268 int ioportrid;
269 void *cookie;
270 dev_t devs[6];
271
272 /*
273 * Data area for output buffers. Someday we should build the output
274 * buffer queue without copying data.
275 */
276 u_char obuf1[256];
277 u_char obuf2[256];
278};
279
280#ifdef COM_ESP
281static int espattach(struct com_s *com, Port_t esp_port);
282#endif
283
284static timeout_t siobusycheck;
285static u_int siodivisor(u_long rclk, speed_t speed);
286static timeout_t siodtrwakeup;
287static void comhardclose(struct com_s *com);
288static void sioinput(struct com_s *com);
289static void siointr1(struct com_s *com);
290static void siointr(void *arg);
291static int commctl(struct com_s *com, int bits, int how);
292static int comparam(struct tty *tp, struct termios *t);
293static void siopoll(void *);
294static void siosettimeout(void);
295static int siosetwater(struct com_s *com, speed_t speed);
296static void comstart(struct tty *tp);
297static void comstop(struct tty *tp, int rw);
298static timeout_t comwakeup;
299static void disc_optim(struct tty *tp, struct termios *t,
300 struct com_s *com);
301
302char sio_driver_name[] = "sio";
303static struct mtx sio_lock;
304static int sio_inited;
305
306/* table and macro for fast conversion from a unit number to its com struct */
307devclass_t sio_devclass;
308#define com_addr(unit) ((struct com_s *) \
309 devclass_get_softc(sio_devclass, unit)) /* XXX */
310
311static d_open_t sioopen;
312static d_close_t sioclose;
313static d_read_t sioread;
314static d_write_t siowrite;
315static d_ioctl_t sioioctl;
316
317#define CDEV_MAJOR 28
318static struct cdevsw sio_cdevsw = {
319 .d_open = sioopen,
320 .d_close = sioclose,
321 .d_read = sioread,
322 .d_write = siowrite,
323 .d_ioctl = sioioctl,
324 .d_poll = ttypoll,
325 .d_name = sio_driver_name,
326 .d_maj = CDEV_MAJOR,
327 .d_flags = D_TTY,
328 .d_kqfilter = ttykqfilter,
329};
330
331int comconsole = -1;
332static volatile speed_t comdefaultrate = CONSPEED;
333static u_long comdefaultrclk = DEFAULT_RCLK;
334SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, "");
335static speed_t gdbdefaultrate = GDBSPEED;
336SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW,
337 &gdbdefaultrate, GDBSPEED, "");
338static u_int com_events; /* input chars + weighted output completions */
339static Port_t siocniobase;
340static int siocnunit = -1;
341static Port_t siogdbiobase;
342static int siogdbunit = -1;
343static void *sio_slow_ih;
344static void *sio_fast_ih;
345static int sio_timeout;
346static int sio_timeouts_until_log;
347static struct callout_handle sio_timeout_handle
348 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
349static int sio_numunits;
350
351#ifdef COM_ESP
352/* XXX configure this properly. */
353/* XXX quite broken for new-bus. */
354static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
355static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
356#endif
357
358/*
359 * handle sysctl read/write requests for console speed
360 *
361 * In addition to setting comdefaultrate for I/O through /dev/console,
362 * also set the initial and lock values for the /dev/ttyXX device
363 * if there is one associated with the console. Finally, if the /dev/tty
364 * device has already been open, change the speed on the open running port
365 * itself.
366 */
367
368static int
369sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)
370{
371 int error, s;
372 speed_t newspeed;
373 struct com_s *com;
374 struct tty *tp;
375
376 newspeed = comdefaultrate;
377
378 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
379 if (error || !req->newptr)
380 return (error);
381
382 comdefaultrate = newspeed;
383
384 if (comconsole < 0) /* serial console not selected? */
385 return (0);
386
387 com = com_addr(comconsole);
388 if (com == NULL)
389 return (ENXIO);
390
391 /*
392 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
393 * (note, the lock rates really are boolean -- if non-zero, disallow
394 * speed changes)
395 */
396 com->it_in.c_ispeed = com->it_in.c_ospeed =
397 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
398 com->it_out.c_ispeed = com->it_out.c_ospeed =
399 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
400
401 /*
402 * if we're open, change the running rate too
403 */
404 tp = com->tp;
405 if (tp && (tp->t_state & TS_ISOPEN)) {
406 tp->t_termios.c_ispeed =
407 tp->t_termios.c_ospeed = comdefaultrate;
408 s = spltty();
409 error = comparam(tp, &tp->t_termios);
410 splx(s);
411 }
412 return error;
413}
414
415SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
416 0, 0, sysctl_machdep_comdefaultrate, "I", "");
417/* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */
418
419#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
420#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
421
422/*
423 * Unload the driver and clear the table.
424 * XXX this is mostly wrong.
425 * XXX TODO:
426 * This is usually called when the card is ejected, but
427 * can be caused by a kldunload of a controller driver.
428 * The idea is to reset the driver's view of the device
429 * and ensure that any driver entry points such as
430 * read and write do not hang.
431 */
432int
433siodetach(dev)
434 device_t dev;
435{
436 struct com_s *com;
437 int i;
438
439 com = (struct com_s *) device_get_softc(dev);
440 if (com == NULL) {
441 device_printf(dev, "NULL com in siounload\n");
442 return (0);
443 }
444 com->gone = 1;
445 for (i = 0 ; i < 6; i++)
446 destroy_dev(com->devs[i]);
447 if (com->irqres) {
448 bus_teardown_intr(dev, com->irqres, com->cookie);
449 bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres);
450 }
451 if (com->ioportres)
452 bus_release_resource(dev, SYS_RES_IOPORT, com->ioportrid,
453 com->ioportres);
454 if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
455 device_printf(dev, "still open, forcing close\n");
456 (*linesw[com->tp->t_line].l_close)(com->tp, 0);
457 com->tp->t_gen++;
458 ttyclose(com->tp);
459 ttwakeup(com->tp);
460 ttwwakeup(com->tp);
461 } else {
462 if (com->ibuf != NULL)
463 free(com->ibuf, M_DEVBUF);
464 device_set_softc(dev, NULL);
465 free(com, M_DEVBUF);
466 }
467 return (0);
468}
469
470int
471sioprobe(dev, xrid, rclk, noprobe)
472 device_t dev;
473 int xrid;
474 u_long rclk;
475 int noprobe;
476{
477#if 0
478 static bool_t already_init;
479 device_t xdev;
480#endif
481 struct com_s *com;
482 u_int divisor;
483 bool_t failures[10];
484 int fn;
485 device_t idev;
486 Port_t iobase;
487 intrmask_t irqmap[4];
488 intrmask_t irqs;
489 u_char mcr_image;
490 int result;
491 u_long xirq;
492 u_int flags = device_get_flags(dev);
493 int rid;
494 struct resource *port;
495
496 rid = xrid;
497 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
498 0, ~0, IO_COMSIZE, RF_ACTIVE);
499 if (!port)
500 return (ENXIO);
501
502 com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
503 if (com == NULL)
504 return (ENOMEM);
505 device_set_softc(dev, com);
506 com->bst = rman_get_bustag(port);
507 com->bsh = rman_get_bushandle(port);
508 if (rclk == 0)
509 rclk = DEFAULT_RCLK;
510 com->rclk = rclk;
511
512 while (sio_inited != 2)
513 if (atomic_cmpset_int(&sio_inited, 0, 1)) {
514 mtx_init(&sio_lock, sio_driver_name, NULL,
515 (comconsole != -1) ?
516 MTX_SPIN | MTX_QUIET : MTX_SPIN);
517 atomic_store_rel_int(&sio_inited, 2);
518 }
519
520#if 0
521 /*
522 * XXX this is broken - when we are first called, there are no
523 * previously configured IO ports. We could hard code
524 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
525 * This code has been doing nothing since the conversion since
526 * "count" is zero the first time around.
527 */
528 if (!already_init) {
529 /*
530 * Turn off MCR_IENABLE for all likely serial ports. An unused
531 * port with its MCR_IENABLE gate open will inhibit interrupts
532 * from any used port that shares the interrupt vector.
533 * XXX the gate enable is elsewhere for some multiports.
534 */
535 device_t *devs;
536 int count, i, xioport;
537
538 devclass_get_devices(sio_devclass, &devs, &count);
539 for (i = 0; i < count; i++) {
540 xdev = devs[i];
541 if (device_is_enabled(xdev) &&
542 bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
543 NULL) == 0)
544 outb(xioport + com_mcr, 0);
545 }
546 free(devs, M_TEMP);
547 already_init = TRUE;
548 }
549#endif
550
551 if (COM_LLCONSOLE(flags)) {
552 printf("sio%d: reserved for low-level i/o\n",
553 device_get_unit(dev));
554 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
555 device_set_softc(dev, NULL);
556 free(com, M_DEVBUF);
557 return (ENXIO);
558 }
559
560 /*
561 * If the device is on a multiport card and has an AST/4
562 * compatible interrupt control register, initialize this
563 * register and prepare to leave MCR_IENABLE clear in the mcr.
564 * Otherwise, prepare to set MCR_IENABLE in the mcr.
565 * Point idev to the device struct giving the correct id_irq.
566 * This is the struct for the master device if there is one.
567 */
568 idev = dev;
569 mcr_image = MCR_IENABLE;
570#ifdef COM_MULTIPORT
571 if (COM_ISMULTIPORT(flags)) {
572 Port_t xiobase;
573 u_long io;
574
575 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
576 if (idev == NULL) {
577 printf("sio%d: master device %d not configured\n",
578 device_get_unit(dev), COM_MPMASTER(flags));
579 idev = dev;
580 }
581 if (!COM_NOTAST4(flags)) {
582 if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
583 NULL) == 0) {
584 xiobase = io;
585 if (bus_get_resource(idev, SYS_RES_IRQ, 0,
586 NULL, NULL) == 0)
587 outb(xiobase + com_scr, 0x80);
588 else
589 outb(xiobase + com_scr, 0);
590 }
591 mcr_image = 0;
592 }
593 }
594#endif /* COM_MULTIPORT */
595 if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
596 mcr_image = 0;
597
598 bzero(failures, sizeof failures);
599 iobase = rman_get_start(port);
600
601 /*
602 * We don't want to get actual interrupts, just masked ones.
603 * Interrupts from this line should already be masked in the ICU,
604 * but mask them in the processor as well in case there are some
605 * (misconfigured) shared interrupts.
606 */
607 mtx_lock_spin(&sio_lock);
608/* EXTRA DELAY? */
609
610 /*
611 * For the TI16754 chips, set prescaler to 1 (4 is often the
612 * default after-reset value) as otherwise it's impossible to
613 * get highest baudrates.
614 */
615 if (COM_TI16754(flags)) {
616 u_char cfcr, efr;
617
618 cfcr = sio_getreg(com, com_cfcr);
619 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
620 efr = sio_getreg(com, com_efr);
621 /* Unlock extended features to turn off prescaler. */
622 sio_setreg(com, com_efr, efr | EFR_EFE);
623 /* Disable EFR. */
624 sio_setreg(com, com_cfcr, (cfcr != CFCR_EFR_ENABLE) ? cfcr : 0);
625 /* Turn off prescaler. */
626 sio_setreg(com, com_mcr,
627 sio_getreg(com, com_mcr) & ~MCR_PRESCALE);
628 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
629 sio_setreg(com, com_efr, efr);
630 sio_setreg(com, com_cfcr, cfcr);
631 }
632
633 /*
634 * Initialize the speed and the word size and wait long enough to
635 * drain the maximum of 16 bytes of junk in device output queues.
636 * The speed is undefined after a master reset and must be set
637 * before relying on anything related to output. There may be
638 * junk after a (very fast) soft reboot and (apparently) after
639 * master reset.
640 * XXX what about the UART bug avoided by waiting in comparam()?
641 * We don't want to to wait long enough to drain at 2 bps.
642 */
643 if (iobase == siocniobase)
644 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
645 else {
646 sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
647 divisor = siodivisor(rclk, SIO_TEST_SPEED);
648 sio_setreg(com, com_dlbl, divisor & 0xff);
649 sio_setreg(com, com_dlbh, divisor >> 8);
650 sio_setreg(com, com_cfcr, CFCR_8BITS);
651 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
652 }
653
654 /*
655 * Enable the interrupt gate and disable device interupts. This
656 * should leave the device driving the interrupt line low and
657 * guarantee an edge trigger if an interrupt can be generated.
658 */
659/* EXTRA DELAY? */
660 sio_setreg(com, com_mcr, mcr_image);
661 sio_setreg(com, com_ier, 0);
662 DELAY(1000); /* XXX */
663 irqmap[0] = isa_irq_pending();
664
665 /*
666 * Attempt to set loopback mode so that we can send a null byte
667 * without annoying any external device.
668 */
669/* EXTRA DELAY? */
670 sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK);
671
672 /*
673 * Attempt to generate an output interrupt. On 8250's, setting
674 * IER_ETXRDY generates an interrupt independent of the current
675 * setting and independent of whether the THR is empty. On 16450's,
676 * setting IER_ETXRDY generates an interrupt independent of the
677 * current setting. On 16550A's, setting IER_ETXRDY only
678 * generates an interrupt when IER_ETXRDY is not already set.
679 */
680 sio_setreg(com, com_ier, IER_ETXRDY);
681
682 /*
683 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
684 * an interrupt. They'd better generate one for actually doing
685 * output. Loopback may be broken on the same incompatibles but
686 * it's unlikely to do more than allow the null byte out.
687 */
688 sio_setreg(com, com_data, 0);
689 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
690
691 /*
692 * Turn off loopback mode so that the interrupt gate works again
693 * (MCR_IENABLE was hidden). This should leave the device driving
694 * an interrupt line high. It doesn't matter if the interrupt
695 * line oscillates while we are not looking at it, since interrupts
696 * are disabled.
697 */
698/* EXTRA DELAY? */
699 sio_setreg(com, com_mcr, mcr_image);
700
701 /*
702 * It seems my Xircom CBEM56G Cardbus modem wants to be reset
703 * to 8 bits *again*, or else probe test 0 will fail.
704 * gwk@sgi.com, 4/19/2001
705 */
706 sio_setreg(com, com_cfcr, CFCR_8BITS);
707
708 /*
709 * Some pcmcia cards have the "TXRDY bug", so we check everyone
710 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
711 */
712 if (noprobe) {
713 /* Reading IIR register twice */
714 for (fn = 0; fn < 2; fn ++) {
715 DELAY(10000);
716 failures[6] = sio_getreg(com, com_iir);
717 }
718 /* Check IIR_TXRDY clear ? */
719 result = 0;
720 if (failures[6] & IIR_TXRDY) {
721 /* No, Double check with clearing IER */
722 sio_setreg(com, com_ier, 0);
723 if (sio_getreg(com, com_iir) & IIR_NOPEND) {
724 /* Ok. We discovered TXRDY bug! */
725 SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
726 } else {
727 /* Unknown, Just omit this chip.. XXX */
728 result = ENXIO;
729 sio_setreg(com, com_mcr, 0);
730 }
731 } else {
732 /* OK. this is well-known guys */
733 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
734 }
735 sio_setreg(com, com_ier, 0);
736 sio_setreg(com, com_cfcr, CFCR_8BITS);
737 mtx_unlock_spin(&sio_lock);
738 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
739 if (iobase == siocniobase)
740 result = 0;
741 if (result != 0) {
742 device_set_softc(dev, NULL);
743 free(com, M_DEVBUF);
744 }
745 return (result);
746 }
747
748 /*
749 * Check that
750 * o the CFCR, IER and MCR in UART hold the values written to them
751 * (the values happen to be all distinct - this is good for
752 * avoiding false positive tests from bus echoes).
753 * o an output interrupt is generated and its vector is correct.
754 * o the interrupt goes away when the IIR in the UART is read.
755 */
756/* EXTRA DELAY? */
757 failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
758 failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
759 failures[2] = sio_getreg(com, com_mcr) - mcr_image;
760 DELAY(10000); /* Some internal modems need this time */
761 irqmap[1] = isa_irq_pending();
762 failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
763 DELAY(1000); /* XXX */
764 irqmap[2] = isa_irq_pending();
765 failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
766
767 /*
768 * Turn off all device interrupts and check that they go off properly.
769 * Leave MCR_IENABLE alone. For ports without a master port, it gates
770 * the OUT2 output of the UART to
771 * the ICU input. Closing the gate would give a floating ICU input
772 * (unless there is another device driving it) and spurious interrupts.
773 * (On the system that this was first tested on, the input floats high
774 * and gives a (masked) interrupt as soon as the gate is closed.)
775 */
776 sio_setreg(com, com_ier, 0);
777 sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
778 failures[7] = sio_getreg(com, com_ier);
779 DELAY(1000); /* XXX */
780 irqmap[3] = isa_irq_pending();
781 failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
782
783 mtx_unlock_spin(&sio_lock);
784
785 irqs = irqmap[1] & ~irqmap[0];
786 if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
787 ((1 << xirq) & irqs) == 0) {
788 printf(
789 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
790 device_get_unit(dev), xirq, irqs);
791 printf(
792 "sio%d: port may not be enabled\n",
793 device_get_unit(dev));
794 }
795 if (bootverbose)
796 printf("sio%d: irq maps: %#x %#x %#x %#x\n",
797 device_get_unit(dev),
798 irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
799
800 result = 0;
801 for (fn = 0; fn < sizeof failures; ++fn)
802 if (failures[fn]) {
803 sio_setreg(com, com_mcr, 0);
804 result = ENXIO;
805 if (bootverbose) {
806 printf("sio%d: probe failed test(s):",
807 device_get_unit(dev));
808 for (fn = 0; fn < sizeof failures; ++fn)
809 if (failures[fn])
810 printf(" %d", fn);
811 printf("\n");
812 }
813 break;
814 }
815 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
816 if (iobase == siocniobase)
817 result = 0;
818 if (result != 0) {
819 device_set_softc(dev, NULL);
820 free(com, M_DEVBUF);
821 }
822 return (result);
823}
824
825#ifdef COM_ESP
826static int
827espattach(com, esp_port)
828 struct com_s *com;
829 Port_t esp_port;
830{
831 u_char dips;
832 u_char val;
833
834 /*
835 * Check the ESP-specific I/O port to see if we're an ESP
836 * card. If not, return failure immediately.
837 */
838 if ((inb(esp_port) & 0xf3) == 0) {
839 printf(" port 0x%x is not an ESP board?\n", esp_port);
840 return (0);
841 }
842
843 /*
844 * We've got something that claims to be a Hayes ESP card.
845 * Let's hope so.
846 */
847
848 /* Get the dip-switch configuration */
849 outb(esp_port + ESP_CMD1, ESP_GETDIPS);
850 dips = inb(esp_port + ESP_STATUS1);
851
852 /*
853 * Bits 0,1 of dips say which COM port we are.
854 */
855 if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03])
856 printf(" : ESP");
857 else {
858 printf(" esp_port has com %d\n", dips & 0x03);
859 return (0);
860 }
861
862 /*
863 * Check for ESP version 2.0 or later: bits 4,5,6 = 010.
864 */
865 outb(esp_port + ESP_CMD1, ESP_GETTEST);
866 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */
867 val = inb(esp_port + ESP_STATUS2);
868 if ((val & 0x70) < 0x20) {
869 printf("-old (%o)", val & 0x70);
870 return (0);
871 }
872
873 /*
874 * Check for ability to emulate 16550: bit 7 == 1
875 */
876 if ((dips & 0x80) == 0) {
877 printf(" slave");
878 return (0);
879 }
880
881 /*
882 * Okay, we seem to be a Hayes ESP card. Whee.
883 */
884 com->esp = TRUE;
885 com->esp_port = esp_port;
886 return (1);
887}
888#endif /* COM_ESP */
889
890int
891sioattach(dev, xrid, rclk)
892 device_t dev;
893 int xrid;
894 u_long rclk;
895{
896 struct com_s *com;
897#ifdef COM_ESP
898 Port_t *espp;
899#endif
900 Port_t iobase;
901 int minorbase;
902 int unit;
903 u_int flags;
904 int rid;
905 struct resource *port;
906 int ret;
907
908 rid = xrid;
909 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
910 0, ~0, IO_COMSIZE, RF_ACTIVE);
911 if (!port)
912 return (ENXIO);
913
914 iobase = rman_get_start(port);
915 unit = device_get_unit(dev);
916 com = device_get_softc(dev);
917 flags = device_get_flags(dev);
918
919 if (unit >= sio_numunits)
920 sio_numunits = unit + 1;
921 /*
922 * sioprobe() has initialized the device registers as follows:
923 * o cfcr = CFCR_8BITS.
924 * It is most important that CFCR_DLAB is off, so that the
925 * data port is not hidden when we enable interrupts.
926 * o ier = 0.
927 * Interrupts are only enabled when the line is open.
928 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
929 * interrupt control register or the config specifies no irq.
930 * Keeping MCR_DTR and MCR_RTS off might stop the external
931 * device from sending before we are ready.
932 */
933 bzero(com, sizeof *com);
934 com->unit = unit;
935 com->ioportres = port;
936 com->ioportrid = rid;
937 com->bst = rman_get_bustag(port);
938 com->bsh = rman_get_bushandle(port);
939 com->cfcr_image = CFCR_8BITS;
940 com->dtr_wait = 3 * hz;
941 com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
942 com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
943 com->tx_fifo_size = 1;
944 com->obufs[0].l_head = com->obuf1;
945 com->obufs[1].l_head = com->obuf2;
946
947 com->data_port = iobase + com_data;
948 com->int_id_port = iobase + com_iir;
949 com->modem_ctl_port = iobase + com_mcr;
950 com->mcr_image = inb(com->modem_ctl_port);
951 com->line_status_port = iobase + com_lsr;
952 com->modem_status_port = iobase + com_msr;
953 com->intr_ctl_port = iobase + com_ier;
954
955 if (rclk == 0)
956 rclk = DEFAULT_RCLK;
957 com->rclk = rclk;
958
959 /*
960 * We don't use all the flags from <sys/ttydefaults.h> since they
961 * are only relevant for logins. It's important to have echo off
962 * initially so that the line doesn't start blathering before the
963 * echo flag can be turned off.
964 */
965 com->it_in.c_iflag = 0;
966 com->it_in.c_oflag = 0;
967 com->it_in.c_cflag = TTYDEF_CFLAG;
968 com->it_in.c_lflag = 0;
969 if (unit == comconsole) {
970 com->it_in.c_iflag = TTYDEF_IFLAG;
971 com->it_in.c_oflag = TTYDEF_OFLAG;
972 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
973 com->it_in.c_lflag = TTYDEF_LFLAG;
974 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
975 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
976 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
977 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
978 } else
979 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
980 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
981 mtx_unlock_spin(&sio_lock);
982 /*
983 * Leave i/o resources allocated if this is a `cn'-level
984 * console, so that other devices can't snarf them.
985 */
986 if (iobase != siocniobase)
987 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
988 return (ENOMEM);
989 }
990 mtx_unlock_spin(&sio_lock);
991 termioschars(&com->it_in);
992 com->it_out = com->it_in;
993
994 /* attempt to determine UART type */
995 printf("sio%d: type", unit);
996
997
998 if (!COM_ISMULTIPORT(flags) &&
999 !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) {
1000 u_char scr;
1001 u_char scr1;
1002 u_char scr2;
1003
1004 scr = sio_getreg(com, com_scr);
1005 sio_setreg(com, com_scr, 0xa5);
1006 scr1 = sio_getreg(com, com_scr);
1007 sio_setreg(com, com_scr, 0x5a);
1008 scr2 = sio_getreg(com, com_scr);
1009 sio_setreg(com, com_scr, scr);
1010 if (scr1 != 0xa5 || scr2 != 0x5a) {
1011 printf(" 8250 or not responding");
1012 goto determined_type;
1013 }
1014 }
1015 sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1016 DELAY(100);
1017 com->st16650a = 0;
1018 switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1019 case FIFO_RX_LOW:
1020 printf(" 16450");
1021 break;
1022 case FIFO_RX_MEDL:
1023 printf(" 16450?");
1024 break;
1025 case FIFO_RX_MEDH:
1026 printf(" 16550?");
1027 break;
1028 case FIFO_RX_HIGH:
1029 if (COM_NOFIFO(flags)) {
1030 printf(" 16550A fifo disabled");
1031 } else {
1032 com->hasfifo = TRUE;
1033 if (COM_ST16650A(flags)) {
1034 com->st16650a = 1;
1035 com->tx_fifo_size = 32;
1036 printf(" ST16650A");
1037 } else if (COM_TI16754(flags)) {
1038 com->tx_fifo_size = 64;
1039 printf(" TI16754");
1040 } else {
1041 com->tx_fifo_size = COM_FIFOSIZE(flags);
1042 printf(" 16550A");
1043 }
1044 }
1045#ifdef COM_ESP
1046 for (espp = likely_esp_ports; *espp != 0; espp++)
1047 if (espattach(com, *espp)) {
1048 com->tx_fifo_size = 1024;
1049 break;
1050 }
1051#endif
1052 if (!com->st16650a && !COM_TI16754(flags)) {
1053 if (!com->tx_fifo_size)
1054 com->tx_fifo_size = 16;
1055 else
1056 printf(" lookalike with %d bytes FIFO",
1057 com->tx_fifo_size);
1058 }
1059
1060 break;
1061 }
1062
1063#ifdef COM_ESP
1064 if (com->esp) {
1065 /*
1066 * Set 16550 compatibility mode.
1067 * We don't use the ESP_MODE_SCALE bit to increase the
1068 * fifo trigger levels because we can't handle large
1069 * bursts of input.
1070 * XXX flow control should be set in comparam(), not here.
1071 */
1072 outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1073 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1074
1075 /* Set RTS/CTS flow control. */
1076 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1077 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1078 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1079
1080 /* Set flow-control levels. */
1081 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1082 outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1083 outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1084 outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1085 outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1086 }
1087#endif /* COM_ESP */
1088 sio_setreg(com, com_fifo, 0);
1089determined_type: ;
1090
1091#ifdef COM_MULTIPORT
1092 if (COM_ISMULTIPORT(flags)) {
1093 device_t masterdev;
1094
1095 com->multiport = TRUE;
1096 printf(" (multiport");
1097 if (unit == COM_MPMASTER(flags))
1098 printf(" master");
1099 printf(")");
1100 masterdev = devclass_get_device(sio_devclass,
1101 COM_MPMASTER(flags));
1102 com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1103 SYS_RES_IRQ, 0, NULL, NULL) != 0);
1104 }
1105#endif /* COM_MULTIPORT */
1106 if (unit == comconsole)
1107 printf(", console");
1108 if (COM_IIR_TXRDYBUG(flags))
1109 printf(" with a bogus IIR_TXRDY register");
1110 printf("\n");
1111
1112 if (sio_fast_ih == NULL) {
1113 swi_add(&tty_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0,
1114 &sio_fast_ih);
1115 swi_add(&clk_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0,
1116 &sio_slow_ih);
1117 }
1118 minorbase = UNIT_TO_MINOR(unit);
1119 com->devs[0] = make_dev(&sio_cdevsw, minorbase,
1120 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
1121 com->devs[1] = make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE,
1122 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
1123 com->devs[2] = make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE,
1124 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
1125 com->devs[3] = make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK,
1126 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
1127 com->devs[4] = make_dev(&sio_cdevsw,
1128 minorbase | CALLOUT_MASK | CONTROL_INIT_STATE,
1129 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
1130 com->devs[5] = make_dev(&sio_cdevsw,
1131 minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE,
1132 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
1133 for (rid = 0; rid < 6; rid++)
1134 com->devs[rid]->si_drv1 = com;
1135 com->flags = flags;
1136 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1137
1138 if (COM_PPSCTS(flags))
1139 com->pps_bit = MSR_CTS;
1140 else
1141 com->pps_bit = MSR_DCD;
1142 pps_init(&com->pps);
1143
1144 rid = 0;
1145 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1146 RF_ACTIVE);
1147 if (com->irqres) {
1148 ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1149 INTR_TYPE_TTY | INTR_FAST,
1150 siointr, com, &com->cookie);
1151 if (ret) {
1152 ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1153 com->irqres, INTR_TYPE_TTY,
1154 siointr, com, &com->cookie);
1155 if (ret == 0)
1156 device_printf(dev, "unable to activate interrupt in fast mode - using normal mode\n");
1157 }
1158 if (ret)
1159 device_printf(dev, "could not activate interrupt\n");
1160#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
1161 defined(ALT_BREAK_TO_DEBUGGER))
1162 /*
1163 * Enable interrupts for early break-to-debugger support
1164 * on the console.
1165 */
1166 if (ret == 0 && unit == comconsole)
1167 outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS |
1168 IER_EMSC);
1169#endif
1170 }
1171
1172 return (0);
1173}
1174
1175static int
1176sioopen(dev, flag, mode, td)
1177 dev_t dev;
1178 int flag;
1179 int mode;
1180 struct thread *td;
1181{
1182 struct com_s *com;
1183 int error;
1184 int mynor;
1185 int s;
1186 struct tty *tp;
1187 int unit;
1188
1189 mynor = minor(dev);
1190 unit = MINOR_TO_UNIT(mynor);
1191 com = com_addr(unit);
1192 if (com == NULL)
1193 return (ENXIO);
1194 if (com->gone)
1195 return (ENXIO);
1196 if (mynor & CONTROL_MASK)
1197 return (0);
1198 tp = dev->si_tty = com->tp = ttymalloc(com->tp);
1199 s = spltty();
1200 /*
1201 * We jump to this label after all non-interrupted sleeps to pick
1202 * up any changes of the device state.
1203 */
1204open_top:
1205 while (com->state & CS_DTR_OFF) {
1206 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
1207 if (com_addr(unit) == NULL)
1208 return (ENXIO);
1209 if (error != 0 || com->gone)
1210 goto out;
1211 }
1212 if (tp->t_state & TS_ISOPEN) {
1213 /*
1214 * The device is open, so everything has been initialized.
1215 * Handle conflicts.
1216 */
1217 if (mynor & CALLOUT_MASK) {
1218 if (!com->active_out) {
1219 error = EBUSY;
1220 goto out;
1221 }
1222 } else {
1223 if (com->active_out) {
1224 if (flag & O_NONBLOCK) {
1225 error = EBUSY;
1226 goto out;
1227 }
1228 error = tsleep(&com->active_out,
1229 TTIPRI | PCATCH, "siobi", 0);
1230 if (com_addr(unit) == NULL)
1231 return (ENXIO);
1232 if (error != 0 || com->gone)
1233 goto out;
1234 goto open_top;
1235 }
1236 }
1237 if (tp->t_state & TS_XCLUDE &&
1238 suser(td)) {
1239 error = EBUSY;
1240 goto out;
1241 }
1242 } else {
1243 /*
1244 * The device isn't open, so there are no conflicts.
1245 * Initialize it. Initialization is done twice in many
1246 * cases: to preempt sleeping callin opens if we are
1247 * callout, and to complete a callin open after DCD rises.
1248 */
1249 tp->t_oproc = comstart;
1250 tp->t_param = comparam;
1251 tp->t_stop = comstop;
1252 tp->t_dev = dev;
1253 tp->t_termios = mynor & CALLOUT_MASK
1254 ? com->it_out : com->it_in;
1255 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1256 com->poll = com->no_irq;
1257 com->poll_output = com->loses_outints;
1258 ++com->wopeners;
1259 error = comparam(tp, &tp->t_termios);
1260 --com->wopeners;
1261 if (error != 0)
1262 goto out;
1263 /*
1264 * XXX we should goto open_top if comparam() slept.
1265 */
1266 if (com->hasfifo) {
1267 int i;
1268 /*
1269 * (Re)enable and drain fifos.
1270 *
1271 * Certain SMC chips cause problems if the fifos
1272 * are enabled while input is ready. Turn off the
1273 * fifo if necessary to clear the input. We test
1274 * the input ready bit after enabling the fifos
1275 * since we've already enabled them in comparam()
1276 * and to handle races between enabling and fresh
1277 * input.
1278 */
1279 for (i = 0; i < 500; i++) {
1280 sio_setreg(com, com_fifo,
1281 FIFO_RCV_RST | FIFO_XMT_RST
1282 | com->fifo_image);
1283 /*
1284 * XXX the delays are for superstitious
1285 * historical reasons. It must be less than
1286 * the character time at the maximum
1287 * supported speed (87 usec at 115200 bps
1288 * 8N1). Otherwise we might loop endlessly
1289 * if data is streaming in. We used to use
1290 * delays of 100. That usually worked
1291 * because DELAY(100) used to usually delay
1292 * for about 85 usec instead of 100.
1293 */
1294 DELAY(50);
1295 if (!(inb(com->line_status_port) & LSR_RXRDY))
1296 break;
1297 sio_setreg(com, com_fifo, 0);
1298 DELAY(50);
1299 (void) inb(com->data_port);
1300 }
1301 if (i == 500) {
1302 error = EIO;
1303 goto out;
1304 }
1305 }
1306
1307 mtx_lock_spin(&sio_lock);
1308 (void) inb(com->line_status_port);
1309 (void) inb(com->data_port);
1310 com->prev_modem_status = com->last_modem_status
1311 = inb(com->modem_status_port);
1312 if (COM_IIR_TXRDYBUG(com->flags)) {
1313 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1314 | IER_EMSC);
1315 } else {
1316 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1317 | IER_ERLS | IER_EMSC);
1318 }
1319 mtx_unlock_spin(&sio_lock);
1320 /*
1321 * Handle initial DCD. Callout devices get a fake initial
1322 * DCD (trapdoor DCD). If we are callout, then any sleeping
1323 * callin opens get woken up and resume sleeping on "siobi"
1324 * instead of "siodcd".
1325 */
1326 /*
1327 * XXX `mynor & CALLOUT_MASK' should be
1328 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
1329 * TRAPDOOR_CARRIER is the default initial state for callout
1330 * devices and SOFT_CARRIER is like CLOCAL except it hides
1331 * the true carrier.
1332 */
1333 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
1334 (*linesw[tp->t_line].l_modem)(tp, 1);
1335 }
1336 /*
1337 * Wait for DCD if necessary.
1338 */
1339 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1340 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
1341 ++com->wopeners;
1342 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
1343 if (com_addr(unit) == NULL)
1344 return (ENXIO);
1345 --com->wopeners;
1346 if (error != 0 || com->gone)
1347 goto out;
1348 goto open_top;
1349 }
1350 error = (*linesw[tp->t_line].l_open)(dev, tp);
1351 disc_optim(tp, &tp->t_termios, com);
1352 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1353 com->active_out = TRUE;
1354 siosettimeout();
1355out:
1356 splx(s);
1357 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
1358 comhardclose(com);
1359 return (error);
1360}
1361
1362static int
1363sioclose(dev, flag, mode, td)
1364 dev_t dev;
1365 int flag;
1366 int mode;
1367 struct thread *td;
1368{
1369 struct com_s *com;
1370 int mynor;
1371 int s;
1372 struct tty *tp;
1373
1374 mynor = minor(dev);
1375 if (mynor & CONTROL_MASK)
1376 return (0);
1377 com = com_addr(MINOR_TO_UNIT(mynor));
1378 if (com == NULL)
1379 return (ENODEV);
1380 tp = com->tp;
1381 s = spltty();
1382 (*linesw[tp->t_line].l_close)(tp, flag);
1383 disc_optim(tp, &tp->t_termios, com);
1384 comstop(tp, FREAD | FWRITE);
1385 comhardclose(com);
1386 ttyclose(tp);
1387 siosettimeout();
1388 splx(s);
1389 if (com->gone) {
1390 printf("sio%d: gone\n", com->unit);
1391 s = spltty();
1392 if (com->ibuf != NULL)
1393 free(com->ibuf, M_DEVBUF);
1394 bzero(tp, sizeof *tp);
1395 splx(s);
1396 }
1397 return (0);
1398}
1399
1400static void
1401comhardclose(com)
1402 struct com_s *com;
1403{
1404 int s;
1405 struct tty *tp;
1406
1407 s = spltty();
1408 com->poll = FALSE;
1409 com->poll_output = FALSE;
1410 com->do_timestamp = FALSE;
1411 com->do_dcd_timestamp = FALSE;
1412 com->pps.ppsparam.mode = 0;
1413 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1414 tp = com->tp;
1415
1416#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
1417 defined(ALT_BREAK_TO_DEBUGGER))
1418 /*
1419 * Leave interrupts enabled and don't clear DTR if this is the
1420 * console. This allows us to detect break-to-debugger events
1421 * while the console device is closed.
1422 */
1423 if (com->unit != comconsole)
1424#endif
1425 {
1426 sio_setreg(com, com_ier, 0);
1427 if (tp->t_cflag & HUPCL
1428 /*
1429 * XXX we will miss any carrier drop between here and the
1430 * next open. Perhaps we should watch DCD even when the
1431 * port is closed; it is not sufficient to check it at
1432 * the next open because it might go up and down while
1433 * we're not watching.
1434 */
1435 || (!com->active_out
1436 && !(com->prev_modem_status & MSR_DCD)
1437 && !(com->it_in.c_cflag & CLOCAL))
1438 || !(tp->t_state & TS_ISOPEN)) {
1439 (void)commctl(com, TIOCM_DTR, DMBIC);
1440 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
1441 timeout(siodtrwakeup, com, com->dtr_wait);
1442 com->state |= CS_DTR_OFF;
1443 }
1444 }
1445 }
1446 if (com->hasfifo) {
1447 /*
1448 * Disable fifos so that they are off after controlled
1449 * reboots. Some BIOSes fail to detect 16550s when the
1450 * fifos are enabled.
1451 */
1452 sio_setreg(com, com_fifo, 0);
1453 }
1454 com->active_out = FALSE;
1455 wakeup(&com->active_out);
1456 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */
1457 splx(s);
1458}
1459
1460static int
1461sioread(dev, uio, flag)
1462 dev_t dev;
1463 struct uio *uio;
1464 int flag;
1465{
1466 int mynor;
1467 struct com_s *com;
1468
1469 mynor = minor(dev);
1470 if (mynor & CONTROL_MASK)
1471 return (ENODEV);
1472 com = com_addr(MINOR_TO_UNIT(mynor));
1473 if (com == NULL || com->gone)
1474 return (ENODEV);
1475 return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag));
1476}
1477
1478static int
1479siowrite(dev, uio, flag)
1480 dev_t dev;
1481 struct uio *uio;
1482 int flag;
1483{
1484 int mynor;
1485 struct com_s *com;
1486 int unit;
1487
1488 mynor = minor(dev);
1489 if (mynor & CONTROL_MASK)
1490 return (ENODEV);
1491
1492 unit = MINOR_TO_UNIT(mynor);
1493 com = com_addr(unit);
1494 if (com == NULL || com->gone)
1495 return (ENODEV);
1496 /*
1497 * (XXX) We disallow virtual consoles if the physical console is
1498 * a serial port. This is in case there is a display attached that
1499 * is not the console. In that situation we don't need/want the X
1500 * server taking over the console.
1501 */
1502 if (constty != NULL && unit == comconsole)
1503 constty = NULL;
1504 return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag));
1505}
1506
1507static void
1508siobusycheck(chan)
1509 void *chan;
1510{
1511 struct com_s *com;
1512 int s;
1513
1514 com = (struct com_s *)chan;
1515
1516 /*
1517 * Clear TS_BUSY if low-level output is complete.
1518 * spl locking is sufficient because siointr1() does not set CS_BUSY.
1519 * If siointr1() clears CS_BUSY after we look at it, then we'll get
1520 * called again. Reading the line status port outside of siointr1()
1521 * is safe because CS_BUSY is clear so there are no output interrupts
1522 * to lose.
1523 */
1524 s = spltty();
1525 if (com->state & CS_BUSY)
1526 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */
1527 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1528 == (LSR_TSRE | LSR_TXRDY)) {
1529 com->tp->t_state &= ~TS_BUSY;
1530 ttwwakeup(com->tp);
1531 com->extra_state &= ~CSE_BUSYCHECK;
1532 } else
1533 timeout(siobusycheck, com, hz / 100);
1534 splx(s);
1535}
1536
1537static u_int
1538siodivisor(rclk, speed)
1539 u_long rclk;
1540 speed_t speed;
1541{
1542 long actual_speed;
1543 u_int divisor;
1544 int error;
1545
1546 if (speed == 0)
1547 return (0);
1548#if UINT_MAX > (ULONG_MAX - 1) / 8
1549 if (speed > (ULONG_MAX - 1) / 8)
1550 return (0);
1551#endif
1552 divisor = (rclk / (8UL * speed) + 1) / 2;
1553 if (divisor == 0 || divisor >= 65536)
1554 return (0);
1555 actual_speed = rclk / (16UL * divisor);
1556
1557 /* 10 times error in percent: */
1558 error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
1559
1560 /* 3.0% maximum error tolerance: */
1561 if (error < -30 || error > 30)
1562 return (0);
1563
1564 return (divisor);
1565}
1566
1567static void
1568siodtrwakeup(chan)
1569 void *chan;
1570{
1571 struct com_s *com;
1572
1573 com = (struct com_s *)chan;
1574 com->state &= ~CS_DTR_OFF;
1575 wakeup(&com->dtr_wait);
1576}
1577
1578/*
1579 * Call this function with the sio_lock mutex held. It will return with the
1580 * lock still held.
1581 */
1582static void
1583sioinput(com)
1584 struct com_s *com;
1585{
1586 u_char *buf;
1587 int incc;
1588 u_char line_status;
1589 int recv_data;
1590 struct tty *tp;
1591
1592 buf = com->ibuf;
1593 tp = com->tp;
1594 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1595 com_events -= (com->iptr - com->ibuf);
1596 com->iptr = com->ibuf;
1597 return;
1598 }
1599 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1600 /*
1601 * Avoid the grotesquely inefficient lineswitch routine
1602 * (ttyinput) in "raw" mode. It usually takes about 450
1603 * instructions (that's without canonical processing or echo!).
1604 * slinput is reasonably fast (usually 40 instructions plus
1605 * call overhead).
1606 */
1607 do {
1608 /*
1609 * This may look odd, but it is using save-and-enable
1610 * semantics instead of the save-and-disable semantics
1611 * that are used everywhere else.
1612 */
1613 mtx_unlock_spin(&sio_lock);
1614 incc = com->iptr - buf;
1615 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1616 && (com->state & CS_RTS_IFLOW
1617 || tp->t_iflag & IXOFF)
1618 && !(tp->t_state & TS_TBLOCK))
1619 ttyblock(tp);
1620 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1621 += b_to_q((char *)buf, incc, &tp->t_rawq);
1622 buf += incc;
1623 tk_nin += incc;
1624 tk_rawcc += incc;
1625 tp->t_rawcc += incc;
1626 ttwakeup(tp);
1627 if (tp->t_state & TS_TTSTOP
1628 && (tp->t_iflag & IXANY
1629 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1630 tp->t_state &= ~TS_TTSTOP;
1631 tp->t_lflag &= ~FLUSHO;
1632 comstart(tp);
1633 }
1634 mtx_lock_spin(&sio_lock);
1635 } while (buf < com->iptr);
1636 } else {
1637 do {
1638 /*
1639 * This may look odd, but it is using save-and-enable
1640 * semantics instead of the save-and-disable semantics
1641 * that are used everywhere else.
1642 */
1643 mtx_unlock_spin(&sio_lock);
1644 line_status = buf[com->ierroff];
1645 recv_data = *buf++;
1646 if (line_status
1647 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1648 if (line_status & LSR_BI)
1649 recv_data |= TTY_BI;
1650 if (line_status & LSR_FE)
1651 recv_data |= TTY_FE;
1652 if (line_status & LSR_OE)
1653 recv_data |= TTY_OE;
1654 if (line_status & LSR_PE)
1655 recv_data |= TTY_PE;
1656 }
1657 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1658 mtx_lock_spin(&sio_lock);
1659 } while (buf < com->iptr);
1660 }
1661 com_events -= (com->iptr - com->ibuf);
1662 com->iptr = com->ibuf;
1663
1664 /*
1665 * There is now room for another low-level buffer full of input,
1666 * so enable RTS if it is now disabled and there is room in the
1667 * high-level buffer.
1668 */
1669 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1670 !(tp->t_state & TS_TBLOCK))
1671 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1672}
1673
1674static void
1675siointr(arg)
1676 void *arg;
1677{
1678 struct com_s *com;
1679
1680#ifndef COM_MULTIPORT
1681 com = (struct com_s *)arg;
1682
1683 mtx_lock_spin(&sio_lock);
1684 siointr1(com);
1685 mtx_unlock_spin(&sio_lock);
1686#else /* COM_MULTIPORT */
1687 bool_t possibly_more_intrs;
1688 int unit;
1689
1690 /*
1691 * Loop until there is no activity on any port. This is necessary
1692 * to get an interrupt edge more than to avoid another interrupt.
1693 * If the IRQ signal is just an OR of the IRQ signals from several
1694 * devices, then the edge from one may be lost because another is
1695 * on.
1696 */
1697 mtx_lock_spin(&sio_lock);
1698 do {
1699 possibly_more_intrs = FALSE;
1700 for (unit = 0; unit < sio_numunits; ++unit) {
1701 com = com_addr(unit);
1702 /*
1703 * XXX COM_LOCK();
1704 * would it work here, or be counter-productive?
1705 */
1706 if (com != NULL
1707 && !com->gone
1708 && (inb(com->int_id_port) & IIR_IMASK)
1709 != IIR_NOPEND) {
1710 siointr1(com);
1711 possibly_more_intrs = TRUE;
1712 }
1713 /* XXX COM_UNLOCK(); */
1714 }
1715 } while (possibly_more_intrs);
1716 mtx_unlock_spin(&sio_lock);
1717#endif /* COM_MULTIPORT */
1718}
1719
1720static struct timespec siots[8192];
1721static int siotso;
1722static int volatile siotsunit = -1;
1723
1724static int
1725sysctl_siots(SYSCTL_HANDLER_ARGS)
1726{
1727 char buf[128];
1728 long long delta;
1729 size_t len;
1730 int error, i;
1731
1732 for (i = 1; i < siotso; i++) {
1733 delta = (long long)(siots[i].tv_sec - siots[i - 1].tv_sec) *
1734 1000000000 +
1735 (siots[i].tv_nsec - siots[i - 1].tv_nsec);
1736 len = sprintf(buf, "%lld\n", delta);
1737 if (delta >= 110000)
1738 len += sprintf(buf + len - 1, ": *** %ld.%09ld\n",
1739 (long)siots[i].tv_sec, siots[i].tv_nsec);
1740 if (i == siotso - 1)
1741 buf[len - 1] = '\0';
1742 error = SYSCTL_OUT(req, buf, len);
1743 if (error != 0)
1744 return (error);
1745 uio_yield();
1746 }
1747 return (0);
1748}
1749
1750SYSCTL_PROC(_machdep, OID_AUTO, siots, CTLTYPE_STRING | CTLFLAG_RD,
1751 0, 0, sysctl_siots, "A", "sio timestamps");
1752
1753static void
1754siointr1(com)
1755 struct com_s *com;
1756{
1757 u_char line_status;
1758 u_char modem_status;
1759 u_char *ioptr;
1760 u_char recv_data;
1761 u_char int_ctl;
1762 u_char int_ctl_new;
1763
1764 int_ctl = inb(com->intr_ctl_port);
1765 int_ctl_new = int_ctl;
1766
1767 while (!com->gone) {
1768 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
1769 modem_status = inb(com->modem_status_port);
1770 if ((modem_status ^ com->last_modem_status) &
1771 com->pps_bit) {
1772 pps_capture(&com->pps);
1773 pps_event(&com->pps,
1774 (modem_status & com->pps_bit) ?
1775 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
1776 }
1777 }
1778 line_status = inb(com->line_status_port);
1779
1780 /* input event? (check first to help avoid overruns) */
1781 while (line_status & LSR_RCV_MASK) {
1782 /* break/unnattached error bits or real input? */
1783 if (!(line_status & LSR_RXRDY))
1784 recv_data = 0;
1785 else
1786 recv_data = inb(com->data_port);
1787#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
1788 /*
1789 * Solaris implements a new BREAK which is initiated
1790 * by a character sequence CR ~ ^b which is similar
1791 * to a familiar pattern used on Sun servers by the
1792 * Remote Console.
1793 */
1794#define KEY_CRTLB 2 /* ^B */
1795#define KEY_CR 13 /* CR '\r' */
1796#define KEY_TILDE 126 /* ~ */
1797
1798 if (com->unit == comconsole) {
1799 static int brk_state1 = 0, brk_state2 = 0;
1800 if (recv_data == KEY_CR) {
1801 brk_state1 = recv_data;
1802 brk_state2 = 0;
1803 } else if (brk_state1 == KEY_CR
1804 && (recv_data == KEY_TILDE
1805 || recv_data == KEY_CRTLB)) {
1806 if (recv_data == KEY_TILDE)
1807 brk_state2 = recv_data;
1808 else if (brk_state2 == KEY_TILDE
1809 && recv_data == KEY_CRTLB) {
1810 breakpoint();
1811 brk_state1 = 0;
1812 brk_state2 = 0;
1813 goto cont;
1814 } else
1815 brk_state2 = 0;
1816 } else
1817 brk_state1 = 0;
1818 }
1819#endif
1820 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1821 /*
1822 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1823 * Otherwise, push the work to a higher level
1824 * (to handle PARMRK) if we're bypassing.
1825 * Otherwise, convert BI/FE and PE+INPCK to 0.
1826 *
1827 * This makes bypassing work right in the
1828 * usual "raw" case (IGNBRK set, and IGNPAR
1829 * and INPCK clear).
1830 *
1831 * Note: BI together with FE/PE means just BI.
1832 */
1833 if (line_status & LSR_BI) {
1834#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
1835 if (com->unit == comconsole) {
1836 breakpoint();
1837 goto cont;
1838 }
1839#endif
1840 if (com->tp == NULL
1841 || com->tp->t_iflag & IGNBRK)
1842 goto cont;
1843 } else {
1844 if (com->tp == NULL
1845 || com->tp->t_iflag & IGNPAR)
1846 goto cont;
1847 }
1848 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1849 && (line_status & (LSR_BI | LSR_FE)
1850 || com->tp->t_iflag & INPCK))
1851 recv_data = 0;
1852 }
1853 ++com->bytes_in;
1854 if (com->hotchar != 0 && recv_data == com->hotchar)
1855 swi_sched(sio_fast_ih, 0);
1856 ioptr = com->iptr;
1857 if (ioptr >= com->ibufend)
1858 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1859 else {
1860 if (com->do_timestamp)
1861 microtime(&com->timestamp);
1862 ++com_events;
1863 swi_sched(sio_slow_ih, SWI_DELAY);
1864#if 0 /* for testing input latency vs efficiency */
1865if (com->iptr - com->ibuf == 8)
1866 swi_sched(sio_fast_ih, 0);
1867#endif
1868 ioptr[0] = recv_data;
1869 ioptr[com->ierroff] = line_status;
1870 com->iptr = ++ioptr;
1871 if (ioptr == com->ihighwater
1872 && com->state & CS_RTS_IFLOW)
1873 outb(com->modem_ctl_port,
1874 com->mcr_image &= ~MCR_RTS);
1875 if (line_status & LSR_OE)
1876 CE_RECORD(com, CE_OVERRUN);
1877 }
1878cont:
1879 /*
1880 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
1881 * jump from the top of the loop to here
1882 */
1883 line_status = inb(com->line_status_port) & 0x7F;
1884 }
1885
1886 /* modem status change? (always check before doing output) */
1887 modem_status = inb(com->modem_status_port);
1888 if (modem_status != com->last_modem_status) {
1889 if (com->do_dcd_timestamp
1890 && !(com->last_modem_status & MSR_DCD)
1891 && modem_status & MSR_DCD)
1892 microtime(&com->dcd_timestamp);
1893
1894 /*
1895 * Schedule high level to handle DCD changes. Note
1896 * that we don't use the delta bits anywhere. Some
1897 * UARTs mess them up, and it's easy to remember the
1898 * previous bits and calculate the delta.
1899 */
1900 com->last_modem_status = modem_status;
1901 if (!(com->state & CS_CHECKMSR)) {
1902 com_events += LOTS_OF_EVENTS;
1903 com->state |= CS_CHECKMSR;
1904 swi_sched(sio_fast_ih, 0);
1905 }
1906
1907 /* handle CTS change immediately for crisp flow ctl */
1908 if (com->state & CS_CTS_OFLOW) {
1909 if (modem_status & MSR_CTS)
1910 com->state |= CS_ODEVREADY;
1911 else
1912 com->state &= ~CS_ODEVREADY;
1913 }
1914 }
1915
1916 /* output queued and everything ready? */
1917 if (line_status & LSR_TXRDY
1918 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1919 ioptr = com->obufq.l_head;
1920 if (com->tx_fifo_size > 1 && com->unit != siotsunit) {
1921 u_int ocount;
1922
1923 ocount = com->obufq.l_tail - ioptr;
1924 if (ocount > com->tx_fifo_size)
1925 ocount = com->tx_fifo_size;
1926 com->bytes_out += ocount;
1927 do
1928 outb(com->data_port, *ioptr++);
1929 while (--ocount != 0);
1930 } else {
1931 outb(com->data_port, *ioptr++);
1932 ++com->bytes_out;
1933 if (com->unit == siotsunit) {
1934 nanouptime(&siots[siotso]);
1935 siotso = (siotso + 1) %
1936 (sizeof siots / sizeof siots[0]);
1937 }
1938 }
1939 com->obufq.l_head = ioptr;
1940 if (COM_IIR_TXRDYBUG(com->flags)) {
1941 int_ctl_new = int_ctl | IER_ETXRDY;
1942 }
1943 if (ioptr >= com->obufq.l_tail) {
1944 struct lbq *qp;
1945
1946 qp = com->obufq.l_next;
1947 qp->l_queued = FALSE;
1948 qp = qp->l_next;
1949 if (qp != NULL) {
1950 com->obufq.l_head = qp->l_head;
1951 com->obufq.l_tail = qp->l_tail;
1952 com->obufq.l_next = qp;
1953 } else {
1954 /* output just completed */
1955 if (COM_IIR_TXRDYBUG(com->flags)) {
1956 int_ctl_new = int_ctl & ~IER_ETXRDY;
1957 }
1958 com->state &= ~CS_BUSY;
1959 }
1960 if (!(com->state & CS_ODONE)) {
1961 com_events += LOTS_OF_EVENTS;
1962 com->state |= CS_ODONE;
1963 /* handle at high level ASAP */
1964 swi_sched(sio_fast_ih, 0);
1965 }
1966 }
1967 if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
1968 outb(com->intr_ctl_port, int_ctl_new);
1969 }
1970 }
1971
1972 /* finished? */
1973#ifndef COM_MULTIPORT
1974 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
1975#endif /* COM_MULTIPORT */
1976 return;
1977 }
1978}
1979
1980static int
1981sioioctl(dev, cmd, data, flag, td)
1982 dev_t dev;
1983 u_long cmd;
1984 caddr_t data;
1985 int flag;
1986 struct thread *td;
1987{
1988 struct com_s *com;
1989 int error;
1990 int mynor;
1991 int s;
1992 struct tty *tp;
1993#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1994 u_long oldcmd;
1995 struct termios term;
1996#endif
1997
1998 mynor = minor(dev);
1999 com = com_addr(MINOR_TO_UNIT(mynor));
2000 if (com == NULL || com->gone)
2001 return (ENODEV);
2002 if (mynor & CONTROL_MASK) {
2003 struct termios *ct;
2004
2005 switch (mynor & CONTROL_MASK) {
2006 case CONTROL_INIT_STATE:
2007 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2008 break;
2009 case CONTROL_LOCK_STATE:
2010 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2011 break;
2012 default:
2013 return (ENODEV); /* /dev/nodev */
2014 }
2015 switch (cmd) {
2016 case TIOCSETA:
2017 error = suser(td);
2018 if (error != 0)
2019 return (error);
2020 *ct = *(struct termios *)data;
2021 return (0);
2022 case TIOCGETA:
2023 *(struct termios *)data = *ct;
2024 return (0);
2025 case TIOCGETD:
2026 *(int *)data = TTYDISC;
2027 return (0);
2028 case TIOCGWINSZ:
2029 bzero(data, sizeof(struct winsize));
2030 return (0);
2031 default:
2032 return (ENOTTY);
2033 }
2034 }
2035 tp = com->tp;
2036#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2037 term = tp->t_termios;
2038 oldcmd = cmd;
2039 error = ttsetcompat(tp, &cmd, data, &term);
2040 if (error != 0)
2041 return (error);
2042 if (cmd != oldcmd)
2043 data = (caddr_t)&term;
2044#endif
2045 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2046 int cc;
2047 struct termios *dt = (struct termios *)data;
2048 struct termios *lt = mynor & CALLOUT_MASK
2049 ? &com->lt_out : &com->lt_in;
2050
2051 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2052 | (dt->c_iflag & ~lt->c_iflag);
2053 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2054 | (dt->c_oflag & ~lt->c_oflag);
2055 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2056 | (dt->c_cflag & ~lt->c_cflag);
2057 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2058 | (dt->c_lflag & ~lt->c_lflag);
2059 for (cc = 0; cc < NCCS; ++cc)
2060 if (lt->c_cc[cc] != 0)
2061 dt->c_cc[cc] = tp->t_cc[cc];
2062 if (lt->c_ispeed != 0)
2063 dt->c_ispeed = tp->t_ispeed;
2064 if (lt->c_ospeed != 0)
2065 dt->c_ospeed = tp->t_ospeed;
2066 }
2067 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
2068 if (error != ENOIOCTL)
2069 return (error);
2070 s = spltty();
2071 error = ttioctl(tp, cmd, data, flag);
2072 disc_optim(tp, &tp->t_termios, com);
2073 if (error != ENOIOCTL) {
2074 splx(s);
2075 return (error);
2076 }
2077 switch (cmd) {
2078 case TIOCSBRK:
2079 sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2080 break;
2081 case TIOCCBRK:
2082 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2083 break;
2084 case TIOCSDTR:
2085 (void)commctl(com, TIOCM_DTR, DMBIS);
2086 break;
2087 case TIOCCDTR:
2088 (void)commctl(com, TIOCM_DTR, DMBIC);
2089 break;
2090 /*
2091 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The
2092 * changes get undone on the next call to comparam().
2093 */
2094 case TIOCMSET:
2095 (void)commctl(com, *(int *)data, DMSET);
2096 break;
2097 case TIOCMBIS:
2098 (void)commctl(com, *(int *)data, DMBIS);
2099 break;
2100 case TIOCMBIC:
2101 (void)commctl(com, *(int *)data, DMBIC);
2102 break;
2103 case TIOCMGET:
2104 *(int *)data = commctl(com, 0, DMGET);
2105 break;
2106 case TIOCMSDTRWAIT:
2107 /* must be root since the wait applies to following logins */
2108 error = suser(td);
2109 if (error != 0) {
2110 splx(s);
2111 return (error);
2112 }
2113 com->dtr_wait = *(int *)data * hz / 100;
2114 break;
2115 case TIOCMGDTRWAIT:
2116 *(int *)data = com->dtr_wait * 100 / hz;
2117 break;
2118 case TIOCTIMESTAMP:
2119 com->do_timestamp = TRUE;
2120 *(struct timeval *)data = com->timestamp;
2121 break;
2122 case TIOCDCDTIMESTAMP:
2123 com->do_dcd_timestamp = TRUE;
2124 *(struct timeval *)data = com->dcd_timestamp;
2125 break;
2126 default:
2127 splx(s);
2128 error = pps_ioctl(cmd, data, &com->pps);
2129 if (error == ENODEV)
2130 error = ENOTTY;
2131 return (error);
2132 }
2133 splx(s);
2134 return (0);
2135}
2136
2137/* software interrupt handler for SWI_TTY */
2138static void
2139siopoll(void *dummy)
2140{
2141 int unit;
2142
2143 if (com_events == 0)
2144 return;
2145repeat:
2146 for (unit = 0; unit < sio_numunits; ++unit) {
2147 struct com_s *com;
2148 int incc;
2149 struct tty *tp;
2150
2151 com = com_addr(unit);
2152 if (com == NULL)
2153 continue;
2154 tp = com->tp;
2155 if (tp == NULL || com->gone) {
2156 /*
2157 * Discard any events related to never-opened or
2158 * going-away devices.
2159 */
2160 mtx_lock_spin(&sio_lock);
2161 incc = com->iptr - com->ibuf;
2162 com->iptr = com->ibuf;
2163 if (com->state & CS_CHECKMSR) {
2164 incc += LOTS_OF_EVENTS;
2165 com->state &= ~CS_CHECKMSR;
2166 }
2167 com_events -= incc;
2168 mtx_unlock_spin(&sio_lock);
2169 continue;
2170 }
2171 if (com->iptr != com->ibuf) {
2172 mtx_lock_spin(&sio_lock);
2173 sioinput(com);
2174 mtx_unlock_spin(&sio_lock);
2175 }
2176 if (com->state & CS_CHECKMSR) {
2177 u_char delta_modem_status;
2178
2179 mtx_lock_spin(&sio_lock);
2180 delta_modem_status = com->last_modem_status
2181 ^ com->prev_modem_status;
2182 com->prev_modem_status = com->last_modem_status;
2183 com_events -= LOTS_OF_EVENTS;
2184 com->state &= ~CS_CHECKMSR;
2185 mtx_unlock_spin(&sio_lock);
2186 if (delta_modem_status & MSR_DCD)
2187 (*linesw[tp->t_line].l_modem)
2188 (tp, com->prev_modem_status & MSR_DCD);
2189 }
2190 if (com->state & CS_ODONE) {
2191 mtx_lock_spin(&sio_lock);
2192 com_events -= LOTS_OF_EVENTS;
2193 com->state &= ~CS_ODONE;
2194 mtx_unlock_spin(&sio_lock);
2195 if (!(com->state & CS_BUSY)
2196 && !(com->extra_state & CSE_BUSYCHECK)) {
2197 timeout(siobusycheck, com, hz / 100);
2198 com->extra_state |= CSE_BUSYCHECK;
2199 }
2200 (*linesw[tp->t_line].l_start)(tp);
2201 }
2202 if (com_events == 0)
2203 break;
2204 }
2205 if (com_events >= LOTS_OF_EVENTS)
2206 goto repeat;
2207}
2208
2209static int
2210comparam(tp, t)
2211 struct tty *tp;
2212 struct termios *t;
2213{
2214 u_int cfcr;
2215 int cflag;
2216 struct com_s *com;
2217 u_int divisor;
2218 u_char dlbh;
2219 u_char dlbl;
2220 int s;
2221 int unit;
2222
2223 unit = DEV_TO_UNIT(tp->t_dev);
2224 com = com_addr(unit);
2225 if (com == NULL)
2226 return (ENODEV);
2227
2228 /* do historical conversions */
2229 if (t->c_ispeed == 0)
2230 t->c_ispeed = t->c_ospeed;
2231
2232 /* check requested parameters */
2233 if (t->c_ospeed == 0)
2234 divisor = 0;
2235 else {
2236 if (t->c_ispeed != t->c_ospeed)
2237 return (EINVAL);
2238 divisor = siodivisor(com->rclk, t->c_ispeed);
2239 if (divisor == 0)
2240 return (EINVAL);
2241 }
2242
2243 /* parameters are OK, convert them to the com struct and the device */
2244 s = spltty();
2245 if (divisor == 0)
2246 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
2247 else
2248 (void)commctl(com, TIOCM_DTR, DMBIS);
2249 cflag = t->c_cflag;
2250 switch (cflag & CSIZE) {
2251 case CS5:
2252 cfcr = CFCR_5BITS;
2253 break;
2254 case CS6:
2255 cfcr = CFCR_6BITS;
2256 break;
2257 case CS7:
2258 cfcr = CFCR_7BITS;
2259 break;
2260 default:
2261 cfcr = CFCR_8BITS;
2262 break;
2263 }
2264 if (cflag & PARENB) {
2265 cfcr |= CFCR_PENAB;
2266 if (!(cflag & PARODD))
2267 cfcr |= CFCR_PEVEN;
2268 }
2269 if (cflag & CSTOPB)
2270 cfcr |= CFCR_STOPB;
2271
2272 if (com->hasfifo && divisor != 0) {
2273 /*
2274 * Use a fifo trigger level low enough so that the input
2275 * latency from the fifo is less than about 16 msec and
2276 * the total latency is less than about 30 msec. These
2277 * latencies are reasonable for humans. Serial comms
2278 * protocols shouldn't expect anything better since modem
2279 * latencies are larger.
2280 *
2281 * The fifo trigger level cannot be set at RX_HIGH for high
2282 * speed connections without further work on reducing
2283 * interrupt disablement times in other parts of the system,
2284 * without producing silo overflow errors.
2285 */
2286 com->fifo_image = com->unit == siotsunit ? 0
2287 : t->c_ospeed <= 4800
2288 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
2289#ifdef COM_ESP
2290 /*
2291 * The Hayes ESP card needs the fifo DMA mode bit set
2292 * in compatibility mode. If not, it will interrupt
2293 * for each character received.
2294 */
2295 if (com->esp)
2296 com->fifo_image |= FIFO_DMA_MODE;
2297#endif
2298 sio_setreg(com, com_fifo, com->fifo_image);
2299 }
2300
2301 /*
2302 * This returns with interrupts disabled so that we can complete
2303 * the speed change atomically. Keeping interrupts disabled is
2304 * especially important while com_data is hidden.
2305 */
2306 (void) siosetwater(com, t->c_ispeed);
2307
2308 if (divisor != 0) {
2309 sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2310 /*
2311 * Only set the divisor registers if they would change,
2312 * since on some 16550 incompatibles (UMC8669F), setting
2313 * them while input is arriving them loses sync until
2314 * data stops arriving.
2315 */
2316 dlbl = divisor & 0xFF;
2317 if (sio_getreg(com, com_dlbl) != dlbl)
2318 sio_setreg(com, com_dlbl, dlbl);
2319 dlbh = divisor >> 8;
2320 if (sio_getreg(com, com_dlbh) != dlbh)
2321 sio_setreg(com, com_dlbh, dlbh);
2322 }
2323
2324 sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
2325
2326 if (!(tp->t_state & TS_TTSTOP))
2327 com->state |= CS_TTGO;
2328
2329 if (cflag & CRTS_IFLOW) {
2330 if (com->st16650a) {
2331 sio_setreg(com, com_cfcr, 0xbf);
2332 sio_setreg(com, com_fifo,
2333 sio_getreg(com, com_fifo) | 0x40);
2334 }
2335 com->state |= CS_RTS_IFLOW;
2336 /*
2337 * If CS_RTS_IFLOW just changed from off to on, the change
2338 * needs to be propagated to MCR_RTS. This isn't urgent,
2339 * so do it later by calling comstart() instead of repeating
2340 * a lot of code from comstart() here.
2341 */
2342 } else if (com->state & CS_RTS_IFLOW) {
2343 com->state &= ~CS_RTS_IFLOW;
2344 /*
2345 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS
2346 * on here, since comstart() won't do it later.
2347 */
2348 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2349 if (com->st16650a) {
2350 sio_setreg(com, com_cfcr, 0xbf);
2351 sio_setreg(com, com_fifo,
2352 sio_getreg(com, com_fifo) & ~0x40);
2353 }
2354 }
2355
2356
2357 /*
2358 * Set up state to handle output flow control.
2359 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2360 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2361 */
2362 com->state |= CS_ODEVREADY;
2363 com->state &= ~CS_CTS_OFLOW;
2364 if (cflag & CCTS_OFLOW) {
2365 com->state |= CS_CTS_OFLOW;
2366 if (!(com->last_modem_status & MSR_CTS))
2367 com->state &= ~CS_ODEVREADY;
2368 if (com->st16650a) {
2369 sio_setreg(com, com_cfcr, 0xbf);
2370 sio_setreg(com, com_fifo,
2371 sio_getreg(com, com_fifo) | 0x80);
2372 }
2373 } else {
2374 if (com->st16650a) {
2375 sio_setreg(com, com_cfcr, 0xbf);
2376 sio_setreg(com, com_fifo,
2377 sio_getreg(com, com_fifo) & ~0x80);
2378 }
2379 }
2380
2381 sio_setreg(com, com_cfcr, com->cfcr_image);
2382
2383 /* XXX shouldn't call functions while intrs are disabled. */
2384 disc_optim(tp, t, com);
2385 /*
2386 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2387 * unconditionally, but that defeated the careful discarding of
2388 * stale input in sioopen().
2389 */
2390 if (com->state >= (CS_BUSY | CS_TTGO))
2391 siointr1(com);
2392
2393 mtx_unlock_spin(&sio_lock);
2394 splx(s);
2395 comstart(tp);
2396 if (com->ibufold != NULL) {
2397 free(com->ibufold, M_DEVBUF);
2398 com->ibufold = NULL;
2399 }
2400 return (0);
2401}
2402
2403/*
2404 * This function must be called with the sio_lock mutex released and will
2405 * return with it obtained.
2406 */
2407static int
2408siosetwater(com, speed)
2409 struct com_s *com;
2410 speed_t speed;
2411{
2412 int cp4ticks;
2413 u_char *ibuf;
2414 int ibufsize;
2415 struct tty *tp;
2416
2417 /*
2418 * Make the buffer size large enough to handle a softtty interrupt
2419 * latency of about 2 ticks without loss of throughput or data
2420 * (about 3 ticks if input flow control is not used or not honoured,
2421 * but a bit less for CS5-CS7 modes).
2422 */
2423 cp4ticks = speed / 10 / hz * 4;
2424 for (ibufsize = 128; ibufsize < cp4ticks;)
2425 ibufsize <<= 1;
2426 if (ibufsize == com->ibufsize) {
2427 mtx_lock_spin(&sio_lock);
2428 return (0);
2429 }
2430
2431 /*
2432 * Allocate input buffer. The extra factor of 2 in the size is
2433 * to allow for an error byte for each input byte.
2434 */
2435 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2436 if (ibuf == NULL) {
2437 mtx_lock_spin(&sio_lock);
2438 return (ENOMEM);
2439 }
2440
2441 /* Initialize non-critical variables. */
2442 com->ibufold = com->ibuf;
2443 com->ibufsize = ibufsize;
2444 tp = com->tp;
2445 if (tp != NULL) {
2446 tp->t_ififosize = 2 * ibufsize;
2447 tp->t_ispeedwat = (speed_t)-1;
2448 tp->t_ospeedwat = (speed_t)-1;
2449 }
2450
2451 /*
2452 * Read current input buffer, if any. Continue with interrupts
2453 * disabled.
2454 */
2455 mtx_lock_spin(&sio_lock);
2456 if (com->iptr != com->ibuf)
2457 sioinput(com);
2458
2459 /*-
2460 * Initialize critical variables, including input buffer watermarks.
2461 * The external device is asked to stop sending when the buffer
2462 * exactly reaches high water, or when the high level requests it.
2463 * The high level is notified immediately (rather than at a later
2464 * clock tick) when this watermark is reached.
2465 * The buffer size is chosen so the watermark should almost never
2466 * be reached.
2467 * The low watermark is invisibly 0 since the buffer is always
2468 * emptied all at once.
2469 */
2470 com->iptr = com->ibuf = ibuf;
2471 com->ibufend = ibuf + ibufsize;
2472 com->ierroff = ibufsize;
2473 com->ihighwater = ibuf + 3 * ibufsize / 4;
2474 return (0);
2475}
2476
2477static void
2478comstart(tp)
2479 struct tty *tp;
2480{
2481 struct com_s *com;
2482 int s;
2483 int unit;
2484
2485 unit = DEV_TO_UNIT(tp->t_dev);
2486 com = com_addr(unit);
2487 if (com == NULL)
2488 return;
2489 s = spltty();
2490 mtx_lock_spin(&sio_lock);
2491 if (tp->t_state & TS_TTSTOP)
2492 com->state &= ~CS_TTGO;
2493 else
2494 com->state |= CS_TTGO;
2495 if (tp->t_state & TS_TBLOCK) {
2496 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2497 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2498 } else {
2499 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2500 && com->state & CS_RTS_IFLOW)
2501 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2502 }
2503 mtx_unlock_spin(&sio_lock);
2504 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2505 ttwwakeup(tp);
2506 splx(s);
2507 return;
2508 }
2509 if (tp->t_outq.c_cc != 0) {
2510 struct lbq *qp;
2511 struct lbq *next;
2512
2513 if (!com->obufs[0].l_queued) {
2514 com->obufs[0].l_tail
2515 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2516 sizeof com->obuf1);
2517 com->obufs[0].l_next = NULL;
2518 com->obufs[0].l_queued = TRUE;
2519 mtx_lock_spin(&sio_lock);
2520 if (com->state & CS_BUSY) {
2521 qp = com->obufq.l_next;
2522 while ((next = qp->l_next) != NULL)
2523 qp = next;
2524 qp->l_next = &com->obufs[0];
2525 } else {
2526 com->obufq.l_head = com->obufs[0].l_head;
2527 com->obufq.l_tail = com->obufs[0].l_tail;
2528 com->obufq.l_next = &com->obufs[0];
2529 com->state |= CS_BUSY;
2530 }
2531 mtx_unlock_spin(&sio_lock);
2532 }
2533 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2534 com->obufs[1].l_tail
2535 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2536 sizeof com->obuf2);
2537 com->obufs[1].l_next = NULL;
2538 com->obufs[1].l_queued = TRUE;
2539 mtx_lock_spin(&sio_lock);
2540 if (com->state & CS_BUSY) {
2541 qp = com->obufq.l_next;
2542 while ((next = qp->l_next) != NULL)
2543 qp = next;
2544 qp->l_next = &com->obufs[1];
2545 } else {
2546 com->obufq.l_head = com->obufs[1].l_head;
2547 com->obufq.l_tail = com->obufs[1].l_tail;
2548 com->obufq.l_next = &com->obufs[1];
2549 com->state |= CS_BUSY;
2550 }
2551 mtx_unlock_spin(&sio_lock);
2552 }
2553 tp->t_state |= TS_BUSY;
2554 }
2555 mtx_lock_spin(&sio_lock);
2556 if (com->state >= (CS_BUSY | CS_TTGO))
2557 siointr1(com); /* fake interrupt to start output */
2558 mtx_unlock_spin(&sio_lock);
2559 ttwwakeup(tp);
2560 splx(s);
2561}
2562
2563static void
2564comstop(tp, rw)
2565 struct tty *tp;
2566 int rw;
2567{
2568 struct com_s *com;
2569
2570 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2571 if (com == NULL || com->gone)
2572 return;
2573 mtx_lock_spin(&sio_lock);
2574 if (rw & FWRITE) {
2575 if (com->hasfifo)
2576#ifdef COM_ESP
2577 /* XXX avoid h/w bug. */
2578 if (!com->esp)
2579#endif
2580 sio_setreg(com, com_fifo,
2581 FIFO_XMT_RST | com->fifo_image);
2582 com->obufs[0].l_queued = FALSE;
2583 com->obufs[1].l_queued = FALSE;
2584 if (com->state & CS_ODONE)
2585 com_events -= LOTS_OF_EVENTS;
2586 com->state &= ~(CS_ODONE | CS_BUSY);
2587 com->tp->t_state &= ~TS_BUSY;
2588 }
2589 if (rw & FREAD) {
2590 if (com->hasfifo)
2591#ifdef COM_ESP
2592 /* XXX avoid h/w bug. */
2593 if (!com->esp)
2594#endif
2595 sio_setreg(com, com_fifo,
2596 FIFO_RCV_RST | com->fifo_image);
2597 com_events -= (com->iptr - com->ibuf);
2598 com->iptr = com->ibuf;
2599 }
2600 mtx_unlock_spin(&sio_lock);
2601 comstart(tp);
2602}
2603
2604static int
2605commctl(com, bits, how)
2606 struct com_s *com;
2607 int bits;
2608 int how;
2609{
2610 int mcr;
2611 int msr;
2612
2613 if (how == DMGET) {
2614 bits = TIOCM_LE; /* XXX - always enabled while open */
2615 mcr = com->mcr_image;
2616 if (mcr & MCR_DTR)
2617 bits |= TIOCM_DTR;
2618 if (mcr & MCR_RTS)
2619 bits |= TIOCM_RTS;
2620 msr = com->prev_modem_status;
2621 if (msr & MSR_CTS)
2622 bits |= TIOCM_CTS;
2623 if (msr & MSR_DCD)
2624 bits |= TIOCM_CD;
2625 if (msr & MSR_DSR)
2626 bits |= TIOCM_DSR;
2627 /*
2628 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
2629 * more volatile by reading the modem status a lot. Perhaps
2630 * we should latch both bits until the status is read here.
2631 */
2632 if (msr & (MSR_RI | MSR_TERI))
2633 bits |= TIOCM_RI;
2634 return (bits);
2635 }
2636 mcr = 0;
2637 if (bits & TIOCM_DTR)
2638 mcr |= MCR_DTR;
2639 if (bits & TIOCM_RTS)
2640 mcr |= MCR_RTS;
2641 if (com->gone)
2642 return(0);
2643 mtx_lock_spin(&sio_lock);
2644 switch (how) {
2645 case DMSET:
2646 outb(com->modem_ctl_port,
2647 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2648 break;
2649 case DMBIS:
2650 outb(com->modem_ctl_port, com->mcr_image |= mcr);
2651 break;
2652 case DMBIC:
2653 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2654 break;
2655 }
2656 mtx_unlock_spin(&sio_lock);
2657 return (0);
2658}
2659
2660static void
2661siosettimeout()
2662{
2663 struct com_s *com;
2664 bool_t someopen;
2665 int unit;
2666
2667 /*
2668 * Set our timeout period to 1 second if no polled devices are open.
2669 * Otherwise set it to max(1/200, 1/hz).
2670 * Enable timeouts iff some device is open.
2671 */
2672 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2673 sio_timeout = hz;
2674 someopen = FALSE;
2675 for (unit = 0; unit < sio_numunits; ++unit) {
2676 com = com_addr(unit);
2677 if (com != NULL && com->tp != NULL
2678 && com->tp->t_state & TS_ISOPEN && !com->gone) {
2679 someopen = TRUE;
2680 if (com->poll || com->poll_output) {
2681 sio_timeout = hz > 200 ? hz / 200 : 1;
2682 break;
2683 }
2684 }
2685 }
2686 if (someopen) {
2687 sio_timeouts_until_log = hz / sio_timeout;
2688 sio_timeout_handle = timeout(comwakeup, (void *)NULL,
2689 sio_timeout);
2690 } else {
2691 /* Flush error messages, if any. */
2692 sio_timeouts_until_log = 1;
2693 comwakeup((void *)NULL);
2694 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2695 }
2696}
2697
2698static void
2699comwakeup(chan)
2700 void *chan;
2701{
2702 struct com_s *com;
2703 int unit;
2704
2705 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2706
2707 /*
2708 * Recover from lost output interrupts.
2709 * Poll any lines that don't use interrupts.
2710 */
2711 for (unit = 0; unit < sio_numunits; ++unit) {
2712 com = com_addr(unit);
2713 if (com != NULL && !com->gone
2714 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2715 mtx_lock_spin(&sio_lock);
2716 siointr1(com);
2717 mtx_unlock_spin(&sio_lock);
2718 }
2719 }
2720
2721 /*
2722 * Check for and log errors, but not too often.
2723 */
2724 if (--sio_timeouts_until_log > 0)
2725 return;
2726 sio_timeouts_until_log = hz / sio_timeout;
2727 for (unit = 0; unit < sio_numunits; ++unit) {
2728 int errnum;
2729
2730 com = com_addr(unit);
2731 if (com == NULL)
2732 continue;
2733 if (com->gone)
2734 continue;
2735 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2736 u_int delta;
2737 u_long total;
2738
2739 mtx_lock_spin(&sio_lock);
2740 delta = com->delta_error_counts[errnum];
2741 com->delta_error_counts[errnum] = 0;
2742 mtx_unlock_spin(&sio_lock);
2743 if (delta == 0)
2744 continue;
2745 total = com->error_counts[errnum] += delta;
2746 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2747 unit, delta, error_desc[errnum],
2748 delta == 1 ? "" : "s", total);
2749 }
2750 }
2751}
2752
2753static void
2754disc_optim(tp, t, com)
2755 struct tty *tp;
2756 struct termios *t;
2757 struct com_s *com;
2758{
2759 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2760 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2761 && (!(t->c_iflag & PARMRK)
2762 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2763 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2764 && linesw[tp->t_line].l_rint == ttyinput)
2765 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2766 else
2767 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2768 com->hotchar = linesw[tp->t_line].l_hotchar;
2769}
2770
2771/*
2772 * Following are all routines needed for SIO to act as console
2773 */
2774#include <sys/cons.h>
2775
2776struct siocnstate {
2777 u_char dlbl;
2778 u_char dlbh;
2779 u_char ier;
2780 u_char cfcr;
2781 u_char mcr;
2782};
2783
2784#ifndef __alpha__
2785static speed_t siocngetspeed(Port_t, u_long rclk);
2786#endif
2787static void siocnclose(struct siocnstate *sp, Port_t iobase);
2788static void siocnopen(struct siocnstate *sp, Port_t iobase, int speed);
2789static void siocntxwait(Port_t iobase);
2790
2791#ifdef __alpha__
2792int siocnattach(int port, int speed);
2793int siogdbattach(int port, int speed);
2794int siogdbgetc(void);
2795void siogdbputc(int c);
2796#else
2797static cn_probe_t siocnprobe;
2798static cn_init_t siocninit;
2799static cn_term_t siocnterm;
2800#endif
2801static cn_checkc_t siocncheckc;
2802static cn_getc_t siocngetc;
2803static cn_putc_t siocnputc;
2804
2805#ifndef __alpha__
2806CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc,
2807 siocnputc, NULL);
2808#endif
2809
2810/* To get the GDB related variables */
2811#if DDB > 0
2812#include <ddb/ddb.h>
2813static struct consdev gdbconsdev;
2814
2815#endif
2816
2817static void
2818siocntxwait(iobase)
2819 Port_t iobase;
2820{
2821 int timo;
2822
2823 /*
2824 * Wait for any pending transmission to finish. Required to avoid
2825 * the UART lockup bug when the speed is changed, and for normal
2826 * transmits.
2827 */
2828 timo = 100000;
2829 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
2830 != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
2831 ;
2832}
2833
2834#ifndef __alpha__
2835
2836/*
2837 * Read the serial port specified and try to figure out what speed
2838 * it's currently running at. We're assuming the serial port has
2839 * been initialized and is basicly idle. This routine is only intended
2840 * to be run at system startup.
2841 *
2842 * If the value read from the serial port doesn't make sense, return 0.
2843 */
2844
2845static speed_t
2846siocngetspeed(iobase, rclk)
2847 Port_t iobase;
2848 u_long rclk;
2849{
2850 u_int divisor;
2851 u_char dlbh;
2852 u_char dlbl;
2853 u_char cfcr;
2854
2855 cfcr = inb(iobase + com_cfcr);
2856 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
2857
2858 dlbl = inb(iobase + com_dlbl);
2859 dlbh = inb(iobase + com_dlbh);
2860
2861 outb(iobase + com_cfcr, cfcr);
2862
2863 divisor = dlbh << 8 | dlbl;
2864
2865 /* XXX there should be more sanity checking. */
2866 if (divisor == 0)
2867 return (CONSPEED);
2868 return (rclk / (16UL * divisor));
2869}
2870
2871#endif
2872
2873static void
2874siocnopen(sp, iobase, speed)
2875 struct siocnstate *sp;
2876 Port_t iobase;
2877 int speed;
2878{
2879 u_int divisor;
2880 u_char dlbh;
2881 u_char dlbl;
2882
2883 /*
2884 * Save all the device control registers except the fifo register
2885 * and set our default ones (cs8 -parenb speed=comdefaultrate).
2886 * We can't save the fifo register since it is read-only.
2887 */
2888 sp->ier = inb(iobase + com_ier);
2889 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */
2890 siocntxwait(iobase);
2891 sp->cfcr = inb(iobase + com_cfcr);
2892 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2893 sp->dlbl = inb(iobase + com_dlbl);
2894 sp->dlbh = inb(iobase + com_dlbh);
2895 /*
2896 * Only set the divisor registers if they would change, since on
2897 * some 16550 incompatibles (Startech), setting them clears the
2898 * data input register. This also reduces the effects of the
2899 * UMC8669F bug.
2900 */
2901 divisor = siodivisor(comdefaultrclk, speed);
2902 dlbl = divisor & 0xFF;
2903 if (sp->dlbl != dlbl)
2904 outb(iobase + com_dlbl, dlbl);
2905 dlbh = divisor >> 8;
2906 if (sp->dlbh != dlbh)
2907 outb(iobase + com_dlbh, dlbh);
2908 outb(iobase + com_cfcr, CFCR_8BITS);
2909 sp->mcr = inb(iobase + com_mcr);
2910 /*
2911 * We don't want interrupts, but must be careful not to "disable"
2912 * them by clearing the MCR_IENABLE bit, since that might cause
2913 * an interrupt by floating the IRQ line.
2914 */
2915 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
2916}
2917
2918static void
2919siocnclose(sp, iobase)
2920 struct siocnstate *sp;
2921 Port_t iobase;
2922{
2923 /*
2924 * Restore the device control registers.
2925 */
2926 siocntxwait(iobase);
2927 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2928 if (sp->dlbl != inb(iobase + com_dlbl))
2929 outb(iobase + com_dlbl, sp->dlbl);
2930 if (sp->dlbh != inb(iobase + com_dlbh))
2931 outb(iobase + com_dlbh, sp->dlbh);
2932 outb(iobase + com_cfcr, sp->cfcr);
2933 /*
2934 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
2935 */
2936 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
2937 outb(iobase + com_ier, sp->ier);
2938}
2939
2940#ifndef __alpha__
2941
2942static void
2943siocnprobe(cp)
2944 struct consdev *cp;
2945{
2946 speed_t boot_speed;
2947 u_char cfcr;
2948 u_int divisor;
2949 int s, unit;
2950 struct siocnstate sp;
2951
2952 /*
2953 * Find our first enabled console, if any. If it is a high-level
2954 * console device, then initialize it and return successfully.
2955 * If it is a low-level console device, then initialize it and
2956 * return unsuccessfully. It must be initialized in both cases
2957 * for early use by console drivers and debuggers. Initializing
2958 * the hardware is not necessary in all cases, since the i/o
2959 * routines initialize it on the fly, but it is necessary if
2960 * input might arrive while the hardware is switched back to an
2961 * uninitialized state. We can't handle multiple console devices
2962 * yet because our low-level routines don't take a device arg.
2963 * We trust the user to set the console flags properly so that we
2964 * don't need to probe.
2965 */
2966 cp->cn_pri = CN_DEAD;
2967
2968 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
2969 int flags;
2970
2971 if (resource_disabled("sio", unit))
2972 continue;
2973 if (resource_int_value("sio", unit, "flags", &flags))
2974 continue;
2975 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
2976 int port;
2977 Port_t iobase;
2978
2979 if (resource_int_value("sio", unit, "port", &port))
2980 continue;
2981 iobase = port;
2982 s = spltty();
2983 if (boothowto & RB_SERIAL) {
2984 boot_speed =
2985 siocngetspeed(iobase, comdefaultrclk);
2986 if (boot_speed)
2987 comdefaultrate = boot_speed;
2988 }
2989
2990 /*
2991 * Initialize the divisor latch. We can't rely on
2992 * siocnopen() to do this the first time, since it
2993 * avoids writing to the latch if the latch appears
2994 * to have the correct value. Also, if we didn't
2995 * just read the speed from the hardware, then we
2996 * need to set the speed in hardware so that
2997 * switching it later is null.
2998 */
2999 cfcr = inb(iobase + com_cfcr);
3000 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3001 divisor = siodivisor(comdefaultrclk, comdefaultrate);
3002 outb(iobase + com_dlbl, divisor & 0xff);
3003 outb(iobase + com_dlbh, divisor >> 8);
3004 outb(iobase + com_cfcr, cfcr);
3005
3006 siocnopen(&sp, iobase, comdefaultrate);
3007
3008 splx(s);
3009 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
3010 cp->cn_dev = makedev(CDEV_MAJOR, unit);
3011 cp->cn_pri = COM_FORCECONSOLE(flags)
3012 || boothowto & RB_SERIAL
3013 ? CN_REMOTE : CN_NORMAL;
3014 siocniobase = iobase;
3015 siocnunit = unit;
3016 }
3017 if (COM_DEBUGGER(flags)) {
3018 printf("sio%d: gdb debugging port\n", unit);
3019 siogdbiobase = iobase;
3020 siogdbunit = unit;
3021#if DDB > 0
3022 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, unit);
3023 gdb_arg = &gdbconsdev;
3024 gdb_getc = siocngetc;
3025 gdb_putc = siocnputc;
3026#endif
3027 }
3028 }
3029 }
3030#ifdef __i386__
3031#if DDB > 0
3032 /*
3033 * XXX Ugly Compatability.
3034 * If no gdb port has been specified, set it to be the console
3035 * as some configuration files don't specify the gdb port.
3036 */
3037 if (gdb_arg == NULL && (boothowto & RB_GDB)) {
3038 printf("Warning: no GDB port specified. Defaulting to sio%d.\n",
3039 siocnunit);
3040 printf("Set flag 0x80 on desired GDB port in your\n");
3041 printf("configuration file (currently sio only).\n");
3042 siogdbiobase = siocniobase;
3043 siogdbunit = siocnunit;
3044 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, siocnunit);
3045 gdb_arg = &gdbconsdev;
3046 gdb_getc = siocngetc;
3047 gdb_putc = siocnputc;
3048 }
3049#endif
3050#endif
3051}
3052
3053static void
3054siocninit(cp)
3055 struct consdev *cp;
3056{
3057 comconsole = DEV_TO_UNIT(cp->cn_dev);
3058}
3059
3060static void
3061siocnterm(cp)
3062 struct consdev *cp;
3063{
3064 comconsole = -1;
3065}
3066
3067#endif
3068
3069#ifdef __alpha__
3070
3071CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL);
3072
3073int
3074siocnattach(port, speed)
3075 int port;
3076 int speed;
3077{
3078 int s;
3079 u_char cfcr;
3080 u_int divisor;
3081 struct siocnstate sp;
3082 int unit = 0; /* XXX random value! */
3083
3084 siocniobase = port;
3085 siocnunit = unit;
3086 comdefaultrate = speed;
3087 sio_consdev.cn_pri = CN_NORMAL;
3088 sio_consdev.cn_dev = makedev(CDEV_MAJOR, unit);
3089
3090 s = spltty();
3091
3092 /*
3093 * Initialize the divisor latch. We can't rely on
3094 * siocnopen() to do this the first time, since it
3095 * avoids writing to the latch if the latch appears
3096 * to have the correct value. Also, if we didn't
3097 * just read the speed from the hardware, then we
3098 * need to set the speed in hardware so that
3099 * switching it later is null.
3100 */
3101 cfcr = inb(siocniobase + com_cfcr);
3102 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
3103 divisor = siodivisor(comdefaultrclk, comdefaultrate);
3104 outb(siocniobase + com_dlbl, divisor & 0xff);
3105 outb(siocniobase + com_dlbh, divisor >> 8);
3106 outb(siocniobase + com_cfcr, cfcr);
3107
3108 siocnopen(&sp, siocniobase, comdefaultrate);
3109 splx(s);
3110
3111 cnadd(&sio_consdev);
3112 return (0);
3113}
3114
3115int
3116siogdbattach(port, speed)
3117 int port;
3118 int speed;
3119{
3120 int s;
3121 u_char cfcr;
3122 u_int divisor;
3123 struct siocnstate sp;
3124 int unit = 1; /* XXX random value! */
3125
3126 siogdbiobase = port;
3127 gdbdefaultrate = speed;
3128
3129 printf("sio%d: gdb debugging port\n", unit);
3130 siogdbunit = unit;
3131#if DDB > 0
3132 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, unit);
3133 gdb_arg = &gdbconsdev;
3134 gdb_getc = siocngetc;
3135 gdb_putc = siocnputc;
3136#endif
3137
3138 s = spltty();
3139
3140 /*
3141 * Initialize the divisor latch. We can't rely on
3142 * siocnopen() to do this the first time, since it
3143 * avoids writing to the latch if the latch appears
3144 * to have the correct value. Also, if we didn't
3145 * just read the speed from the hardware, then we
3146 * need to set the speed in hardware so that
3147 * switching it later is null.
3148 */
3149 cfcr = inb(siogdbiobase + com_cfcr);
3150 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr);
3151 divisor = siodivisor(comdefaultrclk, gdbdefaultrate);
3152 outb(siogdbiobase + com_dlbl, divisor & 0xff);
3153 outb(siogdbiobase + com_dlbh, divisor >> 8);
3154 outb(siogdbiobase + com_cfcr, cfcr);
3155
3156 siocnopen(&sp, siogdbiobase, gdbdefaultrate);
3157 splx(s);
3158
3159 return (0);
3160}
3161
3162#endif
3163
3164static int
3165siocncheckc(struct consdev *cd)
3166{
3167 int c;
3168 dev_t dev;
3169 Port_t iobase;
3170 int s;
3171 struct siocnstate sp;
3172 speed_t speed;
3173
3174 dev = cd->cn_dev;
3175 if (minor(dev) == siocnunit) {
3176 iobase = siocniobase;
3177 speed = comdefaultrate;
3178 } else {
3179 iobase = siogdbiobase;
3180 speed = gdbdefaultrate;
3181 }
3182 s = spltty();
3183 siocnopen(&sp, iobase, speed);
3184 if (inb(iobase + com_lsr) & LSR_RXRDY)
3185 c = inb(iobase + com_data);
3186 else
3187 c = -1;
3188 siocnclose(&sp, iobase);
3189 splx(s);
3190 return (c);
3191}
3192
3193
3194static int
3195siocngetc(struct consdev *cd)
3196{
3197 int c;
3198 dev_t dev;
3199 Port_t iobase;
3200 int s;
3201 struct siocnstate sp;
3202 speed_t speed;
3203
3204 dev = cd->cn_dev;
3205 if (minor(dev) == siocnunit) {
3206 iobase = siocniobase;
3207 speed = comdefaultrate;
3208 } else {
3209 iobase = siogdbiobase;
3210 speed = gdbdefaultrate;
3211 }
3212 s = spltty();
3213 siocnopen(&sp, iobase, speed);
3214 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3215 ;
3216 c = inb(iobase + com_data);
3217 siocnclose(&sp, iobase);
3218 splx(s);
3219 return (c);
3220}
3221
3222static void
3223siocnputc(struct consdev *cd, int c)
3224{
3225 int need_unlock;
3226 int s;
3227 dev_t dev;
3228 struct siocnstate sp;
3229 Port_t iobase;
3230 speed_t speed;
3231
3232 dev = cd->cn_dev;
3233 if (minor(dev) == siocnunit) {
3234 iobase = siocniobase;
3235 speed = comdefaultrate;
3236 } else {
3237 iobase = siogdbiobase;
3238 speed = gdbdefaultrate;
3239 }
3240 s = spltty();
3241 need_unlock = 0;
3242 if (sio_inited == 2 && !mtx_owned(&sio_lock)) {
3243 mtx_lock_spin(&sio_lock);
3244 need_unlock = 1;
3245 }
3246 siocnopen(&sp, iobase, speed);
3247 siocntxwait(iobase);
3248 outb(iobase + com_data, c);
3249 siocnclose(&sp, iobase);
3250 if (need_unlock)
3251 mtx_unlock_spin(&sio_lock);
3252 splx(s);
3253}
3254
3255#ifdef __alpha__
3256int
3257siogdbgetc()
3258{
3259 int c;
3260 Port_t iobase;
3261 speed_t speed;
3262 int s;
3263 struct siocnstate sp;
3264
3265 if (siogdbunit == siocnunit) {
3266 iobase = siocniobase;
3267 speed = comdefaultrate;
3268 } else {
3269 iobase = siogdbiobase;
3270 speed = gdbdefaultrate;
3271 }
3272
3273 s = spltty();
3274 siocnopen(&sp, iobase, speed);
3275 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3276 ;
3277 c = inb(iobase + com_data);
3278 siocnclose(&sp, iobase);
3279 splx(s);
3280 return (c);
3281}
3282
3283void
3284siogdbputc(c)
3285 int c;
3286{
3287 Port_t iobase;
3288 speed_t speed;
3289 int s;
3290 struct siocnstate sp;
3291
3292 if (siogdbunit == siocnunit) {
3293 iobase = siocniobase;
3294 speed = comdefaultrate;
3295 } else {
3296 iobase = siogdbiobase;
3297 speed = gdbdefaultrate;
3298 }
3299
3300 s = spltty();
3301 siocnopen(&sp, iobase, speed);
3302 siocntxwait(siogdbiobase);
3303 outb(siogdbiobase + com_data, c);
3304 siocnclose(&sp, siogdbiobase);
3305 splx(s);
3306}
3307#endif
40#include "opt_comconsole.h"
41#include "opt_compat.h"
42#include "opt_ddb.h"
43#include "opt_sio.h"
44
45/*
46 * Serial driver, based on 386BSD-0.1 com driver.
47 * Mostly rewritten to use pseudo-DMA.
48 * Works for National Semiconductor NS8250-NS16550AF UARTs.
49 * COM driver, based on HP dca driver.
50 *
51 * Changes for PC-Card integration:
52 * - Added PC-Card driver table and handlers
53 */
54#include <sys/param.h>
55#include <sys/systm.h>
56#include <sys/bus.h>
57#include <sys/conf.h>
58#include <sys/fcntl.h>
59#include <sys/interrupt.h>
60#include <sys/kernel.h>
61#include <sys/limits.h>
62#include <sys/lock.h>
63#include <sys/malloc.h>
64#include <sys/module.h>
65#include <sys/mutex.h>
66#include <sys/proc.h>
67#include <sys/reboot.h>
68#include <sys/sysctl.h>
69#include <sys/syslog.h>
70#include <sys/tty.h>
71#include <machine/bus_pio.h>
72#include <machine/bus.h>
73#include <sys/rman.h>
74#include <sys/timepps.h>
75#include <sys/uio.h>
76
77#include <isa/isavar.h>
78
79#include <machine/resource.h>
80
81#include <dev/sio/sioreg.h>
82#include <dev/sio/siovar.h>
83
84#ifdef COM_ESP
85#include <dev/ic/esp.h>
86#endif
87#include <dev/ic/ns16550.h>
88
89#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
90
91#define CALLOUT_MASK 0x80
92#define CONTROL_MASK 0x60
93#define CONTROL_INIT_STATE 0x20
94#define CONTROL_LOCK_STATE 0x40
95#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
96#define MINOR_TO_UNIT(mynor) ((((mynor) & ~0xffffU) >> (8 + 3)) \
97 | ((mynor) & 0x1f))
98#define UNIT_TO_MINOR(unit) ((((unit) & ~0x1fU) << (8 + 3)) \
99 | ((unit) & 0x1f))
100
101#ifdef COM_MULTIPORT
102/* checks in flags for multiport and which is multiport "master chip"
103 * for a given card
104 */
105#define COM_ISMULTIPORT(flags) ((flags) & 0x01)
106#define COM_MPMASTER(flags) (((flags) >> 8) & 0x0ff)
107#define COM_NOTAST4(flags) ((flags) & 0x04)
108#else
109#define COM_ISMULTIPORT(flags) (0)
110#endif /* COM_MULTIPORT */
111
112#define COM_CONSOLE(flags) ((flags) & 0x10)
113#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
114#define COM_LLCONSOLE(flags) ((flags) & 0x40)
115#define COM_DEBUGGER(flags) ((flags) & 0x80)
116#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
117#define COM_NOFIFO(flags) ((flags) & 0x02)
118#define COM_PPSCTS(flags) ((flags) & 0x10000)
119#define COM_ST16650A(flags) ((flags) & 0x20000)
120#define COM_C_NOPROBE (0x40000)
121#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE)
122#define COM_C_IIR_TXRDYBUG (0x80000)
123#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
124#define COM_NOSCR(flags) ((flags) & 0x100000)
125#define COM_TI16754(flags) ((flags) & 0x200000)
126#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
127
128#define sio_getreg(com, off) \
129 (bus_space_read_1((com)->bst, (com)->bsh, (off)))
130#define sio_setreg(com, off, value) \
131 (bus_space_write_1((com)->bst, (com)->bsh, (off), (value)))
132
133/*
134 * com state bits.
135 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
136 * than the other bits so that they can be tested as a group without masking
137 * off the low bits.
138 *
139 * The following com and tty flags correspond closely:
140 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
141 * comstop())
142 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart())
143 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam())
144 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam())
145 * TS_FLUSH is not used.
146 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
147 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
148 */
149#define CS_BUSY 0x80 /* output in progress */
150#define CS_TTGO 0x40 /* output not stopped by XOFF */
151#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */
152#define CS_CHECKMSR 1 /* check of MSR scheduled */
153#define CS_CTS_OFLOW 2 /* use CTS output flow control */
154#define CS_DTR_OFF 0x10 /* DTR held off */
155#define CS_ODONE 4 /* output completed */
156#define CS_RTS_IFLOW 8 /* use RTS input flow control */
157#define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */
158
159static char const * const error_desc[] = {
160#define CE_OVERRUN 0
161 "silo overflow",
162#define CE_INTERRUPT_BUF_OVERFLOW 1
163 "interrupt-level buffer overflow",
164#define CE_TTY_BUF_OVERFLOW 2
165 "tty-level buffer overflow",
166};
167
168#define CE_NTYPES 3
169#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
170
171/* types. XXX - should be elsewhere */
172typedef u_int Port_t; /* hardware port */
173typedef u_char bool_t; /* boolean */
174
175/* queue of linear buffers */
176struct lbq {
177 u_char *l_head; /* next char to process */
178 u_char *l_tail; /* one past the last char to process */
179 struct lbq *l_next; /* next in queue */
180 bool_t l_queued; /* nonzero if queued */
181};
182
183/* com device structure */
184struct com_s {
185 u_int flags; /* Copy isa device flags */
186 u_char state; /* miscellaneous flag bits */
187 bool_t active_out; /* nonzero if the callout device is open */
188 u_char cfcr_image; /* copy of value written to CFCR */
189#ifdef COM_ESP
190 bool_t esp; /* is this unit a hayes esp board? */
191#endif
192 u_char extra_state; /* more flag bits, separate for order trick */
193 u_char fifo_image; /* copy of value written to FIFO */
194 bool_t hasfifo; /* nonzero for 16550 UARTs */
195 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */
196 bool_t loses_outints; /* nonzero if device loses output interrupts */
197 u_char mcr_image; /* copy of value written to MCR */
198#ifdef COM_MULTIPORT
199 bool_t multiport; /* is this unit part of a multiport device? */
200#endif /* COM_MULTIPORT */
201 bool_t no_irq; /* nonzero if irq is not attached */
202 bool_t gone; /* hardware disappeared */
203 bool_t poll; /* nonzero if polling is required */
204 bool_t poll_output; /* nonzero if polling for output is required */
205 int unit; /* unit number */
206 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */
207 u_int tx_fifo_size;
208 u_int wopeners; /* # processes waiting for DCD in open() */
209
210 /*
211 * The high level of the driver never reads status registers directly
212 * because there would be too many side effects to handle conveniently.
213 * Instead, it reads copies of the registers stored here by the
214 * interrupt handler.
215 */
216 u_char last_modem_status; /* last MSR read by intr handler */
217 u_char prev_modem_status; /* last MSR handled by high level */
218
219 u_char hotchar; /* ldisc-specific char to be handled ASAP */
220 u_char *ibuf; /* start of input buffer */
221 u_char *ibufend; /* end of input buffer */
222 u_char *ibufold; /* old input buffer, to be freed */
223 u_char *ihighwater; /* threshold in input buffer */
224 u_char *iptr; /* next free spot in input buffer */
225 int ibufsize; /* size of ibuf (not include error bytes) */
226 int ierroff; /* offset of error bytes in ibuf */
227
228 struct lbq obufq; /* head of queue of output buffers */
229 struct lbq obufs[2]; /* output buffers */
230
231 bus_space_tag_t bst;
232 bus_space_handle_t bsh;
233
234 Port_t data_port; /* i/o ports */
235#ifdef COM_ESP
236 Port_t esp_port;
237#endif
238 Port_t int_id_port;
239 Port_t modem_ctl_port;
240 Port_t line_status_port;
241 Port_t modem_status_port;
242 Port_t intr_ctl_port; /* Ports of IIR register */
243
244 struct tty *tp; /* cross reference */
245
246 /* Initial state. */
247 struct termios it_in; /* should be in struct tty */
248 struct termios it_out;
249
250 /* Lock state. */
251 struct termios lt_in; /* should be in struct tty */
252 struct termios lt_out;
253
254 bool_t do_timestamp;
255 bool_t do_dcd_timestamp;
256 struct timeval timestamp;
257 struct timeval dcd_timestamp;
258 struct pps_state pps;
259 int pps_bit;
260
261 u_long bytes_in; /* statistics */
262 u_long bytes_out;
263 u_int delta_error_counts[CE_NTYPES];
264 u_long error_counts[CE_NTYPES];
265
266 u_long rclk;
267
268 struct resource *irqres;
269 struct resource *ioportres;
270 int ioportrid;
271 void *cookie;
272 dev_t devs[6];
273
274 /*
275 * Data area for output buffers. Someday we should build the output
276 * buffer queue without copying data.
277 */
278 u_char obuf1[256];
279 u_char obuf2[256];
280};
281
282#ifdef COM_ESP
283static int espattach(struct com_s *com, Port_t esp_port);
284#endif
285
286static timeout_t siobusycheck;
287static u_int siodivisor(u_long rclk, speed_t speed);
288static timeout_t siodtrwakeup;
289static void comhardclose(struct com_s *com);
290static void sioinput(struct com_s *com);
291static void siointr1(struct com_s *com);
292static void siointr(void *arg);
293static int commctl(struct com_s *com, int bits, int how);
294static int comparam(struct tty *tp, struct termios *t);
295static void siopoll(void *);
296static void siosettimeout(void);
297static int siosetwater(struct com_s *com, speed_t speed);
298static void comstart(struct tty *tp);
299static void comstop(struct tty *tp, int rw);
300static timeout_t comwakeup;
301static void disc_optim(struct tty *tp, struct termios *t,
302 struct com_s *com);
303
304char sio_driver_name[] = "sio";
305static struct mtx sio_lock;
306static int sio_inited;
307
308/* table and macro for fast conversion from a unit number to its com struct */
309devclass_t sio_devclass;
310#define com_addr(unit) ((struct com_s *) \
311 devclass_get_softc(sio_devclass, unit)) /* XXX */
312
313static d_open_t sioopen;
314static d_close_t sioclose;
315static d_read_t sioread;
316static d_write_t siowrite;
317static d_ioctl_t sioioctl;
318
319#define CDEV_MAJOR 28
320static struct cdevsw sio_cdevsw = {
321 .d_open = sioopen,
322 .d_close = sioclose,
323 .d_read = sioread,
324 .d_write = siowrite,
325 .d_ioctl = sioioctl,
326 .d_poll = ttypoll,
327 .d_name = sio_driver_name,
328 .d_maj = CDEV_MAJOR,
329 .d_flags = D_TTY,
330 .d_kqfilter = ttykqfilter,
331};
332
333int comconsole = -1;
334static volatile speed_t comdefaultrate = CONSPEED;
335static u_long comdefaultrclk = DEFAULT_RCLK;
336SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, "");
337static speed_t gdbdefaultrate = GDBSPEED;
338SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW,
339 &gdbdefaultrate, GDBSPEED, "");
340static u_int com_events; /* input chars + weighted output completions */
341static Port_t siocniobase;
342static int siocnunit = -1;
343static Port_t siogdbiobase;
344static int siogdbunit = -1;
345static void *sio_slow_ih;
346static void *sio_fast_ih;
347static int sio_timeout;
348static int sio_timeouts_until_log;
349static struct callout_handle sio_timeout_handle
350 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
351static int sio_numunits;
352
353#ifdef COM_ESP
354/* XXX configure this properly. */
355/* XXX quite broken for new-bus. */
356static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
357static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
358#endif
359
360/*
361 * handle sysctl read/write requests for console speed
362 *
363 * In addition to setting comdefaultrate for I/O through /dev/console,
364 * also set the initial and lock values for the /dev/ttyXX device
365 * if there is one associated with the console. Finally, if the /dev/tty
366 * device has already been open, change the speed on the open running port
367 * itself.
368 */
369
370static int
371sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)
372{
373 int error, s;
374 speed_t newspeed;
375 struct com_s *com;
376 struct tty *tp;
377
378 newspeed = comdefaultrate;
379
380 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
381 if (error || !req->newptr)
382 return (error);
383
384 comdefaultrate = newspeed;
385
386 if (comconsole < 0) /* serial console not selected? */
387 return (0);
388
389 com = com_addr(comconsole);
390 if (com == NULL)
391 return (ENXIO);
392
393 /*
394 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
395 * (note, the lock rates really are boolean -- if non-zero, disallow
396 * speed changes)
397 */
398 com->it_in.c_ispeed = com->it_in.c_ospeed =
399 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
400 com->it_out.c_ispeed = com->it_out.c_ospeed =
401 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
402
403 /*
404 * if we're open, change the running rate too
405 */
406 tp = com->tp;
407 if (tp && (tp->t_state & TS_ISOPEN)) {
408 tp->t_termios.c_ispeed =
409 tp->t_termios.c_ospeed = comdefaultrate;
410 s = spltty();
411 error = comparam(tp, &tp->t_termios);
412 splx(s);
413 }
414 return error;
415}
416
417SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
418 0, 0, sysctl_machdep_comdefaultrate, "I", "");
419/* TUNABLE_INT("machdep.conspeed", &comdefaultrate); */
420
421#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
422#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
423
424/*
425 * Unload the driver and clear the table.
426 * XXX this is mostly wrong.
427 * XXX TODO:
428 * This is usually called when the card is ejected, but
429 * can be caused by a kldunload of a controller driver.
430 * The idea is to reset the driver's view of the device
431 * and ensure that any driver entry points such as
432 * read and write do not hang.
433 */
434int
435siodetach(dev)
436 device_t dev;
437{
438 struct com_s *com;
439 int i;
440
441 com = (struct com_s *) device_get_softc(dev);
442 if (com == NULL) {
443 device_printf(dev, "NULL com in siounload\n");
444 return (0);
445 }
446 com->gone = 1;
447 for (i = 0 ; i < 6; i++)
448 destroy_dev(com->devs[i]);
449 if (com->irqres) {
450 bus_teardown_intr(dev, com->irqres, com->cookie);
451 bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres);
452 }
453 if (com->ioportres)
454 bus_release_resource(dev, SYS_RES_IOPORT, com->ioportrid,
455 com->ioportres);
456 if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
457 device_printf(dev, "still open, forcing close\n");
458 (*linesw[com->tp->t_line].l_close)(com->tp, 0);
459 com->tp->t_gen++;
460 ttyclose(com->tp);
461 ttwakeup(com->tp);
462 ttwwakeup(com->tp);
463 } else {
464 if (com->ibuf != NULL)
465 free(com->ibuf, M_DEVBUF);
466 device_set_softc(dev, NULL);
467 free(com, M_DEVBUF);
468 }
469 return (0);
470}
471
472int
473sioprobe(dev, xrid, rclk, noprobe)
474 device_t dev;
475 int xrid;
476 u_long rclk;
477 int noprobe;
478{
479#if 0
480 static bool_t already_init;
481 device_t xdev;
482#endif
483 struct com_s *com;
484 u_int divisor;
485 bool_t failures[10];
486 int fn;
487 device_t idev;
488 Port_t iobase;
489 intrmask_t irqmap[4];
490 intrmask_t irqs;
491 u_char mcr_image;
492 int result;
493 u_long xirq;
494 u_int flags = device_get_flags(dev);
495 int rid;
496 struct resource *port;
497
498 rid = xrid;
499 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
500 0, ~0, IO_COMSIZE, RF_ACTIVE);
501 if (!port)
502 return (ENXIO);
503
504 com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
505 if (com == NULL)
506 return (ENOMEM);
507 device_set_softc(dev, com);
508 com->bst = rman_get_bustag(port);
509 com->bsh = rman_get_bushandle(port);
510 if (rclk == 0)
511 rclk = DEFAULT_RCLK;
512 com->rclk = rclk;
513
514 while (sio_inited != 2)
515 if (atomic_cmpset_int(&sio_inited, 0, 1)) {
516 mtx_init(&sio_lock, sio_driver_name, NULL,
517 (comconsole != -1) ?
518 MTX_SPIN | MTX_QUIET : MTX_SPIN);
519 atomic_store_rel_int(&sio_inited, 2);
520 }
521
522#if 0
523 /*
524 * XXX this is broken - when we are first called, there are no
525 * previously configured IO ports. We could hard code
526 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
527 * This code has been doing nothing since the conversion since
528 * "count" is zero the first time around.
529 */
530 if (!already_init) {
531 /*
532 * Turn off MCR_IENABLE for all likely serial ports. An unused
533 * port with its MCR_IENABLE gate open will inhibit interrupts
534 * from any used port that shares the interrupt vector.
535 * XXX the gate enable is elsewhere for some multiports.
536 */
537 device_t *devs;
538 int count, i, xioport;
539
540 devclass_get_devices(sio_devclass, &devs, &count);
541 for (i = 0; i < count; i++) {
542 xdev = devs[i];
543 if (device_is_enabled(xdev) &&
544 bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
545 NULL) == 0)
546 outb(xioport + com_mcr, 0);
547 }
548 free(devs, M_TEMP);
549 already_init = TRUE;
550 }
551#endif
552
553 if (COM_LLCONSOLE(flags)) {
554 printf("sio%d: reserved for low-level i/o\n",
555 device_get_unit(dev));
556 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
557 device_set_softc(dev, NULL);
558 free(com, M_DEVBUF);
559 return (ENXIO);
560 }
561
562 /*
563 * If the device is on a multiport card and has an AST/4
564 * compatible interrupt control register, initialize this
565 * register and prepare to leave MCR_IENABLE clear in the mcr.
566 * Otherwise, prepare to set MCR_IENABLE in the mcr.
567 * Point idev to the device struct giving the correct id_irq.
568 * This is the struct for the master device if there is one.
569 */
570 idev = dev;
571 mcr_image = MCR_IENABLE;
572#ifdef COM_MULTIPORT
573 if (COM_ISMULTIPORT(flags)) {
574 Port_t xiobase;
575 u_long io;
576
577 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
578 if (idev == NULL) {
579 printf("sio%d: master device %d not configured\n",
580 device_get_unit(dev), COM_MPMASTER(flags));
581 idev = dev;
582 }
583 if (!COM_NOTAST4(flags)) {
584 if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
585 NULL) == 0) {
586 xiobase = io;
587 if (bus_get_resource(idev, SYS_RES_IRQ, 0,
588 NULL, NULL) == 0)
589 outb(xiobase + com_scr, 0x80);
590 else
591 outb(xiobase + com_scr, 0);
592 }
593 mcr_image = 0;
594 }
595 }
596#endif /* COM_MULTIPORT */
597 if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
598 mcr_image = 0;
599
600 bzero(failures, sizeof failures);
601 iobase = rman_get_start(port);
602
603 /*
604 * We don't want to get actual interrupts, just masked ones.
605 * Interrupts from this line should already be masked in the ICU,
606 * but mask them in the processor as well in case there are some
607 * (misconfigured) shared interrupts.
608 */
609 mtx_lock_spin(&sio_lock);
610/* EXTRA DELAY? */
611
612 /*
613 * For the TI16754 chips, set prescaler to 1 (4 is often the
614 * default after-reset value) as otherwise it's impossible to
615 * get highest baudrates.
616 */
617 if (COM_TI16754(flags)) {
618 u_char cfcr, efr;
619
620 cfcr = sio_getreg(com, com_cfcr);
621 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
622 efr = sio_getreg(com, com_efr);
623 /* Unlock extended features to turn off prescaler. */
624 sio_setreg(com, com_efr, efr | EFR_EFE);
625 /* Disable EFR. */
626 sio_setreg(com, com_cfcr, (cfcr != CFCR_EFR_ENABLE) ? cfcr : 0);
627 /* Turn off prescaler. */
628 sio_setreg(com, com_mcr,
629 sio_getreg(com, com_mcr) & ~MCR_PRESCALE);
630 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
631 sio_setreg(com, com_efr, efr);
632 sio_setreg(com, com_cfcr, cfcr);
633 }
634
635 /*
636 * Initialize the speed and the word size and wait long enough to
637 * drain the maximum of 16 bytes of junk in device output queues.
638 * The speed is undefined after a master reset and must be set
639 * before relying on anything related to output. There may be
640 * junk after a (very fast) soft reboot and (apparently) after
641 * master reset.
642 * XXX what about the UART bug avoided by waiting in comparam()?
643 * We don't want to to wait long enough to drain at 2 bps.
644 */
645 if (iobase == siocniobase)
646 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
647 else {
648 sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
649 divisor = siodivisor(rclk, SIO_TEST_SPEED);
650 sio_setreg(com, com_dlbl, divisor & 0xff);
651 sio_setreg(com, com_dlbh, divisor >> 8);
652 sio_setreg(com, com_cfcr, CFCR_8BITS);
653 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
654 }
655
656 /*
657 * Enable the interrupt gate and disable device interupts. This
658 * should leave the device driving the interrupt line low and
659 * guarantee an edge trigger if an interrupt can be generated.
660 */
661/* EXTRA DELAY? */
662 sio_setreg(com, com_mcr, mcr_image);
663 sio_setreg(com, com_ier, 0);
664 DELAY(1000); /* XXX */
665 irqmap[0] = isa_irq_pending();
666
667 /*
668 * Attempt to set loopback mode so that we can send a null byte
669 * without annoying any external device.
670 */
671/* EXTRA DELAY? */
672 sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK);
673
674 /*
675 * Attempt to generate an output interrupt. On 8250's, setting
676 * IER_ETXRDY generates an interrupt independent of the current
677 * setting and independent of whether the THR is empty. On 16450's,
678 * setting IER_ETXRDY generates an interrupt independent of the
679 * current setting. On 16550A's, setting IER_ETXRDY only
680 * generates an interrupt when IER_ETXRDY is not already set.
681 */
682 sio_setreg(com, com_ier, IER_ETXRDY);
683
684 /*
685 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
686 * an interrupt. They'd better generate one for actually doing
687 * output. Loopback may be broken on the same incompatibles but
688 * it's unlikely to do more than allow the null byte out.
689 */
690 sio_setreg(com, com_data, 0);
691 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
692
693 /*
694 * Turn off loopback mode so that the interrupt gate works again
695 * (MCR_IENABLE was hidden). This should leave the device driving
696 * an interrupt line high. It doesn't matter if the interrupt
697 * line oscillates while we are not looking at it, since interrupts
698 * are disabled.
699 */
700/* EXTRA DELAY? */
701 sio_setreg(com, com_mcr, mcr_image);
702
703 /*
704 * It seems my Xircom CBEM56G Cardbus modem wants to be reset
705 * to 8 bits *again*, or else probe test 0 will fail.
706 * gwk@sgi.com, 4/19/2001
707 */
708 sio_setreg(com, com_cfcr, CFCR_8BITS);
709
710 /*
711 * Some pcmcia cards have the "TXRDY bug", so we check everyone
712 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
713 */
714 if (noprobe) {
715 /* Reading IIR register twice */
716 for (fn = 0; fn < 2; fn ++) {
717 DELAY(10000);
718 failures[6] = sio_getreg(com, com_iir);
719 }
720 /* Check IIR_TXRDY clear ? */
721 result = 0;
722 if (failures[6] & IIR_TXRDY) {
723 /* No, Double check with clearing IER */
724 sio_setreg(com, com_ier, 0);
725 if (sio_getreg(com, com_iir) & IIR_NOPEND) {
726 /* Ok. We discovered TXRDY bug! */
727 SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
728 } else {
729 /* Unknown, Just omit this chip.. XXX */
730 result = ENXIO;
731 sio_setreg(com, com_mcr, 0);
732 }
733 } else {
734 /* OK. this is well-known guys */
735 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
736 }
737 sio_setreg(com, com_ier, 0);
738 sio_setreg(com, com_cfcr, CFCR_8BITS);
739 mtx_unlock_spin(&sio_lock);
740 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
741 if (iobase == siocniobase)
742 result = 0;
743 if (result != 0) {
744 device_set_softc(dev, NULL);
745 free(com, M_DEVBUF);
746 }
747 return (result);
748 }
749
750 /*
751 * Check that
752 * o the CFCR, IER and MCR in UART hold the values written to them
753 * (the values happen to be all distinct - this is good for
754 * avoiding false positive tests from bus echoes).
755 * o an output interrupt is generated and its vector is correct.
756 * o the interrupt goes away when the IIR in the UART is read.
757 */
758/* EXTRA DELAY? */
759 failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
760 failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
761 failures[2] = sio_getreg(com, com_mcr) - mcr_image;
762 DELAY(10000); /* Some internal modems need this time */
763 irqmap[1] = isa_irq_pending();
764 failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
765 DELAY(1000); /* XXX */
766 irqmap[2] = isa_irq_pending();
767 failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
768
769 /*
770 * Turn off all device interrupts and check that they go off properly.
771 * Leave MCR_IENABLE alone. For ports without a master port, it gates
772 * the OUT2 output of the UART to
773 * the ICU input. Closing the gate would give a floating ICU input
774 * (unless there is another device driving it) and spurious interrupts.
775 * (On the system that this was first tested on, the input floats high
776 * and gives a (masked) interrupt as soon as the gate is closed.)
777 */
778 sio_setreg(com, com_ier, 0);
779 sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
780 failures[7] = sio_getreg(com, com_ier);
781 DELAY(1000); /* XXX */
782 irqmap[3] = isa_irq_pending();
783 failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
784
785 mtx_unlock_spin(&sio_lock);
786
787 irqs = irqmap[1] & ~irqmap[0];
788 if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
789 ((1 << xirq) & irqs) == 0) {
790 printf(
791 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
792 device_get_unit(dev), xirq, irqs);
793 printf(
794 "sio%d: port may not be enabled\n",
795 device_get_unit(dev));
796 }
797 if (bootverbose)
798 printf("sio%d: irq maps: %#x %#x %#x %#x\n",
799 device_get_unit(dev),
800 irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
801
802 result = 0;
803 for (fn = 0; fn < sizeof failures; ++fn)
804 if (failures[fn]) {
805 sio_setreg(com, com_mcr, 0);
806 result = ENXIO;
807 if (bootverbose) {
808 printf("sio%d: probe failed test(s):",
809 device_get_unit(dev));
810 for (fn = 0; fn < sizeof failures; ++fn)
811 if (failures[fn])
812 printf(" %d", fn);
813 printf("\n");
814 }
815 break;
816 }
817 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
818 if (iobase == siocniobase)
819 result = 0;
820 if (result != 0) {
821 device_set_softc(dev, NULL);
822 free(com, M_DEVBUF);
823 }
824 return (result);
825}
826
827#ifdef COM_ESP
828static int
829espattach(com, esp_port)
830 struct com_s *com;
831 Port_t esp_port;
832{
833 u_char dips;
834 u_char val;
835
836 /*
837 * Check the ESP-specific I/O port to see if we're an ESP
838 * card. If not, return failure immediately.
839 */
840 if ((inb(esp_port) & 0xf3) == 0) {
841 printf(" port 0x%x is not an ESP board?\n", esp_port);
842 return (0);
843 }
844
845 /*
846 * We've got something that claims to be a Hayes ESP card.
847 * Let's hope so.
848 */
849
850 /* Get the dip-switch configuration */
851 outb(esp_port + ESP_CMD1, ESP_GETDIPS);
852 dips = inb(esp_port + ESP_STATUS1);
853
854 /*
855 * Bits 0,1 of dips say which COM port we are.
856 */
857 if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03])
858 printf(" : ESP");
859 else {
860 printf(" esp_port has com %d\n", dips & 0x03);
861 return (0);
862 }
863
864 /*
865 * Check for ESP version 2.0 or later: bits 4,5,6 = 010.
866 */
867 outb(esp_port + ESP_CMD1, ESP_GETTEST);
868 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */
869 val = inb(esp_port + ESP_STATUS2);
870 if ((val & 0x70) < 0x20) {
871 printf("-old (%o)", val & 0x70);
872 return (0);
873 }
874
875 /*
876 * Check for ability to emulate 16550: bit 7 == 1
877 */
878 if ((dips & 0x80) == 0) {
879 printf(" slave");
880 return (0);
881 }
882
883 /*
884 * Okay, we seem to be a Hayes ESP card. Whee.
885 */
886 com->esp = TRUE;
887 com->esp_port = esp_port;
888 return (1);
889}
890#endif /* COM_ESP */
891
892int
893sioattach(dev, xrid, rclk)
894 device_t dev;
895 int xrid;
896 u_long rclk;
897{
898 struct com_s *com;
899#ifdef COM_ESP
900 Port_t *espp;
901#endif
902 Port_t iobase;
903 int minorbase;
904 int unit;
905 u_int flags;
906 int rid;
907 struct resource *port;
908 int ret;
909
910 rid = xrid;
911 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
912 0, ~0, IO_COMSIZE, RF_ACTIVE);
913 if (!port)
914 return (ENXIO);
915
916 iobase = rman_get_start(port);
917 unit = device_get_unit(dev);
918 com = device_get_softc(dev);
919 flags = device_get_flags(dev);
920
921 if (unit >= sio_numunits)
922 sio_numunits = unit + 1;
923 /*
924 * sioprobe() has initialized the device registers as follows:
925 * o cfcr = CFCR_8BITS.
926 * It is most important that CFCR_DLAB is off, so that the
927 * data port is not hidden when we enable interrupts.
928 * o ier = 0.
929 * Interrupts are only enabled when the line is open.
930 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
931 * interrupt control register or the config specifies no irq.
932 * Keeping MCR_DTR and MCR_RTS off might stop the external
933 * device from sending before we are ready.
934 */
935 bzero(com, sizeof *com);
936 com->unit = unit;
937 com->ioportres = port;
938 com->ioportrid = rid;
939 com->bst = rman_get_bustag(port);
940 com->bsh = rman_get_bushandle(port);
941 com->cfcr_image = CFCR_8BITS;
942 com->dtr_wait = 3 * hz;
943 com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
944 com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
945 com->tx_fifo_size = 1;
946 com->obufs[0].l_head = com->obuf1;
947 com->obufs[1].l_head = com->obuf2;
948
949 com->data_port = iobase + com_data;
950 com->int_id_port = iobase + com_iir;
951 com->modem_ctl_port = iobase + com_mcr;
952 com->mcr_image = inb(com->modem_ctl_port);
953 com->line_status_port = iobase + com_lsr;
954 com->modem_status_port = iobase + com_msr;
955 com->intr_ctl_port = iobase + com_ier;
956
957 if (rclk == 0)
958 rclk = DEFAULT_RCLK;
959 com->rclk = rclk;
960
961 /*
962 * We don't use all the flags from <sys/ttydefaults.h> since they
963 * are only relevant for logins. It's important to have echo off
964 * initially so that the line doesn't start blathering before the
965 * echo flag can be turned off.
966 */
967 com->it_in.c_iflag = 0;
968 com->it_in.c_oflag = 0;
969 com->it_in.c_cflag = TTYDEF_CFLAG;
970 com->it_in.c_lflag = 0;
971 if (unit == comconsole) {
972 com->it_in.c_iflag = TTYDEF_IFLAG;
973 com->it_in.c_oflag = TTYDEF_OFLAG;
974 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
975 com->it_in.c_lflag = TTYDEF_LFLAG;
976 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
977 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
978 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
979 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
980 } else
981 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
982 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
983 mtx_unlock_spin(&sio_lock);
984 /*
985 * Leave i/o resources allocated if this is a `cn'-level
986 * console, so that other devices can't snarf them.
987 */
988 if (iobase != siocniobase)
989 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
990 return (ENOMEM);
991 }
992 mtx_unlock_spin(&sio_lock);
993 termioschars(&com->it_in);
994 com->it_out = com->it_in;
995
996 /* attempt to determine UART type */
997 printf("sio%d: type", unit);
998
999
1000 if (!COM_ISMULTIPORT(flags) &&
1001 !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) {
1002 u_char scr;
1003 u_char scr1;
1004 u_char scr2;
1005
1006 scr = sio_getreg(com, com_scr);
1007 sio_setreg(com, com_scr, 0xa5);
1008 scr1 = sio_getreg(com, com_scr);
1009 sio_setreg(com, com_scr, 0x5a);
1010 scr2 = sio_getreg(com, com_scr);
1011 sio_setreg(com, com_scr, scr);
1012 if (scr1 != 0xa5 || scr2 != 0x5a) {
1013 printf(" 8250 or not responding");
1014 goto determined_type;
1015 }
1016 }
1017 sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1018 DELAY(100);
1019 com->st16650a = 0;
1020 switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1021 case FIFO_RX_LOW:
1022 printf(" 16450");
1023 break;
1024 case FIFO_RX_MEDL:
1025 printf(" 16450?");
1026 break;
1027 case FIFO_RX_MEDH:
1028 printf(" 16550?");
1029 break;
1030 case FIFO_RX_HIGH:
1031 if (COM_NOFIFO(flags)) {
1032 printf(" 16550A fifo disabled");
1033 } else {
1034 com->hasfifo = TRUE;
1035 if (COM_ST16650A(flags)) {
1036 com->st16650a = 1;
1037 com->tx_fifo_size = 32;
1038 printf(" ST16650A");
1039 } else if (COM_TI16754(flags)) {
1040 com->tx_fifo_size = 64;
1041 printf(" TI16754");
1042 } else {
1043 com->tx_fifo_size = COM_FIFOSIZE(flags);
1044 printf(" 16550A");
1045 }
1046 }
1047#ifdef COM_ESP
1048 for (espp = likely_esp_ports; *espp != 0; espp++)
1049 if (espattach(com, *espp)) {
1050 com->tx_fifo_size = 1024;
1051 break;
1052 }
1053#endif
1054 if (!com->st16650a && !COM_TI16754(flags)) {
1055 if (!com->tx_fifo_size)
1056 com->tx_fifo_size = 16;
1057 else
1058 printf(" lookalike with %d bytes FIFO",
1059 com->tx_fifo_size);
1060 }
1061
1062 break;
1063 }
1064
1065#ifdef COM_ESP
1066 if (com->esp) {
1067 /*
1068 * Set 16550 compatibility mode.
1069 * We don't use the ESP_MODE_SCALE bit to increase the
1070 * fifo trigger levels because we can't handle large
1071 * bursts of input.
1072 * XXX flow control should be set in comparam(), not here.
1073 */
1074 outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1075 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1076
1077 /* Set RTS/CTS flow control. */
1078 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1079 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1080 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1081
1082 /* Set flow-control levels. */
1083 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1084 outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1085 outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1086 outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1087 outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1088 }
1089#endif /* COM_ESP */
1090 sio_setreg(com, com_fifo, 0);
1091determined_type: ;
1092
1093#ifdef COM_MULTIPORT
1094 if (COM_ISMULTIPORT(flags)) {
1095 device_t masterdev;
1096
1097 com->multiport = TRUE;
1098 printf(" (multiport");
1099 if (unit == COM_MPMASTER(flags))
1100 printf(" master");
1101 printf(")");
1102 masterdev = devclass_get_device(sio_devclass,
1103 COM_MPMASTER(flags));
1104 com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1105 SYS_RES_IRQ, 0, NULL, NULL) != 0);
1106 }
1107#endif /* COM_MULTIPORT */
1108 if (unit == comconsole)
1109 printf(", console");
1110 if (COM_IIR_TXRDYBUG(flags))
1111 printf(" with a bogus IIR_TXRDY register");
1112 printf("\n");
1113
1114 if (sio_fast_ih == NULL) {
1115 swi_add(&tty_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0,
1116 &sio_fast_ih);
1117 swi_add(&clk_ithd, "tty:sio", siopoll, NULL, SWI_TTY, 0,
1118 &sio_slow_ih);
1119 }
1120 minorbase = UNIT_TO_MINOR(unit);
1121 com->devs[0] = make_dev(&sio_cdevsw, minorbase,
1122 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
1123 com->devs[1] = make_dev(&sio_cdevsw, minorbase | CONTROL_INIT_STATE,
1124 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
1125 com->devs[2] = make_dev(&sio_cdevsw, minorbase | CONTROL_LOCK_STATE,
1126 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
1127 com->devs[3] = make_dev(&sio_cdevsw, minorbase | CALLOUT_MASK,
1128 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
1129 com->devs[4] = make_dev(&sio_cdevsw,
1130 minorbase | CALLOUT_MASK | CONTROL_INIT_STATE,
1131 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
1132 com->devs[5] = make_dev(&sio_cdevsw,
1133 minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE,
1134 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
1135 for (rid = 0; rid < 6; rid++)
1136 com->devs[rid]->si_drv1 = com;
1137 com->flags = flags;
1138 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1139
1140 if (COM_PPSCTS(flags))
1141 com->pps_bit = MSR_CTS;
1142 else
1143 com->pps_bit = MSR_DCD;
1144 pps_init(&com->pps);
1145
1146 rid = 0;
1147 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1148 RF_ACTIVE);
1149 if (com->irqres) {
1150 ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1151 INTR_TYPE_TTY | INTR_FAST,
1152 siointr, com, &com->cookie);
1153 if (ret) {
1154 ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1155 com->irqres, INTR_TYPE_TTY,
1156 siointr, com, &com->cookie);
1157 if (ret == 0)
1158 device_printf(dev, "unable to activate interrupt in fast mode - using normal mode\n");
1159 }
1160 if (ret)
1161 device_printf(dev, "could not activate interrupt\n");
1162#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
1163 defined(ALT_BREAK_TO_DEBUGGER))
1164 /*
1165 * Enable interrupts for early break-to-debugger support
1166 * on the console.
1167 */
1168 if (ret == 0 && unit == comconsole)
1169 outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS |
1170 IER_EMSC);
1171#endif
1172 }
1173
1174 return (0);
1175}
1176
1177static int
1178sioopen(dev, flag, mode, td)
1179 dev_t dev;
1180 int flag;
1181 int mode;
1182 struct thread *td;
1183{
1184 struct com_s *com;
1185 int error;
1186 int mynor;
1187 int s;
1188 struct tty *tp;
1189 int unit;
1190
1191 mynor = minor(dev);
1192 unit = MINOR_TO_UNIT(mynor);
1193 com = com_addr(unit);
1194 if (com == NULL)
1195 return (ENXIO);
1196 if (com->gone)
1197 return (ENXIO);
1198 if (mynor & CONTROL_MASK)
1199 return (0);
1200 tp = dev->si_tty = com->tp = ttymalloc(com->tp);
1201 s = spltty();
1202 /*
1203 * We jump to this label after all non-interrupted sleeps to pick
1204 * up any changes of the device state.
1205 */
1206open_top:
1207 while (com->state & CS_DTR_OFF) {
1208 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
1209 if (com_addr(unit) == NULL)
1210 return (ENXIO);
1211 if (error != 0 || com->gone)
1212 goto out;
1213 }
1214 if (tp->t_state & TS_ISOPEN) {
1215 /*
1216 * The device is open, so everything has been initialized.
1217 * Handle conflicts.
1218 */
1219 if (mynor & CALLOUT_MASK) {
1220 if (!com->active_out) {
1221 error = EBUSY;
1222 goto out;
1223 }
1224 } else {
1225 if (com->active_out) {
1226 if (flag & O_NONBLOCK) {
1227 error = EBUSY;
1228 goto out;
1229 }
1230 error = tsleep(&com->active_out,
1231 TTIPRI | PCATCH, "siobi", 0);
1232 if (com_addr(unit) == NULL)
1233 return (ENXIO);
1234 if (error != 0 || com->gone)
1235 goto out;
1236 goto open_top;
1237 }
1238 }
1239 if (tp->t_state & TS_XCLUDE &&
1240 suser(td)) {
1241 error = EBUSY;
1242 goto out;
1243 }
1244 } else {
1245 /*
1246 * The device isn't open, so there are no conflicts.
1247 * Initialize it. Initialization is done twice in many
1248 * cases: to preempt sleeping callin opens if we are
1249 * callout, and to complete a callin open after DCD rises.
1250 */
1251 tp->t_oproc = comstart;
1252 tp->t_param = comparam;
1253 tp->t_stop = comstop;
1254 tp->t_dev = dev;
1255 tp->t_termios = mynor & CALLOUT_MASK
1256 ? com->it_out : com->it_in;
1257 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1258 com->poll = com->no_irq;
1259 com->poll_output = com->loses_outints;
1260 ++com->wopeners;
1261 error = comparam(tp, &tp->t_termios);
1262 --com->wopeners;
1263 if (error != 0)
1264 goto out;
1265 /*
1266 * XXX we should goto open_top if comparam() slept.
1267 */
1268 if (com->hasfifo) {
1269 int i;
1270 /*
1271 * (Re)enable and drain fifos.
1272 *
1273 * Certain SMC chips cause problems if the fifos
1274 * are enabled while input is ready. Turn off the
1275 * fifo if necessary to clear the input. We test
1276 * the input ready bit after enabling the fifos
1277 * since we've already enabled them in comparam()
1278 * and to handle races between enabling and fresh
1279 * input.
1280 */
1281 for (i = 0; i < 500; i++) {
1282 sio_setreg(com, com_fifo,
1283 FIFO_RCV_RST | FIFO_XMT_RST
1284 | com->fifo_image);
1285 /*
1286 * XXX the delays are for superstitious
1287 * historical reasons. It must be less than
1288 * the character time at the maximum
1289 * supported speed (87 usec at 115200 bps
1290 * 8N1). Otherwise we might loop endlessly
1291 * if data is streaming in. We used to use
1292 * delays of 100. That usually worked
1293 * because DELAY(100) used to usually delay
1294 * for about 85 usec instead of 100.
1295 */
1296 DELAY(50);
1297 if (!(inb(com->line_status_port) & LSR_RXRDY))
1298 break;
1299 sio_setreg(com, com_fifo, 0);
1300 DELAY(50);
1301 (void) inb(com->data_port);
1302 }
1303 if (i == 500) {
1304 error = EIO;
1305 goto out;
1306 }
1307 }
1308
1309 mtx_lock_spin(&sio_lock);
1310 (void) inb(com->line_status_port);
1311 (void) inb(com->data_port);
1312 com->prev_modem_status = com->last_modem_status
1313 = inb(com->modem_status_port);
1314 if (COM_IIR_TXRDYBUG(com->flags)) {
1315 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1316 | IER_EMSC);
1317 } else {
1318 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1319 | IER_ERLS | IER_EMSC);
1320 }
1321 mtx_unlock_spin(&sio_lock);
1322 /*
1323 * Handle initial DCD. Callout devices get a fake initial
1324 * DCD (trapdoor DCD). If we are callout, then any sleeping
1325 * callin opens get woken up and resume sleeping on "siobi"
1326 * instead of "siodcd".
1327 */
1328 /*
1329 * XXX `mynor & CALLOUT_MASK' should be
1330 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
1331 * TRAPDOOR_CARRIER is the default initial state for callout
1332 * devices and SOFT_CARRIER is like CLOCAL except it hides
1333 * the true carrier.
1334 */
1335 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
1336 (*linesw[tp->t_line].l_modem)(tp, 1);
1337 }
1338 /*
1339 * Wait for DCD if necessary.
1340 */
1341 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1342 && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
1343 ++com->wopeners;
1344 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
1345 if (com_addr(unit) == NULL)
1346 return (ENXIO);
1347 --com->wopeners;
1348 if (error != 0 || com->gone)
1349 goto out;
1350 goto open_top;
1351 }
1352 error = (*linesw[tp->t_line].l_open)(dev, tp);
1353 disc_optim(tp, &tp->t_termios, com);
1354 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1355 com->active_out = TRUE;
1356 siosettimeout();
1357out:
1358 splx(s);
1359 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
1360 comhardclose(com);
1361 return (error);
1362}
1363
1364static int
1365sioclose(dev, flag, mode, td)
1366 dev_t dev;
1367 int flag;
1368 int mode;
1369 struct thread *td;
1370{
1371 struct com_s *com;
1372 int mynor;
1373 int s;
1374 struct tty *tp;
1375
1376 mynor = minor(dev);
1377 if (mynor & CONTROL_MASK)
1378 return (0);
1379 com = com_addr(MINOR_TO_UNIT(mynor));
1380 if (com == NULL)
1381 return (ENODEV);
1382 tp = com->tp;
1383 s = spltty();
1384 (*linesw[tp->t_line].l_close)(tp, flag);
1385 disc_optim(tp, &tp->t_termios, com);
1386 comstop(tp, FREAD | FWRITE);
1387 comhardclose(com);
1388 ttyclose(tp);
1389 siosettimeout();
1390 splx(s);
1391 if (com->gone) {
1392 printf("sio%d: gone\n", com->unit);
1393 s = spltty();
1394 if (com->ibuf != NULL)
1395 free(com->ibuf, M_DEVBUF);
1396 bzero(tp, sizeof *tp);
1397 splx(s);
1398 }
1399 return (0);
1400}
1401
1402static void
1403comhardclose(com)
1404 struct com_s *com;
1405{
1406 int s;
1407 struct tty *tp;
1408
1409 s = spltty();
1410 com->poll = FALSE;
1411 com->poll_output = FALSE;
1412 com->do_timestamp = FALSE;
1413 com->do_dcd_timestamp = FALSE;
1414 com->pps.ppsparam.mode = 0;
1415 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1416 tp = com->tp;
1417
1418#if defined(DDB) && (defined(BREAK_TO_DEBUGGER) || \
1419 defined(ALT_BREAK_TO_DEBUGGER))
1420 /*
1421 * Leave interrupts enabled and don't clear DTR if this is the
1422 * console. This allows us to detect break-to-debugger events
1423 * while the console device is closed.
1424 */
1425 if (com->unit != comconsole)
1426#endif
1427 {
1428 sio_setreg(com, com_ier, 0);
1429 if (tp->t_cflag & HUPCL
1430 /*
1431 * XXX we will miss any carrier drop between here and the
1432 * next open. Perhaps we should watch DCD even when the
1433 * port is closed; it is not sufficient to check it at
1434 * the next open because it might go up and down while
1435 * we're not watching.
1436 */
1437 || (!com->active_out
1438 && !(com->prev_modem_status & MSR_DCD)
1439 && !(com->it_in.c_cflag & CLOCAL))
1440 || !(tp->t_state & TS_ISOPEN)) {
1441 (void)commctl(com, TIOCM_DTR, DMBIC);
1442 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
1443 timeout(siodtrwakeup, com, com->dtr_wait);
1444 com->state |= CS_DTR_OFF;
1445 }
1446 }
1447 }
1448 if (com->hasfifo) {
1449 /*
1450 * Disable fifos so that they are off after controlled
1451 * reboots. Some BIOSes fail to detect 16550s when the
1452 * fifos are enabled.
1453 */
1454 sio_setreg(com, com_fifo, 0);
1455 }
1456 com->active_out = FALSE;
1457 wakeup(&com->active_out);
1458 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */
1459 splx(s);
1460}
1461
1462static int
1463sioread(dev, uio, flag)
1464 dev_t dev;
1465 struct uio *uio;
1466 int flag;
1467{
1468 int mynor;
1469 struct com_s *com;
1470
1471 mynor = minor(dev);
1472 if (mynor & CONTROL_MASK)
1473 return (ENODEV);
1474 com = com_addr(MINOR_TO_UNIT(mynor));
1475 if (com == NULL || com->gone)
1476 return (ENODEV);
1477 return ((*linesw[com->tp->t_line].l_read)(com->tp, uio, flag));
1478}
1479
1480static int
1481siowrite(dev, uio, flag)
1482 dev_t dev;
1483 struct uio *uio;
1484 int flag;
1485{
1486 int mynor;
1487 struct com_s *com;
1488 int unit;
1489
1490 mynor = minor(dev);
1491 if (mynor & CONTROL_MASK)
1492 return (ENODEV);
1493
1494 unit = MINOR_TO_UNIT(mynor);
1495 com = com_addr(unit);
1496 if (com == NULL || com->gone)
1497 return (ENODEV);
1498 /*
1499 * (XXX) We disallow virtual consoles if the physical console is
1500 * a serial port. This is in case there is a display attached that
1501 * is not the console. In that situation we don't need/want the X
1502 * server taking over the console.
1503 */
1504 if (constty != NULL && unit == comconsole)
1505 constty = NULL;
1506 return ((*linesw[com->tp->t_line].l_write)(com->tp, uio, flag));
1507}
1508
1509static void
1510siobusycheck(chan)
1511 void *chan;
1512{
1513 struct com_s *com;
1514 int s;
1515
1516 com = (struct com_s *)chan;
1517
1518 /*
1519 * Clear TS_BUSY if low-level output is complete.
1520 * spl locking is sufficient because siointr1() does not set CS_BUSY.
1521 * If siointr1() clears CS_BUSY after we look at it, then we'll get
1522 * called again. Reading the line status port outside of siointr1()
1523 * is safe because CS_BUSY is clear so there are no output interrupts
1524 * to lose.
1525 */
1526 s = spltty();
1527 if (com->state & CS_BUSY)
1528 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */
1529 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1530 == (LSR_TSRE | LSR_TXRDY)) {
1531 com->tp->t_state &= ~TS_BUSY;
1532 ttwwakeup(com->tp);
1533 com->extra_state &= ~CSE_BUSYCHECK;
1534 } else
1535 timeout(siobusycheck, com, hz / 100);
1536 splx(s);
1537}
1538
1539static u_int
1540siodivisor(rclk, speed)
1541 u_long rclk;
1542 speed_t speed;
1543{
1544 long actual_speed;
1545 u_int divisor;
1546 int error;
1547
1548 if (speed == 0)
1549 return (0);
1550#if UINT_MAX > (ULONG_MAX - 1) / 8
1551 if (speed > (ULONG_MAX - 1) / 8)
1552 return (0);
1553#endif
1554 divisor = (rclk / (8UL * speed) + 1) / 2;
1555 if (divisor == 0 || divisor >= 65536)
1556 return (0);
1557 actual_speed = rclk / (16UL * divisor);
1558
1559 /* 10 times error in percent: */
1560 error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
1561
1562 /* 3.0% maximum error tolerance: */
1563 if (error < -30 || error > 30)
1564 return (0);
1565
1566 return (divisor);
1567}
1568
1569static void
1570siodtrwakeup(chan)
1571 void *chan;
1572{
1573 struct com_s *com;
1574
1575 com = (struct com_s *)chan;
1576 com->state &= ~CS_DTR_OFF;
1577 wakeup(&com->dtr_wait);
1578}
1579
1580/*
1581 * Call this function with the sio_lock mutex held. It will return with the
1582 * lock still held.
1583 */
1584static void
1585sioinput(com)
1586 struct com_s *com;
1587{
1588 u_char *buf;
1589 int incc;
1590 u_char line_status;
1591 int recv_data;
1592 struct tty *tp;
1593
1594 buf = com->ibuf;
1595 tp = com->tp;
1596 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1597 com_events -= (com->iptr - com->ibuf);
1598 com->iptr = com->ibuf;
1599 return;
1600 }
1601 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
1602 /*
1603 * Avoid the grotesquely inefficient lineswitch routine
1604 * (ttyinput) in "raw" mode. It usually takes about 450
1605 * instructions (that's without canonical processing or echo!).
1606 * slinput is reasonably fast (usually 40 instructions plus
1607 * call overhead).
1608 */
1609 do {
1610 /*
1611 * This may look odd, but it is using save-and-enable
1612 * semantics instead of the save-and-disable semantics
1613 * that are used everywhere else.
1614 */
1615 mtx_unlock_spin(&sio_lock);
1616 incc = com->iptr - buf;
1617 if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
1618 && (com->state & CS_RTS_IFLOW
1619 || tp->t_iflag & IXOFF)
1620 && !(tp->t_state & TS_TBLOCK))
1621 ttyblock(tp);
1622 com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
1623 += b_to_q((char *)buf, incc, &tp->t_rawq);
1624 buf += incc;
1625 tk_nin += incc;
1626 tk_rawcc += incc;
1627 tp->t_rawcc += incc;
1628 ttwakeup(tp);
1629 if (tp->t_state & TS_TTSTOP
1630 && (tp->t_iflag & IXANY
1631 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
1632 tp->t_state &= ~TS_TTSTOP;
1633 tp->t_lflag &= ~FLUSHO;
1634 comstart(tp);
1635 }
1636 mtx_lock_spin(&sio_lock);
1637 } while (buf < com->iptr);
1638 } else {
1639 do {
1640 /*
1641 * This may look odd, but it is using save-and-enable
1642 * semantics instead of the save-and-disable semantics
1643 * that are used everywhere else.
1644 */
1645 mtx_unlock_spin(&sio_lock);
1646 line_status = buf[com->ierroff];
1647 recv_data = *buf++;
1648 if (line_status
1649 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1650 if (line_status & LSR_BI)
1651 recv_data |= TTY_BI;
1652 if (line_status & LSR_FE)
1653 recv_data |= TTY_FE;
1654 if (line_status & LSR_OE)
1655 recv_data |= TTY_OE;
1656 if (line_status & LSR_PE)
1657 recv_data |= TTY_PE;
1658 }
1659 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1660 mtx_lock_spin(&sio_lock);
1661 } while (buf < com->iptr);
1662 }
1663 com_events -= (com->iptr - com->ibuf);
1664 com->iptr = com->ibuf;
1665
1666 /*
1667 * There is now room for another low-level buffer full of input,
1668 * so enable RTS if it is now disabled and there is room in the
1669 * high-level buffer.
1670 */
1671 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1672 !(tp->t_state & TS_TBLOCK))
1673 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1674}
1675
1676static void
1677siointr(arg)
1678 void *arg;
1679{
1680 struct com_s *com;
1681
1682#ifndef COM_MULTIPORT
1683 com = (struct com_s *)arg;
1684
1685 mtx_lock_spin(&sio_lock);
1686 siointr1(com);
1687 mtx_unlock_spin(&sio_lock);
1688#else /* COM_MULTIPORT */
1689 bool_t possibly_more_intrs;
1690 int unit;
1691
1692 /*
1693 * Loop until there is no activity on any port. This is necessary
1694 * to get an interrupt edge more than to avoid another interrupt.
1695 * If the IRQ signal is just an OR of the IRQ signals from several
1696 * devices, then the edge from one may be lost because another is
1697 * on.
1698 */
1699 mtx_lock_spin(&sio_lock);
1700 do {
1701 possibly_more_intrs = FALSE;
1702 for (unit = 0; unit < sio_numunits; ++unit) {
1703 com = com_addr(unit);
1704 /*
1705 * XXX COM_LOCK();
1706 * would it work here, or be counter-productive?
1707 */
1708 if (com != NULL
1709 && !com->gone
1710 && (inb(com->int_id_port) & IIR_IMASK)
1711 != IIR_NOPEND) {
1712 siointr1(com);
1713 possibly_more_intrs = TRUE;
1714 }
1715 /* XXX COM_UNLOCK(); */
1716 }
1717 } while (possibly_more_intrs);
1718 mtx_unlock_spin(&sio_lock);
1719#endif /* COM_MULTIPORT */
1720}
1721
1722static struct timespec siots[8192];
1723static int siotso;
1724static int volatile siotsunit = -1;
1725
1726static int
1727sysctl_siots(SYSCTL_HANDLER_ARGS)
1728{
1729 char buf[128];
1730 long long delta;
1731 size_t len;
1732 int error, i;
1733
1734 for (i = 1; i < siotso; i++) {
1735 delta = (long long)(siots[i].tv_sec - siots[i - 1].tv_sec) *
1736 1000000000 +
1737 (siots[i].tv_nsec - siots[i - 1].tv_nsec);
1738 len = sprintf(buf, "%lld\n", delta);
1739 if (delta >= 110000)
1740 len += sprintf(buf + len - 1, ": *** %ld.%09ld\n",
1741 (long)siots[i].tv_sec, siots[i].tv_nsec);
1742 if (i == siotso - 1)
1743 buf[len - 1] = '\0';
1744 error = SYSCTL_OUT(req, buf, len);
1745 if (error != 0)
1746 return (error);
1747 uio_yield();
1748 }
1749 return (0);
1750}
1751
1752SYSCTL_PROC(_machdep, OID_AUTO, siots, CTLTYPE_STRING | CTLFLAG_RD,
1753 0, 0, sysctl_siots, "A", "sio timestamps");
1754
1755static void
1756siointr1(com)
1757 struct com_s *com;
1758{
1759 u_char line_status;
1760 u_char modem_status;
1761 u_char *ioptr;
1762 u_char recv_data;
1763 u_char int_ctl;
1764 u_char int_ctl_new;
1765
1766 int_ctl = inb(com->intr_ctl_port);
1767 int_ctl_new = int_ctl;
1768
1769 while (!com->gone) {
1770 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
1771 modem_status = inb(com->modem_status_port);
1772 if ((modem_status ^ com->last_modem_status) &
1773 com->pps_bit) {
1774 pps_capture(&com->pps);
1775 pps_event(&com->pps,
1776 (modem_status & com->pps_bit) ?
1777 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
1778 }
1779 }
1780 line_status = inb(com->line_status_port);
1781
1782 /* input event? (check first to help avoid overruns) */
1783 while (line_status & LSR_RCV_MASK) {
1784 /* break/unnattached error bits or real input? */
1785 if (!(line_status & LSR_RXRDY))
1786 recv_data = 0;
1787 else
1788 recv_data = inb(com->data_port);
1789#if defined(DDB) && defined(ALT_BREAK_TO_DEBUGGER)
1790 /*
1791 * Solaris implements a new BREAK which is initiated
1792 * by a character sequence CR ~ ^b which is similar
1793 * to a familiar pattern used on Sun servers by the
1794 * Remote Console.
1795 */
1796#define KEY_CRTLB 2 /* ^B */
1797#define KEY_CR 13 /* CR '\r' */
1798#define KEY_TILDE 126 /* ~ */
1799
1800 if (com->unit == comconsole) {
1801 static int brk_state1 = 0, brk_state2 = 0;
1802 if (recv_data == KEY_CR) {
1803 brk_state1 = recv_data;
1804 brk_state2 = 0;
1805 } else if (brk_state1 == KEY_CR
1806 && (recv_data == KEY_TILDE
1807 || recv_data == KEY_CRTLB)) {
1808 if (recv_data == KEY_TILDE)
1809 brk_state2 = recv_data;
1810 else if (brk_state2 == KEY_TILDE
1811 && recv_data == KEY_CRTLB) {
1812 breakpoint();
1813 brk_state1 = 0;
1814 brk_state2 = 0;
1815 goto cont;
1816 } else
1817 brk_state2 = 0;
1818 } else
1819 brk_state1 = 0;
1820 }
1821#endif
1822 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1823 /*
1824 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1825 * Otherwise, push the work to a higher level
1826 * (to handle PARMRK) if we're bypassing.
1827 * Otherwise, convert BI/FE and PE+INPCK to 0.
1828 *
1829 * This makes bypassing work right in the
1830 * usual "raw" case (IGNBRK set, and IGNPAR
1831 * and INPCK clear).
1832 *
1833 * Note: BI together with FE/PE means just BI.
1834 */
1835 if (line_status & LSR_BI) {
1836#if defined(DDB) && defined(BREAK_TO_DEBUGGER)
1837 if (com->unit == comconsole) {
1838 breakpoint();
1839 goto cont;
1840 }
1841#endif
1842 if (com->tp == NULL
1843 || com->tp->t_iflag & IGNBRK)
1844 goto cont;
1845 } else {
1846 if (com->tp == NULL
1847 || com->tp->t_iflag & IGNPAR)
1848 goto cont;
1849 }
1850 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1851 && (line_status & (LSR_BI | LSR_FE)
1852 || com->tp->t_iflag & INPCK))
1853 recv_data = 0;
1854 }
1855 ++com->bytes_in;
1856 if (com->hotchar != 0 && recv_data == com->hotchar)
1857 swi_sched(sio_fast_ih, 0);
1858 ioptr = com->iptr;
1859 if (ioptr >= com->ibufend)
1860 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1861 else {
1862 if (com->do_timestamp)
1863 microtime(&com->timestamp);
1864 ++com_events;
1865 swi_sched(sio_slow_ih, SWI_DELAY);
1866#if 0 /* for testing input latency vs efficiency */
1867if (com->iptr - com->ibuf == 8)
1868 swi_sched(sio_fast_ih, 0);
1869#endif
1870 ioptr[0] = recv_data;
1871 ioptr[com->ierroff] = line_status;
1872 com->iptr = ++ioptr;
1873 if (ioptr == com->ihighwater
1874 && com->state & CS_RTS_IFLOW)
1875 outb(com->modem_ctl_port,
1876 com->mcr_image &= ~MCR_RTS);
1877 if (line_status & LSR_OE)
1878 CE_RECORD(com, CE_OVERRUN);
1879 }
1880cont:
1881 /*
1882 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
1883 * jump from the top of the loop to here
1884 */
1885 line_status = inb(com->line_status_port) & 0x7F;
1886 }
1887
1888 /* modem status change? (always check before doing output) */
1889 modem_status = inb(com->modem_status_port);
1890 if (modem_status != com->last_modem_status) {
1891 if (com->do_dcd_timestamp
1892 && !(com->last_modem_status & MSR_DCD)
1893 && modem_status & MSR_DCD)
1894 microtime(&com->dcd_timestamp);
1895
1896 /*
1897 * Schedule high level to handle DCD changes. Note
1898 * that we don't use the delta bits anywhere. Some
1899 * UARTs mess them up, and it's easy to remember the
1900 * previous bits and calculate the delta.
1901 */
1902 com->last_modem_status = modem_status;
1903 if (!(com->state & CS_CHECKMSR)) {
1904 com_events += LOTS_OF_EVENTS;
1905 com->state |= CS_CHECKMSR;
1906 swi_sched(sio_fast_ih, 0);
1907 }
1908
1909 /* handle CTS change immediately for crisp flow ctl */
1910 if (com->state & CS_CTS_OFLOW) {
1911 if (modem_status & MSR_CTS)
1912 com->state |= CS_ODEVREADY;
1913 else
1914 com->state &= ~CS_ODEVREADY;
1915 }
1916 }
1917
1918 /* output queued and everything ready? */
1919 if (line_status & LSR_TXRDY
1920 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1921 ioptr = com->obufq.l_head;
1922 if (com->tx_fifo_size > 1 && com->unit != siotsunit) {
1923 u_int ocount;
1924
1925 ocount = com->obufq.l_tail - ioptr;
1926 if (ocount > com->tx_fifo_size)
1927 ocount = com->tx_fifo_size;
1928 com->bytes_out += ocount;
1929 do
1930 outb(com->data_port, *ioptr++);
1931 while (--ocount != 0);
1932 } else {
1933 outb(com->data_port, *ioptr++);
1934 ++com->bytes_out;
1935 if (com->unit == siotsunit) {
1936 nanouptime(&siots[siotso]);
1937 siotso = (siotso + 1) %
1938 (sizeof siots / sizeof siots[0]);
1939 }
1940 }
1941 com->obufq.l_head = ioptr;
1942 if (COM_IIR_TXRDYBUG(com->flags)) {
1943 int_ctl_new = int_ctl | IER_ETXRDY;
1944 }
1945 if (ioptr >= com->obufq.l_tail) {
1946 struct lbq *qp;
1947
1948 qp = com->obufq.l_next;
1949 qp->l_queued = FALSE;
1950 qp = qp->l_next;
1951 if (qp != NULL) {
1952 com->obufq.l_head = qp->l_head;
1953 com->obufq.l_tail = qp->l_tail;
1954 com->obufq.l_next = qp;
1955 } else {
1956 /* output just completed */
1957 if (COM_IIR_TXRDYBUG(com->flags)) {
1958 int_ctl_new = int_ctl & ~IER_ETXRDY;
1959 }
1960 com->state &= ~CS_BUSY;
1961 }
1962 if (!(com->state & CS_ODONE)) {
1963 com_events += LOTS_OF_EVENTS;
1964 com->state |= CS_ODONE;
1965 /* handle at high level ASAP */
1966 swi_sched(sio_fast_ih, 0);
1967 }
1968 }
1969 if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
1970 outb(com->intr_ctl_port, int_ctl_new);
1971 }
1972 }
1973
1974 /* finished? */
1975#ifndef COM_MULTIPORT
1976 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
1977#endif /* COM_MULTIPORT */
1978 return;
1979 }
1980}
1981
1982static int
1983sioioctl(dev, cmd, data, flag, td)
1984 dev_t dev;
1985 u_long cmd;
1986 caddr_t data;
1987 int flag;
1988 struct thread *td;
1989{
1990 struct com_s *com;
1991 int error;
1992 int mynor;
1993 int s;
1994 struct tty *tp;
1995#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1996 u_long oldcmd;
1997 struct termios term;
1998#endif
1999
2000 mynor = minor(dev);
2001 com = com_addr(MINOR_TO_UNIT(mynor));
2002 if (com == NULL || com->gone)
2003 return (ENODEV);
2004 if (mynor & CONTROL_MASK) {
2005 struct termios *ct;
2006
2007 switch (mynor & CONTROL_MASK) {
2008 case CONTROL_INIT_STATE:
2009 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2010 break;
2011 case CONTROL_LOCK_STATE:
2012 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2013 break;
2014 default:
2015 return (ENODEV); /* /dev/nodev */
2016 }
2017 switch (cmd) {
2018 case TIOCSETA:
2019 error = suser(td);
2020 if (error != 0)
2021 return (error);
2022 *ct = *(struct termios *)data;
2023 return (0);
2024 case TIOCGETA:
2025 *(struct termios *)data = *ct;
2026 return (0);
2027 case TIOCGETD:
2028 *(int *)data = TTYDISC;
2029 return (0);
2030 case TIOCGWINSZ:
2031 bzero(data, sizeof(struct winsize));
2032 return (0);
2033 default:
2034 return (ENOTTY);
2035 }
2036 }
2037 tp = com->tp;
2038#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2039 term = tp->t_termios;
2040 oldcmd = cmd;
2041 error = ttsetcompat(tp, &cmd, data, &term);
2042 if (error != 0)
2043 return (error);
2044 if (cmd != oldcmd)
2045 data = (caddr_t)&term;
2046#endif
2047 if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2048 int cc;
2049 struct termios *dt = (struct termios *)data;
2050 struct termios *lt = mynor & CALLOUT_MASK
2051 ? &com->lt_out : &com->lt_in;
2052
2053 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2054 | (dt->c_iflag & ~lt->c_iflag);
2055 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2056 | (dt->c_oflag & ~lt->c_oflag);
2057 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2058 | (dt->c_cflag & ~lt->c_cflag);
2059 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2060 | (dt->c_lflag & ~lt->c_lflag);
2061 for (cc = 0; cc < NCCS; ++cc)
2062 if (lt->c_cc[cc] != 0)
2063 dt->c_cc[cc] = tp->t_cc[cc];
2064 if (lt->c_ispeed != 0)
2065 dt->c_ispeed = tp->t_ispeed;
2066 if (lt->c_ospeed != 0)
2067 dt->c_ospeed = tp->t_ospeed;
2068 }
2069 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
2070 if (error != ENOIOCTL)
2071 return (error);
2072 s = spltty();
2073 error = ttioctl(tp, cmd, data, flag);
2074 disc_optim(tp, &tp->t_termios, com);
2075 if (error != ENOIOCTL) {
2076 splx(s);
2077 return (error);
2078 }
2079 switch (cmd) {
2080 case TIOCSBRK:
2081 sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2082 break;
2083 case TIOCCBRK:
2084 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2085 break;
2086 case TIOCSDTR:
2087 (void)commctl(com, TIOCM_DTR, DMBIS);
2088 break;
2089 case TIOCCDTR:
2090 (void)commctl(com, TIOCM_DTR, DMBIC);
2091 break;
2092 /*
2093 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The
2094 * changes get undone on the next call to comparam().
2095 */
2096 case TIOCMSET:
2097 (void)commctl(com, *(int *)data, DMSET);
2098 break;
2099 case TIOCMBIS:
2100 (void)commctl(com, *(int *)data, DMBIS);
2101 break;
2102 case TIOCMBIC:
2103 (void)commctl(com, *(int *)data, DMBIC);
2104 break;
2105 case TIOCMGET:
2106 *(int *)data = commctl(com, 0, DMGET);
2107 break;
2108 case TIOCMSDTRWAIT:
2109 /* must be root since the wait applies to following logins */
2110 error = suser(td);
2111 if (error != 0) {
2112 splx(s);
2113 return (error);
2114 }
2115 com->dtr_wait = *(int *)data * hz / 100;
2116 break;
2117 case TIOCMGDTRWAIT:
2118 *(int *)data = com->dtr_wait * 100 / hz;
2119 break;
2120 case TIOCTIMESTAMP:
2121 com->do_timestamp = TRUE;
2122 *(struct timeval *)data = com->timestamp;
2123 break;
2124 case TIOCDCDTIMESTAMP:
2125 com->do_dcd_timestamp = TRUE;
2126 *(struct timeval *)data = com->dcd_timestamp;
2127 break;
2128 default:
2129 splx(s);
2130 error = pps_ioctl(cmd, data, &com->pps);
2131 if (error == ENODEV)
2132 error = ENOTTY;
2133 return (error);
2134 }
2135 splx(s);
2136 return (0);
2137}
2138
2139/* software interrupt handler for SWI_TTY */
2140static void
2141siopoll(void *dummy)
2142{
2143 int unit;
2144
2145 if (com_events == 0)
2146 return;
2147repeat:
2148 for (unit = 0; unit < sio_numunits; ++unit) {
2149 struct com_s *com;
2150 int incc;
2151 struct tty *tp;
2152
2153 com = com_addr(unit);
2154 if (com == NULL)
2155 continue;
2156 tp = com->tp;
2157 if (tp == NULL || com->gone) {
2158 /*
2159 * Discard any events related to never-opened or
2160 * going-away devices.
2161 */
2162 mtx_lock_spin(&sio_lock);
2163 incc = com->iptr - com->ibuf;
2164 com->iptr = com->ibuf;
2165 if (com->state & CS_CHECKMSR) {
2166 incc += LOTS_OF_EVENTS;
2167 com->state &= ~CS_CHECKMSR;
2168 }
2169 com_events -= incc;
2170 mtx_unlock_spin(&sio_lock);
2171 continue;
2172 }
2173 if (com->iptr != com->ibuf) {
2174 mtx_lock_spin(&sio_lock);
2175 sioinput(com);
2176 mtx_unlock_spin(&sio_lock);
2177 }
2178 if (com->state & CS_CHECKMSR) {
2179 u_char delta_modem_status;
2180
2181 mtx_lock_spin(&sio_lock);
2182 delta_modem_status = com->last_modem_status
2183 ^ com->prev_modem_status;
2184 com->prev_modem_status = com->last_modem_status;
2185 com_events -= LOTS_OF_EVENTS;
2186 com->state &= ~CS_CHECKMSR;
2187 mtx_unlock_spin(&sio_lock);
2188 if (delta_modem_status & MSR_DCD)
2189 (*linesw[tp->t_line].l_modem)
2190 (tp, com->prev_modem_status & MSR_DCD);
2191 }
2192 if (com->state & CS_ODONE) {
2193 mtx_lock_spin(&sio_lock);
2194 com_events -= LOTS_OF_EVENTS;
2195 com->state &= ~CS_ODONE;
2196 mtx_unlock_spin(&sio_lock);
2197 if (!(com->state & CS_BUSY)
2198 && !(com->extra_state & CSE_BUSYCHECK)) {
2199 timeout(siobusycheck, com, hz / 100);
2200 com->extra_state |= CSE_BUSYCHECK;
2201 }
2202 (*linesw[tp->t_line].l_start)(tp);
2203 }
2204 if (com_events == 0)
2205 break;
2206 }
2207 if (com_events >= LOTS_OF_EVENTS)
2208 goto repeat;
2209}
2210
2211static int
2212comparam(tp, t)
2213 struct tty *tp;
2214 struct termios *t;
2215{
2216 u_int cfcr;
2217 int cflag;
2218 struct com_s *com;
2219 u_int divisor;
2220 u_char dlbh;
2221 u_char dlbl;
2222 int s;
2223 int unit;
2224
2225 unit = DEV_TO_UNIT(tp->t_dev);
2226 com = com_addr(unit);
2227 if (com == NULL)
2228 return (ENODEV);
2229
2230 /* do historical conversions */
2231 if (t->c_ispeed == 0)
2232 t->c_ispeed = t->c_ospeed;
2233
2234 /* check requested parameters */
2235 if (t->c_ospeed == 0)
2236 divisor = 0;
2237 else {
2238 if (t->c_ispeed != t->c_ospeed)
2239 return (EINVAL);
2240 divisor = siodivisor(com->rclk, t->c_ispeed);
2241 if (divisor == 0)
2242 return (EINVAL);
2243 }
2244
2245 /* parameters are OK, convert them to the com struct and the device */
2246 s = spltty();
2247 if (divisor == 0)
2248 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
2249 else
2250 (void)commctl(com, TIOCM_DTR, DMBIS);
2251 cflag = t->c_cflag;
2252 switch (cflag & CSIZE) {
2253 case CS5:
2254 cfcr = CFCR_5BITS;
2255 break;
2256 case CS6:
2257 cfcr = CFCR_6BITS;
2258 break;
2259 case CS7:
2260 cfcr = CFCR_7BITS;
2261 break;
2262 default:
2263 cfcr = CFCR_8BITS;
2264 break;
2265 }
2266 if (cflag & PARENB) {
2267 cfcr |= CFCR_PENAB;
2268 if (!(cflag & PARODD))
2269 cfcr |= CFCR_PEVEN;
2270 }
2271 if (cflag & CSTOPB)
2272 cfcr |= CFCR_STOPB;
2273
2274 if (com->hasfifo && divisor != 0) {
2275 /*
2276 * Use a fifo trigger level low enough so that the input
2277 * latency from the fifo is less than about 16 msec and
2278 * the total latency is less than about 30 msec. These
2279 * latencies are reasonable for humans. Serial comms
2280 * protocols shouldn't expect anything better since modem
2281 * latencies are larger.
2282 *
2283 * The fifo trigger level cannot be set at RX_HIGH for high
2284 * speed connections without further work on reducing
2285 * interrupt disablement times in other parts of the system,
2286 * without producing silo overflow errors.
2287 */
2288 com->fifo_image = com->unit == siotsunit ? 0
2289 : t->c_ospeed <= 4800
2290 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
2291#ifdef COM_ESP
2292 /*
2293 * The Hayes ESP card needs the fifo DMA mode bit set
2294 * in compatibility mode. If not, it will interrupt
2295 * for each character received.
2296 */
2297 if (com->esp)
2298 com->fifo_image |= FIFO_DMA_MODE;
2299#endif
2300 sio_setreg(com, com_fifo, com->fifo_image);
2301 }
2302
2303 /*
2304 * This returns with interrupts disabled so that we can complete
2305 * the speed change atomically. Keeping interrupts disabled is
2306 * especially important while com_data is hidden.
2307 */
2308 (void) siosetwater(com, t->c_ispeed);
2309
2310 if (divisor != 0) {
2311 sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2312 /*
2313 * Only set the divisor registers if they would change,
2314 * since on some 16550 incompatibles (UMC8669F), setting
2315 * them while input is arriving them loses sync until
2316 * data stops arriving.
2317 */
2318 dlbl = divisor & 0xFF;
2319 if (sio_getreg(com, com_dlbl) != dlbl)
2320 sio_setreg(com, com_dlbl, dlbl);
2321 dlbh = divisor >> 8;
2322 if (sio_getreg(com, com_dlbh) != dlbh)
2323 sio_setreg(com, com_dlbh, dlbh);
2324 }
2325
2326 sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
2327
2328 if (!(tp->t_state & TS_TTSTOP))
2329 com->state |= CS_TTGO;
2330
2331 if (cflag & CRTS_IFLOW) {
2332 if (com->st16650a) {
2333 sio_setreg(com, com_cfcr, 0xbf);
2334 sio_setreg(com, com_fifo,
2335 sio_getreg(com, com_fifo) | 0x40);
2336 }
2337 com->state |= CS_RTS_IFLOW;
2338 /*
2339 * If CS_RTS_IFLOW just changed from off to on, the change
2340 * needs to be propagated to MCR_RTS. This isn't urgent,
2341 * so do it later by calling comstart() instead of repeating
2342 * a lot of code from comstart() here.
2343 */
2344 } else if (com->state & CS_RTS_IFLOW) {
2345 com->state &= ~CS_RTS_IFLOW;
2346 /*
2347 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS
2348 * on here, since comstart() won't do it later.
2349 */
2350 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2351 if (com->st16650a) {
2352 sio_setreg(com, com_cfcr, 0xbf);
2353 sio_setreg(com, com_fifo,
2354 sio_getreg(com, com_fifo) & ~0x40);
2355 }
2356 }
2357
2358
2359 /*
2360 * Set up state to handle output flow control.
2361 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2362 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2363 */
2364 com->state |= CS_ODEVREADY;
2365 com->state &= ~CS_CTS_OFLOW;
2366 if (cflag & CCTS_OFLOW) {
2367 com->state |= CS_CTS_OFLOW;
2368 if (!(com->last_modem_status & MSR_CTS))
2369 com->state &= ~CS_ODEVREADY;
2370 if (com->st16650a) {
2371 sio_setreg(com, com_cfcr, 0xbf);
2372 sio_setreg(com, com_fifo,
2373 sio_getreg(com, com_fifo) | 0x80);
2374 }
2375 } else {
2376 if (com->st16650a) {
2377 sio_setreg(com, com_cfcr, 0xbf);
2378 sio_setreg(com, com_fifo,
2379 sio_getreg(com, com_fifo) & ~0x80);
2380 }
2381 }
2382
2383 sio_setreg(com, com_cfcr, com->cfcr_image);
2384
2385 /* XXX shouldn't call functions while intrs are disabled. */
2386 disc_optim(tp, t, com);
2387 /*
2388 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2389 * unconditionally, but that defeated the careful discarding of
2390 * stale input in sioopen().
2391 */
2392 if (com->state >= (CS_BUSY | CS_TTGO))
2393 siointr1(com);
2394
2395 mtx_unlock_spin(&sio_lock);
2396 splx(s);
2397 comstart(tp);
2398 if (com->ibufold != NULL) {
2399 free(com->ibufold, M_DEVBUF);
2400 com->ibufold = NULL;
2401 }
2402 return (0);
2403}
2404
2405/*
2406 * This function must be called with the sio_lock mutex released and will
2407 * return with it obtained.
2408 */
2409static int
2410siosetwater(com, speed)
2411 struct com_s *com;
2412 speed_t speed;
2413{
2414 int cp4ticks;
2415 u_char *ibuf;
2416 int ibufsize;
2417 struct tty *tp;
2418
2419 /*
2420 * Make the buffer size large enough to handle a softtty interrupt
2421 * latency of about 2 ticks without loss of throughput or data
2422 * (about 3 ticks if input flow control is not used or not honoured,
2423 * but a bit less for CS5-CS7 modes).
2424 */
2425 cp4ticks = speed / 10 / hz * 4;
2426 for (ibufsize = 128; ibufsize < cp4ticks;)
2427 ibufsize <<= 1;
2428 if (ibufsize == com->ibufsize) {
2429 mtx_lock_spin(&sio_lock);
2430 return (0);
2431 }
2432
2433 /*
2434 * Allocate input buffer. The extra factor of 2 in the size is
2435 * to allow for an error byte for each input byte.
2436 */
2437 ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
2438 if (ibuf == NULL) {
2439 mtx_lock_spin(&sio_lock);
2440 return (ENOMEM);
2441 }
2442
2443 /* Initialize non-critical variables. */
2444 com->ibufold = com->ibuf;
2445 com->ibufsize = ibufsize;
2446 tp = com->tp;
2447 if (tp != NULL) {
2448 tp->t_ififosize = 2 * ibufsize;
2449 tp->t_ispeedwat = (speed_t)-1;
2450 tp->t_ospeedwat = (speed_t)-1;
2451 }
2452
2453 /*
2454 * Read current input buffer, if any. Continue with interrupts
2455 * disabled.
2456 */
2457 mtx_lock_spin(&sio_lock);
2458 if (com->iptr != com->ibuf)
2459 sioinput(com);
2460
2461 /*-
2462 * Initialize critical variables, including input buffer watermarks.
2463 * The external device is asked to stop sending when the buffer
2464 * exactly reaches high water, or when the high level requests it.
2465 * The high level is notified immediately (rather than at a later
2466 * clock tick) when this watermark is reached.
2467 * The buffer size is chosen so the watermark should almost never
2468 * be reached.
2469 * The low watermark is invisibly 0 since the buffer is always
2470 * emptied all at once.
2471 */
2472 com->iptr = com->ibuf = ibuf;
2473 com->ibufend = ibuf + ibufsize;
2474 com->ierroff = ibufsize;
2475 com->ihighwater = ibuf + 3 * ibufsize / 4;
2476 return (0);
2477}
2478
2479static void
2480comstart(tp)
2481 struct tty *tp;
2482{
2483 struct com_s *com;
2484 int s;
2485 int unit;
2486
2487 unit = DEV_TO_UNIT(tp->t_dev);
2488 com = com_addr(unit);
2489 if (com == NULL)
2490 return;
2491 s = spltty();
2492 mtx_lock_spin(&sio_lock);
2493 if (tp->t_state & TS_TTSTOP)
2494 com->state &= ~CS_TTGO;
2495 else
2496 com->state |= CS_TTGO;
2497 if (tp->t_state & TS_TBLOCK) {
2498 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2499 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2500 } else {
2501 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2502 && com->state & CS_RTS_IFLOW)
2503 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2504 }
2505 mtx_unlock_spin(&sio_lock);
2506 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2507 ttwwakeup(tp);
2508 splx(s);
2509 return;
2510 }
2511 if (tp->t_outq.c_cc != 0) {
2512 struct lbq *qp;
2513 struct lbq *next;
2514
2515 if (!com->obufs[0].l_queued) {
2516 com->obufs[0].l_tail
2517 = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
2518 sizeof com->obuf1);
2519 com->obufs[0].l_next = NULL;
2520 com->obufs[0].l_queued = TRUE;
2521 mtx_lock_spin(&sio_lock);
2522 if (com->state & CS_BUSY) {
2523 qp = com->obufq.l_next;
2524 while ((next = qp->l_next) != NULL)
2525 qp = next;
2526 qp->l_next = &com->obufs[0];
2527 } else {
2528 com->obufq.l_head = com->obufs[0].l_head;
2529 com->obufq.l_tail = com->obufs[0].l_tail;
2530 com->obufq.l_next = &com->obufs[0];
2531 com->state |= CS_BUSY;
2532 }
2533 mtx_unlock_spin(&sio_lock);
2534 }
2535 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2536 com->obufs[1].l_tail
2537 = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
2538 sizeof com->obuf2);
2539 com->obufs[1].l_next = NULL;
2540 com->obufs[1].l_queued = TRUE;
2541 mtx_lock_spin(&sio_lock);
2542 if (com->state & CS_BUSY) {
2543 qp = com->obufq.l_next;
2544 while ((next = qp->l_next) != NULL)
2545 qp = next;
2546 qp->l_next = &com->obufs[1];
2547 } else {
2548 com->obufq.l_head = com->obufs[1].l_head;
2549 com->obufq.l_tail = com->obufs[1].l_tail;
2550 com->obufq.l_next = &com->obufs[1];
2551 com->state |= CS_BUSY;
2552 }
2553 mtx_unlock_spin(&sio_lock);
2554 }
2555 tp->t_state |= TS_BUSY;
2556 }
2557 mtx_lock_spin(&sio_lock);
2558 if (com->state >= (CS_BUSY | CS_TTGO))
2559 siointr1(com); /* fake interrupt to start output */
2560 mtx_unlock_spin(&sio_lock);
2561 ttwwakeup(tp);
2562 splx(s);
2563}
2564
2565static void
2566comstop(tp, rw)
2567 struct tty *tp;
2568 int rw;
2569{
2570 struct com_s *com;
2571
2572 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2573 if (com == NULL || com->gone)
2574 return;
2575 mtx_lock_spin(&sio_lock);
2576 if (rw & FWRITE) {
2577 if (com->hasfifo)
2578#ifdef COM_ESP
2579 /* XXX avoid h/w bug. */
2580 if (!com->esp)
2581#endif
2582 sio_setreg(com, com_fifo,
2583 FIFO_XMT_RST | com->fifo_image);
2584 com->obufs[0].l_queued = FALSE;
2585 com->obufs[1].l_queued = FALSE;
2586 if (com->state & CS_ODONE)
2587 com_events -= LOTS_OF_EVENTS;
2588 com->state &= ~(CS_ODONE | CS_BUSY);
2589 com->tp->t_state &= ~TS_BUSY;
2590 }
2591 if (rw & FREAD) {
2592 if (com->hasfifo)
2593#ifdef COM_ESP
2594 /* XXX avoid h/w bug. */
2595 if (!com->esp)
2596#endif
2597 sio_setreg(com, com_fifo,
2598 FIFO_RCV_RST | com->fifo_image);
2599 com_events -= (com->iptr - com->ibuf);
2600 com->iptr = com->ibuf;
2601 }
2602 mtx_unlock_spin(&sio_lock);
2603 comstart(tp);
2604}
2605
2606static int
2607commctl(com, bits, how)
2608 struct com_s *com;
2609 int bits;
2610 int how;
2611{
2612 int mcr;
2613 int msr;
2614
2615 if (how == DMGET) {
2616 bits = TIOCM_LE; /* XXX - always enabled while open */
2617 mcr = com->mcr_image;
2618 if (mcr & MCR_DTR)
2619 bits |= TIOCM_DTR;
2620 if (mcr & MCR_RTS)
2621 bits |= TIOCM_RTS;
2622 msr = com->prev_modem_status;
2623 if (msr & MSR_CTS)
2624 bits |= TIOCM_CTS;
2625 if (msr & MSR_DCD)
2626 bits |= TIOCM_CD;
2627 if (msr & MSR_DSR)
2628 bits |= TIOCM_DSR;
2629 /*
2630 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
2631 * more volatile by reading the modem status a lot. Perhaps
2632 * we should latch both bits until the status is read here.
2633 */
2634 if (msr & (MSR_RI | MSR_TERI))
2635 bits |= TIOCM_RI;
2636 return (bits);
2637 }
2638 mcr = 0;
2639 if (bits & TIOCM_DTR)
2640 mcr |= MCR_DTR;
2641 if (bits & TIOCM_RTS)
2642 mcr |= MCR_RTS;
2643 if (com->gone)
2644 return(0);
2645 mtx_lock_spin(&sio_lock);
2646 switch (how) {
2647 case DMSET:
2648 outb(com->modem_ctl_port,
2649 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2650 break;
2651 case DMBIS:
2652 outb(com->modem_ctl_port, com->mcr_image |= mcr);
2653 break;
2654 case DMBIC:
2655 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2656 break;
2657 }
2658 mtx_unlock_spin(&sio_lock);
2659 return (0);
2660}
2661
2662static void
2663siosettimeout()
2664{
2665 struct com_s *com;
2666 bool_t someopen;
2667 int unit;
2668
2669 /*
2670 * Set our timeout period to 1 second if no polled devices are open.
2671 * Otherwise set it to max(1/200, 1/hz).
2672 * Enable timeouts iff some device is open.
2673 */
2674 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2675 sio_timeout = hz;
2676 someopen = FALSE;
2677 for (unit = 0; unit < sio_numunits; ++unit) {
2678 com = com_addr(unit);
2679 if (com != NULL && com->tp != NULL
2680 && com->tp->t_state & TS_ISOPEN && !com->gone) {
2681 someopen = TRUE;
2682 if (com->poll || com->poll_output) {
2683 sio_timeout = hz > 200 ? hz / 200 : 1;
2684 break;
2685 }
2686 }
2687 }
2688 if (someopen) {
2689 sio_timeouts_until_log = hz / sio_timeout;
2690 sio_timeout_handle = timeout(comwakeup, (void *)NULL,
2691 sio_timeout);
2692 } else {
2693 /* Flush error messages, if any. */
2694 sio_timeouts_until_log = 1;
2695 comwakeup((void *)NULL);
2696 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
2697 }
2698}
2699
2700static void
2701comwakeup(chan)
2702 void *chan;
2703{
2704 struct com_s *com;
2705 int unit;
2706
2707 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
2708
2709 /*
2710 * Recover from lost output interrupts.
2711 * Poll any lines that don't use interrupts.
2712 */
2713 for (unit = 0; unit < sio_numunits; ++unit) {
2714 com = com_addr(unit);
2715 if (com != NULL && !com->gone
2716 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2717 mtx_lock_spin(&sio_lock);
2718 siointr1(com);
2719 mtx_unlock_spin(&sio_lock);
2720 }
2721 }
2722
2723 /*
2724 * Check for and log errors, but not too often.
2725 */
2726 if (--sio_timeouts_until_log > 0)
2727 return;
2728 sio_timeouts_until_log = hz / sio_timeout;
2729 for (unit = 0; unit < sio_numunits; ++unit) {
2730 int errnum;
2731
2732 com = com_addr(unit);
2733 if (com == NULL)
2734 continue;
2735 if (com->gone)
2736 continue;
2737 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2738 u_int delta;
2739 u_long total;
2740
2741 mtx_lock_spin(&sio_lock);
2742 delta = com->delta_error_counts[errnum];
2743 com->delta_error_counts[errnum] = 0;
2744 mtx_unlock_spin(&sio_lock);
2745 if (delta == 0)
2746 continue;
2747 total = com->error_counts[errnum] += delta;
2748 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2749 unit, delta, error_desc[errnum],
2750 delta == 1 ? "" : "s", total);
2751 }
2752 }
2753}
2754
2755static void
2756disc_optim(tp, t, com)
2757 struct tty *tp;
2758 struct termios *t;
2759 struct com_s *com;
2760{
2761 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2762 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2763 && (!(t->c_iflag & PARMRK)
2764 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2765 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2766 && linesw[tp->t_line].l_rint == ttyinput)
2767 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2768 else
2769 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2770 com->hotchar = linesw[tp->t_line].l_hotchar;
2771}
2772
2773/*
2774 * Following are all routines needed for SIO to act as console
2775 */
2776#include <sys/cons.h>
2777
2778struct siocnstate {
2779 u_char dlbl;
2780 u_char dlbh;
2781 u_char ier;
2782 u_char cfcr;
2783 u_char mcr;
2784};
2785
2786#ifndef __alpha__
2787static speed_t siocngetspeed(Port_t, u_long rclk);
2788#endif
2789static void siocnclose(struct siocnstate *sp, Port_t iobase);
2790static void siocnopen(struct siocnstate *sp, Port_t iobase, int speed);
2791static void siocntxwait(Port_t iobase);
2792
2793#ifdef __alpha__
2794int siocnattach(int port, int speed);
2795int siogdbattach(int port, int speed);
2796int siogdbgetc(void);
2797void siogdbputc(int c);
2798#else
2799static cn_probe_t siocnprobe;
2800static cn_init_t siocninit;
2801static cn_term_t siocnterm;
2802#endif
2803static cn_checkc_t siocncheckc;
2804static cn_getc_t siocngetc;
2805static cn_putc_t siocnputc;
2806
2807#ifndef __alpha__
2808CONS_DRIVER(sio, siocnprobe, siocninit, siocnterm, siocngetc, siocncheckc,
2809 siocnputc, NULL);
2810#endif
2811
2812/* To get the GDB related variables */
2813#if DDB > 0
2814#include <ddb/ddb.h>
2815static struct consdev gdbconsdev;
2816
2817#endif
2818
2819static void
2820siocntxwait(iobase)
2821 Port_t iobase;
2822{
2823 int timo;
2824
2825 /*
2826 * Wait for any pending transmission to finish. Required to avoid
2827 * the UART lockup bug when the speed is changed, and for normal
2828 * transmits.
2829 */
2830 timo = 100000;
2831 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
2832 != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
2833 ;
2834}
2835
2836#ifndef __alpha__
2837
2838/*
2839 * Read the serial port specified and try to figure out what speed
2840 * it's currently running at. We're assuming the serial port has
2841 * been initialized and is basicly idle. This routine is only intended
2842 * to be run at system startup.
2843 *
2844 * If the value read from the serial port doesn't make sense, return 0.
2845 */
2846
2847static speed_t
2848siocngetspeed(iobase, rclk)
2849 Port_t iobase;
2850 u_long rclk;
2851{
2852 u_int divisor;
2853 u_char dlbh;
2854 u_char dlbl;
2855 u_char cfcr;
2856
2857 cfcr = inb(iobase + com_cfcr);
2858 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
2859
2860 dlbl = inb(iobase + com_dlbl);
2861 dlbh = inb(iobase + com_dlbh);
2862
2863 outb(iobase + com_cfcr, cfcr);
2864
2865 divisor = dlbh << 8 | dlbl;
2866
2867 /* XXX there should be more sanity checking. */
2868 if (divisor == 0)
2869 return (CONSPEED);
2870 return (rclk / (16UL * divisor));
2871}
2872
2873#endif
2874
2875static void
2876siocnopen(sp, iobase, speed)
2877 struct siocnstate *sp;
2878 Port_t iobase;
2879 int speed;
2880{
2881 u_int divisor;
2882 u_char dlbh;
2883 u_char dlbl;
2884
2885 /*
2886 * Save all the device control registers except the fifo register
2887 * and set our default ones (cs8 -parenb speed=comdefaultrate).
2888 * We can't save the fifo register since it is read-only.
2889 */
2890 sp->ier = inb(iobase + com_ier);
2891 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */
2892 siocntxwait(iobase);
2893 sp->cfcr = inb(iobase + com_cfcr);
2894 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2895 sp->dlbl = inb(iobase + com_dlbl);
2896 sp->dlbh = inb(iobase + com_dlbh);
2897 /*
2898 * Only set the divisor registers if they would change, since on
2899 * some 16550 incompatibles (Startech), setting them clears the
2900 * data input register. This also reduces the effects of the
2901 * UMC8669F bug.
2902 */
2903 divisor = siodivisor(comdefaultrclk, speed);
2904 dlbl = divisor & 0xFF;
2905 if (sp->dlbl != dlbl)
2906 outb(iobase + com_dlbl, dlbl);
2907 dlbh = divisor >> 8;
2908 if (sp->dlbh != dlbh)
2909 outb(iobase + com_dlbh, dlbh);
2910 outb(iobase + com_cfcr, CFCR_8BITS);
2911 sp->mcr = inb(iobase + com_mcr);
2912 /*
2913 * We don't want interrupts, but must be careful not to "disable"
2914 * them by clearing the MCR_IENABLE bit, since that might cause
2915 * an interrupt by floating the IRQ line.
2916 */
2917 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
2918}
2919
2920static void
2921siocnclose(sp, iobase)
2922 struct siocnstate *sp;
2923 Port_t iobase;
2924{
2925 /*
2926 * Restore the device control registers.
2927 */
2928 siocntxwait(iobase);
2929 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2930 if (sp->dlbl != inb(iobase + com_dlbl))
2931 outb(iobase + com_dlbl, sp->dlbl);
2932 if (sp->dlbh != inb(iobase + com_dlbh))
2933 outb(iobase + com_dlbh, sp->dlbh);
2934 outb(iobase + com_cfcr, sp->cfcr);
2935 /*
2936 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
2937 */
2938 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
2939 outb(iobase + com_ier, sp->ier);
2940}
2941
2942#ifndef __alpha__
2943
2944static void
2945siocnprobe(cp)
2946 struct consdev *cp;
2947{
2948 speed_t boot_speed;
2949 u_char cfcr;
2950 u_int divisor;
2951 int s, unit;
2952 struct siocnstate sp;
2953
2954 /*
2955 * Find our first enabled console, if any. If it is a high-level
2956 * console device, then initialize it and return successfully.
2957 * If it is a low-level console device, then initialize it and
2958 * return unsuccessfully. It must be initialized in both cases
2959 * for early use by console drivers and debuggers. Initializing
2960 * the hardware is not necessary in all cases, since the i/o
2961 * routines initialize it on the fly, but it is necessary if
2962 * input might arrive while the hardware is switched back to an
2963 * uninitialized state. We can't handle multiple console devices
2964 * yet because our low-level routines don't take a device arg.
2965 * We trust the user to set the console flags properly so that we
2966 * don't need to probe.
2967 */
2968 cp->cn_pri = CN_DEAD;
2969
2970 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
2971 int flags;
2972
2973 if (resource_disabled("sio", unit))
2974 continue;
2975 if (resource_int_value("sio", unit, "flags", &flags))
2976 continue;
2977 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
2978 int port;
2979 Port_t iobase;
2980
2981 if (resource_int_value("sio", unit, "port", &port))
2982 continue;
2983 iobase = port;
2984 s = spltty();
2985 if (boothowto & RB_SERIAL) {
2986 boot_speed =
2987 siocngetspeed(iobase, comdefaultrclk);
2988 if (boot_speed)
2989 comdefaultrate = boot_speed;
2990 }
2991
2992 /*
2993 * Initialize the divisor latch. We can't rely on
2994 * siocnopen() to do this the first time, since it
2995 * avoids writing to the latch if the latch appears
2996 * to have the correct value. Also, if we didn't
2997 * just read the speed from the hardware, then we
2998 * need to set the speed in hardware so that
2999 * switching it later is null.
3000 */
3001 cfcr = inb(iobase + com_cfcr);
3002 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3003 divisor = siodivisor(comdefaultrclk, comdefaultrate);
3004 outb(iobase + com_dlbl, divisor & 0xff);
3005 outb(iobase + com_dlbh, divisor >> 8);
3006 outb(iobase + com_cfcr, cfcr);
3007
3008 siocnopen(&sp, iobase, comdefaultrate);
3009
3010 splx(s);
3011 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
3012 cp->cn_dev = makedev(CDEV_MAJOR, unit);
3013 cp->cn_pri = COM_FORCECONSOLE(flags)
3014 || boothowto & RB_SERIAL
3015 ? CN_REMOTE : CN_NORMAL;
3016 siocniobase = iobase;
3017 siocnunit = unit;
3018 }
3019 if (COM_DEBUGGER(flags)) {
3020 printf("sio%d: gdb debugging port\n", unit);
3021 siogdbiobase = iobase;
3022 siogdbunit = unit;
3023#if DDB > 0
3024 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, unit);
3025 gdb_arg = &gdbconsdev;
3026 gdb_getc = siocngetc;
3027 gdb_putc = siocnputc;
3028#endif
3029 }
3030 }
3031 }
3032#ifdef __i386__
3033#if DDB > 0
3034 /*
3035 * XXX Ugly Compatability.
3036 * If no gdb port has been specified, set it to be the console
3037 * as some configuration files don't specify the gdb port.
3038 */
3039 if (gdb_arg == NULL && (boothowto & RB_GDB)) {
3040 printf("Warning: no GDB port specified. Defaulting to sio%d.\n",
3041 siocnunit);
3042 printf("Set flag 0x80 on desired GDB port in your\n");
3043 printf("configuration file (currently sio only).\n");
3044 siogdbiobase = siocniobase;
3045 siogdbunit = siocnunit;
3046 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, siocnunit);
3047 gdb_arg = &gdbconsdev;
3048 gdb_getc = siocngetc;
3049 gdb_putc = siocnputc;
3050 }
3051#endif
3052#endif
3053}
3054
3055static void
3056siocninit(cp)
3057 struct consdev *cp;
3058{
3059 comconsole = DEV_TO_UNIT(cp->cn_dev);
3060}
3061
3062static void
3063siocnterm(cp)
3064 struct consdev *cp;
3065{
3066 comconsole = -1;
3067}
3068
3069#endif
3070
3071#ifdef __alpha__
3072
3073CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL);
3074
3075int
3076siocnattach(port, speed)
3077 int port;
3078 int speed;
3079{
3080 int s;
3081 u_char cfcr;
3082 u_int divisor;
3083 struct siocnstate sp;
3084 int unit = 0; /* XXX random value! */
3085
3086 siocniobase = port;
3087 siocnunit = unit;
3088 comdefaultrate = speed;
3089 sio_consdev.cn_pri = CN_NORMAL;
3090 sio_consdev.cn_dev = makedev(CDEV_MAJOR, unit);
3091
3092 s = spltty();
3093
3094 /*
3095 * Initialize the divisor latch. We can't rely on
3096 * siocnopen() to do this the first time, since it
3097 * avoids writing to the latch if the latch appears
3098 * to have the correct value. Also, if we didn't
3099 * just read the speed from the hardware, then we
3100 * need to set the speed in hardware so that
3101 * switching it later is null.
3102 */
3103 cfcr = inb(siocniobase + com_cfcr);
3104 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
3105 divisor = siodivisor(comdefaultrclk, comdefaultrate);
3106 outb(siocniobase + com_dlbl, divisor & 0xff);
3107 outb(siocniobase + com_dlbh, divisor >> 8);
3108 outb(siocniobase + com_cfcr, cfcr);
3109
3110 siocnopen(&sp, siocniobase, comdefaultrate);
3111 splx(s);
3112
3113 cnadd(&sio_consdev);
3114 return (0);
3115}
3116
3117int
3118siogdbattach(port, speed)
3119 int port;
3120 int speed;
3121{
3122 int s;
3123 u_char cfcr;
3124 u_int divisor;
3125 struct siocnstate sp;
3126 int unit = 1; /* XXX random value! */
3127
3128 siogdbiobase = port;
3129 gdbdefaultrate = speed;
3130
3131 printf("sio%d: gdb debugging port\n", unit);
3132 siogdbunit = unit;
3133#if DDB > 0
3134 gdbconsdev.cn_dev = makedev(CDEV_MAJOR, unit);
3135 gdb_arg = &gdbconsdev;
3136 gdb_getc = siocngetc;
3137 gdb_putc = siocnputc;
3138#endif
3139
3140 s = spltty();
3141
3142 /*
3143 * Initialize the divisor latch. We can't rely on
3144 * siocnopen() to do this the first time, since it
3145 * avoids writing to the latch if the latch appears
3146 * to have the correct value. Also, if we didn't
3147 * just read the speed from the hardware, then we
3148 * need to set the speed in hardware so that
3149 * switching it later is null.
3150 */
3151 cfcr = inb(siogdbiobase + com_cfcr);
3152 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr);
3153 divisor = siodivisor(comdefaultrclk, gdbdefaultrate);
3154 outb(siogdbiobase + com_dlbl, divisor & 0xff);
3155 outb(siogdbiobase + com_dlbh, divisor >> 8);
3156 outb(siogdbiobase + com_cfcr, cfcr);
3157
3158 siocnopen(&sp, siogdbiobase, gdbdefaultrate);
3159 splx(s);
3160
3161 return (0);
3162}
3163
3164#endif
3165
3166static int
3167siocncheckc(struct consdev *cd)
3168{
3169 int c;
3170 dev_t dev;
3171 Port_t iobase;
3172 int s;
3173 struct siocnstate sp;
3174 speed_t speed;
3175
3176 dev = cd->cn_dev;
3177 if (minor(dev) == siocnunit) {
3178 iobase = siocniobase;
3179 speed = comdefaultrate;
3180 } else {
3181 iobase = siogdbiobase;
3182 speed = gdbdefaultrate;
3183 }
3184 s = spltty();
3185 siocnopen(&sp, iobase, speed);
3186 if (inb(iobase + com_lsr) & LSR_RXRDY)
3187 c = inb(iobase + com_data);
3188 else
3189 c = -1;
3190 siocnclose(&sp, iobase);
3191 splx(s);
3192 return (c);
3193}
3194
3195
3196static int
3197siocngetc(struct consdev *cd)
3198{
3199 int c;
3200 dev_t dev;
3201 Port_t iobase;
3202 int s;
3203 struct siocnstate sp;
3204 speed_t speed;
3205
3206 dev = cd->cn_dev;
3207 if (minor(dev) == siocnunit) {
3208 iobase = siocniobase;
3209 speed = comdefaultrate;
3210 } else {
3211 iobase = siogdbiobase;
3212 speed = gdbdefaultrate;
3213 }
3214 s = spltty();
3215 siocnopen(&sp, iobase, speed);
3216 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3217 ;
3218 c = inb(iobase + com_data);
3219 siocnclose(&sp, iobase);
3220 splx(s);
3221 return (c);
3222}
3223
3224static void
3225siocnputc(struct consdev *cd, int c)
3226{
3227 int need_unlock;
3228 int s;
3229 dev_t dev;
3230 struct siocnstate sp;
3231 Port_t iobase;
3232 speed_t speed;
3233
3234 dev = cd->cn_dev;
3235 if (minor(dev) == siocnunit) {
3236 iobase = siocniobase;
3237 speed = comdefaultrate;
3238 } else {
3239 iobase = siogdbiobase;
3240 speed = gdbdefaultrate;
3241 }
3242 s = spltty();
3243 need_unlock = 0;
3244 if (sio_inited == 2 && !mtx_owned(&sio_lock)) {
3245 mtx_lock_spin(&sio_lock);
3246 need_unlock = 1;
3247 }
3248 siocnopen(&sp, iobase, speed);
3249 siocntxwait(iobase);
3250 outb(iobase + com_data, c);
3251 siocnclose(&sp, iobase);
3252 if (need_unlock)
3253 mtx_unlock_spin(&sio_lock);
3254 splx(s);
3255}
3256
3257#ifdef __alpha__
3258int
3259siogdbgetc()
3260{
3261 int c;
3262 Port_t iobase;
3263 speed_t speed;
3264 int s;
3265 struct siocnstate sp;
3266
3267 if (siogdbunit == siocnunit) {
3268 iobase = siocniobase;
3269 speed = comdefaultrate;
3270 } else {
3271 iobase = siogdbiobase;
3272 speed = gdbdefaultrate;
3273 }
3274
3275 s = spltty();
3276 siocnopen(&sp, iobase, speed);
3277 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3278 ;
3279 c = inb(iobase + com_data);
3280 siocnclose(&sp, iobase);
3281 splx(s);
3282 return (c);
3283}
3284
3285void
3286siogdbputc(c)
3287 int c;
3288{
3289 Port_t iobase;
3290 speed_t speed;
3291 int s;
3292 struct siocnstate sp;
3293
3294 if (siogdbunit == siocnunit) {
3295 iobase = siocniobase;
3296 speed = comdefaultrate;
3297 } else {
3298 iobase = siogdbiobase;
3299 speed = gdbdefaultrate;
3300 }
3301
3302 s = spltty();
3303 siocnopen(&sp, iobase, speed);
3304 siocntxwait(siogdbiobase);
3305 outb(siogdbiobase + com_data, c);
3306 siocnclose(&sp, siogdbiobase);
3307 splx(s);
3308}
3309#endif