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