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