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