]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/pc98/sio.c
This commit was generated by cvs2svn to compensate for changes in r43552,
[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.79 1999/01/30 12:17:37 phk 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) != 0)
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 */