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