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