]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/pc98/cbus/sio.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / pc98 / cbus / sio.c
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  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  *      from: @(#)com.c 7.5 (Berkeley) 5/16/91
31  *      from: i386/isa sio.c,v 1.234
32  */
33
34 #include "opt_comconsole.h"
35 #include "opt_compat.h"
36 #include "opt_gdb.h"
37 #include "opt_kdb.h"
38 #include "opt_sio.h"
39
40 /*
41  * Serial driver, based on 386BSD-0.1 com driver.
42  * Mostly rewritten to use pseudo-DMA.
43  * Works for National Semiconductor NS8250-NS16550AF UARTs.
44  * COM driver, based on HP dca driver.
45  *
46  * Changes for PC Card integration:
47  *      - Added PC Card driver table and handlers
48  */
49 /*===============================================================
50  * 386BSD(98),FreeBSD-1.1x(98) com driver.
51  * -----
52  * modified for PC9801 by M.Ishii 
53  *                      Kyoto University Microcomputer Club (KMC)
54  * Chou "TEFUTEFU" Hirotomi
55  *                      Kyoto Univ.  the faculty of medicine
56  *===============================================================
57  * FreeBSD-2.0.1(98) sio driver.
58  * -----
59  * modified for pc98 Internal i8251 and MICRO CORE MC16550II
60  *                      T.Koike(hfc01340@niftyserve.or.jp)
61  * implement kernel device configuration
62  *                      aizu@orient.center.nitech.ac.jp
63  *
64  * Notes.
65  * -----
66  *  PC98 localization based on 386BSD(98) com driver. Using its PC98 local
67  *  functions.
68  *  This driver is under debugging,has bugs.
69  */
70 /*
71  * modified for AIWA B98-01
72  * by T.Hatanou <hatanou@yasuda.comm.waseda.ac.jp>  last update: 15 Sep.1995 
73  */
74 /*
75  * Modified by Y.Takahashi of Kogakuin University.
76  */
77 /*
78  * modified for 8251(FIFO) by Seigo TANIMURA <tanimura@FreeBSD.org>
79  */
80
81 #include <sys/param.h>
82 #include <sys/systm.h>
83 #include <sys/bus.h>
84 #include <sys/conf.h>
85 #include <sys/fcntl.h>
86 #include <sys/interrupt.h>
87 #include <sys/kdb.h>
88 #include <sys/kernel.h>
89 #include <sys/limits.h>
90 #include <sys/lock.h>
91 #include <sys/malloc.h>
92 #include <sys/module.h>
93 #include <sys/mutex.h>
94 #include <sys/proc.h>
95 #include <sys/reboot.h>
96 #include <sys/serial.h>
97 #include <sys/sysctl.h>
98 #include <sys/syslog.h>
99 #include <sys/tty.h>
100 #include <machine/bus.h>
101 #include <sys/rman.h>
102 #include <sys/timepps.h>
103 #include <sys/uio.h>
104 #include <sys/cons.h>
105
106 #include <isa/isavar.h>
107
108 #include <machine/resource.h>
109
110 #include <dev/sio/sioreg.h>
111 #include <dev/sio/siovar.h>
112
113 #ifdef PC98
114 #include <pc98/cbus/cbus.h>
115 #include <pc98/pc98/pc98_machdep.h>
116 #endif
117
118 #ifdef COM_ESP
119 #include <dev/ic/esp.h>
120 #endif
121 #include <dev/ic/ns16550.h>
122 #ifdef PC98
123 #include <dev/ic/i8251.h>
124 #include <dev/ic/i8255.h>
125 #include <dev/ic/rsa.h>
126 #endif
127
128 #define LOTS_OF_EVENTS  64      /* helps separate urgent events from input */
129
130 /*
131  * Meaning of flags:
132  *
133  * 0x00000001   shared IRQs
134  * 0x00000002   disable FIFO
135  * 0x00000008   recover sooner from lost output interrupts
136  * 0x00000010   device is potential system console
137  * 0x00000020   device is forced to become system console
138  * 0x00000040   device is reserved for low-level IO
139  * 0x00000080   use this port for remote kernel debugging
140  * 0x0000??00   minor number of master port
141  * 0x00010000   PPS timestamping on CTS instead of DCD
142  * 0x00080000   IIR_TXRDY bug
143  * 0x00400000   If no comconsole found then mark as a comconsole
144  * 0x1?000000   interface type
145  */
146
147 #ifdef COM_MULTIPORT
148 /* checks in flags for multiport and which is multiport "master chip"
149  * for a given card
150  */
151 #define COM_ISMULTIPORT(flags)  ((flags) & 0x01)
152 #define COM_MPMASTER(flags)     (((flags) >> 8) & 0x0ff)
153 #ifndef PC98
154 #define COM_NOTAST4(flags)      ((flags) & 0x04)
155 #endif
156 #else
157 #define COM_ISMULTIPORT(flags)  (0)
158 #endif /* COM_MULTIPORT */
159
160 #define COM_C_IIR_TXRDYBUG      0x80000
161 #define COM_CONSOLE(flags)      ((flags) & 0x10)
162 #define COM_DEBUGGER(flags)     ((flags) & 0x80)
163 #ifndef PC98
164 #define COM_FIFOSIZE(flags)     (((flags) & 0xff000000) >> 24)
165 #endif
166 #define COM_FORCECONSOLE(flags) ((flags) & 0x20)
167 #define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
168 #define COM_LLCONSOLE(flags)    ((flags) & 0x40)
169 #define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
170 #define COM_NOFIFO(flags)       ((flags) & 0x02)
171 #ifndef PC98
172 #define COM_NOSCR(flags)        ((flags) & 0x100000)
173 #endif
174 #define COM_PPSCTS(flags)       ((flags) & 0x10000)
175 #ifndef PC98
176 #define COM_ST16650A(flags)     ((flags) & 0x20000)
177 #define COM_TI16754(flags)      ((flags) & 0x200000)
178 #endif
179
180 #define sio_getreg(com, off) \
181         (bus_space_read_1((com)->bst, (com)->bsh, (off)))
182 #define sio_setreg(com, off, value) \
183         (bus_space_write_1((com)->bst, (com)->bsh, (off), (value)))
184
185 /*
186  * com state bits.
187  * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
188  * than the other bits so that they can be tested as a group without masking
189  * off the low bits.
190  *
191  * The following com and tty flags correspond closely:
192  *      CS_BUSY         = TS_BUSY (maintained by comstart(), siopoll() and
193  *                                 comstop())
194  *      CS_TTGO         = ~TS_TTSTOP (maintained by comparam() and comstart())
195  *      CS_CTS_OFLOW    = CCTS_OFLOW (maintained by comparam())
196  *      CS_RTS_IFLOW    = CRTS_IFLOW (maintained by comparam())
197  * TS_FLUSH is not used.
198  * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
199  * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
200  */
201 #define CS_BUSY         0x80    /* output in progress */
202 #define CS_TTGO         0x40    /* output not stopped by XOFF */
203 #define CS_ODEVREADY    0x20    /* external device h/w ready (CTS) */
204 #define CS_CHECKMSR     1       /* check of MSR scheduled */
205 #define CS_CTS_OFLOW    2       /* use CTS output flow control */
206 #define CS_ODONE        4       /* output completed */
207 #define CS_RTS_IFLOW    8       /* use RTS input flow control */
208 #define CSE_BUSYCHECK   1       /* siobusycheck() scheduled */
209
210 static  char const * const      error_desc[] = {
211 #define CE_OVERRUN                      0
212         "silo overflow",
213 #define CE_INTERRUPT_BUF_OVERFLOW       1
214         "interrupt-level buffer overflow",
215 #define CE_TTY_BUF_OVERFLOW             2
216         "tty-level buffer overflow",
217 };
218
219 #define CE_NTYPES                       3
220 #define CE_RECORD(com, errnum)          (++(com)->delta_error_counts[errnum])
221
222 /* types.  XXX - should be elsewhere */
223 typedef u_int   Port_t;         /* hardware port */
224 typedef u_char  bool_t;         /* boolean */
225
226 /* queue of linear buffers */
227 struct lbq {
228         u_char  *l_head;        /* next char to process */
229         u_char  *l_tail;        /* one past the last char to process */
230         struct lbq *l_next;     /* next in queue */
231         bool_t  l_queued;       /* nonzero if queued */
232 };
233
234 /* com device structure */
235 struct com_s {
236         u_char  state;          /* miscellaneous flag bits */
237         u_char  cfcr_image;     /* copy of value written to CFCR */
238 #ifdef COM_ESP
239         bool_t  esp;            /* is this unit a hayes esp board? */
240 #endif
241         u_char  extra_state;    /* more flag bits, separate for order trick */
242         u_char  fifo_image;     /* copy of value written to FIFO */
243         bool_t  hasfifo;        /* nonzero for 16550 UARTs */
244         bool_t  loses_outints;  /* nonzero if device loses output interrupts */
245         u_char  mcr_image;      /* copy of value written to MCR */
246 #ifdef COM_MULTIPORT
247         bool_t  multiport;      /* is this unit part of a multiport device? */
248 #endif /* COM_MULTIPORT */
249         bool_t  no_irq;         /* nonzero if irq is not attached */
250         bool_t  gone;           /* hardware disappeared */
251         bool_t  poll;           /* nonzero if polling is required */
252         bool_t  poll_output;    /* nonzero if polling for output is required */
253         bool_t  st16650a;       /* nonzero if Startech 16650A compatible */
254         int     unit;           /* unit number */
255         u_int   flags;          /* copy of device flags */
256         u_int   tx_fifo_size;
257
258         /*
259          * The high level of the driver never reads status registers directly
260          * because there would be too many side effects to handle conveniently.
261          * Instead, it reads copies of the registers stored here by the
262          * interrupt handler.
263          */
264         u_char  last_modem_status;      /* last MSR read by intr handler */
265         u_char  prev_modem_status;      /* last MSR handled by high level */
266
267         u_char  *ibuf;          /* start of input buffer */
268         u_char  *ibufend;       /* end of input buffer */
269         u_char  *ibufold;       /* old input buffer, to be freed */
270         u_char  *ihighwater;    /* threshold in input buffer */
271         u_char  *iptr;          /* next free spot in input buffer */
272         int     ibufsize;       /* size of ibuf (not include error bytes) */
273         int     ierroff;        /* offset of error bytes in ibuf */
274
275         struct lbq      obufq;  /* head of queue of output buffers */
276         struct lbq      obufs[2];       /* output buffers */
277
278         bus_space_tag_t         bst;
279         bus_space_handle_t      bsh;
280
281 #ifdef PC98
282         Port_t  cmd_port;
283         Port_t  sts_port;
284         Port_t  in_modem_port;
285         Port_t  intr_ctrl_port;
286         Port_t  rsabase;        /* Iobase address of an I/O-DATA RSA board. */
287         int     intr_enable;
288         int     pc98_prev_modem_status;
289         int     pc98_modem_delta;
290         int     modem_car_chg_timer;
291         int     pc98_prev_siocmd;
292         int     pc98_prev_siomod;
293         int     modem_checking;
294         int     pc98_if_type;
295
296         bool_t  pc98_8251fifo;
297         bool_t  pc98_8251fifo_enable;
298 #endif /* PC98 */
299         Port_t  data_port;      /* i/o ports */
300 #ifdef COM_ESP
301         Port_t  esp_port;
302 #endif
303         Port_t  int_ctl_port;
304         Port_t  int_id_port;
305         Port_t  modem_ctl_port;
306         Port_t  line_status_port;
307         Port_t  modem_status_port;
308
309         struct tty      *tp;    /* cross reference */
310
311         struct  pps_state pps;
312         int     pps_bit;
313 #ifdef ALT_BREAK_TO_DEBUGGER
314         int     alt_brk_state;
315 #endif
316
317         u_long  bytes_in;       /* statistics */
318         u_long  bytes_out;
319         u_int   delta_error_counts[CE_NTYPES];
320         u_long  error_counts[CE_NTYPES];
321
322         u_long  rclk;
323
324         struct resource *irqres;
325         struct resource *ioportres;
326         int     ioportrid;
327         void    *cookie;
328
329         /*
330          * Data area for output buffers.  Someday we should build the output
331          * buffer queue without copying data.
332          */
333 #ifdef PC98
334         int     obufsize;
335         u_char  *obuf1;
336         u_char  *obuf2;
337 #else
338         u_char  obuf1[256];
339         u_char  obuf2[256];
340 #endif
341 };
342
343 #ifdef COM_ESP
344 static  int     espattach(struct com_s *com, Port_t esp_port);
345 #endif
346
347 static  void    combreak(struct tty *tp, int sig);
348 static  timeout_t siobusycheck;
349 static  u_int   siodivisor(u_long rclk, speed_t speed);
350 static  void    comclose(struct tty *tp);
351 static  int     comopen(struct tty *tp, struct cdev *dev);
352 static  void    sioinput(struct com_s *com);
353 static  void    siointr1(struct com_s *com);
354 static  int     siointr(void *arg);
355 static  int     commodem(struct tty *tp, int sigon, int sigoff);
356 static  int     comparam(struct tty *tp, struct termios *t);
357 static  void    siopoll(void *);
358 static  void    siosettimeout(void);
359 static  int     siosetwater(struct com_s *com, speed_t speed);
360 static  void    comstart(struct tty *tp);
361 static  void    comstop(struct tty *tp, int rw);
362 static  timeout_t comwakeup;
363
364 char            sio_driver_name[] = "sio";
365 static struct   mtx sio_lock;
366 static int      sio_inited;
367
368 /* table and macro for fast conversion from a unit number to its com struct */
369 devclass_t      sio_devclass;
370 #define com_addr(unit)  ((struct com_s *) \
371                          devclass_get_softc(sio_devclass, unit)) /* XXX */
372
373 int     comconsole = -1;
374 static  volatile speed_t        comdefaultrate = CONSPEED;
375 static  u_long                  comdefaultrclk = DEFAULT_RCLK;
376 SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, "");
377 static  speed_t                 gdbdefaultrate = GDBSPEED;
378 SYSCTL_UINT(_machdep, OID_AUTO, gdbspeed, CTLFLAG_RW,
379             &gdbdefaultrate, GDBSPEED, "");
380 static  u_int   com_events;     /* input chars + weighted output completions */
381 static  Port_t  siocniobase;
382 static  int     siocnunit = -1;
383 static  void    *sio_slow_ih;
384 static  void    *sio_fast_ih;
385 static  int     sio_timeout;
386 static  int     sio_timeouts_until_log;
387 static  struct  callout_handle sio_timeout_handle
388     = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
389 static  int     sio_numunits;
390
391 #ifdef PC98
392 struct  siodev  {
393         short   if_type;
394         short   irq;
395         Port_t  cmd, sts, ctrl, mod;
396 };
397 static  int     sysclock;
398
399 #define COM_INT_DISABLE         {int previpri; previpri=spltty();
400 #define COM_INT_ENABLE          splx(previpri);}
401 #define IEN_TxFLAG              IEN_Tx
402
403 #define COM_CARRIER_DETECT_EMULATE      0
404 #define PC98_CHECK_MODEM_INTERVAL       (hz/10)
405 #define DCD_OFF_TOLERANCE               2
406 #define DCD_ON_RECOGNITION              2
407 #define IS_8251(if_type)                (!(if_type & 0x10))
408 #define COM1_EXT_CLOCK                  0x40000
409
410 static  void    commint(struct cdev *dev);
411 static  void    com_tiocm_bis(struct com_s *com, int msr);
412 static  void    com_tiocm_bic(struct com_s *com, int msr);
413 static  int     com_tiocm_get(struct com_s *com);
414 static  int     com_tiocm_get_delta(struct com_s *com);
415 static  void    pc98_msrint_start(struct cdev *dev);
416 static  void    com_cflag_and_speed_set(struct com_s *com, int cflag, int speed);
417 static  int     pc98_ttspeedtab(struct com_s *com, int speed, u_int *divisor);
418 static  int     pc98_get_modem_status(struct com_s *com);
419 static  timeout_t       pc98_check_msr;
420 static  void    pc98_set_baud_rate(struct com_s *com, u_int count);
421 static  void    pc98_i8251_reset(struct com_s *com, int mode, int command);
422 static  void    pc98_disable_i8251_interrupt(struct com_s *com, int mod);
423 static  void    pc98_enable_i8251_interrupt(struct com_s *com, int mod);
424 static  int     pc98_check_i8251_interrupt(struct com_s *com);
425 static  int     pc98_i8251_get_cmd(struct com_s *com);
426 static  int     pc98_i8251_get_mod(struct com_s *com);
427 static  void    pc98_i8251_set_cmd(struct com_s *com, int x);
428 static  void    pc98_i8251_or_cmd(struct com_s *com, int x);
429 static  void    pc98_i8251_clear_cmd(struct com_s *com, int x);
430 static  void    pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x);
431 static  int     pc98_check_if_type(device_t dev, struct siodev *iod);
432 static  int     pc98_check_8251vfast(void);
433 static  int     pc98_check_8251fifo(void);
434 static  void    pc98_check_sysclock(void);
435 static  void    pc98_set_ioport(struct com_s *com);
436
437 #define com_int_Tx_disable(com) \
438                 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP)
439 #define com_int_Tx_enable(com) \
440                 pc98_enable_i8251_interrupt(com,IEN_TxFLAG)
441 #define com_int_Rx_disable(com) \
442                 pc98_disable_i8251_interrupt(com,IEN_Rx)
443 #define com_int_Rx_enable(com) \
444                 pc98_enable_i8251_interrupt(com,IEN_Rx)
445 #define com_int_TxRx_disable(com) \
446                 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx)
447 #define com_int_TxRx_enable(com) \
448                 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx)
449 #define com_send_break_on(com) \
450                 (IS_8251((com)->pc98_if_type) ? \
451                  pc98_i8251_or_cmd((com), CMD8251_SBRK) : \
452                  sio_setreg((com), com_cfcr, (com)->cfcr_image |= CFCR_SBREAK))
453 #define com_send_break_off(com) \
454                 (IS_8251((com)->pc98_if_type) ? \
455                  pc98_i8251_clear_cmd((com), CMD8251_SBRK) : \
456                  sio_setreg((com), com_cfcr, (com)->cfcr_image &= ~CFCR_SBREAK))
457
458 static struct speedtab pc98speedtab[] = {       /* internal RS232C interface */
459         { 0,            0, },
460         { 50,           50, },
461         { 75,           75, },
462         { 150,          150, },
463         { 200,          200, },
464         { 300,          300, },
465         { 600,          600, },
466         { 1200,         1200, },
467         { 2400,         2400, },
468         { 4800,         4800, },
469         { 9600,         9600, },
470         { 19200,        19200, },
471         { 38400,        38400, },
472         { 51200,        51200, },
473         { 76800,        76800, },
474         { 20800,        20800, },
475         { 31200,        31200, },
476         { 41600,        41600, },
477         { 62400,        62400, },
478         { -1,           -1 }
479 };
480 static struct speedtab pc98fast_speedtab[] = {
481         { 9600,         0x80 | (DEFAULT_RCLK / (16 * (9600))), },
482         { 19200,        0x80 | (DEFAULT_RCLK / (16 * (19200))), },
483         { 38400,        0x80 | (DEFAULT_RCLK / (16 * (38400))), },
484         { 57600,        0x80 | (DEFAULT_RCLK / (16 * (57600))), },
485         { 115200,       0x80 | (DEFAULT_RCLK / (16 * (115200))), },
486         { -1,           -1 }
487 };
488 static struct speedtab comspeedtab_pio9032b[] = {
489         { 300,          6, },
490         { 600,          5, },
491         { 1200,         4, },
492         { 2400,         3, },
493         { 4800,         2, },
494         { 9600,         1, },
495         { 19200,        0, },
496         { 38400,        7, },
497         { -1,           -1 }
498 };
499 static struct speedtab comspeedtab_b98_01[] = {
500         { 75,           11, },
501         { 150,          10, },
502         { 300,          9, },
503         { 600,          8, },
504         { 1200,         7, },
505         { 2400,         6, },
506         { 4800,         5, },
507         { 9600,         4, },
508         { 19200,        3, },
509         { 38400,        2, },
510         { 76800,        1, },
511         { 153600,       0, },
512         { -1,           -1 }
513 };
514 static struct speedtab comspeedtab_ind[] = {
515         { 300,          1536, },
516         { 600,          768, },
517         { 1200,         384, },
518         { 2400,         192, },
519         { 4800,         96, },
520         { 9600,         48, },
521         { 19200,        24, },
522         { 38400,        12, },
523         { 57600,        8, },
524         { 115200,       4, },
525         { 153600,       3, },
526         { 230400,       2, },
527         { 460800,       1, },
528         { -1,           -1 }
529 };
530
531 struct {
532         char    *name;
533         short   port_table[7];
534         short   irr_mask;
535         struct speedtab *speedtab;
536         short   check_irq;
537 } if_8251_type[] = {
538         /* COM_IF_INTERNAL */
539         { " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1},
540              -1, pc98speedtab, 1 },
541         /* COM_IF_PC9861K_1 */
542         { " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1},
543              3, NULL, 1 },
544         /* COM_IF_PC9861K_2 */
545         { " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1},
546               3, NULL, 1 },
547         /* COM_IF_IND_SS_1 */
548         { " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1},
549              3, comspeedtab_ind, 1 },
550         /* COM_IF_IND_SS_2 */
551         { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1},
552              3, comspeedtab_ind, 1 },
553         /* COM_IF_PIO9032B_1 */
554         { " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1},
555               7, comspeedtab_pio9032b, 1 },
556         /* COM_IF_PIO9032B_2 */
557         { " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1},
558               7, comspeedtab_pio9032b, 1 },
559         /* COM_IF_B98_01_1 */
560         { " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3},
561               7, comspeedtab_b98_01, 0 },
562         /* COM_IF_B98_01_2 */
563         { " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7},
564              7, comspeedtab_b98_01, 0 },
565 };
566 #define PC98SIO_data_port(type)         (if_8251_type[type].port_table[0])
567 #define PC98SIO_cmd_port(type)          (if_8251_type[type].port_table[1])
568 #define PC98SIO_sts_port(type)          (if_8251_type[type].port_table[2])
569 #define PC98SIO_in_modem_port(type)     (if_8251_type[type].port_table[3])
570 #define PC98SIO_intr_ctrl_port(type)    (if_8251_type[type].port_table[4])
571 #define PC98SIO_baud_rate_port(type)    (if_8251_type[type].port_table[5])
572 #define PC98SIO_func_port(type)         (if_8251_type[type].port_table[6])
573
574 #define I8251F_data             0x130
575 #define I8251F_lsr              0x132
576 #define I8251F_msr              0x134
577 #define I8251F_iir              0x136
578 #define I8251F_fcr              0x138
579 #define I8251F_div              0x13a
580
581
582 static bus_addr_t port_table_0[] =
583         {0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007};
584 static bus_addr_t port_table_1[] =
585         {0x000, 0x002, 0x004, 0x006, 0x008, 0x00a, 0x00c, 0x00e};
586 static bus_addr_t port_table_8[] =
587         {0x000, 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700};
588 static bus_addr_t port_table_rsa[] = {
589         0x008, 0x009, 0x00a, 0x00b, 0x00c, 0x00d, 0x00e, 0x00f,
590         0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007
591 };
592
593 struct {
594         char            *name;
595         short           irr_read;
596         short           irr_write;
597         bus_addr_t      *iat;
598         bus_size_t      iatsz;
599         u_long          rclk;
600 } if_16550a_type[] = {
601         /* COM_IF_RSA98 */
602         {" (RSA-98)", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK},
603         /* COM_IF_NS16550 */
604         {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK},
605         /* COM_IF_SECOND_CCU */
606         {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK},
607         /* COM_IF_MC16550II */
608         {" (MC16550II)", -1, 0x1000, port_table_8, IO_COMSIZE,
609          DEFAULT_RCLK * 4},
610         /* COM_IF_MCRS98 */
611         {" (MC-RS98)", -1, 0x1000, port_table_8, IO_COMSIZE, DEFAULT_RCLK * 4},
612         /* COM_IF_RSB3000 */
613         {" (RSB-3000)", 0xbf, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 10},
614         /* COM_IF_RSB384 */
615         {" (RSB-384)", 0xbf, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 10},
616         /* COM_IF_MODEM_CARD */
617         {"", -1, -1, port_table_0, IO_COMSIZE, DEFAULT_RCLK},
618         /* COM_IF_RSA98III */
619         {" (RSA-98III)", -1, -1, port_table_rsa, 16, DEFAULT_RCLK * 8},
620         /* COM_IF_ESP98 */
621         {" (ESP98)", -1, -1, port_table_1, IO_COMSIZE, DEFAULT_RCLK * 4},
622 };
623 #endif /* PC98 */
624
625 #ifdef GDB
626 static  Port_t  siogdbiobase = 0;
627 #endif
628
629 #ifdef COM_ESP
630 #ifdef PC98
631
632 /* XXX configure this properly. */
633 /* XXX quite broken for new-bus. */
634 static  Port_t  likely_com_ports[] = { 0, 0xb0, 0xb1, 0 };
635 static  Port_t  likely_esp_ports[] = { 0xc0d0, 0 };
636
637 #define ESP98_CMD1      (ESP_CMD1 * 0x100)
638 #define ESP98_CMD2      (ESP_CMD2 * 0x100)
639 #define ESP98_STATUS1   (ESP_STATUS1 * 0x100)
640 #define ESP98_STATUS2   (ESP_STATUS2 * 0x100)
641
642 #else /* PC98 */
643
644 /* XXX configure this properly. */
645 static  Port_t  likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
646 static  Port_t  likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
647
648 #endif /* PC98 */
649 #endif
650
651 /*
652  * handle sysctl read/write requests for console speed
653  * 
654  * In addition to setting comdefaultrate for I/O through /dev/console,
655  * also set the initial and lock values for the /dev/ttyXX device
656  * if there is one associated with the console.  Finally, if the /dev/tty
657  * device has already been open, change the speed on the open running port
658  * itself.
659  */
660
661 static int
662 sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)
663 {
664         int error, s;
665         speed_t newspeed;
666         struct com_s *com;
667         struct tty *tp;
668
669         newspeed = comdefaultrate;
670
671         error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
672         if (error || !req->newptr)
673                 return (error);
674
675         comdefaultrate = newspeed;
676
677         if (comconsole < 0)             /* serial console not selected? */
678                 return (0);
679
680         com = com_addr(comconsole);
681         if (com == NULL)
682                 return (ENXIO);
683
684         tp = com->tp;
685         if (tp == NULL)
686                 return (ENXIO);
687
688         /*
689          * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
690          * (note, the lock rates really are boolean -- if non-zero, disallow
691          *  speed changes)
692          */
693         tp->t_init_in.c_ispeed  = tp->t_init_in.c_ospeed =
694         tp->t_lock_in.c_ispeed  = tp->t_lock_in.c_ospeed =
695         tp->t_init_out.c_ispeed = tp->t_init_out.c_ospeed =
696         tp->t_lock_out.c_ispeed = tp->t_lock_out.c_ospeed = comdefaultrate;
697
698         if (tp->t_state & TS_ISOPEN) {
699                 tp->t_termios.c_ispeed =
700                 tp->t_termios.c_ospeed = comdefaultrate;
701                 s = spltty();
702                 error = comparam(tp, &tp->t_termios);
703                 splx(s);
704         }
705         return error;
706 }
707
708 SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
709             0, 0, sysctl_machdep_comdefaultrate, "I", "");
710 TUNABLE_INT("machdep.conspeed", __DEVOLATILE(int *, &comdefaultrate));
711
712 /*
713  *      Unload the driver and clear the table.
714  *      XXX this is mostly wrong.
715  *      XXX TODO:
716  *      This is usually called when the card is ejected, but
717  *      can be caused by a kldunload of a controller driver.
718  *      The idea is to reset the driver's view of the device
719  *      and ensure that any driver entry points such as
720  *      read and write do not hang.
721  */
722 int
723 siodetach(device_t dev)
724 {
725         struct com_s    *com;
726
727         com = (struct com_s *) device_get_softc(dev);
728         if (com == NULL) {
729                 device_printf(dev, "NULL com in siounload\n");
730                 return (0);
731         }
732         com->gone = TRUE;
733         if (com->tp)
734                 ttyfree(com->tp);
735         if (com->irqres) {
736                 bus_teardown_intr(dev, com->irqres, com->cookie);
737                 bus_release_resource(dev, SYS_RES_IRQ, 0, com->irqres);
738         }
739         if (com->ioportres)
740                 bus_release_resource(dev, SYS_RES_IOPORT, com->ioportrid,
741                                      com->ioportres);
742         if (com->ibuf != NULL)
743                 free(com->ibuf, M_DEVBUF);
744 #ifdef PC98
745         if (com->obuf1 != NULL)
746                 free(com->obuf1, M_DEVBUF);
747 #endif
748
749         device_set_softc(dev, NULL);
750         free(com, M_DEVBUF);
751         return (0);
752 }
753
754 int
755 sioprobe(dev, xrid, rclk, noprobe)
756         device_t        dev;
757         int             xrid;
758         u_long          rclk;
759         int             noprobe;
760 {
761 #if 0
762         static bool_t   already_init;
763         device_t        xdev;
764 #endif
765         struct com_s    *com;
766         u_int           divisor;
767         bool_t          failures[10];
768         int             fn;
769         device_t        idev;
770         Port_t          iobase;
771         intrmask_t      irqmap[4];
772         intrmask_t      irqs;
773         u_char          mcr_image;
774         int             result;
775         u_long          xirq;
776         u_int           flags = device_get_flags(dev);
777         int             rid;
778         struct resource *port;
779 #ifdef PC98
780         int             tmp;
781         struct siodev   iod;
782 #endif
783
784 #ifdef PC98
785         iod.if_type = GET_IFTYPE(flags);
786         if ((iod.if_type < 0 || iod.if_type > COM_IF_END1) &&
787             (iod.if_type < 0x10 || iod.if_type > COM_IF_END2))
788                         return ENXIO;
789 #endif
790
791         rid = xrid;
792 #ifdef PC98
793         if (IS_8251(iod.if_type)) {
794                 port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
795                                               RF_ACTIVE);
796         } else if (iod.if_type == COM_IF_MODEM_CARD ||
797                    iod.if_type == COM_IF_RSA98III ||
798                    isa_get_vendorid(dev)) {
799                 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
800                   if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE);
801         } else {
802                 port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
803                    if_16550a_type[iod.if_type & 0x0f].iat,
804                    if_16550a_type[iod.if_type & 0x0f].iatsz, RF_ACTIVE);
805         }
806 #else
807         port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
808                                   0, ~0, IO_COMSIZE, RF_ACTIVE);
809 #endif
810         if (!port)
811                 return (ENXIO);
812 #ifdef PC98
813         if (!IS_8251(iod.if_type)) {
814                 if (isa_load_resourcev(port,
815                        if_16550a_type[iod.if_type & 0x0f].iat,
816                        if_16550a_type[iod.if_type & 0x0f].iatsz) != 0) {
817                         bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
818                         return ENXIO;
819                 }
820         }
821 #endif
822
823         com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
824         if (com == NULL) {
825                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
826                 return (ENOMEM);
827         }
828         device_set_softc(dev, com);
829         com->bst = rman_get_bustag(port);
830         com->bsh = rman_get_bushandle(port);
831 #ifdef PC98
832         if (!IS_8251(iod.if_type) && rclk == 0)
833                 rclk = if_16550a_type[iod.if_type & 0x0f].rclk;
834 #else
835         if (rclk == 0)
836                 rclk = DEFAULT_RCLK;
837 #endif
838         com->rclk = rclk;
839
840         while (sio_inited != 2)
841                 if (atomic_cmpset_int(&sio_inited, 0, 1)) {
842                         mtx_init(&sio_lock, sio_driver_name, NULL,
843                             (comconsole != -1) ?
844                             MTX_SPIN | MTX_QUIET : MTX_SPIN);
845                         atomic_store_rel_int(&sio_inited, 2);
846                 }
847
848 #if 0
849         /*
850          * XXX this is broken - when we are first called, there are no
851          * previously configured IO ports.  We could hard code
852          * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
853          * This code has been doing nothing since the conversion since
854          * "count" is zero the first time around.
855          */
856         if (!already_init) {
857                 /*
858                  * Turn off MCR_IENABLE for all likely serial ports.  An unused
859                  * port with its MCR_IENABLE gate open will inhibit interrupts
860                  * from any used port that shares the interrupt vector.
861                  * XXX the gate enable is elsewhere for some multiports.
862                  */
863                 device_t *devs;
864                 int count, i, xioport;
865 #ifdef PC98
866                 int xiftype;
867 #endif
868
869                 devclass_get_devices(sio_devclass, &devs, &count);
870 #ifdef PC98
871                 for (i = 0; i < count; i++) {
872                         xdev = devs[i];
873                         xioport = bus_get_resource_start(xdev, SYS_RES_IOPORT, 0);
874                         xiftype = GET_IFTYPE(device_get_flags(xdev));
875                         if (device_is_enabled(xdev) && xioport > 0) {
876                             if (IS_8251(xiftype))
877                                 outb((xioport & 0xff00) | PC98SIO_cmd_port(xiftype & 0x0f), 0xf2);
878                             else
879                                 outb(xioport + if_16550a_type[xiftype & 0x0f].iat[com_mcr], 0);
880                         }
881                 }
882 #else
883                 for (i = 0; i < count; i++) {
884                         xdev = devs[i];
885                         if (device_is_enabled(xdev) &&
886                             bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
887                                              NULL) == 0)
888                                 outb(xioport + com_mcr, 0);
889                 }
890 #endif
891                 free(devs, M_TEMP);
892                 already_init = TRUE;
893         }
894 #endif
895
896         if (COM_LLCONSOLE(flags)) {
897                 printf("sio%d: reserved for low-level i/o\n",
898                        device_get_unit(dev));
899                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
900                 device_set_softc(dev, NULL);
901                 free(com, M_DEVBUF);
902                 return (ENXIO);
903         }
904
905 #ifdef PC98
906         DELAY(10);
907
908         /*
909          * If the port is i8251 UART (internal, B98_01)
910          */
911         if (pc98_check_if_type(dev, &iod) == -1) {
912                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
913                 device_set_softc(dev, NULL);
914                 free(com, M_DEVBUF);
915                 return (ENXIO);
916         }
917         if (iod.irq > 0)
918                 bus_set_resource(dev, SYS_RES_IRQ, 0, iod.irq, 1);
919         if (IS_8251(iod.if_type)) {
920                 outb(iod.cmd, 0);
921                 DELAY(10);
922                 outb(iod.cmd, 0);
923                 DELAY(10);
924                 outb(iod.cmd, 0);
925                 DELAY(10);
926                 outb(iod.cmd, CMD8251_RESET);
927                 DELAY(1000);            /* for a while...*/
928                 outb(iod.cmd, 0xf2);    /* MODE (dummy) */
929                 DELAY(10);
930                 outb(iod.cmd, 0x01);    /* CMD (dummy) */
931                 DELAY(1000);            /* for a while...*/
932                 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) {
933                     result = (ENXIO);
934                 }
935                 if (if_8251_type[iod.if_type & 0x0f].check_irq) {
936                     COM_INT_DISABLE
937                     tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx));
938                     outb( iod.ctrl, tmp|IEN_TxEMP );
939                     DELAY(10);
940                     result = isa_irq_pending() ? 0 : ENXIO;
941                     outb( iod.ctrl, tmp );
942                     COM_INT_ENABLE
943                 } else {
944                     /*
945                      * B98_01 doesn't activate TxEMP interrupt line
946                      * when being reset, so we can't check irq pending.
947                      */
948                     result = 0;
949                 }
950                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
951                 if (result) {
952                         device_set_softc(dev, NULL);
953                         free(com, M_DEVBUF);
954                 }
955                 return result;
956         }
957 #endif /* PC98 */
958         /*
959          * If the device is on a multiport card and has an AST/4
960          * compatible interrupt control register, initialize this
961          * register and prepare to leave MCR_IENABLE clear in the mcr.
962          * Otherwise, prepare to set MCR_IENABLE in the mcr.
963          * Point idev to the device struct giving the correct id_irq.
964          * This is the struct for the master device if there is one.
965          */
966         idev = dev;
967         mcr_image = MCR_IENABLE;
968 #ifdef COM_MULTIPORT
969         if (COM_ISMULTIPORT(flags)) {
970 #ifndef PC98
971                 Port_t xiobase;
972                 u_long io;
973 #endif
974
975                 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
976                 if (idev == NULL) {
977                         printf("sio%d: master device %d not configured\n",
978                                device_get_unit(dev), COM_MPMASTER(flags));
979                         idev = dev;
980                 }
981 #ifndef PC98
982                 if (!COM_NOTAST4(flags)) {
983                         if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
984                                              NULL) == 0) {
985                                 xiobase = io;
986                                 if (bus_get_resource(idev, SYS_RES_IRQ, 0,
987                                     NULL, NULL) == 0)
988                                         outb(xiobase + com_scr, 0x80);
989                                 else
990                                         outb(xiobase + com_scr, 0);
991                         }
992                         mcr_image = 0;
993                 }
994 #endif
995         }
996 #endif /* COM_MULTIPORT */
997         if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
998                 mcr_image = 0;
999
1000         bzero(failures, sizeof failures);
1001         iobase = rman_get_start(port);
1002
1003 #ifdef PC98
1004         if (iod.if_type == COM_IF_RSA98III) {
1005                 mcr_image = 0;
1006
1007                 outb(iobase + rsa_msr,   0x04);
1008                 outb(iobase + rsa_frr,   0x00);
1009                 if ((inb(iobase + rsa_srr) & 0x36) != 0x36) {
1010                         bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1011                         device_set_softc(dev, NULL);
1012                         free(com, M_DEVBUF);
1013                         return (ENXIO);
1014                 }
1015                 outb(iobase + rsa_ier,   0x00);
1016                 outb(iobase + rsa_frr,   0x00);
1017                 outb(iobase + rsa_tivsr, 0x00);
1018                 outb(iobase + rsa_tcr,   0x00);
1019         }
1020
1021         tmp = if_16550a_type[iod.if_type & 0x0f].irr_write;
1022         if (tmp != -1) {
1023             /* MC16550II */
1024             int irqout;
1025             switch (isa_get_irq(idev)) {
1026             case 3: irqout = 4; break;
1027             case 5: irqout = 5; break;
1028             case 6: irqout = 6; break;
1029             case 12: irqout = 7; break;
1030             default:
1031                 printf("sio%d: irq configuration error\n",
1032                        device_get_unit(dev));
1033                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1034                 device_set_softc(dev, NULL);
1035                 free(com, M_DEVBUF);
1036                 return (ENXIO);
1037             }
1038             outb((iobase & 0x00ff) | tmp, irqout);
1039         }
1040 #endif
1041
1042         /*
1043          * We don't want to get actual interrupts, just masked ones.
1044          * Interrupts from this line should already be masked in the ICU,
1045          * but mask them in the processor as well in case there are some
1046          * (misconfigured) shared interrupts.
1047          */
1048         mtx_lock_spin(&sio_lock);
1049 /* EXTRA DELAY? */
1050
1051         /*
1052          * Initialize the speed and the word size and wait long enough to
1053          * drain the maximum of 16 bytes of junk in device output queues.
1054          * The speed is undefined after a master reset and must be set
1055          * before relying on anything related to output.  There may be
1056          * junk after a (very fast) soft reboot and (apparently) after
1057          * master reset.
1058          * XXX what about the UART bug avoided by waiting in comparam()?
1059          * We don't want to to wait long enough to drain at 2 bps.
1060          */
1061         if (iobase == siocniobase)
1062                 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
1063         else {
1064                 sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
1065                 divisor = siodivisor(rclk, SIO_TEST_SPEED);
1066                 sio_setreg(com, com_dlbl, divisor & 0xff);
1067                 sio_setreg(com, com_dlbh, divisor >> 8);
1068                 sio_setreg(com, com_cfcr, CFCR_8BITS);
1069                 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
1070         }
1071
1072         /*
1073          * Enable the interrupt gate and disable device interrupts.  This
1074          * should leave the device driving the interrupt line low and
1075          * guarantee an edge trigger if an interrupt can be generated.
1076          */
1077 /* EXTRA DELAY? */
1078         sio_setreg(com, com_mcr, mcr_image);
1079         sio_setreg(com, com_ier, 0);
1080         DELAY(1000);            /* XXX */
1081         irqmap[0] = isa_irq_pending();
1082
1083         /*
1084          * Attempt to set loopback mode so that we can send a null byte
1085          * without annoying any external device.
1086          */
1087 /* EXTRA DELAY? */
1088         sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK);
1089
1090         /*
1091          * Attempt to generate an output interrupt.  On 8250's, setting
1092          * IER_ETXRDY generates an interrupt independent of the current
1093          * setting and independent of whether the THR is empty.  On 16450's,
1094          * setting IER_ETXRDY generates an interrupt independent of the
1095          * current setting.  On 16550A's, setting IER_ETXRDY only
1096          * generates an interrupt when IER_ETXRDY is not already set.
1097          */
1098         sio_setreg(com, com_ier, IER_ETXRDY);
1099 #ifdef PC98
1100         if (iod.if_type == COM_IF_RSA98III)
1101                 outb(iobase + rsa_ier, 0x04);
1102 #endif
1103
1104         /*
1105          * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
1106          * an interrupt.  They'd better generate one for actually doing
1107          * output.  Loopback may be broken on the same incompatibles but
1108          * it's unlikely to do more than allow the null byte out.
1109          */
1110         sio_setreg(com, com_data, 0);
1111         if (iobase == siocniobase)
1112                 DELAY((1 + 2) * 1000000 / (comdefaultrate / 10));
1113         else
1114                 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
1115
1116         /*
1117          * Turn off loopback mode so that the interrupt gate works again
1118          * (MCR_IENABLE was hidden).  This should leave the device driving
1119          * an interrupt line high.  It doesn't matter if the interrupt
1120          * line oscillates while we are not looking at it, since interrupts
1121          * are disabled.
1122          */
1123 /* EXTRA DELAY? */
1124         sio_setreg(com, com_mcr, mcr_image);
1125  
1126         /*
1127          * It seems my Xircom CBEM56G Cardbus modem wants to be reset
1128          * to 8 bits *again*, or else probe test 0 will fail.
1129          * gwk@sgi.com, 4/19/2001
1130          */
1131         sio_setreg(com, com_cfcr, CFCR_8BITS);
1132
1133         /*
1134          * Some PCMCIA cards (Palido 321s, DC-1S, ...) have the "TXRDY bug",
1135          * so we probe for a buggy IIR_TXRDY implementation even in the
1136          * noprobe case.  We don't probe for it in the !noprobe case because
1137          * noprobe is always set for PCMCIA cards and the problem is not
1138          * known to affect any other cards.
1139          */
1140         if (noprobe) {
1141                 /* Read IIR a few times. */
1142                 for (fn = 0; fn < 2; fn ++) {
1143                         DELAY(10000);
1144                         failures[6] = sio_getreg(com, com_iir);
1145                 }
1146
1147                 /* IIR_TXRDY should be clear.  Is it? */
1148                 result = 0;
1149                 if (failures[6] & IIR_TXRDY) {
1150                         /*
1151                          * No.  We seem to have the bug.  Does our fix for
1152                          * it work?
1153                          */
1154                         sio_setreg(com, com_ier, 0);
1155                         if (sio_getreg(com, com_iir) & IIR_NOPEND) {
1156                                 /* Yes.  We discovered the TXRDY bug! */
1157                                 SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
1158                         } else {
1159                                 /* No.  Just fail.  XXX */
1160                                 result = ENXIO;
1161                                 sio_setreg(com, com_mcr, 0);
1162                         }
1163                 } else {
1164                         /* Yes.  No bug. */
1165                         CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
1166                 }
1167                 sio_setreg(com, com_ier, 0);
1168                 sio_setreg(com, com_cfcr, CFCR_8BITS);
1169                 mtx_unlock_spin(&sio_lock);
1170                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1171                 if (iobase == siocniobase)
1172                         result = 0;
1173                 if (result != 0) {
1174                         device_set_softc(dev, NULL);
1175                         free(com, M_DEVBUF);
1176                 }
1177                 return (result);
1178         }
1179
1180         /*
1181          * Check that
1182          *      o the CFCR, IER and MCR in UART hold the values written to them
1183          *        (the values happen to be all distinct - this is good for
1184          *        avoiding false positive tests from bus echoes).
1185          *      o an output interrupt is generated and its vector is correct.
1186          *      o the interrupt goes away when the IIR in the UART is read.
1187          */
1188 /* EXTRA DELAY? */
1189         failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
1190         failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
1191         failures[2] = sio_getreg(com, com_mcr) - mcr_image;
1192         DELAY(10000);           /* Some internal modems need this time */
1193         irqmap[1] = isa_irq_pending();
1194         failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
1195 #ifdef PC98
1196         if (iod.if_type == COM_IF_RSA98III)
1197                 inb(iobase + rsa_srr);
1198 #endif
1199         DELAY(1000);            /* XXX */
1200         irqmap[2] = isa_irq_pending();
1201         failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
1202 #ifdef PC98
1203         if (iod.if_type == COM_IF_RSA98III)
1204                 inb(iobase + rsa_srr);
1205 #endif
1206
1207         /*
1208          * Turn off all device interrupts and check that they go off properly.
1209          * Leave MCR_IENABLE alone.  For ports without a master port, it gates
1210          * the OUT2 output of the UART to
1211          * the ICU input.  Closing the gate would give a floating ICU input
1212          * (unless there is another device driving it) and spurious interrupts.
1213          * (On the system that this was first tested on, the input floats high
1214          * and gives a (masked) interrupt as soon as the gate is closed.)
1215          */
1216         sio_setreg(com, com_ier, 0);
1217         sio_setreg(com, com_cfcr, CFCR_8BITS);  /* dummy to avoid bus echo */
1218         failures[7] = sio_getreg(com, com_ier);
1219 #ifdef PC98
1220         if (iod.if_type == COM_IF_RSA98III)
1221                 outb(iobase + rsa_ier, 0x00);
1222 #endif
1223         DELAY(1000);            /* XXX */
1224         irqmap[3] = isa_irq_pending();
1225         failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
1226 #ifdef PC98
1227         if (iod.if_type == COM_IF_RSA98III) {
1228                 inb(iobase + rsa_srr);
1229                 outb(iobase + rsa_frr, 0x00);
1230         }
1231 #endif
1232
1233         mtx_unlock_spin(&sio_lock);
1234
1235         irqs = irqmap[1] & ~irqmap[0];
1236         if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
1237             ((1 << xirq) & irqs) == 0) {
1238                 printf(
1239                 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
1240                     device_get_unit(dev), xirq, irqs);
1241                 printf(
1242                 "sio%d: port may not be enabled\n",
1243                     device_get_unit(dev));
1244         }
1245         if (bootverbose)
1246                 printf("sio%d: irq maps: %#x %#x %#x %#x\n",
1247                     device_get_unit(dev),
1248                     irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
1249
1250         result = 0;
1251         for (fn = 0; fn < sizeof failures; ++fn)
1252                 if (failures[fn]) {
1253                         sio_setreg(com, com_mcr, 0);
1254                         result = ENXIO;
1255                         if (bootverbose) {
1256                                 printf("sio%d: probe failed test(s):",
1257                                     device_get_unit(dev));
1258                                 for (fn = 0; fn < sizeof failures; ++fn)
1259                                         if (failures[fn])
1260                                                 printf(" %d", fn);
1261                                 printf("\n");
1262                         }
1263                         break;
1264                 }
1265         bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1266         if (iobase == siocniobase)
1267                 result = 0;
1268         if (result != 0) {
1269                 device_set_softc(dev, NULL);
1270                 free(com, M_DEVBUF);
1271         }
1272         return (result);
1273 }
1274
1275 #ifdef COM_ESP
1276 static int
1277 espattach(com, esp_port)
1278         struct com_s            *com;
1279         Port_t                  esp_port;
1280 {
1281         u_char  dips;
1282         u_char  val;
1283
1284         /*
1285          * Check the ESP-specific I/O port to see if we're an ESP
1286          * card.  If not, return failure immediately.
1287          */
1288         if ((inb(esp_port) & 0xf3) == 0) {
1289                 printf(" port 0x%x is not an ESP board?\n", esp_port);
1290                 return (0);
1291         }
1292
1293         /*
1294          * We've got something that claims to be a Hayes ESP card.
1295          * Let's hope so.
1296          */
1297
1298         /* Get the dip-switch configuration */
1299 #ifdef PC98
1300         outb(esp_port + ESP98_CMD1, ESP_GETDIPS);
1301         dips = inb(esp_port + ESP98_STATUS1);
1302 #else
1303         outb(esp_port + ESP_CMD1, ESP_GETDIPS);
1304         dips = inb(esp_port + ESP_STATUS1);
1305 #endif
1306
1307         /*
1308          * Bits 0,1 of dips say which COM port we are.
1309          */
1310 #ifdef PC98
1311         if ((rman_get_start(com->ioportres) & 0xff) ==
1312             likely_com_ports[dips & 0x03])
1313 #else
1314         if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03])
1315 #endif
1316                 printf(" : ESP");
1317         else {
1318                 printf(" esp_port has com %d\n", dips & 0x03);
1319                 return (0);
1320         }
1321
1322         /*
1323          * Check for ESP version 2.0 or later:  bits 4,5,6 = 010.
1324          */
1325 #ifdef PC98
1326         outb(esp_port + ESP98_CMD1, ESP_GETTEST);
1327         val = inb(esp_port + ESP98_STATUS1);    /* clear reg 1 */
1328         val = inb(esp_port + ESP98_STATUS2);
1329 #else
1330         outb(esp_port + ESP_CMD1, ESP_GETTEST);
1331         val = inb(esp_port + ESP_STATUS1);      /* clear reg 1 */
1332         val = inb(esp_port + ESP_STATUS2);
1333 #endif
1334         if ((val & 0x70) < 0x20) {
1335                 printf("-old (%o)", val & 0x70);
1336                 return (0);
1337         }
1338
1339         /*
1340          * Check for ability to emulate 16550:  bit 7 == 1
1341          */
1342         if ((dips & 0x80) == 0) {
1343                 printf(" slave");
1344                 return (0);
1345         }
1346
1347         /*
1348          * Okay, we seem to be a Hayes ESP card.  Whee.
1349          */
1350         com->esp = TRUE;
1351         com->esp_port = esp_port;
1352         return (1);
1353 }
1354 #endif /* COM_ESP */
1355
1356 int
1357 sioattach(dev, xrid, rclk)
1358         device_t        dev;
1359         int             xrid;
1360         u_long          rclk;
1361 {
1362         struct com_s    *com;
1363 #ifdef COM_ESP
1364         Port_t          *espp;
1365 #endif
1366         Port_t          iobase;
1367         int             unit;
1368         u_int           flags;
1369         int             rid;
1370         struct resource *port;
1371         int             ret;
1372         int             error;
1373         struct tty      *tp;
1374 #ifdef PC98
1375         u_char          *obuf;
1376         u_long          obufsize;
1377         int             if_type = GET_IFTYPE(device_get_flags(dev));
1378 #endif
1379
1380         rid = xrid;
1381 #ifdef PC98
1382         if (IS_8251(if_type)) {
1383                 port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
1384                                               RF_ACTIVE);
1385         } else if (if_type == COM_IF_MODEM_CARD ||
1386                    if_type == COM_IF_RSA98III ||
1387                    isa_get_vendorid(dev)) {
1388                 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
1389                           if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE);
1390         } else {
1391                 port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
1392                            if_16550a_type[if_type & 0x0f].iat,
1393                            if_16550a_type[if_type & 0x0f].iatsz, RF_ACTIVE);
1394         }
1395 #else
1396         port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1397                                   0, ~0, IO_COMSIZE, RF_ACTIVE);
1398 #endif
1399         if (!port)
1400                 return (ENXIO);
1401 #ifdef PC98
1402         if (!IS_8251(if_type)) {
1403                 if (isa_load_resourcev(port,
1404                                if_16550a_type[if_type & 0x0f].iat,
1405                                if_16550a_type[if_type & 0x0f].iatsz) != 0) {
1406                         bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1407                         return ENXIO;
1408                 }
1409         }
1410 #endif
1411
1412         iobase = rman_get_start(port);
1413         unit = device_get_unit(dev);
1414         com = device_get_softc(dev);
1415         flags = device_get_flags(dev);
1416
1417         if (unit >= sio_numunits)
1418                 sio_numunits = unit + 1;
1419
1420 #ifdef PC98
1421         obufsize = 256;
1422         if (if_type == COM_IF_RSA98III)
1423                 obufsize = 2048;
1424         if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL) {
1425                 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1426                 return ENXIO;
1427         }
1428         bzero(obuf, obufsize * 2);
1429 #endif
1430
1431         /*
1432          * sioprobe() has initialized the device registers as follows:
1433          *      o cfcr = CFCR_8BITS.
1434          *        It is most important that CFCR_DLAB is off, so that the
1435          *        data port is not hidden when we enable interrupts.
1436          *      o ier = 0.
1437          *        Interrupts are only enabled when the line is open.
1438          *      o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1439          *        interrupt control register or the config specifies no irq.
1440          *        Keeping MCR_DTR and MCR_RTS off might stop the external
1441          *        device from sending before we are ready.
1442          */
1443         bzero(com, sizeof *com);
1444         com->unit = unit;
1445         com->ioportres = port;
1446         com->ioportrid = rid;
1447         com->bst = rman_get_bustag(port);
1448         com->bsh = rman_get_bushandle(port);
1449         com->cfcr_image = CFCR_8BITS;
1450         com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1451         com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1452         com->tx_fifo_size = 1;
1453 #ifdef PC98
1454         com->obufsize = obufsize;
1455         com->obuf1 = obuf;
1456         com->obuf2 = obuf + obufsize;
1457 #endif
1458         com->obufs[0].l_head = com->obuf1;
1459         com->obufs[1].l_head = com->obuf2;
1460
1461 #ifdef PC98
1462         com->pc98_if_type = if_type;
1463
1464         if (IS_8251(if_type)) {
1465             pc98_set_ioport(com);
1466
1467             if (if_type == COM_IF_INTERNAL && pc98_check_8251fifo()) {
1468                 com->pc98_8251fifo = 1;
1469                 com->pc98_8251fifo_enable = 0;
1470             }
1471         } else {
1472             bus_addr_t  *iat = if_16550a_type[if_type & 0x0f].iat;
1473
1474             com->data_port = iobase + iat[com_data];
1475             com->int_ctl_port = iobase + iat[com_ier];
1476             com->int_id_port = iobase + iat[com_iir];
1477             com->modem_ctl_port = iobase + iat[com_mcr];
1478             com->mcr_image = inb(com->modem_ctl_port);
1479             com->line_status_port = iobase + iat[com_lsr];
1480             com->modem_status_port = iobase + iat[com_msr];
1481         }
1482 #else /* not PC98 */
1483         com->data_port = iobase + com_data;
1484         com->int_ctl_port = iobase + com_ier;
1485         com->int_id_port = iobase + com_iir;
1486         com->modem_ctl_port = iobase + com_mcr;
1487         com->mcr_image = inb(com->modem_ctl_port);
1488         com->line_status_port = iobase + com_lsr;
1489         com->modem_status_port = iobase + com_msr;
1490 #endif
1491
1492         tp = com->tp = ttyalloc();
1493         tp->t_oproc = comstart;
1494         tp->t_param = comparam;
1495         tp->t_stop = comstop;
1496         tp->t_modem = commodem;
1497         tp->t_break = combreak;
1498         tp->t_close = comclose;
1499         tp->t_open = comopen;
1500         tp->t_sc = com;
1501
1502 #ifdef PC98
1503         if (!IS_8251(if_type) && rclk == 0)
1504                 rclk = if_16550a_type[if_type & 0x0f].rclk;
1505 #else
1506         if (rclk == 0)
1507                 rclk = DEFAULT_RCLK;
1508 #endif
1509         com->rclk = rclk;
1510
1511         if (unit == comconsole)
1512                 ttyconsolemode(tp, comdefaultrate);
1513         error = siosetwater(com, tp->t_init_in.c_ispeed);
1514         mtx_unlock_spin(&sio_lock);
1515         if (error) {
1516                 /*
1517                  * Leave i/o resources allocated if this is a `cn'-level
1518                  * console, so that other devices can't snarf them.
1519                  */
1520                 if (iobase != siocniobase)
1521                         bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1522                 return (ENOMEM);
1523         }
1524
1525         /* attempt to determine UART type */
1526         printf("sio%d: type", unit);
1527
1528 #ifndef PC98
1529         if (!COM_ISMULTIPORT(flags) &&
1530             !COM_IIR_TXRDYBUG(flags) && !COM_NOSCR(flags)) {
1531                 u_char  scr;
1532                 u_char  scr1;
1533                 u_char  scr2;
1534
1535                 scr = sio_getreg(com, com_scr);
1536                 sio_setreg(com, com_scr, 0xa5);
1537                 scr1 = sio_getreg(com, com_scr);
1538                 sio_setreg(com, com_scr, 0x5a);
1539                 scr2 = sio_getreg(com, com_scr);
1540                 sio_setreg(com, com_scr, scr);
1541                 if (scr1 != 0xa5 || scr2 != 0x5a) {
1542                         printf(" 8250 or not responding");
1543                         goto determined_type;
1544                 }
1545         }
1546 #endif /* !PC98 */
1547 #ifdef PC98
1548         if (IS_8251(com->pc98_if_type)) {
1549             if (com->pc98_8251fifo && !COM_NOFIFO(flags))
1550                 com->tx_fifo_size = 16;
1551             com_int_TxRx_disable( com );
1552             com_cflag_and_speed_set( com, tp->t_init_in.c_cflag, comdefaultrate );
1553             com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
1554             com_send_break_off( com );
1555
1556             if (com->pc98_if_type == COM_IF_INTERNAL) {
1557                 printf(" (internal%s%s)",
1558                        com->pc98_8251fifo ? " fifo" : "",
1559                        PC98SIO_baud_rate_port(com->pc98_if_type) != -1 ?
1560                        " v-fast" : "");
1561             } else {
1562                 printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name);
1563             }
1564         } else {
1565 #endif /* PC98 */
1566         sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1567         DELAY(100);
1568         switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1569         case FIFO_RX_LOW:
1570                 printf(" 16450");
1571                 break;
1572         case FIFO_RX_MEDL:
1573                 printf(" 16450?");
1574                 break;
1575         case FIFO_RX_MEDH:
1576                 printf(" 16550?");
1577                 break;
1578         case FIFO_RX_HIGH:
1579                 if (COM_NOFIFO(flags)) {
1580                         printf(" 16550A fifo disabled");
1581                         break;
1582                 }
1583                 com->hasfifo = TRUE;
1584 #ifdef PC98
1585                 if (com->pc98_if_type == COM_IF_RSA98III) {
1586                         com->tx_fifo_size = 2048;
1587                         com->rsabase = iobase;
1588                         outb(com->rsabase + rsa_ier, 0x00);
1589                         outb(com->rsabase + rsa_frr, 0x00);
1590                 }
1591 #else
1592                 if (COM_ST16650A(flags)) {
1593                         printf(" ST16650A");
1594                         com->st16650a = TRUE;
1595                         com->tx_fifo_size = 32;
1596                         break;
1597                 }
1598                 if (COM_TI16754(flags)) {
1599                         printf(" TI16754");
1600                         com->tx_fifo_size = 64;
1601                         break;
1602                 }
1603 #endif
1604                 printf(" 16550A");
1605 #ifdef COM_ESP
1606 #ifdef PC98
1607                 if (com->pc98_if_type == COM_IF_ESP98)
1608 #endif
1609                 for (espp = likely_esp_ports; *espp != 0; espp++)
1610                         if (espattach(com, *espp)) {
1611                                 com->tx_fifo_size = 1024;
1612                                 break;
1613                         }
1614                 if (com->esp)
1615                         break;
1616 #endif
1617 #ifdef PC98
1618                 com->tx_fifo_size = 16;
1619 #else
1620                 com->tx_fifo_size = COM_FIFOSIZE(flags);
1621                 if (com->tx_fifo_size == 0)
1622                         com->tx_fifo_size = 16;
1623                 else
1624                         printf(" lookalike with %u bytes FIFO",
1625                                com->tx_fifo_size);
1626 #endif
1627                 break;
1628         }
1629         
1630 #ifdef PC98
1631         if (com->pc98_if_type == COM_IF_RSB3000) {
1632             /* Set RSB-2000/3000 Extended Buffer mode. */
1633             u_char lcr;
1634             lcr = sio_getreg(com, com_cfcr);
1635             sio_setreg(com, com_cfcr, lcr | CFCR_DLAB);
1636             sio_setreg(com, com_emr, EMR_EXBUFF | EMR_EFMODE);
1637             sio_setreg(com, com_cfcr, lcr);
1638         }
1639 #endif
1640
1641 #ifdef COM_ESP
1642         if (com->esp) {
1643                 /*
1644                  * Set 16550 compatibility mode.
1645                  * We don't use the ESP_MODE_SCALE bit to increase the
1646                  * fifo trigger levels because we can't handle large
1647                  * bursts of input.
1648                  * XXX flow control should be set in comparam(), not here.
1649                  */
1650 #ifdef PC98
1651                 outb(com->esp_port + ESP98_CMD1, ESP_SETMODE);
1652                 outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1653 #else
1654                 outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1655                 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1656 #endif
1657
1658                 /* Set RTS/CTS flow control. */
1659 #ifdef PC98
1660                 outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE);
1661                 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS);
1662                 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS);
1663 #else
1664                 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1665                 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1666                 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1667 #endif
1668
1669                 /* Set flow-control levels. */
1670 #ifdef PC98
1671                 outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW);
1672                 outb(com->esp_port + ESP98_CMD2, HIBYTE(768));
1673                 outb(com->esp_port + ESP98_CMD2, LOBYTE(768));
1674                 outb(com->esp_port + ESP98_CMD2, HIBYTE(512));
1675                 outb(com->esp_port + ESP98_CMD2, LOBYTE(512));
1676 #else
1677                 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1678                 outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1679                 outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1680                 outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1681                 outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1682 #endif
1683
1684 #ifdef PC98
1685                 /* Set UART clock prescaler. */
1686                 outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK);
1687                 outb(com->esp_port + ESP98_CMD2, 2);    /* 4 times */
1688 #endif
1689         }
1690 #endif /* COM_ESP */
1691         sio_setreg(com, com_fifo, 0);
1692 #ifdef PC98
1693         printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name);
1694 #else
1695 determined_type: ;
1696 #endif
1697
1698 #ifdef COM_MULTIPORT
1699         if (COM_ISMULTIPORT(flags)) {
1700                 device_t masterdev;
1701
1702                 com->multiport = TRUE;
1703                 printf(" (multiport");
1704                 if (unit == COM_MPMASTER(flags))
1705                         printf(" master");
1706                 printf(")");
1707                 masterdev = devclass_get_device(sio_devclass,
1708                     COM_MPMASTER(flags));
1709                 com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1710                     SYS_RES_IRQ, 0, NULL, NULL) != 0);
1711          }
1712 #endif /* COM_MULTIPORT */
1713 #ifdef PC98
1714         }
1715 #endif
1716         if (unit == comconsole)
1717                 printf(", console");
1718         if (COM_IIR_TXRDYBUG(flags))
1719                 printf(" with a buggy IIR_TXRDY implementation");
1720         printf("\n");
1721
1722         if (sio_fast_ih == NULL) {
1723                 swi_add(&tty_intr_event, "sio", siopoll, NULL, SWI_TTY, 0,
1724                     &sio_fast_ih);
1725                 swi_add(&clk_intr_event, "sio", siopoll, NULL, SWI_CLOCK, 0,
1726                     &sio_slow_ih);
1727         }
1728
1729         com->flags = flags;
1730         com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1731         tp->t_pps = &com->pps;
1732
1733         if (COM_PPSCTS(flags))
1734                 com->pps_bit = MSR_CTS;
1735         else
1736                 com->pps_bit = MSR_DCD;
1737         pps_init(&com->pps);
1738
1739         rid = 0;
1740         com->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
1741         if (com->irqres) {
1742                 ret = bus_setup_intr(dev, com->irqres,
1743                                      INTR_TYPE_TTY,
1744                                      siointr, NULL, com, &com->cookie);
1745                 if (ret) {
1746                         ret = bus_setup_intr(dev,
1747                                              com->irqres, INTR_TYPE_TTY,
1748                                              NULL, (driver_intr_t *)siointr, 
1749                                              com, &com->cookie);
1750                         if (ret == 0)
1751                                 device_printf(dev, "unable to activate interrupt in fast mode - using normal mode\n");
1752                 }
1753                 if (ret)
1754                         device_printf(dev, "could not activate interrupt\n");
1755 #if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
1756     defined(ALT_BREAK_TO_DEBUGGER))
1757                 /*
1758                  * Enable interrupts for early break-to-debugger support
1759                  * on the console.
1760                  */
1761                 if (ret == 0 && unit == comconsole)
1762                         outb(siocniobase + com_ier, IER_ERXRDY | IER_ERLS |
1763                             IER_EMSC);
1764 #endif
1765         }
1766
1767         /* We're ready, open the doors... */
1768         ttycreate(tp, TS_CALLOUT, "d%r", unit);
1769
1770         return (0);
1771 }
1772
1773 static int
1774 comopen(struct tty *tp, struct cdev *dev)
1775 {
1776         struct com_s    *com;
1777         int i;
1778
1779         com = tp->t_sc;
1780         com->poll = com->no_irq;
1781         com->poll_output = com->loses_outints;
1782 #ifdef PC98
1783         if (IS_8251(com->pc98_if_type)) {
1784                 com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS);
1785                 pc98_msrint_start(dev);
1786                 if (com->pc98_8251fifo) {
1787                         com->pc98_8251fifo_enable = 1;
1788                         outb(I8251F_fcr,
1789                              FIFO_ENABLE | FIFO_XMT_RST | FIFO_RCV_RST);
1790                 }
1791         }
1792 #endif
1793         if (com->hasfifo) {
1794                 /*
1795                  * (Re)enable and drain fifos.
1796                  *
1797                  * Certain SMC chips cause problems if the fifos
1798                  * are enabled while input is ready.  Turn off the
1799                  * fifo if necessary to clear the input.  We test
1800                  * the input ready bit after enabling the fifos
1801                  * since we've already enabled them in comparam()
1802                  * and to handle races between enabling and fresh
1803                  * input.
1804                  */
1805                 for (i = 0; i < 500; i++) {
1806                         sio_setreg(com, com_fifo,
1807                             FIFO_RCV_RST | FIFO_XMT_RST | com->fifo_image);
1808 #ifdef PC98
1809                         if (com->pc98_if_type == COM_IF_RSA98III)
1810                                 outb(com->rsabase + rsa_frr , 0x00);
1811 #endif
1812                         /*
1813                          * XXX the delays are for superstitious
1814                          * historical reasons.  It must be less than
1815                          * the character time at the maximum
1816                          * supported speed (87 usec at 115200 bps
1817                          * 8N1).  Otherwise we might loop endlessly
1818                          * if data is streaming in.  We used to use
1819                          * delays of 100.  That usually worked
1820                          * because DELAY(100) used to usually delay
1821                          * for about 85 usec instead of 100.
1822                          */
1823                         DELAY(50);
1824 #ifdef PC98
1825                         if (com->pc98_if_type == COM_IF_RSA98III ?
1826                             !(inb(com->rsabase + rsa_srr) & 0x08) :
1827                             !(inb(com->line_status_port) & LSR_RXRDY))
1828                                 break;
1829 #else
1830                         if (!(inb(com->line_status_port) & LSR_RXRDY))
1831                                 break;
1832 #endif
1833                         sio_setreg(com, com_fifo, 0);
1834                         DELAY(50);
1835                         (void) inb(com->data_port);
1836                 }
1837                 if (i == 500)
1838                         return (EIO);
1839         }
1840
1841         mtx_lock_spin(&sio_lock);
1842 #ifdef PC98
1843         if (IS_8251(com->pc98_if_type)) {
1844                 com_tiocm_bis(com, TIOCM_LE);
1845                 com->pc98_prev_modem_status = pc98_get_modem_status(com);
1846                 com_int_Rx_enable(com);
1847         } else {
1848 #endif
1849         (void) inb(com->line_status_port);
1850         (void) inb(com->data_port);
1851         com->prev_modem_status = com->last_modem_status
1852             = inb(com->modem_status_port);
1853         outb(com->int_ctl_port,
1854              IER_ERXRDY | IER_ERLS | IER_EMSC
1855              | (COM_IIR_TXRDYBUG(com->flags) ? 0 : IER_ETXRDY));
1856 #ifdef PC98
1857         if (com->pc98_if_type == COM_IF_RSA98III) {
1858                 outb(com->rsabase + rsa_ier, 0x1d);
1859                 outb(com->int_ctl_port, IER_ERLS | IER_EMSC);
1860         }
1861 #endif
1862 #ifdef PC98
1863         }
1864 #endif
1865         mtx_unlock_spin(&sio_lock);
1866         siosettimeout();
1867         /* XXX: should be generic ? */
1868 #ifdef PC98
1869         if ((IS_8251(com->pc98_if_type) &&
1870              (pc98_get_modem_status(com) & TIOCM_CAR)) ||
1871             (!IS_8251(com->pc98_if_type) &&
1872              (com->prev_modem_status & MSR_DCD)) ||
1873             ISCALLOUT(dev))
1874                 ttyld_modem(tp, 1);
1875 #else
1876         if (com->prev_modem_status & MSR_DCD || ISCALLOUT(dev))
1877                 ttyld_modem(tp, 1);
1878 #endif
1879         return (0);
1880 }
1881
1882 static void
1883 comclose(tp)
1884         struct tty      *tp;
1885 {
1886         int             s;
1887         struct com_s    *com;
1888
1889         s = spltty();
1890         com = tp->t_sc;
1891         com->poll = FALSE;
1892         com->poll_output = FALSE;
1893 #ifdef PC98
1894         com_send_break_off(com);
1895 #else
1896         sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1897 #endif
1898
1899 #if defined(KDB) && (defined(BREAK_TO_DEBUGGER) || \
1900     defined(ALT_BREAK_TO_DEBUGGER))
1901         /*
1902          * Leave interrupts enabled and don't clear DTR if this is the
1903          * console. This allows us to detect break-to-debugger events
1904          * while the console device is closed.
1905          */
1906         if (com->unit != comconsole)
1907 #endif
1908         {
1909 #ifdef PC98
1910                 int     tmp;
1911                 if (IS_8251(com->pc98_if_type))
1912                         com_int_TxRx_disable(com);
1913                 else
1914                         sio_setreg(com, com_ier, 0);
1915                 if (com->pc98_if_type == COM_IF_RSA98III)
1916                         outb(com->rsabase + rsa_ier, 0x00);
1917                 if (IS_8251(com->pc98_if_type))
1918                         tmp = pc98_get_modem_status(com) & TIOCM_CAR;
1919                 else
1920                         tmp = com->prev_modem_status & MSR_DCD;
1921 #else
1922                 sio_setreg(com, com_ier, 0);
1923 #endif
1924                 if (tp->t_cflag & HUPCL
1925                     /*
1926                      * XXX we will miss any carrier drop between here and the
1927                      * next open.  Perhaps we should watch DCD even when the
1928                      * port is closed; it is not sufficient to check it at
1929                      * the next open because it might go up and down while
1930                      * we're not watching.
1931                      */
1932                     || (!tp->t_actout
1933 #ifdef PC98
1934                         && !(tmp)
1935 #else
1936                         && !(com->prev_modem_status & MSR_DCD)
1937 #endif
1938                         && !(tp->t_init_in.c_cflag & CLOCAL))
1939                     || !(tp->t_state & TS_ISOPEN)) {
1940 #ifdef PC98
1941                         if (IS_8251(com->pc98_if_type))
1942                             com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
1943                         else
1944 #endif
1945                         (void)commodem(tp, 0, SER_DTR);
1946                         ttydtrwaitstart(tp);
1947                 }
1948 #ifdef PC98
1949                 else {
1950                         if (IS_8251(com->pc98_if_type))
1951                                 com_tiocm_bic(com, TIOCM_LE);
1952                 }
1953 #endif
1954         }
1955 #ifdef PC98
1956         if (com->pc98_8251fifo) {
1957             if (com->pc98_8251fifo_enable)
1958                 outb(I8251F_fcr, FIFO_XMT_RST | FIFO_RCV_RST);
1959             com->pc98_8251fifo_enable = 0;
1960         }
1961 #endif
1962         if (com->hasfifo) {
1963                 /*
1964                  * Disable fifos so that they are off after controlled
1965                  * reboots.  Some BIOSes fail to detect 16550s when the
1966                  * fifos are enabled.
1967                  */
1968                 sio_setreg(com, com_fifo, 0);
1969         }
1970         tp->t_actout = FALSE;
1971         wakeup(&tp->t_actout);
1972         wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */
1973         siosettimeout();
1974         splx(s);
1975 }
1976
1977 static void
1978 siobusycheck(chan)
1979         void    *chan;
1980 {
1981         struct com_s    *com;
1982         int             s;
1983
1984         com = (struct com_s *)chan;
1985
1986         /*
1987          * Clear TS_BUSY if low-level output is complete.
1988          * spl locking is sufficient because siointr1() does not set CS_BUSY.
1989          * If siointr1() clears CS_BUSY after we look at it, then we'll get
1990          * called again.  Reading the line status port outside of siointr1()
1991          * is safe because CS_BUSY is clear so there are no output interrupts
1992          * to lose.
1993          */
1994         s = spltty();
1995         if (com->state & CS_BUSY)
1996                 com->extra_state &= ~CSE_BUSYCHECK;     /* False alarm. */
1997 #ifdef  PC98
1998         else if ((IS_8251(com->pc98_if_type) &&
1999                   ((com->pc98_8251fifo_enable &&
2000                     (inb(I8251F_lsr) & (FLSR_TxRDY | FLSR_TxEMP))
2001                     == (FLSR_TxRDY | FLSR_TxEMP)) ||
2002                    (!com->pc98_8251fifo_enable &&
2003                     (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP))
2004                     == (STS8251_TxRDY | STS8251_TxEMP)))) ||
2005                  ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2006                   == (LSR_TSRE | LSR_TXRDY))) {
2007 #else
2008         else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2009             == (LSR_TSRE | LSR_TXRDY)) {
2010 #endif
2011                 com->tp->t_state &= ~TS_BUSY;
2012                 ttwwakeup(com->tp);
2013                 com->extra_state &= ~CSE_BUSYCHECK;
2014         } else
2015                 timeout(siobusycheck, com, hz / 100);
2016         splx(s);
2017 }
2018
2019 static u_int
2020 siodivisor(rclk, speed)
2021         u_long  rclk;
2022         speed_t speed;
2023 {
2024         long    actual_speed;
2025         u_int   divisor;
2026         int     error;
2027
2028         if (speed == 0)
2029                 return (0);
2030 #if UINT_MAX > (ULONG_MAX - 1) / 8
2031         if (speed > (ULONG_MAX - 1) / 8)
2032                 return (0);
2033 #endif
2034         divisor = (rclk / (8UL * speed) + 1) / 2;
2035         if (divisor == 0 || divisor >= 65536)
2036                 return (0);
2037         actual_speed = rclk / (16UL * divisor);
2038
2039         /* 10 times error in percent: */
2040         error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
2041
2042         /* 3.0% maximum error tolerance: */
2043         if (error < -30 || error > 30)
2044                 return (0);
2045
2046         return (divisor);
2047 }
2048
2049 /*
2050  * Call this function with the sio_lock mutex held.  It will return with the
2051  * lock still held.
2052  */
2053 static void
2054 sioinput(com)
2055         struct com_s    *com;
2056 {
2057         u_char          *buf;
2058         int             incc;
2059         u_char          line_status;
2060         int             recv_data;
2061         struct tty      *tp;
2062
2063         buf = com->ibuf;
2064         tp = com->tp;
2065         if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
2066                 com_events -= (com->iptr - com->ibuf);
2067                 com->iptr = com->ibuf;
2068                 return;
2069         }
2070         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
2071                 /*
2072                  * Avoid the grotesquely inefficient lineswitch routine
2073                  * (ttyinput) in "raw" mode.  It usually takes about 450
2074                  * instructions (that's without canonical processing or echo!).
2075                  * slinput is reasonably fast (usually 40 instructions plus
2076                  * call overhead).
2077                  */
2078                 do {
2079                         /*
2080                          * This may look odd, but it is using save-and-enable
2081                          * semantics instead of the save-and-disable semantics
2082                          * that are used everywhere else.
2083                          */
2084                         mtx_unlock_spin(&sio_lock);
2085                         incc = com->iptr - buf;
2086                         if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
2087                             && (com->state & CS_RTS_IFLOW
2088                                 || tp->t_iflag & IXOFF)
2089                             && !(tp->t_state & TS_TBLOCK))
2090                                 ttyblock(tp);
2091                         com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
2092                                 += b_to_q((char *)buf, incc, &tp->t_rawq);
2093                         buf += incc;
2094                         tk_nin += incc;
2095                         tk_rawcc += incc;
2096                         tp->t_rawcc += incc;
2097                         ttwakeup(tp);
2098                         if (tp->t_state & TS_TTSTOP
2099                             && (tp->t_iflag & IXANY
2100                                 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
2101                                 tp->t_state &= ~TS_TTSTOP;
2102                                 tp->t_lflag &= ~FLUSHO;
2103                                 comstart(tp);
2104                         }
2105                         mtx_lock_spin(&sio_lock);
2106                 } while (buf < com->iptr);
2107         } else {
2108                 do {
2109                         /*
2110                          * This may look odd, but it is using save-and-enable
2111                          * semantics instead of the save-and-disable semantics
2112                          * that are used everywhere else.
2113                          */
2114                         mtx_unlock_spin(&sio_lock);
2115                         line_status = buf[com->ierroff];
2116                         recv_data = *buf++;
2117                         if (line_status
2118                             & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
2119                                 if (line_status & LSR_BI)
2120                                         recv_data |= TTY_BI;
2121                                 if (line_status & LSR_FE)
2122                                         recv_data |= TTY_FE;
2123                                 if (line_status & LSR_OE)
2124                                         recv_data |= TTY_OE;
2125                                 if (line_status & LSR_PE)
2126                                         recv_data |= TTY_PE;
2127                         }
2128                         ttyld_rint(tp, recv_data);
2129                         mtx_lock_spin(&sio_lock);
2130                 } while (buf < com->iptr);
2131         }
2132         com_events -= (com->iptr - com->ibuf);
2133         com->iptr = com->ibuf;
2134
2135         /*
2136          * There is now room for another low-level buffer full of input,
2137          * so enable RTS if it is now disabled and there is room in the
2138          * high-level buffer.
2139          */
2140 #ifdef PC98
2141         if (IS_8251(com->pc98_if_type)) {
2142                 if ((com->state & CS_RTS_IFLOW) &&
2143                     !(com_tiocm_get(com) & TIOCM_RTS) &&
2144                     !(tp->t_state & TS_TBLOCK))
2145                         com_tiocm_bis(com, TIOCM_RTS);
2146         } else {
2147                 if ((com->state & CS_RTS_IFLOW) &&
2148                     !(com->mcr_image & MCR_RTS) &&
2149                     !(tp->t_state & TS_TBLOCK))
2150                         outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2151         }
2152 #else
2153         if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
2154             !(tp->t_state & TS_TBLOCK))
2155                 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2156 #endif
2157 }
2158
2159 static int
2160 siointr(arg)
2161         void            *arg;
2162 {
2163         struct com_s    *com;
2164 #if defined(PC98) && defined(COM_MULTIPORT)
2165         u_char          rsa_buf_status;
2166 #endif
2167
2168 #ifndef COM_MULTIPORT
2169         com = (struct com_s *)arg;
2170
2171         mtx_lock_spin(&sio_lock);
2172         siointr1(com);
2173         mtx_unlock_spin(&sio_lock);
2174 #else /* COM_MULTIPORT */
2175         bool_t          possibly_more_intrs;
2176         int             unit;
2177
2178         /*
2179          * Loop until there is no activity on any port.  This is necessary
2180          * to get an interrupt edge more than to avoid another interrupt.
2181          * If the IRQ signal is just an OR of the IRQ signals from several
2182          * devices, then the edge from one may be lost because another is
2183          * on.
2184          */
2185         mtx_lock_spin(&sio_lock);
2186         do {
2187                 possibly_more_intrs = FALSE;
2188                 for (unit = 0; unit < sio_numunits; ++unit) {
2189                         com = com_addr(unit);
2190                         /*
2191                          * XXX COM_LOCK();
2192                          * would it work here, or be counter-productive?
2193                          */
2194 #ifdef PC98
2195                         if (com != NULL 
2196                             && !com->gone
2197                             && IS_8251(com->pc98_if_type)) {
2198                                 siointr1(com);
2199                         } else if (com != NULL 
2200                             && !com->gone
2201                             && com->pc98_if_type == COM_IF_RSA98III) {
2202                                 rsa_buf_status =
2203                                     inb(com->rsabase + rsa_srr) & 0xc9;
2204                                 if ((rsa_buf_status & 0xc8)
2205                                     || !(rsa_buf_status & 0x01)) {
2206                                     siointr1(com);
2207                                     if (rsa_buf_status !=
2208                                         (inb(com->rsabase + rsa_srr) & 0xc9))
2209                                         possibly_more_intrs = TRUE;
2210                                 }
2211                         } else
2212 #endif
2213                         if (com != NULL 
2214                             && !com->gone
2215                             && (inb(com->int_id_port) & IIR_IMASK)
2216                                != IIR_NOPEND) {
2217                                 siointr1(com);
2218                                 possibly_more_intrs = TRUE;
2219                         }
2220                         /* XXX COM_UNLOCK(); */
2221                 }
2222         } while (possibly_more_intrs);
2223         mtx_unlock_spin(&sio_lock);
2224 #endif /* COM_MULTIPORT */
2225         return (FILTER_HANDLED);
2226 }
2227
2228 static struct timespec siots[8];
2229 static int siotso;
2230 static int volatile siotsunit = -1;
2231
2232 static int
2233 sysctl_siots(SYSCTL_HANDLER_ARGS)
2234 {
2235         char buf[128];
2236         long long delta;
2237         size_t len;
2238         int error, i, tso;
2239
2240         for (i = 1, tso = siotso; i < tso; i++) {
2241                 delta = (long long)(siots[i].tv_sec - siots[i - 1].tv_sec) *
2242                     1000000000 +
2243                     (siots[i].tv_nsec - siots[i - 1].tv_nsec);
2244                 len = sprintf(buf, "%lld\n", delta);
2245                 if (delta >= 110000)
2246                         len += sprintf(buf + len - 1, ": *** %ld.%09ld\n",
2247                             (long)siots[i].tv_sec, siots[i].tv_nsec) - 1;
2248                 if (i == tso - 1)
2249                         buf[len - 1] = '\0';
2250                 error = SYSCTL_OUT(req, buf, len);
2251                 if (error != 0)
2252                         return (error);
2253                 uio_yield();
2254         }
2255         return (0);
2256 }
2257
2258 SYSCTL_PROC(_machdep, OID_AUTO, siots, CTLTYPE_STRING | CTLFLAG_RD,
2259     0, 0, sysctl_siots, "A", "sio timestamps");
2260
2261 static void
2262 siointr1(com)
2263         struct com_s    *com;
2264 {
2265         u_char  int_ctl;
2266         u_char  int_ctl_new;
2267         u_char  line_status;
2268         u_char  modem_status;
2269         u_char  *ioptr;
2270         u_char  recv_data;
2271 #ifdef PC98
2272         u_char  tmp = 0;
2273         u_char  rsa_buf_status = 0;
2274         int     rsa_tx_fifo_size = 0;
2275 #endif /* PC98 */
2276 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
2277         int     kdb_brk;
2278
2279 again:
2280 #endif
2281
2282         if (COM_IIR_TXRDYBUG(com->flags)) {
2283                 int_ctl = inb(com->int_ctl_port);
2284                 int_ctl_new = int_ctl;
2285         } else {
2286                 int_ctl = 0;
2287                 int_ctl_new = 0;
2288         }
2289
2290         while (!com->gone) {
2291 #ifdef PC98
2292 status_read:;
2293                 if (IS_8251(com->pc98_if_type)) {
2294                         if (com->pc98_8251fifo_enable)
2295                                 tmp = inb(I8251F_lsr);
2296                         else
2297                                 tmp = inb(com->sts_port);
2298 more_intr:
2299                         line_status = 0;
2300                         if (com->pc98_8251fifo_enable) {
2301                             if (tmp & FLSR_TxRDY) line_status |= LSR_TXRDY;
2302                             if (tmp & FLSR_RxRDY) line_status |= LSR_RXRDY;
2303                             if (tmp & FLSR_TxEMP) line_status |= LSR_TSRE;
2304                             if (tmp & FLSR_PE)    line_status |= LSR_PE;
2305                             if (tmp & FLSR_OE)    line_status |= LSR_OE;
2306                             if (tmp & FLSR_BI)    line_status |= LSR_BI;
2307                         } else {
2308                             if (tmp & STS8251_TxRDY)  line_status |= LSR_TXRDY;
2309                             if (tmp & STS8251_RxRDY)  line_status |= LSR_RXRDY;
2310                             if (tmp & STS8251_TxEMP)  line_status |= LSR_TSRE;
2311                             if (tmp & STS8251_PE)     line_status |= LSR_PE;
2312                             if (tmp & STS8251_OE)     line_status |= LSR_OE;
2313                             if (tmp & STS8251_FE)     line_status |= LSR_FE;
2314                             if (tmp & STS8251_BI)     line_status |= LSR_BI;
2315                         }
2316                 } else {
2317 #endif /* PC98 */
2318                 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
2319                         modem_status = inb(com->modem_status_port);
2320                         if ((modem_status ^ com->last_modem_status) &
2321                             com->pps_bit) {
2322                                 pps_capture(&com->pps);
2323                                 pps_event(&com->pps,
2324                                     (modem_status & com->pps_bit) ? 
2325                                     PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
2326                         }
2327                 }
2328                 line_status = inb(com->line_status_port);
2329 #ifdef PC98
2330                 }
2331                 if (com->pc98_if_type == COM_IF_RSA98III)
2332                         rsa_buf_status = inb(com->rsabase + rsa_srr);
2333 #endif /* PC98 */
2334
2335                 /* input event? (check first to help avoid overruns) */
2336 #ifndef PC98
2337                 while (line_status & LSR_RCV_MASK) {
2338 #else
2339                 while ((line_status & LSR_RCV_MASK)
2340                        || (com->pc98_if_type == COM_IF_RSA98III
2341                            && (rsa_buf_status & 0x08))) {
2342 #endif /* PC98 */
2343                         /* break/unnattached error bits or real input? */
2344 #ifdef PC98
2345                         if (IS_8251(com->pc98_if_type)) {
2346                                 if (com->pc98_8251fifo_enable) {
2347                                     recv_data = inb(I8251F_data);
2348                                     if (tmp &
2349                                         (FLSR_PE | FLSR_OE | FLSR_BI)) {
2350                                         pc98_i8251_or_cmd(com, CMD8251_ER);
2351                                         recv_data = 0;
2352                                     }
2353                                 } else {
2354                                     recv_data = inb(com->data_port);
2355                                     if (tmp & (STS8251_PE | STS8251_OE |
2356                                                STS8251_FE | STS8251_BI)) {
2357                                         pc98_i8251_or_cmd(com, CMD8251_ER);
2358                                         recv_data = 0;
2359                                     }
2360                                 }
2361                         } else if (com->pc98_if_type == COM_IF_RSA98III) {
2362                                 if (!(rsa_buf_status & 0x08))
2363                                         recv_data = 0;
2364                                 else
2365                                         recv_data = inb(com->data_port);
2366                         } else
2367 #endif
2368                         if (!(line_status & LSR_RXRDY))
2369                                 recv_data = 0;
2370                         else
2371                                 recv_data = inb(com->data_port);
2372 #ifdef KDB
2373 #ifdef ALT_BREAK_TO_DEBUGGER
2374                         if (com->unit == comconsole &&
2375                             (kdb_brk = kdb_alt_break(recv_data,
2376                                         &com->alt_brk_state)) != 0) {
2377                                 mtx_unlock_spin(&sio_lock);
2378                                 switch (kdb_brk) {
2379                                 case KDB_REQ_DEBUGGER:
2380                                         kdb_enter(KDB_WHY_BREAK,
2381                                             "Break sequence on console");
2382                                         break;
2383                                 case KDB_REQ_PANIC:
2384                                         kdb_panic("panic on console");
2385                                         break;
2386                                 case KDB_REQ_REBOOT:
2387                                         kdb_reboot();
2388                                         break;
2389                                 }
2390                                 mtx_lock_spin(&sio_lock);
2391                                 goto again;
2392                         }
2393 #endif /* ALT_BREAK_TO_DEBUGGER */
2394 #endif /* KDB */
2395                         if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
2396                                 /*
2397                                  * Don't store BI if IGNBRK or FE/PE if IGNPAR.
2398                                  * Otherwise, push the work to a higher level
2399                                  * (to handle PARMRK) if we're bypassing.
2400                                  * Otherwise, convert BI/FE and PE+INPCK to 0.
2401                                  *
2402                                  * This makes bypassing work right in the
2403                                  * usual "raw" case (IGNBRK set, and IGNPAR
2404                                  * and INPCK clear).
2405                                  *
2406                                  * Note: BI together with FE/PE means just BI.
2407                                  */
2408                                 if (line_status & LSR_BI) {
2409 #if defined(KDB) && defined(BREAK_TO_DEBUGGER)
2410                                         if (com->unit == comconsole) {
2411                                                 kdb_enter(KDB_WHY_BREAK,
2412                                                     "Line break on console");
2413                                                 goto cont;
2414                                         }
2415 #endif
2416                                         if (com->tp == NULL
2417                                             || com->tp->t_iflag & IGNBRK)
2418                                                 goto cont;
2419                                 } else {
2420                                         if (com->tp == NULL
2421                                             || com->tp->t_iflag & IGNPAR)
2422                                                 goto cont;
2423                                 }
2424                                 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
2425                                     && (line_status & (LSR_BI | LSR_FE)
2426                                         || com->tp->t_iflag & INPCK))
2427                                         recv_data = 0;
2428                         }
2429                         ++com->bytes_in;
2430                         if (com->tp != NULL &&
2431                             com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar)
2432                                 swi_sched(sio_fast_ih, 0);
2433                         ioptr = com->iptr;
2434                         if (ioptr >= com->ibufend)
2435                                 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
2436                         else {
2437                                 if (com->tp != NULL && com->tp->t_do_timestamp)
2438                                         microtime(&com->tp->t_timestamp);
2439                                 ++com_events;
2440                                 swi_sched(sio_slow_ih, SWI_DELAY);
2441 #if 0 /* for testing input latency vs efficiency */
2442 if (com->iptr - com->ibuf == 8)
2443         swi_sched(sio_fast_ih, 0);
2444 #endif
2445                                 ioptr[0] = recv_data;
2446                                 ioptr[com->ierroff] = line_status;
2447                                 com->iptr = ++ioptr;
2448                                 if (ioptr == com->ihighwater
2449                                     && com->state & CS_RTS_IFLOW)
2450 #ifdef PC98
2451                                         IS_8251(com->pc98_if_type) ?
2452                                                 com_tiocm_bic(com, TIOCM_RTS) :
2453 #endif
2454                                         outb(com->modem_ctl_port,
2455                                              com->mcr_image &= ~MCR_RTS);
2456                                 if (line_status & LSR_OE)
2457                                         CE_RECORD(com, CE_OVERRUN);
2458                         }
2459 cont:
2460                         if (line_status & LSR_TXRDY
2461                             && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY))
2462                                 goto txrdy;
2463
2464                         /*
2465                          * "& 0x7F" is to avoid the gcc-1.40 generating a slow
2466                          * jump from the top of the loop to here
2467                          */
2468 #ifdef PC98
2469                         if (IS_8251(com->pc98_if_type))
2470                                 goto status_read;
2471                         else
2472 #endif
2473                         line_status = inb(com->line_status_port) & 0x7F;
2474 #ifdef PC98
2475                         if (com->pc98_if_type == COM_IF_RSA98III)
2476                                 rsa_buf_status = inb(com->rsabase + rsa_srr);
2477 #endif /* PC98 */
2478                 }
2479
2480                 /* modem status change? (always check before doing output) */
2481 #ifdef PC98
2482                 if (!IS_8251(com->pc98_if_type)) {
2483 #endif
2484                 modem_status = inb(com->modem_status_port);
2485                 if (modem_status != com->last_modem_status) {
2486                         /*
2487                          * Schedule high level to handle DCD changes.  Note
2488                          * that we don't use the delta bits anywhere.  Some
2489                          * UARTs mess them up, and it's easy to remember the
2490                          * previous bits and calculate the delta.
2491                          */
2492                         com->last_modem_status = modem_status;
2493                         if (!(com->state & CS_CHECKMSR)) {
2494                                 com_events += LOTS_OF_EVENTS;
2495                                 com->state |= CS_CHECKMSR;
2496                                 swi_sched(sio_fast_ih, 0);
2497                         }
2498
2499                         /* handle CTS change immediately for crisp flow ctl */
2500                         if (com->state & CS_CTS_OFLOW) {
2501                                 if (modem_status & MSR_CTS)
2502                                         com->state |= CS_ODEVREADY;
2503                                 else
2504                                         com->state &= ~CS_ODEVREADY;
2505                         }
2506                 }
2507 #ifdef PC98
2508                 }
2509 #endif
2510
2511 txrdy:
2512                 /* output queued and everything ready? */
2513 #ifndef PC98
2514                 if (line_status & LSR_TXRDY
2515                     && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2516 #else
2517                 if (((com->pc98_if_type == COM_IF_RSA98III)
2518                      ? (rsa_buf_status & 0x02)
2519                      : (line_status & LSR_TXRDY))
2520                     && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2521 #endif
2522 #ifdef PC98
2523                         Port_t  tmp_data_port;
2524                         
2525                         if (IS_8251(com->pc98_if_type) &&
2526                             com->pc98_8251fifo_enable)
2527                                 tmp_data_port = I8251F_data;
2528                         else
2529                                 tmp_data_port = com->data_port;
2530 #endif
2531
2532                         ioptr = com->obufq.l_head;
2533                         if (com->tx_fifo_size > 1 && com->unit != siotsunit) {
2534                                 u_int   ocount;
2535
2536                                 ocount = com->obufq.l_tail - ioptr;
2537 #ifdef PC98
2538                                 if (com->pc98_if_type == COM_IF_RSA98III) {
2539                                   rsa_buf_status = inb(com->rsabase + rsa_srr);
2540                                   rsa_tx_fifo_size = 1024;
2541                                   if (!(rsa_buf_status & 0x01))
2542                                       rsa_tx_fifo_size = 2048;
2543                                   if (ocount > rsa_tx_fifo_size)
2544                                       ocount = rsa_tx_fifo_size;
2545                                 } else
2546 #endif
2547                                 if (ocount > com->tx_fifo_size)
2548                                         ocount = com->tx_fifo_size;
2549                                 com->bytes_out += ocount;
2550                                 do
2551 #ifdef PC98
2552                                         outb(tmp_data_port, *ioptr++);
2553 #else
2554                                         outb(com->data_port, *ioptr++);
2555 #endif
2556                                 while (--ocount != 0);
2557                         } else {
2558 #ifdef PC98
2559                                 outb(tmp_data_port, *ioptr++);
2560 #else
2561                                 outb(com->data_port, *ioptr++);
2562 #endif
2563                                 ++com->bytes_out;
2564                                 if (com->unit == siotsunit
2565                                     && siotso < sizeof siots / sizeof siots[0])
2566                                         nanouptime(&siots[siotso++]);
2567                         }
2568 #ifdef PC98
2569                         if (IS_8251(com->pc98_if_type))
2570                             if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG))
2571                                 com_int_Tx_enable(com);
2572 #endif
2573                         com->obufq.l_head = ioptr;
2574                         if (COM_IIR_TXRDYBUG(com->flags))
2575                                 int_ctl_new = int_ctl | IER_ETXRDY;
2576                         if (ioptr >= com->obufq.l_tail) {
2577                                 struct lbq      *qp;
2578
2579                                 qp = com->obufq.l_next;
2580                                 qp->l_queued = FALSE;
2581                                 qp = qp->l_next;
2582                                 if (qp != NULL) {
2583                                         com->obufq.l_head = qp->l_head;
2584                                         com->obufq.l_tail = qp->l_tail;
2585                                         com->obufq.l_next = qp;
2586                                 } else {
2587                                         /* output just completed */
2588                                         if (COM_IIR_TXRDYBUG(com->flags))
2589                                                 int_ctl_new = int_ctl
2590                                                               & ~IER_ETXRDY;
2591                                         com->state &= ~CS_BUSY;
2592 #if defined(PC98)
2593                                         if (IS_8251(com->pc98_if_type) &&
2594                                             pc98_check_i8251_interrupt(com) & IEN_TxFLAG)
2595                                                 com_int_Tx_disable(com);
2596 #endif
2597                                 }
2598                                 if (!(com->state & CS_ODONE)) {
2599                                         com_events += LOTS_OF_EVENTS;
2600                                         com->state |= CS_ODONE;
2601                                         /* handle at high level ASAP */
2602                                         swi_sched(sio_fast_ih, 0);
2603                                 }
2604                         }
2605 #ifdef PC98
2606                         if (COM_IIR_TXRDYBUG(com->flags)
2607                             && int_ctl != int_ctl_new) {
2608                                 if (com->pc98_if_type == COM_IF_RSA98III) {
2609                                     int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
2610                                     outb(com->int_ctl_port, int_ctl_new);
2611                                     outb(com->rsabase + rsa_ier, 0x1d);
2612                                 } else
2613                                     outb(com->int_ctl_port, int_ctl_new);
2614                         }
2615 #else
2616                         if (COM_IIR_TXRDYBUG(com->flags)
2617                             && int_ctl != int_ctl_new)
2618                                 outb(com->int_ctl_port, int_ctl_new);
2619 #endif
2620                 }
2621 #ifdef PC98
2622                 else if (line_status & LSR_TXRDY) {
2623                     if (IS_8251(com->pc98_if_type))
2624                         if (pc98_check_i8251_interrupt(com) & IEN_TxFLAG)
2625                             com_int_Tx_disable(com);
2626                 }
2627                 if (IS_8251(com->pc98_if_type)) {
2628                     if (com->pc98_8251fifo_enable) {
2629                         if ((tmp = inb(I8251F_lsr)) & FLSR_RxRDY)
2630                             goto more_intr;
2631                     } else {
2632                         if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
2633                             goto more_intr;
2634                     }
2635                 }
2636 #endif
2637
2638                 /* finished? */
2639 #ifndef COM_MULTIPORT
2640 #ifdef PC98
2641                 if (IS_8251(com->pc98_if_type))
2642                         return;
2643 #endif
2644                 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
2645 #endif /* COM_MULTIPORT */
2646                         return;
2647         }
2648 }
2649
2650 /* software interrupt handler for SWI_TTY */
2651 static void
2652 siopoll(void *dummy)
2653 {
2654         int             unit;
2655
2656         if (com_events == 0)
2657                 return;
2658 repeat:
2659         for (unit = 0; unit < sio_numunits; ++unit) {
2660                 struct com_s    *com;
2661                 int             incc;
2662                 struct tty      *tp;
2663
2664                 com = com_addr(unit);
2665                 if (com == NULL)
2666                         continue;
2667                 tp = com->tp;
2668                 if (tp == NULL || com->gone) {
2669                         /*
2670                          * Discard any events related to never-opened or
2671                          * going-away devices.
2672                          */
2673                         mtx_lock_spin(&sio_lock);
2674                         incc = com->iptr - com->ibuf;
2675                         com->iptr = com->ibuf;
2676                         if (com->state & CS_CHECKMSR) {
2677                                 incc += LOTS_OF_EVENTS;
2678                                 com->state &= ~CS_CHECKMSR;
2679                         }
2680                         com_events -= incc;
2681                         mtx_unlock_spin(&sio_lock);
2682                         continue;
2683                 }
2684                 if (com->iptr != com->ibuf) {
2685                         mtx_lock_spin(&sio_lock);
2686                         sioinput(com);
2687                         mtx_unlock_spin(&sio_lock);
2688                 }
2689                 if (com->state & CS_CHECKMSR) {
2690                         u_char  delta_modem_status;
2691
2692 #ifdef PC98
2693                         if (!IS_8251(com->pc98_if_type)) {
2694 #endif
2695                         mtx_lock_spin(&sio_lock);
2696                         delta_modem_status = com->last_modem_status
2697                                              ^ com->prev_modem_status;
2698                         com->prev_modem_status = com->last_modem_status;
2699                         com_events -= LOTS_OF_EVENTS;
2700                         com->state &= ~CS_CHECKMSR;
2701                         mtx_unlock_spin(&sio_lock);
2702                         if (delta_modem_status & MSR_DCD)
2703                                 ttyld_modem(tp,
2704                                     com->prev_modem_status & MSR_DCD);
2705 #ifdef PC98
2706                         }
2707 #endif
2708                 }
2709                 if (com->state & CS_ODONE) {
2710                         mtx_lock_spin(&sio_lock);
2711                         com_events -= LOTS_OF_EVENTS;
2712                         com->state &= ~CS_ODONE;
2713                         mtx_unlock_spin(&sio_lock);
2714                         if (!(com->state & CS_BUSY)
2715                             && !(com->extra_state & CSE_BUSYCHECK)) {
2716                                 timeout(siobusycheck, com, hz / 100);
2717                                 com->extra_state |= CSE_BUSYCHECK;
2718                         }
2719                         ttyld_start(tp);
2720                 }
2721                 if (com_events == 0)
2722                         break;
2723         }
2724         if (com_events >= LOTS_OF_EVENTS)
2725                 goto repeat;
2726 }
2727
2728 static void
2729 combreak(tp, sig)
2730         struct tty      *tp;
2731         int             sig;
2732 {
2733         struct com_s    *com;
2734
2735         com = tp->t_sc;
2736
2737 #ifdef PC98
2738         if (sig)
2739                 com_send_break_on(com);
2740         else
2741                 com_send_break_off(com);
2742 #else
2743         if (sig)
2744                 sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2745         else
2746                 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2747 #endif
2748 }
2749
2750 static int
2751 comparam(tp, t)
2752         struct tty      *tp;
2753         struct termios  *t;
2754 {
2755         u_int           cfcr;
2756         int             cflag;
2757         struct com_s    *com;
2758         u_int           divisor;
2759         u_char          dlbh;
2760         u_char          dlbl;
2761         u_char          efr_flowbits;
2762         int             s;
2763 #ifdef PC98
2764         u_char          param = 0;
2765 #endif
2766
2767         com = tp->t_sc;
2768         if (com == NULL)
2769                 return (ENODEV);
2770
2771 #ifdef PC98
2772         cfcr = 0;
2773
2774         if (IS_8251(com->pc98_if_type)) {
2775                 if (pc98_ttspeedtab(com, t->c_ospeed, &divisor) != 0)
2776                         return (EINVAL);
2777         } else {
2778 #endif
2779         /* check requested parameters */
2780         if (t->c_ispeed != (t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed))
2781                 return (EINVAL);
2782         divisor = siodivisor(com->rclk, t->c_ispeed);
2783         if (divisor == 0)
2784                 return (EINVAL);
2785 #ifdef PC98
2786         }
2787 #endif
2788
2789         /* parameters are OK, convert them to the com struct and the device */
2790         s = spltty();
2791 #ifdef PC98
2792         if (IS_8251(com->pc98_if_type)) {
2793                 if (t->c_ospeed == 0)
2794                         com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
2795                 else
2796                         com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
2797         } else
2798 #endif
2799         if (t->c_ospeed == 0)
2800                 (void)commodem(tp, 0, SER_DTR); /* hang up line */
2801         else
2802                 (void)commodem(tp, SER_DTR, 0);
2803         cflag = t->c_cflag;
2804 #ifdef PC98
2805         if (!IS_8251(com->pc98_if_type)) {
2806 #endif
2807         switch (cflag & CSIZE) {
2808         case CS5:
2809                 cfcr = CFCR_5BITS;
2810                 break;
2811         case CS6:
2812                 cfcr = CFCR_6BITS;
2813                 break;
2814         case CS7:
2815                 cfcr = CFCR_7BITS;
2816                 break;
2817         default:
2818                 cfcr = CFCR_8BITS;
2819                 break;
2820         }
2821         if (cflag & PARENB) {
2822                 cfcr |= CFCR_PENAB;
2823                 if (!(cflag & PARODD))
2824                         cfcr |= CFCR_PEVEN;
2825         }
2826         if (cflag & CSTOPB)
2827                 cfcr |= CFCR_STOPB;
2828
2829         if (com->hasfifo) {
2830                 /*
2831                  * Use a fifo trigger level low enough so that the input
2832                  * latency from the fifo is less than about 16 msec and
2833                  * the total latency is less than about 30 msec.  These
2834                  * latencies are reasonable for humans.  Serial comms
2835                  * protocols shouldn't expect anything better since modem
2836                  * latencies are larger.
2837                  *
2838                  * The fifo trigger level cannot be set at RX_HIGH for high
2839                  * speed connections without further work on reducing 
2840                  * interrupt disablement times in other parts of the system,
2841                  * without producing silo overflow errors.
2842                  */
2843                 com->fifo_image = com->unit == siotsunit ? 0
2844                                   : t->c_ispeed <= 4800
2845                                   ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
2846 #ifdef COM_ESP
2847                 /*
2848                  * The Hayes ESP card needs the fifo DMA mode bit set
2849                  * in compatibility mode.  If not, it will interrupt
2850                  * for each character received.
2851                  */
2852                 if (com->esp)
2853                         com->fifo_image |= FIFO_DMA_MODE;
2854 #endif
2855                 sio_setreg(com, com_fifo, com->fifo_image);
2856         }
2857 #ifdef PC98
2858         }
2859 #endif
2860
2861         /*
2862          * This returns with interrupts disabled so that we can complete
2863          * the speed change atomically.  Keeping interrupts disabled is
2864          * especially important while com_data is hidden.
2865          */
2866         (void) siosetwater(com, t->c_ispeed);
2867
2868 #ifdef PC98
2869         if (IS_8251(com->pc98_if_type))
2870                 com_cflag_and_speed_set(com, cflag, t->c_ospeed);
2871         else {
2872 #endif
2873         sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2874         /*
2875          * Only set the divisor registers if they would change, since on
2876          * some 16550 incompatibles (UMC8669F), setting them while input
2877          * is arriving loses sync until data stops arriving.
2878          */
2879         dlbl = divisor & 0xFF;
2880         if (sio_getreg(com, com_dlbl) != dlbl)
2881                 sio_setreg(com, com_dlbl, dlbl);
2882         dlbh = divisor >> 8;
2883         if (sio_getreg(com, com_dlbh) != dlbh)
2884                 sio_setreg(com, com_dlbh, dlbh);
2885 #ifdef PC98
2886         }
2887 #endif
2888
2889         efr_flowbits = 0;
2890
2891         if (cflag & CRTS_IFLOW) {
2892                 com->state |= CS_RTS_IFLOW;
2893                 efr_flowbits |= EFR_AUTORTS;
2894                 /*
2895                  * If CS_RTS_IFLOW just changed from off to on, the change
2896                  * needs to be propagated to MCR_RTS.  This isn't urgent,
2897                  * so do it later by calling comstart() instead of repeating
2898                  * a lot of code from comstart() here.
2899                  */
2900         } else if (com->state & CS_RTS_IFLOW) {
2901                 com->state &= ~CS_RTS_IFLOW;
2902                 /*
2903                  * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
2904                  * on here, since comstart() won't do it later.
2905                  */
2906 #ifdef PC98
2907                 if (IS_8251(com->pc98_if_type))
2908                         com_tiocm_bis(com, TIOCM_RTS);
2909                 else
2910                         outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2911 #else
2912                 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2913 #endif
2914         }
2915
2916         /*
2917          * Set up state to handle output flow control.
2918          * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2919          * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2920          */
2921         com->state |= CS_ODEVREADY;
2922         com->state &= ~CS_CTS_OFLOW;
2923 #ifdef PC98
2924         if (com->pc98_if_type == COM_IF_RSA98III) {
2925                 param = inb(com->rsabase + rsa_msr);
2926                 outb(com->rsabase + rsa_msr, param & 0x14);
2927         }
2928 #endif
2929         if (cflag & CCTS_OFLOW) {
2930                 com->state |= CS_CTS_OFLOW;
2931                 efr_flowbits |= EFR_AUTOCTS;
2932 #ifdef PC98
2933                 if (IS_8251(com->pc98_if_type)) {
2934                         if (!(pc98_get_modem_status(com) & TIOCM_CTS))
2935                                 com->state &= ~CS_ODEVREADY;
2936                 } else if (com->pc98_if_type == COM_IF_RSA98III) {
2937                         /* Set automatic flow control mode */
2938                         outb(com->rsabase + rsa_msr, param | 0x08);
2939                 } else
2940 #endif
2941                 if (!(com->last_modem_status & MSR_CTS))
2942                         com->state &= ~CS_ODEVREADY;
2943         }
2944
2945 #ifdef PC98
2946         if (!IS_8251(com->pc98_if_type))
2947                 sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
2948 #else
2949         if (com->st16650a) {
2950                 sio_setreg(com, com_lcr, LCR_EFR_ENABLE);
2951                 sio_setreg(com, com_efr,
2952                            (sio_getreg(com, com_efr)
2953                             & ~(EFR_AUTOCTS | EFR_AUTORTS)) | efr_flowbits);
2954         }
2955         sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
2956 #endif
2957
2958         /* XXX shouldn't call functions while intrs are disabled. */
2959         ttyldoptim(tp);
2960
2961         mtx_unlock_spin(&sio_lock);
2962         splx(s);
2963         comstart(tp);
2964         if (com->ibufold != NULL) {
2965                 free(com->ibufold, M_DEVBUF);
2966                 com->ibufold = NULL;
2967         }
2968         return (0);
2969 }
2970
2971 /*
2972  * This function must be called with the sio_lock mutex released and will
2973  * return with it obtained.
2974  */
2975 static int
2976 siosetwater(com, speed)
2977         struct com_s    *com;
2978         speed_t         speed;
2979 {
2980         int             cp4ticks;
2981         u_char          *ibuf;
2982         int             ibufsize;
2983         struct tty      *tp;
2984
2985         /*
2986          * Make the buffer size large enough to handle a softtty interrupt
2987          * latency of about 2 ticks without loss of throughput or data
2988          * (about 3 ticks if input flow control is not used or not honoured,
2989          * but a bit less for CS5-CS7 modes).
2990          */
2991         cp4ticks = speed / 10 / hz * 4;
2992         for (ibufsize = 128; ibufsize < cp4ticks;)
2993                 ibufsize <<= 1;
2994 #ifdef PC98
2995         if (com->pc98_if_type == COM_IF_RSA98III)
2996                 ibufsize = 2048;
2997 #endif
2998         if (ibufsize == com->ibufsize) {
2999                 mtx_lock_spin(&sio_lock);
3000                 return (0);
3001         }
3002
3003         /*
3004          * Allocate input buffer.  The extra factor of 2 in the size is
3005          * to allow for an error byte for each input byte.
3006          */
3007         ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
3008         if (ibuf == NULL) {
3009                 mtx_lock_spin(&sio_lock);
3010                 return (ENOMEM);
3011         }
3012
3013         /* Initialize non-critical variables. */
3014         com->ibufold = com->ibuf;
3015         com->ibufsize = ibufsize;
3016         tp = com->tp;
3017         if (tp != NULL) {
3018                 tp->t_ififosize = 2 * ibufsize;
3019                 tp->t_ispeedwat = (speed_t)-1;
3020                 tp->t_ospeedwat = (speed_t)-1;
3021         }
3022
3023         /*
3024          * Read current input buffer, if any.  Continue with interrupts
3025          * disabled.
3026          */
3027         mtx_lock_spin(&sio_lock);
3028         if (com->iptr != com->ibuf)
3029                 sioinput(com);
3030
3031         /*-
3032          * Initialize critical variables, including input buffer watermarks.
3033          * The external device is asked to stop sending when the buffer
3034          * exactly reaches high water, or when the high level requests it.
3035          * The high level is notified immediately (rather than at a later
3036          * clock tick) when this watermark is reached.
3037          * The buffer size is chosen so the watermark should almost never
3038          * be reached.
3039          * The low watermark is invisibly 0 since the buffer is always
3040          * emptied all at once.
3041          */
3042         com->iptr = com->ibuf = ibuf;
3043         com->ibufend = ibuf + ibufsize;
3044         com->ierroff = ibufsize;
3045         com->ihighwater = ibuf + 3 * ibufsize / 4;
3046         return (0);
3047 }
3048
3049 static void
3050 comstart(tp)
3051         struct tty      *tp;
3052 {
3053         struct com_s    *com;
3054         int             s;
3055
3056         com = tp->t_sc;
3057         if (com == NULL)
3058                 return;
3059         s = spltty();
3060         mtx_lock_spin(&sio_lock);
3061         if (tp->t_state & TS_TTSTOP)
3062                 com->state &= ~CS_TTGO;
3063         else
3064                 com->state |= CS_TTGO;
3065         if (tp->t_state & TS_TBLOCK) {
3066 #ifdef PC98
3067                 if (IS_8251(com->pc98_if_type)) {
3068                     if ((com_tiocm_get(com) & TIOCM_RTS) &&
3069                         (com->state & CS_RTS_IFLOW))
3070                         com_tiocm_bic(com, TIOCM_RTS);
3071                 } else {
3072                     if ((com->mcr_image & MCR_RTS) &&
3073                         (com->state & CS_RTS_IFLOW))
3074                         outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3075                 }
3076 #else
3077                 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
3078                         outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3079 #endif
3080         } else {
3081 #ifdef PC98
3082                 if (IS_8251(com->pc98_if_type)) {
3083                     if (!(com_tiocm_get(com) & TIOCM_RTS) &&
3084                         com->iptr < com->ihighwater &&
3085                         com->state & CS_RTS_IFLOW)
3086                         com_tiocm_bis(com, TIOCM_RTS);
3087                 } else {
3088                     if (!(com->mcr_image & MCR_RTS) &&
3089                         com->iptr < com->ihighwater &&
3090                         com->state & CS_RTS_IFLOW)
3091                         outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3092                 }
3093 #else
3094                 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
3095                     && com->state & CS_RTS_IFLOW)
3096                         outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3097 #endif
3098         }
3099         mtx_unlock_spin(&sio_lock);
3100         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
3101                 ttwwakeup(tp);
3102                 splx(s);
3103                 return;
3104         }
3105         if (tp->t_outq.c_cc != 0) {
3106                 struct lbq      *qp;
3107                 struct lbq      *next;
3108
3109                 if (!com->obufs[0].l_queued) {
3110                         com->obufs[0].l_tail
3111                             = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
3112 #ifdef PC98
3113                                                   com->obufsize);
3114 #else
3115                                                   sizeof com->obuf1);
3116 #endif
3117                         com->obufs[0].l_next = NULL;
3118                         com->obufs[0].l_queued = TRUE;
3119                         mtx_lock_spin(&sio_lock);
3120                         if (com->state & CS_BUSY) {
3121                                 qp = com->obufq.l_next;
3122                                 while ((next = qp->l_next) != NULL)
3123                                         qp = next;
3124                                 qp->l_next = &com->obufs[0];
3125                         } else {
3126                                 com->obufq.l_head = com->obufs[0].l_head;
3127                                 com->obufq.l_tail = com->obufs[0].l_tail;
3128                                 com->obufq.l_next = &com->obufs[0];
3129                                 com->state |= CS_BUSY;
3130                         }
3131                         mtx_unlock_spin(&sio_lock);
3132                 }
3133                 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
3134                         com->obufs[1].l_tail
3135                             = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
3136 #ifdef PC98
3137                                                   com->obufsize);
3138 #else
3139                                                   sizeof com->obuf2);
3140 #endif
3141                         com->obufs[1].l_next = NULL;
3142                         com->obufs[1].l_queued = TRUE;
3143                         mtx_lock_spin(&sio_lock);
3144                         if (com->state & CS_BUSY) {
3145                                 qp = com->obufq.l_next;
3146                                 while ((next = qp->l_next) != NULL)
3147                                         qp = next;
3148                                 qp->l_next = &com->obufs[1];
3149                         } else {
3150                                 com->obufq.l_head = com->obufs[1].l_head;
3151                                 com->obufq.l_tail = com->obufs[1].l_tail;
3152                                 com->obufq.l_next = &com->obufs[1];
3153                                 com->state |= CS_BUSY;
3154                         }
3155                         mtx_unlock_spin(&sio_lock);
3156                 }
3157                 tp->t_state |= TS_BUSY;
3158         }
3159         mtx_lock_spin(&sio_lock);
3160         if (com->state >= (CS_BUSY | CS_TTGO))
3161                 siointr1(com);  /* fake interrupt to start output */
3162         mtx_unlock_spin(&sio_lock);
3163         ttwwakeup(tp);
3164         splx(s);
3165 }
3166
3167 static void
3168 comstop(tp, rw)
3169         struct tty      *tp;
3170         int             rw;
3171 {
3172         struct com_s    *com;
3173 #ifdef PC98
3174         int             rsa98_tmp  = 0;
3175 #endif
3176
3177         com = tp->t_sc;
3178         if (com == NULL || com->gone)
3179                 return;
3180         mtx_lock_spin(&sio_lock);
3181         if (rw & FWRITE) {
3182 #ifdef PC98
3183                 if (!IS_8251(com->pc98_if_type)) {
3184 #endif
3185                 if (com->hasfifo)
3186 #ifdef COM_ESP
3187                     /* XXX avoid h/w bug. */
3188                     if (!com->esp)
3189 #endif
3190                         sio_setreg(com, com_fifo,
3191                                    FIFO_XMT_RST | com->fifo_image);
3192 #ifdef PC98
3193                 if (com->pc98_if_type == COM_IF_RSA98III)
3194                     for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3195                         sio_setreg(com, com_fifo,
3196                                    FIFO_XMT_RST | com->fifo_image);
3197                 }
3198 #endif
3199                 com->obufs[0].l_queued = FALSE;
3200                 com->obufs[1].l_queued = FALSE;
3201                 if (com->state & CS_ODONE)
3202                         com_events -= LOTS_OF_EVENTS;
3203                 com->state &= ~(CS_ODONE | CS_BUSY);
3204                 com->tp->t_state &= ~TS_BUSY;
3205         }
3206         if (rw & FREAD) {
3207 #ifdef PC98
3208                 if (!IS_8251(com->pc98_if_type)) {
3209                     if (com->pc98_if_type == COM_IF_RSA98III)
3210                         for (rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3211                             sio_getreg(com, com_data);
3212 #endif
3213                 if (com->hasfifo)
3214 #ifdef COM_ESP
3215                     /* XXX avoid h/w bug. */
3216                     if (!com->esp)
3217 #endif
3218                         sio_setreg(com, com_fifo,
3219                                    FIFO_RCV_RST | com->fifo_image);
3220 #ifdef PC98
3221                 }
3222 #endif
3223                 com_events -= (com->iptr - com->ibuf);
3224                 com->iptr = com->ibuf;
3225         }
3226         mtx_unlock_spin(&sio_lock);
3227         comstart(tp);
3228 }
3229
3230 static int
3231 commodem(struct tty *tp, int sigon, int sigoff)
3232 {
3233         struct com_s    *com;
3234         int     bitand, bitor, msr;
3235 #ifdef PC98
3236         int     clr, set;
3237 #endif
3238
3239         com = tp->t_sc;
3240         if (com->gone)
3241                 return(0);
3242         if (sigon != 0 || sigoff != 0) {
3243 #ifdef PC98
3244                 if (IS_8251(com->pc98_if_type)) {
3245                         bitand = bitor = 0;     
3246                         clr = set = 0;
3247                         if (sigoff & SER_DTR) {
3248                                 bitand |= TIOCM_DTR;
3249                                 clr |= CMD8251_DTR;
3250                         }
3251                         if (sigoff & SER_RTS) {
3252                                 bitand |= TIOCM_RTS;
3253                                 clr |= CMD8251_RxEN | CMD8251_RTS;
3254                         }
3255                         if (sigon & SER_DTR) {
3256                                 bitor |= TIOCM_DTR;
3257                                 set |= CMD8251_TxEN | CMD8251_RxEN |
3258                                         CMD8251_DTR;
3259                         }
3260                         if (sigon & SER_RTS) {
3261                                 bitor |= TIOCM_RTS;
3262                                 set |= CMD8251_TxEN | CMD8251_RxEN |
3263                                         CMD8251_RTS;
3264                         }
3265                         bitand = ~bitand;
3266                         mtx_lock_spin(&sio_lock);
3267                         com->pc98_prev_modem_status &= bitand;
3268                         com->pc98_prev_modem_status |= bitor;
3269                         pc98_i8251_clear_or_cmd(com, clr, set);
3270                         mtx_unlock_spin(&sio_lock);
3271                         return (0);
3272                 } else {
3273 #endif
3274                 bitand = bitor = 0;
3275                 if (sigoff & SER_DTR)
3276                         bitand |= MCR_DTR;
3277                 if (sigoff & SER_RTS)
3278                         bitand |= MCR_RTS;
3279                 if (sigon & SER_DTR)
3280                         bitor |= MCR_DTR;
3281                 if (sigon & SER_RTS)
3282                         bitor |= MCR_RTS;
3283                 bitand = ~bitand;
3284                 mtx_lock_spin(&sio_lock);
3285                 com->mcr_image &= bitand;
3286                 com->mcr_image |= bitor;
3287                 outb(com->modem_ctl_port, com->mcr_image);
3288                 mtx_unlock_spin(&sio_lock);
3289                 return (0);
3290 #ifdef PC98
3291                 }
3292 #endif
3293         } else {
3294 #ifdef PC98
3295                 if (IS_8251(com->pc98_if_type))
3296                         return (com_tiocm_get(com));
3297                 else {
3298 #endif
3299                 bitor = 0;
3300                 if (com->mcr_image & MCR_DTR)
3301                         bitor |= SER_DTR;
3302                 if (com->mcr_image & MCR_RTS)
3303                         bitor |= SER_RTS;
3304                 msr = com->prev_modem_status;
3305                 if (msr & MSR_CTS)
3306                         bitor |= SER_CTS;
3307                 if (msr & MSR_DCD)
3308                         bitor |= SER_DCD;
3309                 if (msr & MSR_DSR)
3310                         bitor |= SER_DSR;
3311                 if (msr & MSR_DSR)
3312                         bitor |= SER_DSR;
3313                 if (msr & (MSR_RI | MSR_TERI))
3314                         bitor |= SER_RI;
3315                 return (bitor);
3316 #ifdef PC98
3317                 }
3318 #endif
3319         }
3320 }
3321
3322 static void
3323 siosettimeout()
3324 {
3325         struct com_s    *com;
3326         bool_t          someopen;
3327         int             unit;
3328
3329         /*
3330          * Set our timeout period to 1 second if no polled devices are open.
3331          * Otherwise set it to max(1/200, 1/hz).
3332          * Enable timeouts iff some device is open.
3333          */
3334         untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3335         sio_timeout = hz;
3336         someopen = FALSE;
3337         for (unit = 0; unit < sio_numunits; ++unit) {
3338                 com = com_addr(unit);
3339                 if (com != NULL && com->tp != NULL
3340                     && com->tp->t_state & TS_ISOPEN && !com->gone) {
3341                         someopen = TRUE;
3342                         if (com->poll || com->poll_output) {
3343                                 sio_timeout = hz > 200 ? hz / 200 : 1;
3344                                 break;
3345                         }
3346                 }
3347         }
3348         if (someopen) {
3349                 sio_timeouts_until_log = hz / sio_timeout;
3350                 sio_timeout_handle = timeout(comwakeup, (void *)NULL,
3351                                              sio_timeout);
3352         } else {
3353                 /* Flush error messages, if any. */
3354                 sio_timeouts_until_log = 1;
3355                 comwakeup((void *)NULL);
3356                 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3357         }
3358 }
3359
3360 static void
3361 comwakeup(chan)
3362         void    *chan;
3363 {
3364         struct com_s    *com;
3365         int             unit;
3366
3367         sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
3368
3369         /*
3370          * Recover from lost output interrupts.
3371          * Poll any lines that don't use interrupts.
3372          */
3373         for (unit = 0; unit < sio_numunits; ++unit) {
3374                 com = com_addr(unit);
3375                 if (com != NULL && !com->gone
3376                     && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
3377                         mtx_lock_spin(&sio_lock);
3378                         siointr1(com);
3379                         mtx_unlock_spin(&sio_lock);
3380                 }
3381         }
3382
3383         /*
3384          * Check for and log errors, but not too often.
3385          */
3386         if (--sio_timeouts_until_log > 0)
3387                 return;
3388         sio_timeouts_until_log = hz / sio_timeout;
3389         for (unit = 0; unit < sio_numunits; ++unit) {
3390                 int     errnum;
3391
3392                 com = com_addr(unit);
3393                 if (com == NULL)
3394                         continue;
3395                 if (com->gone)
3396                         continue;
3397                 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3398                         u_int   delta;
3399                         u_long  total;
3400
3401                         mtx_lock_spin(&sio_lock);
3402                         delta = com->delta_error_counts[errnum];
3403                         com->delta_error_counts[errnum] = 0;
3404                         mtx_unlock_spin(&sio_lock);
3405                         if (delta == 0)
3406                                 continue;
3407                         total = com->error_counts[errnum] += delta;
3408                         log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3409                             unit, delta, error_desc[errnum],
3410                             delta == 1 ? "" : "s", total);
3411                 }
3412         }
3413 }
3414
3415 #ifdef PC98
3416 /* commint is called when modem control line changes */
3417 static void
3418 commint(struct cdev *dev)
3419 {
3420         register struct tty *tp;
3421         int     stat,delta;
3422         struct com_s *com;
3423
3424         com = dev->si_drv1;
3425         tp = com->tp;
3426
3427         stat = com_tiocm_get(com);
3428         delta = com_tiocm_get_delta(com);
3429
3430         if (com->state & CS_CTS_OFLOW) {
3431                 if (stat & TIOCM_CTS)
3432                         com->state |= CS_ODEVREADY;
3433                 else
3434                         com->state &= ~CS_ODEVREADY;
3435         }
3436         if ((delta & TIOCM_CAR) && (ISCALLOUT(dev)) == 0) {
3437             if (stat & TIOCM_CAR )
3438                 (void)ttyld_modem(tp, 1);
3439             else if (ttyld_modem(tp, 0) == 0) {
3440                 /* negate DTR, RTS */
3441                 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3442                                 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3443                 /* disable IENABLE */
3444                 com_int_TxRx_disable( com );
3445             }
3446         }
3447 }
3448 #endif
3449
3450 /*
3451  * Following are all routines needed for SIO to act as console
3452  */
3453 struct siocnstate {
3454         u_char  dlbl;
3455         u_char  dlbh;
3456         u_char  ier;
3457         u_char  cfcr;
3458         u_char  mcr;
3459 };
3460
3461 /*
3462  * This is a function in order to not replicate "ttyd%d" more
3463  * places than absolutely necessary.
3464  */
3465 static void
3466 siocnset(struct consdev *cd, int unit)
3467 {
3468
3469         cd->cn_unit = unit;
3470         sprintf(cd->cn_name, "ttyd%d", unit);
3471 }
3472
3473 static speed_t siocngetspeed(Port_t, u_long rclk);
3474 static void siocnclose(struct siocnstate *sp, Port_t iobase);
3475 static void siocnopen(struct siocnstate *sp, Port_t iobase, int speed);
3476 static void siocntxwait(Port_t iobase);
3477
3478 static cn_probe_t sio_cnprobe;
3479 static cn_init_t sio_cninit;
3480 static cn_term_t sio_cnterm;
3481 static cn_getc_t sio_cngetc;
3482 static cn_putc_t sio_cnputc;
3483
3484 CONSOLE_DRIVER(sio);
3485
3486 static void
3487 siocntxwait(iobase)
3488         Port_t  iobase;
3489 {
3490         int     timo;
3491
3492         /*
3493          * Wait for any pending transmission to finish.  Required to avoid
3494          * the UART lockup bug when the speed is changed, and for normal
3495          * transmits.
3496          */
3497         timo = 100000;
3498         while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3499                != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3500                 ;
3501 }
3502
3503 /*
3504  * Read the serial port specified and try to figure out what speed
3505  * it's currently running at.  We're assuming the serial port has
3506  * been initialized and is basicly idle.  This routine is only intended
3507  * to be run at system startup.
3508  *
3509  * If the value read from the serial port doesn't make sense, return 0.
3510  */
3511
3512 static speed_t
3513 siocngetspeed(iobase, rclk)
3514         Port_t  iobase;
3515         u_long  rclk;
3516 {
3517         u_int   divisor;
3518         u_char  dlbh;
3519         u_char  dlbl;
3520         u_char  cfcr;
3521
3522         cfcr = inb(iobase + com_cfcr);
3523         outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3524
3525         dlbl = inb(iobase + com_dlbl);
3526         dlbh = inb(iobase + com_dlbh);
3527
3528         outb(iobase + com_cfcr, cfcr);
3529
3530         divisor = dlbh << 8 | dlbl;
3531
3532         /* XXX there should be more sanity checking. */
3533         if (divisor == 0)
3534                 return (CONSPEED);
3535         return (rclk / (16UL * divisor));
3536 }
3537
3538 static void
3539 siocnopen(sp, iobase, speed)
3540         struct siocnstate       *sp;
3541         Port_t                  iobase;
3542         int                     speed;
3543 {
3544         u_int   divisor;
3545         u_char  dlbh;
3546         u_char  dlbl;
3547
3548         /*
3549          * Save all the device control registers except the fifo register
3550          * and set our default ones (cs8 -parenb speed=comdefaultrate).
3551          * We can't save the fifo register since it is read-only.
3552          */
3553         sp->ier = inb(iobase + com_ier);
3554         outb(iobase + com_ier, 0);      /* spltty() doesn't stop siointr() */
3555         siocntxwait(iobase);
3556         sp->cfcr = inb(iobase + com_cfcr);
3557         outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3558         sp->dlbl = inb(iobase + com_dlbl);
3559         sp->dlbh = inb(iobase + com_dlbh);
3560         /*
3561          * Only set the divisor registers if they would change, since on
3562          * some 16550 incompatibles (Startech), setting them clears the
3563          * data input register.  This also reduces the effects of the
3564          * UMC8669F bug.
3565          */
3566         divisor = siodivisor(comdefaultrclk, speed);
3567         dlbl = divisor & 0xFF;
3568         if (sp->dlbl != dlbl)
3569                 outb(iobase + com_dlbl, dlbl);
3570         dlbh = divisor >> 8;
3571         if (sp->dlbh != dlbh)
3572                 outb(iobase + com_dlbh, dlbh);
3573         outb(iobase + com_cfcr, CFCR_8BITS);
3574         sp->mcr = inb(iobase + com_mcr);
3575         /*
3576          * We don't want interrupts, but must be careful not to "disable"
3577          * them by clearing the MCR_IENABLE bit, since that might cause
3578          * an interrupt by floating the IRQ line.
3579          */
3580         outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
3581 }
3582
3583 static void
3584 siocnclose(sp, iobase)
3585         struct siocnstate       *sp;
3586         Port_t                  iobase;
3587 {
3588         /*
3589          * Restore the device control registers.
3590          */
3591         siocntxwait(iobase);
3592         outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3593         if (sp->dlbl != inb(iobase + com_dlbl))
3594                 outb(iobase + com_dlbl, sp->dlbl);
3595         if (sp->dlbh != inb(iobase + com_dlbh))
3596                 outb(iobase + com_dlbh, sp->dlbh);
3597         outb(iobase + com_cfcr, sp->cfcr);
3598         /*
3599          * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
3600          */
3601         outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
3602         outb(iobase + com_ier, sp->ier);
3603 }
3604
3605 static void
3606 sio_cnprobe(cp)
3607         struct consdev  *cp;
3608 {
3609         speed_t                 boot_speed;
3610         u_char                  cfcr;
3611         u_int                   divisor;
3612         int                     s, unit;
3613         struct siocnstate       sp;
3614
3615         /*
3616          * Find our first enabled console, if any.  If it is a high-level
3617          * console device, then initialize it and return successfully.
3618          * If it is a low-level console device, then initialize it and
3619          * return unsuccessfully.  It must be initialized in both cases
3620          * for early use by console drivers and debuggers.  Initializing
3621          * the hardware is not necessary in all cases, since the i/o
3622          * routines initialize it on the fly, but it is necessary if
3623          * input might arrive while the hardware is switched back to an
3624          * uninitialized state.  We can't handle multiple console devices
3625          * yet because our low-level routines don't take a device arg.
3626          * We trust the user to set the console flags properly so that we
3627          * don't need to probe.
3628          */
3629         cp->cn_pri = CN_DEAD;
3630
3631         for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
3632                 int flags;
3633
3634                 if (resource_disabled("sio", unit))
3635                         continue;
3636                 if (resource_int_value("sio", unit, "flags", &flags))
3637                         continue;
3638                 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
3639                         int port;
3640                         Port_t iobase;
3641
3642                         if (resource_int_value("sio", unit, "port", &port))
3643                                 continue;
3644                         iobase = port;
3645                         s = spltty();
3646                         if ((boothowto & RB_SERIAL) && COM_CONSOLE(flags)) {
3647                                 boot_speed =
3648                                     siocngetspeed(iobase, comdefaultrclk);
3649                                 if (boot_speed)
3650                                         comdefaultrate = boot_speed;
3651                         }
3652
3653                         /*
3654                          * Initialize the divisor latch.  We can't rely on
3655                          * siocnopen() to do this the first time, since it 
3656                          * avoids writing to the latch if the latch appears
3657                          * to have the correct value.  Also, if we didn't
3658                          * just read the speed from the hardware, then we
3659                          * need to set the speed in hardware so that
3660                          * switching it later is null.
3661                          */
3662                         cfcr = inb(iobase + com_cfcr);
3663                         outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3664                         divisor = siodivisor(comdefaultrclk, comdefaultrate);
3665                         outb(iobase + com_dlbl, divisor & 0xff);
3666                         outb(iobase + com_dlbh, divisor >> 8);
3667                         outb(iobase + com_cfcr, cfcr);
3668
3669                         siocnopen(&sp, iobase, comdefaultrate);
3670
3671                         splx(s);
3672                         if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
3673                                 siocnset(cp, unit);
3674                                 cp->cn_pri = COM_FORCECONSOLE(flags)
3675                                              || boothowto & RB_SERIAL
3676                                              ? CN_REMOTE : CN_NORMAL;
3677                                 siocniobase = iobase;
3678                                 siocnunit = unit;
3679                         }
3680 #ifdef GDB
3681                         if (COM_DEBUGGER(flags))
3682                                 siogdbiobase = iobase;
3683 #endif
3684                 }
3685         }
3686 }
3687
3688 static void
3689 sio_cninit(cp)
3690         struct consdev  *cp;
3691 {
3692         comconsole = cp->cn_unit;
3693 }
3694
3695 static void
3696 sio_cnterm(cp)
3697         struct consdev  *cp;
3698 {
3699         comconsole = -1;
3700 }
3701
3702 static int
3703 sio_cngetc(struct consdev *cd)
3704 {
3705         int     c;
3706         Port_t  iobase;
3707         int     s;
3708         struct siocnstate       sp;
3709         speed_t speed;
3710
3711         if (cd != NULL && cd->cn_unit == siocnunit) {
3712                 iobase = siocniobase;
3713                 speed = comdefaultrate;
3714         } else {
3715 #ifdef GDB
3716                 iobase = siogdbiobase;
3717                 speed = gdbdefaultrate;
3718 #else
3719                 return (-1);
3720 #endif
3721         }
3722         s = spltty();
3723         siocnopen(&sp, iobase, speed);
3724         if (inb(iobase + com_lsr) & LSR_RXRDY)
3725                 c = inb(iobase + com_data);
3726         else
3727                 c = -1;
3728         siocnclose(&sp, iobase);
3729         splx(s);
3730         return (c);
3731 }
3732
3733 static void
3734 sio_cnputc(struct consdev *cd, int c)
3735 {
3736         int     need_unlock;
3737         int     s;
3738         struct siocnstate       sp;
3739         Port_t  iobase;
3740         speed_t speed;
3741
3742         if (cd != NULL && cd->cn_unit == siocnunit) {
3743                 iobase = siocniobase;
3744                 speed = comdefaultrate;
3745         } else {
3746 #ifdef GDB
3747                 iobase = siogdbiobase;
3748                 speed = gdbdefaultrate;
3749 #else
3750                 return;
3751 #endif
3752         }
3753         s = spltty();
3754         need_unlock = 0;
3755         if (!kdb_active && sio_inited == 2 && !mtx_owned(&sio_lock)) {
3756                 mtx_lock_spin(&sio_lock);
3757                 need_unlock = 1;
3758         }
3759         siocnopen(&sp, iobase, speed);
3760         siocntxwait(iobase);
3761         outb(iobase + com_data, c);
3762         siocnclose(&sp, iobase);
3763         if (need_unlock)
3764                 mtx_unlock_spin(&sio_lock);
3765         splx(s);
3766 }
3767
3768 /*
3769  * Remote gdb(1) support.
3770  */
3771
3772 #if defined(GDB)
3773
3774 #include <gdb/gdb.h>
3775
3776 static gdb_probe_f siogdbprobe;
3777 static gdb_init_f siogdbinit;
3778 static gdb_term_f siogdbterm;
3779 static gdb_getc_f siogdbgetc;
3780 static gdb_putc_f siogdbputc;
3781
3782 GDB_DBGPORT(sio, siogdbprobe, siogdbinit, siogdbterm, siogdbgetc, siogdbputc);
3783
3784 static int
3785 siogdbprobe(void)
3786 {
3787         return ((siogdbiobase != 0) ? 0 : -1);
3788 }
3789
3790 static void
3791 siogdbinit(void)
3792 {
3793 }
3794
3795 static void
3796 siogdbterm(void)
3797 {
3798 }
3799
3800 static void
3801 siogdbputc(int c)
3802 {
3803         sio_cnputc(NULL, c);
3804 }
3805
3806 static int
3807 siogdbgetc(void)
3808 {
3809         return (sio_cngetc(NULL));
3810 }
3811
3812 #endif
3813
3814 #ifdef PC98
3815 /*
3816  *  pc98 local function
3817  */
3818 static void
3819 com_tiocm_bis(struct com_s *com, int msr)
3820 {
3821         int     s;
3822         int     tmp = 0;
3823
3824         s=spltty();
3825         com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3826         tmp |= CMD8251_TxEN|CMD8251_RxEN;
3827         if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3828         if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3829
3830         pc98_i8251_or_cmd( com, tmp );
3831         splx(s);
3832 }
3833
3834 static void
3835 com_tiocm_bic(struct com_s *com, int msr)
3836 {
3837         int     s;
3838         int     tmp = msr;
3839
3840         s=spltty();
3841         com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
3842         if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
3843         if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
3844
3845         pc98_i8251_clear_cmd( com, tmp );
3846         splx(s);
3847 }
3848
3849 static int
3850 com_tiocm_get(struct com_s *com)
3851 {
3852         return( com->pc98_prev_modem_status );
3853 }
3854
3855 static int
3856 com_tiocm_get_delta(struct com_s *com)
3857 {
3858         int     tmp;
3859
3860         tmp = com->pc98_modem_delta;
3861         com->pc98_modem_delta = 0;
3862         return( tmp );
3863 }
3864
3865 /* convert to TIOCM_?? ( ioctl.h ) */
3866 static int
3867 pc98_get_modem_status(struct com_s *com)
3868 {
3869         register int    msr;
3870
3871         msr = com->pc98_prev_modem_status
3872                         & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3873         if (com->pc98_8251fifo_enable) {
3874                 int     stat2;
3875
3876                 stat2 = inb(I8251F_msr);
3877                 if ( stat2 & MSR_DCD ) msr |= TIOCM_CAR;
3878                 if ( stat2 & MSR_RI ) msr |= TIOCM_RI;
3879                 if ( stat2 & MSR_DSR ) msr |= TIOCM_DSR;
3880                 if ( stat2 & MSR_CTS ) msr |= TIOCM_CTS;
3881 #if COM_CARRIER_DETECT_EMULATE
3882                 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
3883                         msr |= TIOCM_CAR;
3884                 }
3885 #endif
3886         } else {
3887                 int     stat, stat2;
3888                 
3889                 stat  = inb(com->sts_port);
3890                 stat2 = inb(com->in_modem_port);
3891                 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
3892                 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
3893                 if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
3894                 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
3895 #if COM_CARRIER_DETECT_EMULATE
3896                 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
3897                         msr |= TIOCM_CAR;
3898                 }
3899 #endif
3900         }
3901         return(msr);
3902 }
3903
3904 static void
3905 pc98_check_msr(void* chan)
3906 {
3907         int     msr, delta;
3908         int     s;
3909         register struct tty *tp;
3910         struct  com_s *com;
3911         struct cdev *dev;
3912
3913         dev=(struct cdev *)chan;
3914         com = dev->si_drv1;
3915         tp = dev->si_tty;
3916
3917         s = spltty();
3918         msr = pc98_get_modem_status(com);
3919         /* make change flag */
3920         delta = msr ^ com->pc98_prev_modem_status;
3921         if ( delta & TIOCM_CAR ) {
3922             if ( com->modem_car_chg_timer ) {
3923                 if ( -- com->modem_car_chg_timer )
3924                     msr ^= TIOCM_CAR;
3925             } else {
3926                 if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ?
3927                      DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0)
3928                     msr ^= TIOCM_CAR;
3929             }
3930         } else
3931             com->modem_car_chg_timer = 0;
3932         delta = ( msr ^ com->pc98_prev_modem_status ) &
3933                         (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
3934         com->pc98_prev_modem_status = msr;
3935         delta = ( com->pc98_modem_delta |= delta );
3936         splx(s);
3937         if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
3938                 if ( delta ) {
3939                         commint(dev);
3940                 }
3941                 timeout(pc98_check_msr, (caddr_t)dev,
3942                                         PC98_CHECK_MODEM_INTERVAL);
3943         } else {
3944                 com->modem_checking = 0;
3945         }
3946 }
3947
3948 static void
3949 pc98_msrint_start(struct cdev *dev)
3950 {
3951         struct  com_s *com;
3952         int     s = spltty();
3953
3954         com = dev->si_drv1;
3955         /* modem control line check routine envoke interval is 1/10 sec */
3956         if ( com->modem_checking == 0 ) {
3957                 com->pc98_prev_modem_status = pc98_get_modem_status(com);
3958                 com->pc98_modem_delta = 0;
3959                 timeout(pc98_check_msr, (caddr_t)dev,
3960                                         PC98_CHECK_MODEM_INTERVAL);
3961                 com->modem_checking = 1;
3962         }
3963         splx(s);
3964 }
3965
3966 static void
3967 pc98_disable_i8251_interrupt(struct com_s *com, int mod)
3968 {
3969         /* disable interrupt */
3970         register int    tmp;
3971
3972         mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3973         COM_INT_DISABLE
3974         tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3975         outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
3976         COM_INT_ENABLE
3977 }
3978
3979 static void
3980 pc98_enable_i8251_interrupt(struct com_s *com, int mod)
3981 {
3982         register int    tmp;
3983
3984         COM_INT_DISABLE
3985         tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
3986         outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
3987         COM_INT_ENABLE
3988 }
3989
3990 static int
3991 pc98_check_i8251_interrupt(struct com_s *com)
3992 {
3993         return ( com->intr_enable & 0x07 );
3994 }
3995
3996 static void
3997 pc98_i8251_clear_cmd(struct com_s *com, int x)
3998 {
3999         int     tmp;
4000
4001         COM_INT_DISABLE
4002         tmp = com->pc98_prev_siocmd & ~(x);
4003         if (com->pc98_8251fifo_enable)
4004             outb(I8251F_fcr, 0);
4005         outb(com->cmd_port, tmp);
4006         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4007         if (com->pc98_8251fifo_enable)
4008             outb(I8251F_fcr, FIFO_ENABLE);
4009         COM_INT_ENABLE
4010 }
4011
4012 static void
4013 pc98_i8251_or_cmd(struct com_s *com, int x)
4014 {
4015         int     tmp;
4016
4017         COM_INT_DISABLE
4018         if (com->pc98_8251fifo_enable)
4019             outb(I8251F_fcr, 0);
4020         tmp = com->pc98_prev_siocmd | (x);
4021         outb(com->cmd_port, tmp);
4022         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4023         if (com->pc98_8251fifo_enable)
4024             outb(I8251F_fcr, FIFO_ENABLE);
4025         COM_INT_ENABLE
4026 }
4027
4028 static void
4029 pc98_i8251_set_cmd(struct com_s *com, int x)
4030 {
4031         int     tmp;
4032
4033         COM_INT_DISABLE
4034         if (com->pc98_8251fifo_enable)
4035             outb(I8251F_fcr, 0);
4036         tmp = (x);
4037         outb(com->cmd_port, tmp);
4038         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4039         if (com->pc98_8251fifo_enable)
4040             outb(I8251F_fcr, FIFO_ENABLE);
4041         COM_INT_ENABLE
4042 }
4043
4044 static void
4045 pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
4046 {
4047         int     tmp;
4048         COM_INT_DISABLE
4049         if (com->pc98_8251fifo_enable)
4050             outb(I8251F_fcr, 0);
4051         tmp = com->pc98_prev_siocmd & ~(clr);
4052         tmp |= (x);
4053         outb(com->cmd_port, tmp);
4054         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4055         if (com->pc98_8251fifo_enable)
4056             outb(I8251F_fcr, FIFO_ENABLE);
4057         COM_INT_ENABLE
4058 }
4059
4060 static int
4061 pc98_i8251_get_cmd(struct com_s *com)
4062 {
4063         return com->pc98_prev_siocmd;
4064 }
4065
4066 static int
4067 pc98_i8251_get_mod(struct com_s *com)
4068 {
4069         return com->pc98_prev_siomod;
4070 }
4071
4072 static void
4073 pc98_i8251_reset(struct com_s *com, int mode, int command)
4074 {
4075         if (com->pc98_8251fifo_enable)
4076             outb(I8251F_fcr, 0);
4077         outb(com->cmd_port, 0); /* dummy */
4078         DELAY(2);
4079         outb(com->cmd_port, 0); /* dummy */
4080         DELAY(2);
4081         outb(com->cmd_port, 0); /* dummy */
4082         DELAY(2);
4083         outb(com->cmd_port, CMD8251_RESET);     /* internal reset */
4084         DELAY(2);
4085         outb(com->cmd_port, mode );     /* mode register */
4086         com->pc98_prev_siomod = mode;
4087         DELAY(2);
4088         pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
4089         DELAY(10);
4090         if (com->pc98_8251fifo_enable)
4091             outb(I8251F_fcr, FIFO_ENABLE | FIFO_XMT_RST | FIFO_RCV_RST);
4092 }
4093
4094 static void
4095 pc98_check_sysclock(void)
4096 {
4097         /* get system clock from port */
4098         if ( pc98_machine_type & M_8M ) {
4099         /* 8 MHz system & H98 */
4100                 sysclock = 8;
4101         } else {
4102         /* 5 MHz system */
4103                 sysclock = 5;
4104         }
4105 }
4106
4107 static void
4108 com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
4109 {
4110         int     cfcr=0;
4111         int     previnterrupt;
4112         int     tmp;
4113         u_int   count;
4114
4115         if (pc98_ttspeedtab(com, speed, &count) != 0)
4116                 return;
4117
4118         previnterrupt = pc98_check_i8251_interrupt(com);
4119         pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
4120
4121         switch ( cflag&CSIZE ) {
4122           case CS5:
4123                 cfcr = MOD8251_5BITS; break;
4124           case CS6:
4125                 cfcr = MOD8251_6BITS; break;
4126           case CS7:
4127                 cfcr = MOD8251_7BITS; break;
4128           case CS8:
4129                 cfcr = MOD8251_8BITS; break;
4130         }
4131         if ( cflag&PARENB ) {
4132             if ( cflag&PARODD )
4133                 cfcr |= MOD8251_PENAB;
4134             else
4135                 cfcr |= MOD8251_PENAB | MOD8251_PEVEN;
4136         }
4137
4138         if ( cflag&CSTOPB )
4139                 cfcr |= MOD8251_STOP2;
4140         else
4141                 cfcr |= MOD8251_STOP1;
4142
4143         if ( count & 0x10000 )
4144                 cfcr |= MOD8251_CLKx1;
4145         else
4146                 cfcr |= MOD8251_CLKx16;
4147
4148         while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
4149                 ;
4150
4151         /* set baud rate from ospeed */
4152         pc98_set_baud_rate( com, count );
4153
4154         if ( cfcr != pc98_i8251_get_mod(com) )
4155                 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
4156
4157         pc98_enable_i8251_interrupt( com, previnterrupt );
4158 }
4159
4160 static int
4161 pc98_ttspeedtab(struct com_s *com, int speed, u_int *divisor)
4162 {
4163         int     if_type, effect_sp, count = -1, mod;
4164
4165         if_type = com->pc98_if_type & 0x0f;
4166
4167         switch (com->pc98_if_type) {
4168         case COM_IF_INTERNAL:
4169             if (PC98SIO_baud_rate_port(if_type) != -1) {
4170                 count = ttspeedtab(speed, if_8251_type[if_type].speedtab);
4171                 if (count > 0) {
4172                     count |= COM1_EXT_CLOCK;
4173                     break;
4174                 }
4175             }
4176
4177             /* for *1CLK asynchronous! mode, TEFUTEFU */
4178             mod = (sysclock == 5) ? 2457600 : 1996800;
4179             effect_sp = ttspeedtab( speed, pc98speedtab );
4180             if ( effect_sp < 0 )        /* XXX */
4181                 effect_sp = ttspeedtab( (speed - 1), pc98speedtab );
4182             if ( effect_sp <= 0 )
4183                 return effect_sp;
4184             if ( effect_sp == speed )
4185                 mod /= 16;
4186             if ( mod % effect_sp )
4187                 return(-1);
4188             count = mod / effect_sp;
4189             if ( count > 65535 )
4190                 return(-1);
4191             if ( effect_sp != speed )
4192                 count |= 0x10000;
4193             break;
4194         case COM_IF_PC9861K_1:
4195         case COM_IF_PC9861K_2:
4196             count = 1;
4197             break;
4198         case COM_IF_IND_SS_1:
4199         case COM_IF_IND_SS_2:
4200         case COM_IF_PIO9032B_1:
4201         case COM_IF_PIO9032B_2:
4202             count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4203             break;
4204         case COM_IF_B98_01_1:
4205         case COM_IF_B98_01_2:
4206             count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4207 #ifdef B98_01_OLD
4208             if (count == 0 || count == 1) {
4209                 count += 4;
4210                 count |= 0x20000;  /* x1 mode for 76800 and 153600 */
4211             }
4212 #endif
4213             break;
4214         }
4215
4216         if (count < 0)
4217                 return count;
4218
4219         *divisor = (u_int) count;
4220         return 0;
4221 }
4222
4223 static void
4224 pc98_set_baud_rate( struct com_s *com, u_int count )
4225 {
4226         int     if_type, io, s;
4227
4228         if_type = com->pc98_if_type & 0x0f;
4229         io = rman_get_start(com->ioportres) & 0xff00;
4230
4231         switch (com->pc98_if_type) {
4232         case COM_IF_INTERNAL:
4233             if (PC98SIO_baud_rate_port(if_type) != -1) {
4234                 if (count & COM1_EXT_CLOCK) {
4235                     outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff);
4236                     break;
4237                 } else {
4238                     outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09);
4239                 }
4240             }
4241
4242             if (count == 0)
4243                 return;
4244
4245             /* set i8253 */
4246             s = splclock();
4247             if (count != 3)
4248                 outb( 0x77, 0xb6 );
4249             else
4250                 outb( 0x77, 0xb4 );
4251             outb( 0x5f, 0);
4252             outb( 0x75, count & 0xff );
4253             outb( 0x5f, 0);
4254             outb( 0x75, (count >> 8) & 0xff );
4255             splx(s);
4256             break;
4257         case COM_IF_IND_SS_1:
4258         case COM_IF_IND_SS_2:
4259             outb(io | PC98SIO_intr_ctrl_port(if_type), 0);
4260             outb(io | PC98SIO_baud_rate_port(if_type), 0);
4261             outb(io | PC98SIO_baud_rate_port(if_type), 0xc0);
4262             outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80);
4263             outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff);
4264             break;
4265         case COM_IF_PIO9032B_1:
4266         case COM_IF_PIO9032B_2:
4267             outb(io | PC98SIO_baud_rate_port(if_type), count);
4268             break;
4269         case COM_IF_B98_01_1:
4270         case COM_IF_B98_01_2:
4271             outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f);
4272 #ifdef B98_01_OLD
4273             /*
4274              * Some old B98_01 board should be controlled
4275              * in different way, but this hasn't been tested yet.
4276              */
4277             outb(io | PC98SIO_func_port(if_type),
4278                  (count & 0x20000) ? 0xf0 : 0xf2);
4279 #endif
4280             break;
4281         }
4282 }
4283 static int
4284 pc98_check_if_type(device_t dev, struct siodev *iod)
4285 {
4286         int     irr, io, if_type, tmp;
4287         static  short   irq_tab[2][8] = {
4288                 {  3,  5,  6,  9, 10, 12, 13, -1},
4289                 {  3, 10, 12, 13,  5,  6,  9, -1}
4290         };
4291
4292         if_type = iod->if_type & 0x0f;
4293         iod->irq = 0;
4294         io = isa_get_port(dev) & 0xff00;
4295
4296         if (IS_8251(iod->if_type)) {
4297             if (PC98SIO_func_port(if_type) != -1) {
4298                 outb(io | PC98SIO_func_port(if_type), 0xf2);
4299                 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab);
4300                 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1)
4301                     outb(io | PC98SIO_baud_rate_port(if_type), tmp);
4302             }
4303
4304             iod->cmd  = io | PC98SIO_cmd_port(if_type);
4305             iod->sts  = io | PC98SIO_sts_port(if_type);
4306             iod->mod  = io | PC98SIO_in_modem_port(if_type);
4307             iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type);
4308
4309             if (iod->if_type == COM_IF_INTERNAL) {
4310                 iod->irq = 4;
4311
4312                 if (pc98_check_8251vfast()) {
4313                         PC98SIO_baud_rate_port(if_type) = I8251F_div;
4314                         if_8251_type[if_type].speedtab = pc98fast_speedtab;
4315                 }
4316             } else {
4317                 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask;
4318                 if ((isa_get_port(dev) & 0xff) == IO_COM2)
4319                     iod->irq = irq_tab[0][tmp];
4320                 else
4321                     iod->irq = irq_tab[1][tmp];
4322             }
4323         } else {
4324             irr = if_16550a_type[if_type].irr_read;
4325 #ifdef COM_MULTIPORT
4326             if (!COM_ISMULTIPORT(device_get_flags(dev)) ||
4327                     device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev)))
4328 #endif
4329             if (irr != -1) {
4330                 tmp = inb(io | irr);
4331                 if (isa_get_port(dev) & 0x01)   /* XXX depend on RSB-384 */
4332                     iod->irq = irq_tab[1][tmp >> 3];
4333                 else
4334                     iod->irq = irq_tab[0][tmp & 0x07];
4335             }
4336             iod->cmd  = 0;
4337             iod->sts  = 0;
4338             iod->mod  = 0;
4339             iod->ctrl = 0;
4340         }
4341         if ( iod->irq == -1 ) return -1;
4342
4343         return 0;
4344 }
4345 static void
4346 pc98_set_ioport(struct com_s *com)
4347 {
4348         int     if_type = com->pc98_if_type & 0x0f;
4349         Port_t  io = rman_get_start(com->ioportres) & 0xff00;
4350
4351         pc98_check_sysclock();
4352         com->data_port          = io | PC98SIO_data_port(if_type);
4353         com->cmd_port           = io | PC98SIO_cmd_port(if_type);
4354         com->sts_port           = io | PC98SIO_sts_port(if_type);
4355         com->in_modem_port      = io | PC98SIO_in_modem_port(if_type);
4356         com->intr_ctrl_port     = io | PC98SIO_intr_ctrl_port(if_type);
4357 }
4358 static int
4359 pc98_check_8251vfast(void)
4360 {
4361     int i;
4362
4363     outb(I8251F_div, 0x8c);
4364     DELAY(10);
4365     for (i = 0; i < 100; i++) {
4366         if ((inb(I8251F_div) & 0x80) != 0) {
4367             i = 0;
4368             break;
4369         }
4370         DELAY(1);
4371     }
4372     outb(I8251F_div, 0);
4373     DELAY(10);
4374     for (; i < 100; i++) {
4375         if ((inb(I8251F_div) & 0x80) == 0)
4376             return 1;
4377         DELAY(1);
4378     }
4379
4380     return 0;
4381 }
4382 static int
4383 pc98_check_8251fifo(void)
4384 {
4385     u_char      tmp1, tmp2;
4386
4387     tmp1 = inb(I8251F_iir);
4388     DELAY(10);
4389     tmp2 = inb(I8251F_iir);
4390     if (((tmp1 ^ tmp2) & 0x40) != 0 && ((tmp1 | tmp2) & 0x20) == 0)
4391         return 1;
4392
4393     return 0;
4394 }
4395 #endif /* PC98 defined */