]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/pc98/sio.c
Sync with sys/i386/isa/sio.c revision 1.225.
[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.76 1999/01/19 00:21:53 peter 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 #endif
1785 determined_type: ;
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 && p->p_ucred->cr_uid != 0) {
1916                         error = EBUSY;
1917                         goto out;
1918                 }
1919         } else {
1920                 /*
1921                  * The device isn't open, so there are no conflicts.
1922                  * Initialize it.  Initialization is done twice in many
1923                  * cases: to preempt sleeping callin opens if we are
1924                  * callout, and to complete a callin open after DCD rises.
1925                  */
1926                 tp->t_oproc = comstart;
1927                 tp->t_param = comparam;
1928                 tp->t_dev = dev;
1929                 tp->t_termios = mynor & CALLOUT_MASK
1930                                 ? com->it_out : com->it_in;
1931 #ifndef PC98
1932                 tp->t_ififosize = 2 * RS_IBUFSIZE;
1933 #else
1934                 tp->t_ififosize = 2 * com->CE_INPUT_OFFSET;
1935 #endif
1936                 tp->t_ispeedwat = (speed_t)-1;
1937                 tp->t_ospeedwat = (speed_t)-1;
1938 #ifdef PC98
1939                 if (!IS_8251(com->pc98_if_type))
1940 #endif
1941                 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1942                 com->poll = com->no_irq;
1943                 com->poll_output = com->loses_outints;
1944                 ++com->wopeners;
1945                 error = comparam(tp, &tp->t_termios);
1946                 --com->wopeners;
1947                 if (error != 0)
1948                         goto out;
1949 #ifdef PC98
1950                 if (IS_8251(com->pc98_if_type)) {
1951                         com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS);
1952                         pc98_msrint_start(dev);
1953                 }
1954 #endif
1955                 /*
1956                  * XXX we should goto open_top if comparam() slept.
1957                  */
1958                 iobase = com->iobase;
1959                 if (com->hasfifo) {
1960                         /*
1961                          * (Re)enable and drain fifos.
1962                          *
1963                          * Certain SMC chips cause problems if the fifos
1964                          * are enabled while input is ready.  Turn off the
1965                          * fifo if necessary to clear the input.  We test
1966                          * the input ready bit after enabling the fifos
1967                          * since we've already enabled them in comparam()
1968                          * and to handle races between enabling and fresh
1969                          * input.
1970                          */
1971                         while (TRUE) {
1972 #ifdef PC98
1973                                 outb(iobase + (com_fifo << port_shift),
1974                                      FIFO_RCV_RST | FIFO_XMT_RST
1975                                      | com->fifo_image);
1976                                 if (com->pc98_if_type == COM_IF_RSA98III)
1977                                   outb(com->rsabase + rsa_frr , 0x00);
1978 #else
1979                                 outb(iobase + com_fifo,
1980                                      FIFO_RCV_RST | FIFO_XMT_RST
1981                                      | com->fifo_image);
1982 #endif
1983                                 /*
1984                                  * XXX the delays are for superstitious
1985                                  * historical reasons.  It must be less than
1986                                  * the character time at the maximum
1987                                  * supported speed (87 usec at 115200 bps
1988                                  * 8N1).  Otherwise we might loop endlessly
1989                                  * if data is streaming in.  We used to use
1990                                  * delays of 100.  That usually worked
1991                                  * because DELAY(100) used to usually delay
1992                                  * for about 85 usec instead of 100.
1993                                  */
1994                                 DELAY(50);
1995 #ifndef PC98
1996                                 if (!(inb(com->line_status_port) & LSR_RXRDY))
1997 #else
1998                                 if (com->pc98_if_type == COM_IF_RSA98III
1999                                     ? !(inb(com->rsabase + rsa_srr) & 0x08)
2000                                     : !(inb(com->line_status_port) & LSR_RXRDY))
2001 #endif
2002                                         break;
2003 #ifdef PC98
2004                                 outb(iobase + (com_fifo << port_shift), 0);
2005 #else
2006                                 outb(iobase + com_fifo, 0);
2007 #endif
2008                                 DELAY(50);
2009                                 (void) inb(com->data_port);
2010                         }
2011                 }
2012
2013                 disable_intr();
2014 #ifdef PC98
2015                 if (IS_8251(com->pc98_if_type)) {
2016                     com_tiocm_bis(com, TIOCM_LE);
2017                     com->pc98_prev_modem_status = pc98_get_modem_status(com);
2018                     com_int_Rx_enable(com);
2019                 } else {
2020 #endif
2021                 (void) inb(com->line_status_port);
2022                 (void) inb(com->data_port);
2023                 com->prev_modem_status = com->last_modem_status
2024                     = inb(com->modem_status_port);
2025                 if (COM_IIR_TXRDYBUG(com)) {
2026                         outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
2027                                                 | IER_EMSC);
2028                 } else {
2029                         outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
2030                                                 | IER_ERLS | IER_EMSC);
2031                 }
2032 #ifdef PC98
2033                 if (com->pc98_if_type == COM_IF_RSA98III) {
2034                         outb(com->rsabase + rsa_ier, 0x1d);
2035                         outb(com->intr_ctl_port, IER_ERLS | IER_EMSC);
2036                 }
2037 #endif
2038 #ifdef PC98
2039                 }
2040 #endif
2041                 enable_intr();
2042                 /*
2043                  * Handle initial DCD.  Callout devices get a fake initial
2044                  * DCD (trapdoor DCD).  If we are callout, then any sleeping
2045                  * callin opens get woken up and resume sleeping on "siobi"
2046                  * instead of "siodcd".
2047                  */
2048                 /*
2049                  * XXX `mynor & CALLOUT_MASK' should be
2050                  * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
2051                  * TRAPDOOR_CARRIER is the default initial state for callout
2052                  * devices and SOFT_CARRIER is like CLOCAL except it hides
2053                  * the true carrier.
2054                  */
2055 #ifdef PC98
2056                 if ((IS_8251(com->pc98_if_type) &&
2057                         (pc98_get_modem_status(com) & TIOCM_CAR)) ||
2058                     (!IS_8251(com->pc98_if_type) &&
2059                         (com->prev_modem_status & MSR_DCD)) ||
2060                     mynor & CALLOUT_MASK)
2061 #else
2062                 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
2063 #endif
2064                         (*linesw[tp->t_line].l_modem)(tp, 1);
2065         }
2066         /*
2067          * Wait for DCD if necessary.
2068          */
2069         if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
2070             && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
2071                 ++com->wopeners;
2072                 error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "siodcd", 0);
2073                 if (com_addr(unit) == NULL)
2074                         return (ENXIO);
2075                 --com->wopeners;
2076                 if (error != 0 || com->gone)
2077                         goto out;
2078                 goto open_top;
2079         }
2080         error = (*linesw[tp->t_line].l_open)(dev, tp);
2081         disc_optim(tp, &tp->t_termios, com);
2082         if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
2083                 com->active_out = TRUE;
2084         siosettimeout();
2085 out:
2086         splx(s);
2087         if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
2088                 comhardclose(com);
2089         return (error);
2090 }
2091
2092 static int
2093 sioclose(dev, flag, mode, p)
2094         dev_t           dev;
2095         int             flag;
2096         int             mode;
2097         struct proc     *p;
2098 {
2099         struct com_s    *com;
2100         int             mynor;
2101         int             s;
2102         struct tty      *tp;
2103
2104         mynor = minor(dev);
2105         if (mynor & CONTROL_MASK)
2106                 return (0);
2107         com = com_addr(MINOR_TO_UNIT(mynor));
2108         tp = com->tp;
2109         s = spltty();
2110         (*linesw[tp->t_line].l_close)(tp, flag);
2111 #ifdef PC98
2112         com->modem_checking = 0;
2113 #endif
2114         disc_optim(tp, &tp->t_termios, com);
2115         siostop(tp, FREAD | FWRITE);
2116         comhardclose(com);
2117         ttyclose(tp);
2118         siosettimeout();
2119         splx(s);
2120         if (com->gone) {
2121                 printf("sio%d: gone\n", com->unit);
2122                 s = spltty();
2123                 com_addr(com->unit) = 0;
2124                 bzero(tp,sizeof *tp);
2125                 bzero(com,sizeof *com);
2126                 free(com,M_TTYS);
2127                 splx(s);
2128         }
2129         return (0);
2130 }
2131
2132 static void
2133 comhardclose(com)
2134         struct com_s    *com;
2135 {
2136         Port_t          iobase;
2137         int             s;
2138         struct tty      *tp;
2139         int             unit;
2140 #ifdef PC98
2141         int             port_shift = 0;
2142 #endif
2143
2144         unit = com->unit;
2145         iobase = com->iobase;
2146         s = spltty();
2147         com->poll = FALSE;
2148         com->poll_output = FALSE;
2149         com->do_timestamp = FALSE;
2150         com->do_dcd_timestamp = FALSE;
2151 #ifdef PC98
2152         if (IS_8251(com->pc98_if_type))
2153             com_send_break_off(com);
2154         else {
2155             port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
2156             outb(iobase + (com_cfcr << port_shift),
2157                  com->cfcr_image &= ~CFCR_SBREAK);
2158         }
2159 #else
2160         outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2161 #endif
2162         {
2163 #ifdef PC98
2164                 int tmp;
2165                 if (IS_8251(com->pc98_if_type))
2166                         com_int_TxRx_disable(com);
2167                 else
2168                         outb(iobase + (com_ier << port_shift), 0);
2169                 if (com->pc98_if_type == COM_IF_RSA98III) {
2170                         outb(com->rsabase + rsa_ier, 0x00);
2171                 }
2172 #else
2173                 outb(iobase + com_ier, 0);
2174 #endif
2175                 tp = com->tp;
2176 #ifdef PC98
2177                 if (IS_8251(com->pc98_if_type))
2178                         tmp = pc98_get_modem_status(com) & TIOCM_CAR;
2179                 else
2180                         tmp = com->prev_modem_status & MSR_DCD;
2181 #endif
2182                 if (tp->t_cflag & HUPCL
2183                     /*
2184                      * XXX we will miss any carrier drop between here and the
2185                      * next open.  Perhaps we should watch DCD even when the
2186                      * port is closed; it is not sufficient to check it at
2187                      * the next open because it might go up and down while
2188                      * we're not watching.
2189                      */
2190                     || !com->active_out
2191 #ifdef PC98
2192                        && !(tmp)
2193 #else
2194                        && !(com->prev_modem_status & MSR_DCD)
2195 #endif
2196                        && !(com->it_in.c_cflag & CLOCAL)
2197                     || !(tp->t_state & TS_ISOPEN)) {
2198 #ifdef PC98
2199                         if (IS_8251(com->pc98_if_type))
2200                             com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
2201                         else
2202 #endif
2203                         (void)commctl(com, TIOCM_DTR, DMBIC);
2204                         if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
2205                                 timeout(siodtrwakeup, com, com->dtr_wait);
2206                                 com->state |= CS_DTR_OFF;
2207                         }
2208                 }
2209 #ifdef PC98
2210                 else {
2211                         if (IS_8251(com->pc98_if_type))
2212                                 com_tiocm_bic(com, TIOCM_LE );
2213                 }
2214 #endif
2215         }
2216         if (com->hasfifo) {
2217                 /*
2218                  * Disable fifos so that they are off after controlled
2219                  * reboots.  Some BIOSes fail to detect 16550s when the
2220                  * fifos are enabled.
2221                  */
2222 #ifdef PC98
2223                 outb(iobase + (com_fifo << port_shift), 0);
2224 #else
2225                 outb(iobase + com_fifo, 0);
2226 #endif
2227         }
2228         com->active_out = FALSE;
2229         wakeup(&com->active_out);
2230         wakeup(TSA_CARR_ON(tp));        /* restart any wopeners */
2231         splx(s);
2232 }
2233
2234 static int
2235 sioread(dev, uio, flag)
2236         dev_t           dev;
2237         struct uio      *uio;
2238         int             flag;
2239 {
2240         int             mynor;
2241         int             unit;
2242         struct tty      *tp;
2243
2244         mynor = minor(dev);
2245         if (mynor & CONTROL_MASK)
2246                 return (ENODEV);
2247         unit = MINOR_TO_UNIT(mynor);
2248         if (com_addr(unit)->gone)
2249                 return (ENODEV);
2250         tp = com_addr(unit)->tp;
2251         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
2252 }
2253
2254 static int
2255 siowrite(dev, uio, flag)
2256         dev_t           dev;
2257         struct uio      *uio;
2258         int             flag;
2259 {
2260         int             mynor;
2261         struct tty      *tp;
2262         int             unit;
2263
2264         mynor = minor(dev);
2265         if (mynor & CONTROL_MASK)
2266                 return (ENODEV);
2267
2268         unit = MINOR_TO_UNIT(mynor);
2269         if (com_addr(unit)->gone)
2270                 return (ENODEV);
2271         tp = com_addr(unit)->tp;
2272         /*
2273          * (XXX) We disallow virtual consoles if the physical console is
2274          * a serial port.  This is in case there is a display attached that
2275          * is not the console.  In that situation we don't need/want the X
2276          * server taking over the console.
2277          */
2278         if (constty != NULL && unit == comconsole)
2279                 constty = NULL;
2280         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
2281 }
2282
2283 static void
2284 siobusycheck(chan)
2285         void    *chan;
2286 {
2287         struct com_s    *com;
2288         int             s;
2289
2290         com = (struct com_s *)chan;
2291
2292         /*
2293          * Clear TS_BUSY if low-level output is complete.
2294          * spl locking is sufficient because siointr1() does not set CS_BUSY.
2295          * If siointr1() clears CS_BUSY after we look at it, then we'll get
2296          * called again.  Reading the line status port outside of siointr1()
2297          * is safe because CS_BUSY is clear so there are no output interrupts
2298          * to lose.
2299          */
2300         s = spltty();
2301         if (com->state & CS_BUSY)
2302                 com->extra_state &= ~CSE_BUSYCHECK;     /* False alarm. */
2303 #ifdef  PC98
2304         else if (IS_8251(com->pc98_if_type) &&
2305                  (inb(com->sts_port) & (STS8251_TxRDY | STS8251_TxEMP))
2306                  == (STS8251_TxRDY | STS8251_TxEMP) ||
2307                  (inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2308                  == (LSR_TSRE | LSR_TXRDY)) {
2309 #else
2310         else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
2311             == (LSR_TSRE | LSR_TXRDY)) {
2312 #endif
2313                 com->tp->t_state &= ~TS_BUSY;
2314                 ttwwakeup(com->tp);
2315                 com->extra_state &= ~CSE_BUSYCHECK;
2316         } else
2317                 timeout(siobusycheck, com, hz / 100);
2318         splx(s);
2319 }
2320
2321 static void
2322 siodtrwakeup(chan)
2323         void    *chan;
2324 {
2325         struct com_s    *com;
2326
2327         com = (struct com_s *)chan;
2328         com->state &= ~CS_DTR_OFF;
2329         wakeup(&com->dtr_wait);
2330 }
2331
2332 static void
2333 siointr(unit)
2334         int     unit;
2335 {
2336 #ifndef COM_MULTIPORT
2337         COM_LOCK();
2338         siointr1(com_addr(unit));
2339         COM_UNLOCK();
2340 #else /* COM_MULTIPORT */
2341         struct com_s    *com;
2342         bool_t          possibly_more_intrs;
2343 #ifdef PC98
2344         u_char          rsa_buf_status;
2345 #endif
2346
2347         /*
2348          * Loop until there is no activity on any port.  This is necessary
2349          * to get an interrupt edge more than to avoid another interrupt.
2350          * If the IRQ signal is just an OR of the IRQ signals from several
2351          * devices, then the edge from one may be lost because another is
2352          * on.
2353          */
2354         COM_LOCK();
2355         do {
2356                 possibly_more_intrs = FALSE;
2357                 for (unit = 0; unit < NSIOTOT; ++unit) {
2358                         com = com_addr(unit);
2359                         /*
2360                          * XXX COM_LOCK();
2361                          * would it work here, or be counter-productive?
2362                          */
2363 #ifdef PC98
2364                         if (com != NULL 
2365                             && !com->gone
2366                             && IS_8251(com->pc98_if_type)){
2367                                 siointr1(com);
2368                         } else
2369 #endif /* PC98 */
2370 #ifdef PC98
2371                         if (com != NULL 
2372                             && !com->gone
2373                             && com->pc98_if_type == COM_IF_RSA98III) {
2374                           rsa_buf_status = inb(com->rsabase + rsa_srr) & 0xc9;
2375                           if ((rsa_buf_status & 0xc8)
2376                               || !(rsa_buf_status & 0x01)) {
2377                             siointr1(com);
2378                             if(rsa_buf_status
2379                                != (inb(com->rsabase + rsa_srr) & 0xc9))
2380                               possibly_more_intrs = TRUE;
2381                           }
2382                         } else
2383 #endif
2384                         if (com != NULL 
2385                             && !com->gone
2386                             && (inb(com->int_id_port) & IIR_IMASK)
2387                                != IIR_NOPEND) {
2388                                 siointr1(com);
2389                                 possibly_more_intrs = TRUE;
2390                         }
2391                         /* XXX COM_UNLOCK(); */
2392                 }
2393         } while (possibly_more_intrs);
2394         COM_UNLOCK();
2395 #endif /* COM_MULTIPORT */
2396 }
2397
2398 static void
2399 siointr1(com)
2400         struct com_s    *com;
2401 {
2402         u_char  line_status;
2403         u_char  modem_status;
2404         u_char  *ioptr;
2405         u_char  recv_data;
2406         u_char  int_ctl;
2407         u_char  int_ctl_new;
2408
2409 #ifdef PC98
2410         u_char  tmp=0;
2411         u_char  rsa_buf_status = 0;
2412         int     rsa_tx_fifo_size=0;
2413         recv_data=0;
2414 #endif /* PC98 */
2415
2416         int_ctl = inb(com->intr_ctl_port);
2417         int_ctl_new = int_ctl;
2418
2419         while (!com->gone) {
2420 #ifdef PC98
2421 status_read:;
2422                 if (IS_8251(com->pc98_if_type)) {
2423                         tmp = inb(com->sts_port);
2424 more_intr:
2425                         line_status = 0;
2426                         if (tmp & STS8251_TxRDY) line_status |= LSR_TXRDY;
2427                         if (tmp & STS8251_RxRDY) line_status |= LSR_RXRDY;
2428                         if (tmp & STS8251_TxEMP) line_status |= LSR_TSRE;
2429                         if (tmp & STS8251_PE)    line_status |= LSR_PE;
2430                         if (tmp & STS8251_OE)    line_status |= LSR_OE;
2431                         if (tmp & STS8251_FE)    line_status |= LSR_FE;
2432                         if (tmp & STS8251_BD_SD) line_status |= LSR_BI;
2433                 } else
2434 #endif /* PC98 */
2435                 line_status = inb(com->line_status_port);
2436 #ifdef PC98
2437                 if (com->pc98_if_type == COM_IF_RSA98III)
2438                         rsa_buf_status = inb(com->rsabase + rsa_srr);
2439 #endif /* PC98 */
2440
2441                 /* input event? (check first to help avoid overruns) */
2442 #ifndef PC98
2443                 while (line_status & LSR_RCV_MASK) {
2444 #else
2445                 while ((line_status & LSR_RCV_MASK)
2446                        || (com->pc98_if_type == COM_IF_RSA98III
2447                            && (rsa_buf_status & 0x08))) {
2448 #endif /* PC98 */
2449                         /* break/unnattached error bits or real input? */
2450 #ifdef PC98
2451                         if (IS_8251(com->pc98_if_type)) {
2452                                 recv_data = inb(com->data_port);
2453                                 if (tmp & 0x78) {
2454                                         pc98_i8251_or_cmd(com,CMD8251_ER);
2455                                         recv_data = 0;
2456                                 }
2457                         } else {
2458 #endif /* PC98 */
2459 #ifdef PC98
2460                         if (com->pc98_if_type == COM_IF_RSA98III) {
2461                           if (!(rsa_buf_status & 0x08))
2462                             recv_data = 0;
2463                           else {
2464                             recv_data = inb(com->data_port);
2465                           }
2466                         } else
2467 #endif
2468                         if (!(line_status & LSR_RXRDY))
2469                                 recv_data = 0;
2470                         else
2471                                 recv_data = inb(com->data_port);
2472 #ifdef PC98
2473                         }
2474 #endif
2475                         if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
2476                                 /*
2477                                  * Don't store BI if IGNBRK or FE/PE if IGNPAR.
2478                                  * Otherwise, push the work to a higher level
2479                                  * (to handle PARMRK) if we're bypassing.
2480                                  * Otherwise, convert BI/FE and PE+INPCK to 0.
2481                                  *
2482                                  * This makes bypassing work right in the
2483                                  * usual "raw" case (IGNBRK set, and IGNPAR
2484                                  * and INPCK clear).
2485                                  *
2486                                  * Note: BI together with FE/PE means just BI.
2487                                  */
2488                                 if (line_status & LSR_BI) {
2489 #if defined(DDB) && defined(BREAK_TO_DEBUGGER)
2490                                         if (com->unit == comconsole) {
2491                                                 breakpoint();
2492                                                 goto cont;
2493                                         }
2494 #endif
2495                                         if (com->tp == NULL
2496                                             || com->tp->t_iflag & IGNBRK)
2497                                                 goto cont;
2498                                 } else {
2499                                         if (com->tp == NULL
2500                                             || com->tp->t_iflag & IGNPAR)
2501                                                 goto cont;
2502                                 }
2503                                 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
2504                                     && (line_status & (LSR_BI | LSR_FE)
2505                                         || com->tp->t_iflag & INPCK))
2506                                         recv_data = 0;
2507                         }
2508                         ++com->bytes_in;
2509                         if (com->hotchar != 0 && recv_data == com->hotchar)
2510                                 setsofttty();
2511                         ioptr = com->iptr;
2512                         if (ioptr >= com->ibufend)
2513                                 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
2514                         else {
2515                                 if (com->do_timestamp)
2516                                         microtime(&com->timestamp);
2517                                 ++com_events;
2518                                 schedsofttty();
2519 #if 0 /* for testing input latency vs efficiency */
2520 if (com->iptr - com->ibuf == 8)
2521         setsofttty();
2522 #endif
2523                                 ioptr[0] = recv_data;
2524 #ifdef PC98
2525                                 ioptr[com->CE_INPUT_OFFSET] = line_status;
2526 #else
2527                                 ioptr[CE_INPUT_OFFSET] = line_status;
2528 #endif
2529                                 com->iptr = ++ioptr;
2530                                 if (ioptr == com->ihighwater
2531                                     && com->state & CS_RTS_IFLOW)
2532 #ifdef PC98
2533                                         if (IS_8251(com->pc98_if_type))
2534                                                 com_tiocm_bic(com, TIOCM_RTS);
2535                                         else
2536 #endif
2537                                         outb(com->modem_ctl_port,
2538                                              com->mcr_image &= ~MCR_RTS);
2539                                 if (line_status & LSR_OE)
2540                                         CE_RECORD(com, CE_OVERRUN);
2541                         }
2542 cont:
2543                         /*
2544                          * "& 0x7F" is to avoid the gcc-1.40 generating a slow
2545                          * jump from the top of the loop to here
2546                          */
2547 #ifdef PC98
2548                         if (IS_8251(com->pc98_if_type))
2549                                 goto status_read;
2550                         else
2551 #endif
2552                         line_status = inb(com->line_status_port) & 0x7F;
2553 #ifdef PC98
2554                         if (com->pc98_if_type == COM_IF_RSA98III)
2555                                 rsa_buf_status = inb(com->rsabase + rsa_srr);
2556 #endif /* PC98 */
2557                 }
2558
2559                 /* modem status change? (always check before doing output) */
2560 #ifdef PC98
2561                 if (!IS_8251(com->pc98_if_type)) {
2562 #endif
2563                 modem_status = inb(com->modem_status_port);
2564                 if (modem_status != com->last_modem_status) {
2565                         if (com->do_dcd_timestamp
2566                             && !(com->last_modem_status & MSR_DCD)
2567                             && modem_status & MSR_DCD)
2568                                 microtime(&com->dcd_timestamp);
2569
2570                         /*
2571                          * Schedule high level to handle DCD changes.  Note
2572                          * that we don't use the delta bits anywhere.  Some
2573                          * UARTs mess them up, and it's easy to remember the
2574                          * previous bits and calculate the delta.
2575                          */
2576                         com->last_modem_status = modem_status;
2577                         if (!(com->state & CS_CHECKMSR)) {
2578                                 com_events += LOTS_OF_EVENTS;
2579                                 com->state |= CS_CHECKMSR;
2580                                 setsofttty();
2581                         }
2582
2583                         /* handle CTS change immediately for crisp flow ctl */
2584                         if (com->state & CS_CTS_OFLOW) {
2585                                 if (modem_status & MSR_CTS)
2586                                         com->state |= CS_ODEVREADY;
2587                                 else
2588                                         com->state &= ~CS_ODEVREADY;
2589                         }
2590                 }
2591 #ifdef PC98
2592                 }
2593 #endif
2594
2595                 /* output queued and everything ready? */
2596 #ifndef PC98
2597                 if (line_status & LSR_TXRDY
2598                     && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2599 #else
2600                 if (((com->pc98_if_type == COM_IF_RSA98III)
2601                      ? (rsa_buf_status & 0x02)
2602                      : (line_status & LSR_TXRDY))
2603                     && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
2604 #endif
2605                         ioptr = com->obufq.l_head;
2606                         if (com->tx_fifo_size > 1) {
2607                                 u_int   ocount;
2608
2609                                 ocount = com->obufq.l_tail - ioptr;
2610 #ifdef PC98
2611                                 if (com->pc98_if_type == COM_IF_RSA98III) {
2612                                   rsa_buf_status = inb(com->rsabase + rsa_srr);
2613                                   rsa_tx_fifo_size = 1024;
2614                                   if (!(rsa_buf_status & 0x01))
2615                                     rsa_tx_fifo_size = 2048;
2616                                   if (ocount > rsa_tx_fifo_size)
2617                                     ocount = rsa_tx_fifo_size;
2618                                 } else
2619 #endif
2620                                 if (ocount > com->tx_fifo_size)
2621                                         ocount = com->tx_fifo_size;
2622                                 com->bytes_out += ocount;
2623                                 do
2624                                         outb(com->data_port, *ioptr++);
2625                                 while (--ocount != 0);
2626                         } else {
2627                                 outb(com->data_port, *ioptr++);
2628                                 ++com->bytes_out;
2629                         }
2630 #ifdef PC98
2631                         if (IS_8251(com->pc98_if_type))
2632                             if (!(pc98_check_i8251_interrupt(com) & IEN_TxFLAG))
2633                                         com_int_Tx_enable(com);
2634 #endif
2635                         com->obufq.l_head = ioptr;
2636                         if (COM_IIR_TXRDYBUG(com)) {
2637                                 int_ctl_new = int_ctl | IER_ETXRDY;
2638                         }
2639                         if (ioptr >= com->obufq.l_tail) {
2640                                 struct lbq      *qp;
2641
2642                                 qp = com->obufq.l_next;
2643                                 qp->l_queued = FALSE;
2644                                 qp = qp->l_next;
2645                                 if (qp != NULL) {
2646                                         com->obufq.l_head = qp->l_head;
2647                                         com->obufq.l_tail = qp->l_tail;
2648                                         com->obufq.l_next = qp;
2649                                 } else {
2650                                         /* output just completed */
2651                                         if ( COM_IIR_TXRDYBUG(com) ) {
2652                                                 int_ctl_new = int_ctl & ~IER_ETXRDY;
2653                                         }
2654                                         com->state &= ~CS_BUSY;
2655 #if defined(PC98)
2656                                         if (IS_8251(com->pc98_if_type))
2657                                             if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2658                                                 com_int_Tx_disable(com);
2659 #endif
2660                                 }
2661                                 if (!(com->state & CS_ODONE)) {
2662                                         com_events += LOTS_OF_EVENTS;
2663                                         com->state |= CS_ODONE;
2664                                         setsofttty();   /* handle at high level ASAP */
2665                                 }
2666                         }
2667                         if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) {
2668                                 if (com->pc98_if_type == COM_IF_RSA98III) {
2669                                   int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
2670                                   outb(com->intr_ctl_port, int_ctl_new);
2671                                   outb(com->rsabase + rsa_ier, 0x1d);
2672                                 } else
2673                                 outb(com->intr_ctl_port, int_ctl_new);
2674                         }
2675                 }
2676 #ifdef PC98
2677                 else if (line_status & LSR_TXRDY) {
2678                     if (IS_8251(com->pc98_if_type))
2679                         if ( pc98_check_i8251_interrupt(com) & IEN_TxFLAG )
2680                             com_int_Tx_disable(com);
2681                 }
2682                 if (IS_8251(com->pc98_if_type))
2683                     if ((tmp = inb(com->sts_port)) & STS8251_RxRDY)
2684                         goto more_intr;
2685 #endif
2686
2687                 /* finished? */
2688 #ifndef COM_MULTIPORT
2689 #ifdef PC98
2690                 if (IS_8251(com->pc98_if_type))
2691                         return;
2692 #endif
2693                 if ((inb(com->int_id_port) & IIR_IMASK) == IIR_NOPEND)
2694 #endif /* COM_MULTIPORT */
2695                         return;
2696         }
2697 }
2698
2699 static int
2700 sioioctl(dev, cmd, data, flag, p)
2701         dev_t           dev;
2702         u_long          cmd;
2703         caddr_t         data;
2704         int             flag;
2705         struct proc     *p;
2706 {
2707         struct com_s    *com;
2708         int             error;
2709         Port_t          iobase;
2710         int             mynor;
2711         int             s;
2712         struct tty      *tp;
2713 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2714         int             oldcmd;
2715         struct termios  term;
2716 #endif
2717
2718         mynor = minor(dev);
2719         com = com_addr(MINOR_TO_UNIT(mynor));
2720         if (com->gone)
2721                 return (ENODEV);
2722         iobase = com->iobase;
2723         if (mynor & CONTROL_MASK) {
2724                 struct termios  *ct;
2725
2726                 switch (mynor & CONTROL_MASK) {
2727                 case CONTROL_INIT_STATE:
2728                         ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2729                         break;
2730                 case CONTROL_LOCK_STATE:
2731                         ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2732                         break;
2733                 default:
2734                         return (ENODEV);        /* /dev/nodev */
2735                 }
2736                 switch (cmd) {
2737                 case TIOCSETA:
2738                         error = suser(p->p_ucred, &p->p_acflag);
2739                         if (error != 0)
2740                                 return (error);
2741                         *ct = *(struct termios *)data;
2742                         return (0);
2743                 case TIOCGETA:
2744                         *(struct termios *)data = *ct;
2745                         return (0);
2746                 case TIOCGETD:
2747                         *(int *)data = TTYDISC;
2748                         return (0);
2749                 case TIOCGWINSZ:
2750                         bzero(data, sizeof(struct winsize));
2751                         return (0);
2752                 default:
2753                         return (ENOTTY);
2754                 }
2755         }
2756         tp = com->tp;
2757 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
2758         term = tp->t_termios;
2759         oldcmd = cmd;
2760         error = ttsetcompat(tp, &cmd, data, &term);
2761         if (error != 0)
2762                 return (error);
2763         if (cmd != oldcmd)
2764                 data = (caddr_t)&term;
2765 #endif
2766         if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
2767                 int     cc;
2768                 struct termios *dt = (struct termios *)data;
2769                 struct termios *lt = mynor & CALLOUT_MASK
2770                                      ? &com->lt_out : &com->lt_in;
2771
2772                 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2773                               | (dt->c_iflag & ~lt->c_iflag);
2774                 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2775                               | (dt->c_oflag & ~lt->c_oflag);
2776                 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2777                               | (dt->c_cflag & ~lt->c_cflag);
2778                 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2779                               | (dt->c_lflag & ~lt->c_lflag);
2780                 for (cc = 0; cc < NCCS; ++cc)
2781                         if (lt->c_cc[cc] != 0)
2782                                 dt->c_cc[cc] = tp->t_cc[cc];
2783                 if (lt->c_ispeed != 0)
2784                         dt->c_ispeed = tp->t_ispeed;
2785                 if (lt->c_ospeed != 0)
2786                         dt->c_ospeed = tp->t_ospeed;
2787         }
2788         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
2789         if (error != ENOIOCTL)
2790                 return (error);
2791         s = spltty();
2792         error = ttioctl(tp, cmd, data, flag);
2793         disc_optim(tp, &tp->t_termios, com);
2794         if (error != ENOIOCTL) {
2795                 splx(s);
2796                 return (error);
2797         }
2798 #ifdef PC98
2799         if (IS_8251(com->pc98_if_type)) {
2800             switch (cmd) {
2801             case TIOCSBRK:
2802                 com_send_break_on( com );
2803                 break;
2804             case TIOCCBRK:
2805                 com_send_break_off( com );
2806                 break;
2807             case TIOCSDTR:
2808                 com_tiocm_bis(com, TIOCM_DTR | TIOCM_RTS );
2809                 break;
2810             case TIOCCDTR:
2811                 com_tiocm_bic(com, TIOCM_DTR);
2812                 break;
2813         /*
2814          * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2815          * changes get undone on the next call to comparam().
2816          */
2817             case TIOCMSET:
2818                 com_tiocm_set( com, *(int *)data );
2819                 break;
2820             case TIOCMBIS:
2821                 com_tiocm_bis( com, *(int *)data );
2822                 break;
2823             case TIOCMBIC:
2824                 com_tiocm_bic( com, *(int *)data );
2825                 break;
2826             case TIOCMGET:
2827                 *(int *)data = com_tiocm_get(com);
2828                 break;
2829             case TIOCMSDTRWAIT:
2830                 /* must be root since the wait applies to following logins */
2831                 error = suser(p->p_ucred, &p->p_acflag);
2832                 if (error != 0) {
2833                         splx(s);
2834                         return (error);
2835                 }
2836                 com->dtr_wait = *(int *)data * hz / 100;
2837                 break;
2838             case TIOCMGDTRWAIT:
2839                 *(int *)data = com->dtr_wait * 100 / hz;
2840                 break;
2841             case TIOCTIMESTAMP:
2842                 com->do_timestamp = TRUE;
2843                 *(struct timeval *)data = com->timestamp;
2844                 break;
2845             case TIOCDCDTIMESTAMP:
2846                 com->do_dcd_timestamp = TRUE;
2847                 *(struct timeval *)data = com->dcd_timestamp;
2848                 break;
2849             default:
2850                 splx(s);
2851                 return (ENOTTY);
2852             }
2853         } else {
2854             int port_shift;
2855             port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
2856 #endif
2857         switch (cmd) {
2858         case TIOCSBRK:
2859 #ifdef PC98
2860                 outb(iobase + (com_cfcr << port_shift),
2861                      com->cfcr_image |= CFCR_SBREAK);
2862 #else
2863                 outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2864 #endif
2865                 break;
2866         case TIOCCBRK:
2867 #ifdef PC98
2868                 outb(iobase + (com_cfcr << port_shift),
2869                      com->cfcr_image &= ~CFCR_SBREAK);
2870 #else
2871                 outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2872 #endif
2873                 break;
2874         case TIOCSDTR:
2875                 (void)commctl(com, TIOCM_DTR, DMBIS);
2876                 break;
2877         case TIOCCDTR:
2878                 (void)commctl(com, TIOCM_DTR, DMBIC);
2879                 break;
2880         /*
2881          * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set.  The
2882          * changes get undone on the next call to comparam().
2883          */
2884         case TIOCMSET:
2885                 (void)commctl(com, *(int *)data, DMSET);
2886                 break;
2887         case TIOCMBIS:
2888                 (void)commctl(com, *(int *)data, DMBIS);
2889                 break;
2890         case TIOCMBIC:
2891                 (void)commctl(com, *(int *)data, DMBIC);
2892                 break;
2893         case TIOCMGET:
2894                 *(int *)data = commctl(com, 0, DMGET);
2895                 break;
2896         case TIOCMSDTRWAIT:
2897                 /* must be root since the wait applies to following logins */
2898                 error = suser(p->p_ucred, &p->p_acflag);
2899                 if (error != 0) {
2900                         splx(s);
2901                         return (error);
2902                 }
2903                 com->dtr_wait = *(int *)data * hz / 100;
2904                 break;
2905         case TIOCMGDTRWAIT:
2906                 *(int *)data = com->dtr_wait * 100 / hz;
2907                 break;
2908         case TIOCTIMESTAMP:
2909                 com->do_timestamp = TRUE;
2910                 *(struct timeval *)data = com->timestamp;
2911                 break;
2912         case TIOCDCDTIMESTAMP:
2913                 com->do_dcd_timestamp = TRUE;
2914                 *(struct timeval *)data = com->dcd_timestamp;
2915                 break;
2916         default:
2917                 splx(s);
2918                 return (ENOTTY);
2919         }
2920 #ifdef PC98
2921         }
2922 #endif
2923         splx(s);
2924         return (0);
2925 }
2926
2927 static void
2928 siopoll()
2929 {
2930         int             unit;
2931
2932         if (com_events == 0)
2933                 return;
2934 repeat:
2935         for (unit = 0; unit < NSIOTOT; ++unit) {
2936                 u_char          *buf;
2937                 struct com_s    *com;
2938                 u_char          *ibuf;
2939                 int             incc;
2940                 struct tty      *tp;
2941 #ifdef PC98
2942                 int             tmp;
2943 #endif
2944
2945                 com = com_addr(unit);
2946                 if (com == NULL)
2947                         continue;
2948                 tp = com->tp;
2949                 if (tp == NULL || com->gone) {
2950                         /*
2951                          * Discard any events related to never-opened or
2952                          * going-away devices.
2953                          */
2954                         disable_intr();
2955                         incc = com->iptr - com->ibuf;
2956                         com->iptr = com->ibuf;
2957                         if (com->state & CS_CHECKMSR) {
2958                                 incc += LOTS_OF_EVENTS;
2959                                 com->state &= ~CS_CHECKMSR;
2960                         }
2961                         com_events -= incc;
2962                         enable_intr();
2963                         continue;
2964                 }
2965
2966                 /* switch the role of the low-level input buffers */
2967                 if (com->iptr == (ibuf = com->ibuf)) {
2968                         buf = NULL;     /* not used, but compiler can't tell */
2969                         incc = 0;
2970                 } else {
2971                         buf = ibuf;
2972                         disable_intr();
2973                         incc = com->iptr - buf;
2974                         com_events -= incc;
2975                         if (ibuf == com->ibuf1)
2976                                 ibuf = com->ibuf2;
2977                         else
2978                                 ibuf = com->ibuf1;
2979 #ifndef PC98
2980                         com->ibufend = ibuf + RS_IBUFSIZE;
2981                         com->ihighwater = ibuf + RS_IHIGHWATER;
2982 #else
2983                         com->ibufend = ibuf + com->CE_INPUT_OFFSET;
2984                         com->ihighwater = ibuf + (3 * com->CE_INPUT_OFFSET / 4);
2985 #endif
2986                         com->iptr = ibuf;
2987
2988                         /*
2989                          * There is now room for another low-level buffer full
2990                          * of input, so enable RTS if it is now disabled and
2991                          * there is room in the high-level buffer.
2992                          */
2993 #ifdef PC98
2994                         if (IS_8251(com->pc98_if_type))
2995                                 tmp = com_tiocm_get(com) & TIOCM_RTS;
2996                         else
2997                                 tmp = com->mcr_image & MCR_RTS;
2998 #endif
2999                         if ((com->state & CS_RTS_IFLOW)
3000 #ifdef PC98
3001                             && !(tmp)
3002 #else
3003                             && !(com->mcr_image & MCR_RTS)
3004 #endif
3005                             && !(tp->t_state & TS_TBLOCK))
3006 #ifdef PC98
3007                                 if (IS_8251(com->pc98_if_type))
3008                                         com_tiocm_bis(com, TIOCM_RTS);
3009                                 else
3010 #endif
3011                                 outb(com->modem_ctl_port,
3012                                      com->mcr_image |= MCR_RTS);
3013                         enable_intr();
3014                         com->ibuf = ibuf;
3015                 }
3016
3017                 if (com->state & CS_CHECKMSR) {
3018                         u_char  delta_modem_status;
3019
3020 #ifdef PC98
3021                         if (!IS_8251(com->pc98_if_type)) {
3022 #endif
3023                         disable_intr();
3024                         delta_modem_status = com->last_modem_status
3025                                              ^ com->prev_modem_status;
3026                         com->prev_modem_status = com->last_modem_status;
3027                         com_events -= LOTS_OF_EVENTS;
3028                         com->state &= ~CS_CHECKMSR;
3029                         enable_intr();
3030                         if (delta_modem_status & MSR_DCD)
3031                                 (*linesw[tp->t_line].l_modem)
3032                                         (tp, com->prev_modem_status & MSR_DCD);
3033 #ifdef PC98
3034                         }
3035 #endif
3036                 }
3037                 if (com->state & CS_ODONE) {
3038                         disable_intr();
3039                         com_events -= LOTS_OF_EVENTS;
3040                         com->state &= ~CS_ODONE;
3041                         enable_intr();
3042                         if (!(com->state & CS_BUSY)
3043                             && !(com->extra_state & CSE_BUSYCHECK)) {
3044                                 timeout(siobusycheck, com, hz / 100);
3045                                 com->extra_state |= CSE_BUSYCHECK;
3046                         }
3047                         (*linesw[tp->t_line].l_start)(tp);
3048                 }
3049                 if (incc <= 0 || !(tp->t_state & TS_ISOPEN) ||
3050                     !(tp->t_cflag & CREAD))
3051                         continue;
3052                 /*
3053                  * Avoid the grotesquely inefficient lineswitch routine
3054                  * (ttyinput) in "raw" mode.  It usually takes about 450
3055                  * instructions (that's without canonical processing or echo!).
3056                  * slinput is reasonably fast (usually 40 instructions plus
3057                  * call overhead).
3058                  */
3059                 if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
3060                         if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
3061                             && (com->state & CS_RTS_IFLOW
3062                                 || tp->t_iflag & IXOFF)
3063                             && !(tp->t_state & TS_TBLOCK))
3064                                 ttyblock(tp);
3065                         tk_nin += incc;
3066                         tk_rawcc += incc;
3067                         tp->t_rawcc += incc;
3068                         com->delta_error_counts[CE_TTY_BUF_OVERFLOW]
3069                                 += b_to_q((char *)buf, incc, &tp->t_rawq);
3070                         ttwakeup(tp);
3071                         if (tp->t_state & TS_TTSTOP
3072                             && (tp->t_iflag & IXANY
3073                                 || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
3074                                 tp->t_state &= ~TS_TTSTOP;
3075                                 tp->t_lflag &= ~FLUSHO;
3076                                 comstart(tp);
3077                         }
3078                 } else {
3079                         do {
3080                                 u_char  line_status;
3081                                 int     recv_data;
3082
3083 #ifndef PC98
3084                                 line_status = (u_char) buf[CE_INPUT_OFFSET];
3085 #else
3086                                 line_status = (u_char) buf[com->CE_INPUT_OFFSET];
3087 #endif
3088                                 recv_data = (u_char) *buf++;
3089                                 if (line_status
3090                                     & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
3091                                         if (line_status & LSR_BI)
3092                                                 recv_data |= TTY_BI;
3093                                         if (line_status & LSR_FE)
3094                                                 recv_data |= TTY_FE;
3095                                         if (line_status & LSR_OE)
3096                                                 recv_data |= TTY_OE;
3097                                         if (line_status & LSR_PE)
3098                                                 recv_data |= TTY_PE;
3099                                 }
3100                                 (*linesw[tp->t_line].l_rint)(recv_data, tp);
3101                         } while (--incc > 0);
3102                 }
3103                 if (com_events == 0)
3104                         break;
3105         }
3106         if (com_events >= LOTS_OF_EVENTS)
3107                 goto repeat;
3108 }
3109
3110 static int
3111 comparam(tp, t)
3112         struct tty      *tp;
3113         struct termios  *t;
3114 {
3115         u_int           cfcr;
3116         int             cflag;
3117         struct com_s    *com;
3118         int             divisor;
3119         u_char          dlbh;
3120         u_char          dlbl;
3121         Port_t          iobase;
3122         int             s;
3123         int             unit;
3124 #ifdef PC98
3125         Port_t          tmp_port;
3126         int             tmp_flg;
3127         int             port_shift = 0;
3128         u_char          param = 0;
3129 #endif
3130
3131 #ifdef PC98
3132         cfcr = 0;
3133         unit = DEV_TO_UNIT(tp->t_dev);
3134         com = com_addr(unit);
3135         iobase = com->iobase;
3136         if (IS_8251(com->pc98_if_type)) {
3137             divisor = pc98_ttspeedtab(com, t->c_ospeed);
3138         } else {
3139             port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
3140
3141             /* do historical conversions */
3142             if (t->c_ispeed == 0)
3143                 t->c_ispeed = t->c_ospeed;
3144
3145             /* check requested parameters */
3146             divisor = ttspeedtab(t->c_ospeed,
3147                         if_16550a_type[com->pc98_if_type & 0x0f].speedtab);
3148         }
3149 #else
3150         /* do historical conversions */
3151         if (t->c_ispeed == 0)
3152                 t->c_ispeed = t->c_ospeed;
3153
3154         /* check requested parameters */
3155         divisor = ttspeedtab(t->c_ospeed, comspeedtab);
3156 #endif
3157         if (divisor < 0 || divisor > 0 && t->c_ispeed != t->c_ospeed)
3158                 return (EINVAL);
3159
3160         /* parameters are OK, convert them to the com struct and the device */
3161 #ifndef PC98
3162         unit = DEV_TO_UNIT(tp->t_dev);
3163         com = com_addr(unit);
3164         iobase = com->iobase;
3165 #endif
3166         s = spltty();
3167 #ifdef PC98
3168         if (IS_8251(com->pc98_if_type)) {
3169                 if (divisor == 0)
3170                         com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
3171                 else
3172                         com_tiocm_bis( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
3173         } else {
3174 #endif
3175         if (divisor == 0)
3176                 (void)commctl(com, TIOCM_DTR, DMBIC);   /* hang up line */
3177         else
3178                 (void)commctl(com, TIOCM_DTR, DMBIS);
3179 #ifdef PC98
3180         }
3181 #endif
3182         cflag = t->c_cflag;
3183 #ifdef PC98
3184         if (!IS_8251(com->pc98_if_type)) {
3185 #endif
3186         switch (cflag & CSIZE) {
3187         case CS5:
3188                 cfcr = CFCR_5BITS;
3189                 break;
3190         case CS6:
3191                 cfcr = CFCR_6BITS;
3192                 break;
3193         case CS7:
3194                 cfcr = CFCR_7BITS;
3195                 break;
3196         default:
3197                 cfcr = CFCR_8BITS;
3198                 break;
3199         }
3200         if (cflag & PARENB) {
3201                 cfcr |= CFCR_PENAB;
3202                 if (!(cflag & PARODD))
3203                         cfcr |= CFCR_PEVEN;
3204         }
3205         if (cflag & CSTOPB)
3206                 cfcr |= CFCR_STOPB;
3207
3208         if (com->hasfifo && divisor != 0) {
3209                 /*
3210                  * Use a fifo trigger level low enough so that the input
3211                  * latency from the fifo is less than about 16 msec and
3212                  * the total latency is less than about 30 msec.  These
3213                  * latencies are reasonable for humans.  Serial comms
3214                  * protocols shouldn't expect anything better since modem
3215                  * latencies are larger.
3216                  */
3217                 com->fifo_image = t->c_ospeed <= 4800
3218                                   ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH;
3219 #ifdef COM_ESP
3220                 /*
3221                  * The Hayes ESP card needs the fifo DMA mode bit set
3222                  * in compatibility mode.  If not, it will interrupt
3223                  * for each character received.
3224                  */
3225                 if (com->esp)
3226                         com->fifo_image |= FIFO_DMA_MODE;
3227 #endif
3228 #ifdef PC98
3229                 outb(iobase + (com_fifo << port_shift), com->fifo_image);
3230 #else
3231                 outb(iobase + com_fifo, com->fifo_image);
3232 #endif
3233         }
3234 #ifdef PC98
3235         }
3236 #endif
3237
3238         disable_intr();         /* very important while com_data is hidden */
3239
3240 #ifdef PC98
3241         if (IS_8251(com->pc98_if_type))
3242             com_cflag_and_speed_set(com, cflag, t->c_ospeed);
3243         else {
3244 #endif
3245         if (divisor != 0) {
3246 #ifdef PC98
3247                 outb(iobase + (com_cfcr << port_shift), cfcr | CFCR_DLAB);
3248 #else
3249                 outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
3250 #endif
3251                 /*
3252                  * Only set the divisor registers if they would change,
3253                  * since on some 16550 incompatibles (UMC8669F), setting
3254                  * them while input is arriving them loses sync until
3255                  * data stops arriving.
3256                  */
3257                 dlbl = divisor & 0xFF;
3258 #ifdef PC98
3259                 if (inb(iobase + (com_dlbl << port_shift)) != dlbl)
3260                         outb(iobase + (com_dlbl << port_shift), dlbl);
3261                 dlbh = (u_int) divisor >> 8;
3262                 if (inb(iobase + (com_dlbh << port_shift)) != dlbh)
3263                         outb(iobase + (com_dlbh << port_shift), dlbh);
3264 #else
3265                 if (inb(iobase + com_dlbl) != dlbl)
3266                         outb(iobase + com_dlbl, dlbl);
3267                 dlbh = (u_int) divisor >> 8;
3268                 if (inb(iobase + com_dlbh) != dlbh)
3269                         outb(iobase + com_dlbh, dlbh);
3270 #endif
3271         }
3272
3273
3274 #ifdef PC98
3275         }
3276         outb(iobase + (com_cfcr << port_shift), com->cfcr_image = cfcr);
3277 #else
3278         outb(iobase + com_cfcr, com->cfcr_image = cfcr);
3279 #endif
3280
3281         if (!(tp->t_state & TS_TTSTOP))
3282                 com->state |= CS_TTGO;
3283
3284         if (cflag & CRTS_IFLOW) {
3285                 if (com->st16650a) {
3286                         outb(iobase + com_cfcr, 0xbf);
3287                         outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x40);
3288                 }
3289                 com->state |= CS_RTS_IFLOW;
3290                 /*
3291                  * If CS_RTS_IFLOW just changed from off to on, the change
3292                  * needs to be propagated to MCR_RTS.  This isn't urgent,
3293                  * so do it later by calling comstart() instead of repeating
3294                  * a lot of code from comstart() here.
3295                  */
3296         } else if (com->state & CS_RTS_IFLOW) {
3297                 com->state &= ~CS_RTS_IFLOW;
3298                 /*
3299                  * CS_RTS_IFLOW just changed from on to off.  Force MCR_RTS
3300                  * on here, since comstart() won't do it later.
3301                  */
3302 #ifdef PC98
3303                 if (IS_8251(com->pc98_if_type))
3304                         com_tiocm_bis(com, TIOCM_RTS);
3305                 else
3306 #endif
3307                 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3308                 if (com->st16650a) {
3309                         outb(iobase + com_cfcr, 0xbf);
3310                         outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x40);
3311                 }
3312         }
3313
3314
3315         /*
3316          * Set up state to handle output flow control.
3317          * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
3318          * Now has 10+ msec latency, while CTS flow has 50- usec latency.
3319          */
3320         com->state |= CS_ODEVREADY;
3321         com->state &= ~CS_CTS_OFLOW;
3322 #ifdef PC98
3323         if (com->pc98_if_type == COM_IF_RSA98III) {
3324                 param = inb(com->rsabase + rsa_msr);
3325                 outb(com->rsabase + rsa_msr, param & 0x14);
3326         }
3327 #endif
3328         if (cflag & CCTS_OFLOW) {
3329                 com->state |= CS_CTS_OFLOW;
3330 #ifdef PC98
3331                 if (IS_8251(com->pc98_if_type)) {
3332                         if (!(pc98_get_modem_status(com) & TIOCM_CTS))
3333                                 com->state &= ~CS_ODEVREADY;
3334                 } else {
3335 #endif
3336 #ifdef PC98
3337                 if (com->pc98_if_type == COM_IF_RSA98III) {
3338                         /* Set automatic flow control mode */
3339                         outb(com->rsabase + rsa_msr, param | 0x08);
3340                 } else
3341 #endif
3342                 if (!(com->last_modem_status & MSR_CTS))
3343                         com->state &= ~CS_ODEVREADY;
3344                 if (com->st16650a) {
3345                         outb(iobase + com_cfcr, 0xbf);
3346                         outb(iobase + com_fifo, inb(iobase + com_fifo) | 0x80);
3347                 }
3348 #ifdef PC98
3349                 }
3350 #endif
3351         } else {
3352                 if (com->st16650a) {
3353                         outb(iobase + com_cfcr, 0xbf);
3354                         outb(iobase + com_fifo, inb(iobase + com_fifo) & ~0x80);
3355                 }
3356         }
3357
3358
3359 #ifdef PC98
3360         outb(iobase + (com_cfcr << port_shift), com->cfcr_image);
3361 #else
3362         outb(iobase + com_cfcr, com->cfcr_image);
3363 #endif
3364
3365
3366         /* XXX shouldn't call functions while intrs are disabled. */
3367         disc_optim(tp, t, com);
3368         /*
3369          * Recover from fiddling with CS_TTGO.  We used to call siointr1()
3370          * unconditionally, but that defeated the careful discarding of
3371          * stale input in sioopen().
3372          */
3373         if (com->state >= (CS_BUSY | CS_TTGO))
3374                 siointr1(com);
3375
3376         enable_intr();
3377         splx(s);
3378         comstart(tp);
3379         return (0);
3380 }
3381
3382 static void
3383 comstart(tp)
3384         struct tty      *tp;
3385 {
3386         struct com_s    *com;
3387         int             s;
3388         int             unit;
3389 #ifdef PC98
3390         int             tmp;
3391 #endif
3392
3393         unit = DEV_TO_UNIT(tp->t_dev);
3394         com = com_addr(unit);
3395         s = spltty();
3396         disable_intr();
3397         if (tp->t_state & TS_TTSTOP)
3398                 com->state &= ~CS_TTGO;
3399         else
3400                 com->state |= CS_TTGO;
3401         if (tp->t_state & TS_TBLOCK) {
3402 #ifdef PC98
3403                 if (IS_8251(com->pc98_if_type))
3404                         tmp = com_tiocm_get(com) & TIOCM_RTS;
3405                 else
3406                         tmp = com->mcr_image & MCR_RTS;
3407                 if (tmp && (com->state & CS_RTS_IFLOW))
3408 #else
3409                 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
3410 #endif
3411 #ifdef PC98
3412                         if (IS_8251(com->pc98_if_type))
3413                                 com_tiocm_bic(com, TIOCM_RTS);
3414                         else
3415 #endif
3416                         outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
3417         } else {
3418 #ifdef PC98
3419                 if (IS_8251(com->pc98_if_type))
3420                         tmp = com_tiocm_get(com) & TIOCM_RTS;
3421                 else
3422                         tmp = com->mcr_image & MCR_RTS;
3423                 if (!(tmp) && com->iptr < com->ihighwater
3424                         && com->state & CS_RTS_IFLOW)
3425 #else
3426                 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
3427                     && com->state & CS_RTS_IFLOW)
3428 #endif
3429 #ifdef PC98
3430                         if (IS_8251(com->pc98_if_type))
3431                                 com_tiocm_bis(com, TIOCM_RTS);
3432                         else
3433 #endif
3434                         outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
3435         }
3436         enable_intr();
3437         if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
3438                 ttwwakeup(tp);
3439 #ifdef PC98
3440 /*              if(IS_8251(com->pc98_if_type))
3441                         com_int_Tx_enable(com); */
3442 #endif
3443                 splx(s);
3444                 return;
3445         }
3446         if (tp->t_outq.c_cc != 0) {
3447                 struct lbq      *qp;
3448                 struct lbq      *next;
3449
3450                 if (!com->obufs[0].l_queued) {
3451                         com->obufs[0].l_tail
3452                             = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1,
3453 #ifndef PC98
3454                                                   sizeof com->obuf1);
3455 #else
3456                                                   com->CE_INPUT_OFFSET);
3457 #endif
3458                         com->obufs[0].l_next = NULL;
3459                         com->obufs[0].l_queued = TRUE;
3460                         disable_intr();
3461                         if (com->state & CS_BUSY) {
3462                                 qp = com->obufq.l_next;
3463                                 while ((next = qp->l_next) != NULL)
3464                                         qp = next;
3465                                 qp->l_next = &com->obufs[0];
3466                         } else {
3467                                 com->obufq.l_head = com->obufs[0].l_head;
3468                                 com->obufq.l_tail = com->obufs[0].l_tail;
3469                                 com->obufq.l_next = &com->obufs[0];
3470                                 com->state |= CS_BUSY;
3471                         }
3472                         enable_intr();
3473                 }
3474                 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
3475                         com->obufs[1].l_tail
3476                             = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2,
3477 #ifndef PC98
3478                                                   sizeof com->obuf2);
3479 #else
3480                                                   com->CE_INPUT_OFFSET);
3481 #endif
3482                         com->obufs[1].l_next = NULL;
3483                         com->obufs[1].l_queued = TRUE;
3484                         disable_intr();
3485                         if (com->state & CS_BUSY) {
3486                                 qp = com->obufq.l_next;
3487                                 while ((next = qp->l_next) != NULL)
3488                                         qp = next;
3489                                 qp->l_next = &com->obufs[1];
3490                         } else {
3491                                 com->obufq.l_head = com->obufs[1].l_head;
3492                                 com->obufq.l_tail = com->obufs[1].l_tail;
3493                                 com->obufq.l_next = &com->obufs[1];
3494                                 com->state |= CS_BUSY;
3495                         }
3496                         enable_intr();
3497                 }
3498                 tp->t_state |= TS_BUSY;
3499         }
3500         disable_intr();
3501         if (com->state >= (CS_BUSY | CS_TTGO))
3502                 siointr1(com);  /* fake interrupt to start output */
3503         enable_intr();
3504 #ifdef PC98
3505 /*              if(IS_8251(com->pc98_if_type))
3506                         com_int_Tx_enable(com); */
3507 #endif
3508         ttwwakeup(tp);
3509         splx(s);
3510 }
3511
3512 static void
3513 siostop(tp, rw)
3514         struct tty      *tp;
3515         int             rw;
3516 {
3517         struct com_s    *com;
3518 #ifdef PC98
3519         int             port_shift = 0;
3520         int             rsa98_tmp  = 0;
3521 #endif
3522
3523         com = com_addr(DEV_TO_UNIT(tp->t_dev));
3524         if (com->gone)
3525                 return;
3526 #ifdef PC98
3527         if (IS_8251(com->pc98_if_type))
3528             port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
3529 #endif
3530         disable_intr();
3531         if (rw & FWRITE) {
3532                 if (com->hasfifo)
3533 #ifdef COM_ESP
3534                     /* XXX avoid h/w bug. */
3535                     if (!com->esp)
3536 #endif
3537 #ifdef PC98
3538                         outb(com->iobase + (com_fifo << port_shift),
3539                              FIFO_XMT_RST | com->fifo_image);
3540                         if (com->pc98_if_type == COM_IF_RSA98III)
3541                             for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3542                                 outb(com->iobase + (com_fifo << port_shift),
3543                                      FIFO_XMT_RST | com->fifo_image);
3544 #else
3545                         outb(com->iobase + com_fifo,
3546                              FIFO_XMT_RST | com->fifo_image);
3547 #endif
3548                 com->obufs[0].l_queued = FALSE;
3549                 com->obufs[1].l_queued = FALSE;
3550                 if (com->state & CS_ODONE)
3551                         com_events -= LOTS_OF_EVENTS;
3552                 com->state &= ~(CS_ODONE | CS_BUSY);
3553                 com->tp->t_state &= ~TS_BUSY;
3554         }
3555         if (rw & FREAD) {
3556                 if (com->hasfifo)
3557 #ifdef COM_ESP
3558                     /* XXX avoid h/w bug. */
3559                     if (!com->esp)
3560 #endif
3561 #ifdef PC98
3562                         if (com->pc98_if_type == COM_IF_RSA98III) {
3563                             for(rsa98_tmp = 0; rsa98_tmp < 2048; rsa98_tmp++)
3564                                 inb(com->data_port);
3565                         }
3566                         outb(com->iobase + (com_fifo << port_shift),
3567                              FIFO_RCV_RST | com->fifo_image);
3568 #else
3569                         outb(com->iobase + com_fifo,
3570                              FIFO_RCV_RST | com->fifo_image);
3571 #endif
3572                 com_events -= (com->iptr - com->ibuf);
3573                 com->iptr = com->ibuf;
3574         }
3575         enable_intr();
3576         comstart(tp);
3577 }
3578
3579 static struct tty *
3580 siodevtotty(dev)
3581         dev_t   dev;
3582 {
3583         int     mynor;
3584         int     unit;
3585
3586         mynor = minor(dev);
3587         if (mynor & CONTROL_MASK)
3588                 return (NULL);
3589         unit = MINOR_TO_UNIT(mynor);
3590         if ((u_int) unit >= NSIOTOT)
3591                 return (NULL);
3592         return (&sio_tty[unit]);
3593 }
3594
3595 static int
3596 commctl(com, bits, how)
3597         struct com_s    *com;
3598         int             bits;
3599         int             how;
3600 {
3601         int     mcr;
3602         int     msr;
3603
3604         if (how == DMGET) {
3605                 bits = TIOCM_LE;        /* XXX - always enabled while open */
3606                 mcr = com->mcr_image;
3607                 if (mcr & MCR_DTR)
3608                         bits |= TIOCM_DTR;
3609                 if (mcr & MCR_RTS)
3610                         bits |= TIOCM_RTS;
3611                 msr = com->prev_modem_status;
3612                 if (msr & MSR_CTS)
3613                         bits |= TIOCM_CTS;
3614                 if (msr & MSR_DCD)
3615                         bits |= TIOCM_CD;
3616                 if (msr & MSR_DSR)
3617                         bits |= TIOCM_DSR;
3618                 /*
3619                  * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
3620                  * more volatile by reading the modem status a lot.  Perhaps
3621                  * we should latch both bits until the status is read here.
3622                  */
3623                 if (msr & (MSR_RI | MSR_TERI))
3624                         bits |= TIOCM_RI;
3625                 return (bits);
3626         }
3627         mcr = 0;
3628         if (bits & TIOCM_DTR)
3629                 mcr |= MCR_DTR;
3630         if (bits & TIOCM_RTS)
3631                 mcr |= MCR_RTS;
3632         if (com->gone)
3633                 return(0);
3634         disable_intr();
3635         switch (how) {
3636         case DMSET:
3637                 outb(com->modem_ctl_port,
3638                      com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
3639                 break;
3640         case DMBIS:
3641                 outb(com->modem_ctl_port, com->mcr_image |= mcr);
3642                 break;
3643         case DMBIC:
3644                 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
3645                 break;
3646         }
3647         enable_intr();
3648         return (0);
3649 }
3650
3651 static void
3652 siosettimeout()
3653 {
3654         struct com_s    *com;
3655         bool_t          someopen;
3656         int             unit;
3657
3658         /*
3659          * Set our timeout period to 1 second if no polled devices are open.
3660          * Otherwise set it to max(1/200, 1/hz).
3661          * Enable timeouts iff some device is open.
3662          */
3663         untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3664         sio_timeout = hz;
3665         someopen = FALSE;
3666         for (unit = 0; unit < NSIOTOT; ++unit) {
3667                 com = com_addr(unit);
3668                 if (com != NULL && com->tp != NULL
3669                     && com->tp->t_state & TS_ISOPEN && !com->gone) {
3670                         someopen = TRUE;
3671                         if (com->poll || com->poll_output) {
3672                                 sio_timeout = hz > 200 ? hz / 200 : 1;
3673                                 break;
3674                         }
3675                 }
3676         }
3677         if (someopen) {
3678                 sio_timeouts_until_log = hz / sio_timeout;
3679                 sio_timeout_handle = timeout(comwakeup, (void *)NULL,
3680                                              sio_timeout);
3681         } else {
3682                 /* Flush error messages, if any. */
3683                 sio_timeouts_until_log = 1;
3684                 comwakeup((void *)NULL);
3685                 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3686         }
3687 }
3688
3689 static void
3690 comwakeup(chan)
3691         void    *chan;
3692 {
3693         struct com_s    *com;
3694         int             unit;
3695
3696         sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
3697
3698         /*
3699          * Recover from lost output interrupts.
3700          * Poll any lines that don't use interrupts.
3701          */
3702         for (unit = 0; unit < NSIOTOT; ++unit) {
3703                 com = com_addr(unit);
3704                 if (com != NULL && !com->gone
3705                     && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
3706                         disable_intr();
3707                         siointr1(com);
3708                         enable_intr();
3709                 }
3710         }
3711
3712         /*
3713          * Check for and log errors, but not too often.
3714          */
3715         if (--sio_timeouts_until_log > 0)
3716                 return;
3717         sio_timeouts_until_log = hz / sio_timeout;
3718         for (unit = 0; unit < NSIOTOT; ++unit) {
3719                 int     errnum;
3720
3721                 com = com_addr(unit);
3722                 if (com == NULL)
3723                         continue;
3724                 if (com->gone)
3725                         continue;
3726                 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3727                         u_int   delta;
3728                         u_long  total;
3729
3730                         disable_intr();
3731                         delta = com->delta_error_counts[errnum];
3732                         com->delta_error_counts[errnum] = 0;
3733                         enable_intr();
3734                         if (delta == 0)
3735                                 continue;
3736                         total = com->error_counts[errnum] += delta;
3737                         log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3738                             unit, delta, error_desc[errnum],
3739                             delta == 1 ? "" : "s", total);
3740                 }
3741         }
3742 }
3743
3744 #ifdef PC98
3745 /* commint is called when modem control line changes */
3746 static void
3747 commint(dev_t dev)
3748 {
3749         register struct tty *tp;
3750         int     stat,delta;
3751         struct com_s *com;
3752         int     mynor,unit;
3753
3754         mynor = minor(dev);
3755         unit = MINOR_TO_UNIT(mynor);
3756         com = com_addr(unit);
3757         tp = com->tp;
3758
3759         stat = com_tiocm_get(com);
3760         delta = com_tiocm_get_delta(com);
3761
3762         if (com->state & CS_CTS_OFLOW) {
3763                 if (stat & TIOCM_CTS)
3764                         com->state |= CS_ODEVREADY;
3765                 else
3766                         com->state &= ~CS_ODEVREADY;
3767         }
3768         if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
3769             if (stat & TIOCM_CAR )
3770                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
3771             else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
3772                 /* negate DTR, RTS */
3773                 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3774                                 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3775                 /* disable IENABLE */
3776                 com_int_TxRx_disable( com );
3777             }
3778         }
3779 }
3780 #endif
3781
3782 static void
3783 disc_optim(tp, t, com)
3784         struct tty      *tp;
3785         struct termios  *t;
3786         struct com_s    *com;
3787 {
3788         if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
3789             && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
3790             && (!(t->c_iflag & PARMRK)
3791                 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
3792             && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
3793             && linesw[tp->t_line].l_rint == ttyinput)
3794                 tp->t_state |= TS_CAN_BYPASS_L_RINT;
3795         else
3796                 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
3797         com->hotchar = linesw[tp->t_line].l_hotchar;
3798 }
3799
3800 /*
3801  * Following are all routines needed for SIO to act as console
3802  */
3803 #include <machine/cons.h>
3804
3805 struct siocnstate {
3806         u_char  dlbl;
3807         u_char  dlbh;
3808         u_char  ier;
3809         u_char  cfcr;
3810         u_char  mcr;
3811 };
3812
3813 static speed_t siocngetspeed __P((Port_t, struct speedtab *));
3814 static void siocnclose  __P((struct siocnstate *sp));
3815 static void siocnopen   __P((struct siocnstate *sp));
3816 static void siocntxwait __P((void));
3817
3818 /*
3819  * XXX: sciocnget() and sciocnputc() are not declared static, as they are
3820  * referred to from i386/i386/i386-gdbstub.c.
3821  */
3822 static cn_probe_t siocnprobe;
3823 static cn_init_t siocninit;
3824 static cn_checkc_t siocncheckc;
3825        cn_getc_t siocngetc;
3826        cn_putc_t siocnputc;
3827
3828 CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc);
3829
3830 static void
3831 siocntxwait()
3832 {
3833         int     timo;
3834
3835         /*
3836          * Wait for any pending transmission to finish.  Required to avoid
3837          * the UART lockup bug when the speed is changed, and for normal
3838          * transmits.
3839          */
3840         timo = 100000;
3841         while ((inb(siocniobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3842                != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3843                 ;
3844 }
3845
3846 /*
3847  * Read the serial port specified and try to figure out what speed
3848  * it's currently running at.  We're assuming the serial port has
3849  * been initialized and is basicly idle.  This routine is only intended
3850  * to be run at system startup.
3851  *
3852  * If the value read from the serial port doesn't make sense, return 0.
3853  */
3854
3855 static speed_t
3856 siocngetspeed(iobase, table)
3857         Port_t iobase;
3858         struct speedtab *table;
3859 {
3860         int     code;
3861         u_char  dlbh;
3862         u_char  dlbl;
3863         u_char  cfcr;
3864
3865         cfcr = inb(iobase + com_cfcr);
3866         outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3867
3868         dlbl = inb(iobase + com_dlbl);
3869         dlbh = inb(iobase + com_dlbh);
3870
3871         outb(iobase + com_cfcr, cfcr);
3872
3873         code = dlbh << 8 | dlbl;
3874
3875         for ( ; table->sp_speed != -1; table++)
3876                 if (table->sp_code == code)
3877                         return (table->sp_speed);
3878
3879         return 0;       /* didn't match anything sane */
3880 }
3881
3882 static void
3883 siocnopen(sp)
3884         struct siocnstate       *sp;
3885 {
3886         int     divisor;
3887         u_char  dlbh;
3888         u_char  dlbl;
3889         Port_t  iobase;
3890
3891         /*
3892          * Save all the device control registers except the fifo register
3893          * and set our default ones (cs8 -parenb speed=comdefaultrate).
3894          * We can't save the fifo register since it is read-only.
3895          */
3896         iobase = siocniobase;
3897         sp->ier = inb(iobase + com_ier);
3898         outb(iobase + com_ier, 0);      /* spltty() doesn't stop siointr() */
3899         siocntxwait();
3900         sp->cfcr = inb(iobase + com_cfcr);
3901         outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3902         sp->dlbl = inb(iobase + com_dlbl);
3903         sp->dlbh = inb(iobase + com_dlbh);
3904         /*
3905          * Only set the divisor registers if they would change, since on
3906          * some 16550 incompatibles (Startech), setting them clears the
3907          * data input register.  This also reduces the effects of the
3908          * UMC8669F bug.
3909          */
3910         divisor = ttspeedtab(comdefaultrate, comspeedtab);
3911         dlbl = divisor & 0xFF;
3912         if (sp->dlbl != dlbl)
3913                 outb(iobase + com_dlbl, dlbl);
3914         dlbh = (u_int) divisor >> 8;
3915         if (sp->dlbh != dlbh)
3916                 outb(iobase + com_dlbh, dlbh);
3917         outb(iobase + com_cfcr, CFCR_8BITS);
3918         sp->mcr = inb(iobase + com_mcr);
3919         /*
3920          * We don't want interrupts, but must be careful not to "disable"
3921          * them by clearing the MCR_IENABLE bit, since that might cause
3922          * an interrupt by floating the IRQ line.
3923          */
3924         outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
3925 }
3926
3927 static void
3928 siocnclose(sp)
3929         struct siocnstate       *sp;
3930 {
3931         Port_t  iobase;
3932
3933         /*
3934          * Restore the device control registers.
3935          */
3936         siocntxwait();
3937         iobase = siocniobase;
3938         outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3939         if (sp->dlbl != inb(iobase + com_dlbl))
3940                 outb(iobase + com_dlbl, sp->dlbl);
3941         if (sp->dlbh != inb(iobase + com_dlbh))
3942                 outb(iobase + com_dlbh, sp->dlbh);
3943         outb(iobase + com_cfcr, sp->cfcr);
3944         /*
3945          * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
3946          */
3947         outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
3948         outb(iobase + com_ier, sp->ier);
3949 }
3950
3951 static void
3952 siocnprobe(cp)
3953         struct consdev  *cp;
3954 {
3955         speed_t                 boot_speed;
3956         u_char                  cfcr;
3957         struct isa_device       *dvp;
3958         int                     s;
3959         struct siocnstate       sp;
3960
3961         /*
3962          * Find our first enabled console, if any.  If it is a high-level
3963          * console device, then initialize it and return successfully.
3964          * If it is a low-level console device, then initialize it and
3965          * return unsuccessfully.  It must be initialized in both cases
3966          * for early use by console drivers and debuggers.  Initializing
3967          * the hardware is not necessary in all cases, since the i/o
3968          * routines initialize it on the fly, but it is necessary if
3969          * input might arrive while the hardware is switched back to an
3970          * uninitialized state.  We can't handle multiple console devices
3971          * yet because our low-level routines don't take a device arg.
3972          * We trust the user to set the console flags properly so that we
3973          * don't need to probe.
3974          */
3975         cp->cn_pri = CN_DEAD;
3976         for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++)
3977                 if (dvp->id_driver == &siodriver && dvp->id_enabled
3978                     && COM_CONSOLE(dvp)) {
3979                         siocniobase = dvp->id_iobase;
3980                         s = spltty();
3981                         if (boothowto & RB_SERIAL) {
3982                                 boot_speed = siocngetspeed(siocniobase,
3983                                                            comspeedtab);
3984                                 if (boot_speed)
3985                                         comdefaultrate = boot_speed;
3986                         }
3987
3988                         /*
3989                          * Initialize the divisor latch.  We can't rely on
3990                          * siocnopen() to do this the first time, since it 
3991                          * avoids writing to the latch if the latch appears
3992                          * to have the correct value.  Also, if we didn't
3993                          * just read the speed from the hardware, then we
3994                          * need to set the speed in hardware so that
3995                          * switching it later is null.
3996                          */
3997                         cfcr = inb(siocniobase + com_cfcr);
3998                         outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
3999                         outb(siocniobase + com_dlbl,
4000                              COMBRD(comdefaultrate) & 0xff);
4001                         outb(siocniobase + com_dlbh,
4002                              (u_int) COMBRD(comdefaultrate) >> 8);
4003                         outb(siocniobase + com_cfcr, cfcr);
4004
4005                         siocnopen(&sp);
4006                         splx(s);
4007                         if (!COM_LLCONSOLE(dvp)) {
4008                                 cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit);
4009                                 cp->cn_pri = COM_FORCECONSOLE(dvp)
4010                                              || boothowto & RB_SERIAL
4011                                              ? CN_REMOTE : CN_NORMAL;
4012                         }
4013                         break;
4014                 }
4015 }
4016
4017 static void
4018 siocninit(cp)
4019         struct consdev  *cp;
4020 {
4021         comconsole = DEV_TO_UNIT(cp->cn_dev);
4022 }
4023
4024 static int
4025 siocncheckc(dev)
4026         dev_t   dev;
4027 {
4028         int     c;
4029         Port_t  iobase;
4030         int     s;
4031         struct siocnstate       sp;
4032
4033         iobase = siocniobase;
4034         s = spltty();
4035         siocnopen(&sp);
4036         if (inb(iobase + com_lsr) & LSR_RXRDY)
4037                 c = inb(iobase + com_data);
4038         else
4039                 c = -1;
4040         siocnclose(&sp);
4041         splx(s);
4042         return (c);
4043 }
4044
4045
4046 int
4047 siocngetc(dev)
4048         dev_t   dev;
4049 {
4050         int     c;
4051         Port_t  iobase;
4052         int     s;
4053         struct siocnstate       sp;
4054
4055         iobase = siocniobase;
4056         s = spltty();
4057         siocnopen(&sp);
4058         while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4059                 ;
4060         c = inb(iobase + com_data);
4061         siocnclose(&sp);
4062         splx(s);
4063         return (c);
4064 }
4065
4066 void
4067 siocnputc(dev, c)
4068         dev_t   dev;
4069         int     c;
4070 {
4071         int     s;
4072         struct siocnstate       sp;
4073
4074         s = spltty();
4075         siocnopen(&sp);
4076         siocntxwait();
4077         outb(siocniobase + com_data, c);
4078         siocnclose(&sp);
4079         splx(s);
4080 }
4081
4082
4083 /*
4084  * support PnP cards if we are using 'em
4085  */
4086
4087 #if NPNP > 0
4088
4089 static pnpid_t siopnp_ids[] = {
4090         { 0x5015f435, "MOT1550"},
4091         { 0x8113b04e, "Supra1381"},
4092         { 0x9012b04e, "Supra1290"},
4093         { 0x7121b04e, "SupraExpress 56i Sp"},
4094         { 0x11007256, "USR0011"},
4095         { 0x30207256, "USR2030"},
4096         { 0x31307256, "USR3031"},
4097         { 0 }
4098 };
4099
4100 static char *siopnp_probe(u_long csn, u_long vend_id);
4101 static void siopnp_attach(u_long csn, u_long vend_id, char *name,
4102         struct isa_device *dev);
4103 static u_long nsiopnp = NSIO;
4104
4105 static struct pnp_device siopnp = {
4106         "siopnp",
4107         siopnp_probe,
4108         siopnp_attach,
4109         &nsiopnp,
4110         &tty_imask
4111 };
4112 DATA_SET (pnpdevice_set, siopnp);
4113
4114 static char *
4115 siopnp_probe(u_long csn, u_long vend_id)
4116 {
4117         pnpid_t *id;
4118         char *s = NULL;
4119
4120         for(id = siopnp_ids; id->vend_id != 0; id++) {
4121                 if (vend_id == id->vend_id) {
4122                         s = id->id_str;
4123                         break;
4124                 }
4125         }
4126
4127         if (s) {
4128                 struct pnp_cinfo d;
4129                 read_pnp_parms(&d, 0);
4130                 if (d.enable == 0 || d.flags & 1) {
4131                         printf("CSN %lu is disabled.\n", csn);
4132                         return (NULL);
4133                 }
4134
4135         }
4136
4137         return (s);
4138 }
4139
4140 static void
4141 siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
4142 {
4143         struct pnp_cinfo d;
4144         struct isa_device *dvp;
4145
4146         if (dev->id_unit >= NSIOTOT)
4147                 return;
4148
4149         if (read_pnp_parms(&d, 0) == 0) {
4150                 printf("failed to read pnp parms\n");
4151                 return;
4152         }
4153
4154         write_pnp_parms(&d, 0);
4155
4156         enable_pnp_card();
4157
4158         dev->id_iobase = d.port[0];
4159         dev->id_irq = (1 << d.irq[0]);
4160         dev->id_ointr = siointr;
4161         dev->id_ri_flags = RI_FAST;
4162         dev->id_drq = -1;
4163
4164         if (dev->id_driver == NULL) {
4165                 dev->id_driver = &siodriver;
4166                 dvp = find_isadev(isa_devtab_tty, &siodriver, 0);
4167                 if (dvp != NULL)
4168                         dev->id_id = dvp->id_id;
4169         }
4170
4171         if ((dev->id_alive = sioprobe(dev)) != 0)
4172                 sioattach(dev);
4173         else
4174                 printf("sio%d: probe failed\n", dev->id_unit);
4175 }
4176 #endif
4177
4178 #ifdef PC98
4179 /*
4180  *  pc98 local function
4181  */
4182
4183 static void
4184 com_tiocm_set(struct com_s *com, int msr)
4185 {
4186         int     s;
4187         int     tmp = 0;
4188         int     mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
4189
4190         s=spltty();
4191         com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
4192            | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4193         tmp |= (CMD8251_TxEN|CMD8251_RxEN);
4194         if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4195         if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4196         pc98_i8251_clear_or_cmd( com, mask, tmp );
4197         splx(s);
4198 }
4199
4200 static void
4201 com_tiocm_bis(struct com_s *com, int msr)
4202 {
4203         int     s;
4204         int     tmp = 0;
4205
4206         s=spltty();
4207         com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4208         tmp |= CMD8251_TxEN|CMD8251_RxEN;
4209         if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4210         if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4211
4212         pc98_i8251_or_cmd( com, tmp );
4213         splx(s);
4214 }
4215
4216 static void
4217 com_tiocm_bic(struct com_s *com, int msr)
4218 {
4219         int     s;
4220         int     tmp = msr;
4221
4222         s=spltty();
4223         com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4224         if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4225         if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4226
4227         pc98_i8251_clear_cmd( com, tmp );
4228         splx(s);
4229 }
4230
4231 static int
4232 com_tiocm_get(struct com_s *com)
4233 {
4234         return( com->pc98_prev_modem_status );
4235 }
4236
4237 static int
4238 com_tiocm_get_delta(struct com_s *com)
4239 {
4240         int     tmp;
4241
4242         tmp = com->pc98_modem_delta;
4243         com->pc98_modem_delta = 0;
4244         return( tmp );
4245 }
4246
4247 /* convert to TIOCM_?? ( ioctl.h ) */
4248 static int
4249 pc98_get_modem_status(struct com_s *com)
4250 {
4251         int     stat, stat2;
4252         register int    msr;
4253
4254         stat  = inb(com->sts_port);
4255         stat2 = inb(com->in_modem_port);
4256         msr = com->pc98_prev_modem_status
4257                         & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4258         if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
4259         if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
4260         if (   stat & STS8251_DSR ) msr |= TIOCM_DSR;
4261         if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
4262 #if COM_CARRIER_DETECT_EMULATE
4263         if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
4264                 msr |= TIOCM_CAR;
4265         }
4266 #endif
4267         return(msr);
4268 }
4269
4270 static void
4271 pc98_check_msr(void* chan)
4272 {
4273         int     msr, delta;
4274         int     s;
4275         register struct tty *tp;
4276         struct  com_s *com;
4277         int     mynor;
4278         int     unit;
4279         dev_t   dev;
4280
4281         dev=(dev_t)chan;
4282         mynor = minor(dev);
4283         unit = MINOR_TO_UNIT(mynor);
4284         com = com_addr(unit);
4285         tp = com->tp;
4286
4287         s = spltty();
4288         msr = pc98_get_modem_status(com);
4289         /* make change flag */
4290         delta = msr ^ com->pc98_prev_modem_status;
4291         if ( delta & TIOCM_CAR ) {
4292             if ( com->modem_car_chg_timer ) {
4293                 if ( -- com->modem_car_chg_timer )
4294                     msr ^= TIOCM_CAR;
4295             } else {
4296                 if ( com->modem_car_chg_timer = ( msr & TIOCM_CAR ) ?
4297                              DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE )
4298                     msr ^= TIOCM_CAR;
4299             }
4300         } else
4301             com->modem_car_chg_timer = 0;
4302         delta = ( msr ^ com->pc98_prev_modem_status ) &
4303                         (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4304         com->pc98_prev_modem_status = msr;
4305         delta = ( com->pc98_modem_delta |= delta );
4306         splx(s);
4307         if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
4308                 if ( delta ) {
4309                         commint(dev);
4310                 }
4311                 timeout(pc98_check_msr, (caddr_t)dev,
4312                                         PC98_CHECK_MODEM_INTERVAL);
4313         } else {
4314                 com->modem_checking = 0;
4315         }
4316 }
4317
4318 static void
4319 pc98_msrint_start(dev_t dev)
4320 {
4321         struct  com_s *com;
4322         int     mynor;
4323         int     unit;
4324         int     s = spltty();
4325
4326         mynor = minor(dev);
4327         unit = MINOR_TO_UNIT(mynor);
4328         com = com_addr(unit);
4329         /* modem control line check routine envoke interval is 1/10 sec */
4330         if ( com->modem_checking == 0 ) {
4331                 com->pc98_prev_modem_status = pc98_get_modem_status(com);
4332                 com->pc98_modem_delta = 0;
4333                 timeout(pc98_check_msr, (caddr_t)dev,
4334                                         PC98_CHECK_MODEM_INTERVAL);
4335                 com->modem_checking = 1;
4336         }
4337         splx(s);
4338 }
4339
4340 static void
4341 pc98_disable_i8251_interrupt(struct com_s *com, int mod)
4342 {
4343         /* disable interrupt */
4344         register int    tmp;
4345
4346         mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4347         COM_INT_DISABLE
4348         tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4349         outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
4350         COM_INT_ENABLE
4351 }
4352
4353 static void
4354 pc98_enable_i8251_interrupt(struct com_s *com, int mod)
4355 {
4356         register int    tmp;
4357
4358         COM_INT_DISABLE
4359         tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4360         outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
4361         COM_INT_ENABLE
4362 }
4363
4364 static int
4365 pc98_check_i8251_interrupt(struct com_s *com)
4366 {
4367         return ( com->intr_enable & 0x07 );
4368 }
4369
4370 static void
4371 pc98_i8251_clear_cmd(struct com_s *com, int x)
4372 {
4373         int     tmp;
4374
4375         COM_INT_DISABLE
4376         tmp = com->pc98_prev_siocmd & ~(x);
4377         outb(com->cmd_port, tmp);
4378         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4379         COM_INT_ENABLE
4380 }
4381
4382 static void
4383 pc98_i8251_or_cmd(struct com_s *com, int x)
4384 {
4385         int     tmp;
4386
4387         COM_INT_DISABLE
4388         tmp = com->pc98_prev_siocmd | (x);
4389         outb(com->cmd_port, tmp);
4390         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4391         COM_INT_ENABLE
4392 }
4393
4394 static void
4395 pc98_i8251_set_cmd(struct com_s *com, int x)
4396 {
4397         int     tmp;
4398
4399         COM_INT_DISABLE
4400         tmp = (x);
4401         outb(com->cmd_port, tmp);
4402         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4403         COM_INT_ENABLE
4404 }
4405
4406 static void
4407 pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
4408 {
4409         int     tmp;
4410         COM_INT_DISABLE
4411         tmp = com->pc98_prev_siocmd & ~(clr);
4412         tmp |= (x);
4413         outb(com->cmd_port, tmp);
4414         com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4415         COM_INT_ENABLE
4416 }
4417
4418 static int
4419 pc98_i8251_get_cmd(struct com_s *com)
4420 {
4421         return com->pc98_prev_siocmd;
4422 }
4423
4424 static int
4425 pc98_i8251_get_mod(struct com_s *com)
4426 {
4427         return com->pc98_prev_siomod;
4428 }
4429
4430 static void
4431 pc98_i8251_reset(struct com_s *com, int mode, int command)
4432 {
4433         outb(com->cmd_port, 0); /* dummy */
4434         DELAY(2);
4435         outb(com->cmd_port, 0); /* dummy */
4436         DELAY(2);
4437         outb(com->cmd_port, 0); /* dummy */
4438         DELAY(2);
4439         outb(com->cmd_port, CMD8251_RESET);     /* internal reset */
4440         DELAY(2);
4441         outb(com->cmd_port, mode );     /* mode register */
4442         com->pc98_prev_siomod = mode;
4443         DELAY(2);
4444         pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
4445 }
4446
4447 static void
4448 pc98_check_sysclock(void)
4449 {
4450         /* get system clock from port */
4451         if ( pc98_machine_type & M_8M ) {
4452         /* 8 MHz system & H98 */
4453                 sysclock = 8;
4454         } else {
4455         /* 5 MHz system */
4456                 sysclock = 5;
4457         }
4458 }
4459
4460 static void
4461 com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
4462 {
4463         int     cfcr=0, count;
4464         int     previnterrupt;
4465
4466         count = pc98_ttspeedtab( com, speed );
4467         if ( count < 0 ) return;
4468
4469         previnterrupt = pc98_check_i8251_interrupt(com);
4470         pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
4471
4472         switch ( cflag&CSIZE ) {
4473           case CS5:
4474                 cfcr = MOD8251_5BITS; break;
4475           case CS6:
4476                 cfcr = MOD8251_6BITS; break;
4477           case CS7:
4478                 cfcr = MOD8251_7BITS; break;
4479           case CS8:
4480                 cfcr = MOD8251_8BITS; break;
4481         }
4482         if ( cflag&PARENB ) {
4483             if ( cflag&PARODD )
4484                 cfcr |= MOD8251_PODD;
4485             else
4486                 cfcr |= MOD8251_PEVEN;
4487         } else
4488                 cfcr |= MOD8251_PDISAB;
4489
4490         if ( cflag&CSTOPB )
4491                 cfcr |= MOD8251_STOP2;
4492         else
4493                 cfcr |= MOD8251_STOP1;
4494
4495         if ( count & 0x10000 )
4496                 cfcr |= MOD8251_CLKX1;
4497         else
4498                 cfcr |= MOD8251_CLKX16;
4499
4500         if (epson_machine_id != 0x20) { /* XXX */
4501                 int     tmp;
4502                 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
4503                         ;
4504         }
4505         /* set baud rate from ospeed */
4506         pc98_set_baud_rate( com, count );
4507
4508         if ( cfcr != pc98_i8251_get_mod(com) )
4509                 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
4510
4511         pc98_enable_i8251_interrupt( com, previnterrupt );
4512 }
4513
4514 static int
4515 pc98_ttspeedtab(struct com_s *com, int speed)
4516 {
4517         int     if_type, effect_sp, count = -1, mod;
4518
4519         if_type = com->pc98_if_type & 0x0f;
4520
4521         switch (com->pc98_if_type) {
4522         case COM_IF_INTERNAL:
4523             if (PC98SIO_baud_rate_port(if_type) != -1) {
4524                 count = ttspeedtab(speed, if_8251_type[if_type].speedtab);
4525                 if (count > 0) {
4526                     count |= COM1_EXT_CLOCK;
4527                     break;
4528                 }
4529             }
4530
4531             /* for *1CLK asynchronous! mode, TEFUTEFU */
4532             mod = (sysclock == 5) ? 2457600 : 1996800;
4533             effect_sp = ttspeedtab( speed, pc98speedtab );
4534             if ( effect_sp < 0 )        /* XXX */
4535                 effect_sp = ttspeedtab( (speed - 1), pc98speedtab );
4536             if ( effect_sp <= 0 )
4537                 return effect_sp;
4538             if ( effect_sp == speed )
4539                 mod /= 16;
4540             if ( mod % effect_sp )
4541                 return(-1);
4542             count = mod / effect_sp;
4543             if ( count > 65535 )
4544                 return(-1);
4545             if ( effect_sp != speed )
4546                 count |= 0x10000;
4547             break;
4548         case COM_IF_PC9861K_1:
4549         case COM_IF_PC9861K_2:
4550             count = 1;
4551             break;
4552         case COM_IF_IND_SS_1:
4553         case COM_IF_IND_SS_2:
4554         case COM_IF_PIO9032B_1:
4555         case COM_IF_PIO9032B_2:
4556             if ( speed == 0 ) return 0;
4557             count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4558             break;
4559         case COM_IF_B98_01_1:
4560         case COM_IF_B98_01_2:
4561             if ( speed == 0 ) return 0;
4562             count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4563 #ifdef B98_01_OLD
4564             if (count == 0 || count == 1) {
4565                 count += 4;
4566                 count |= 0x20000;  /* x1 mode for 76800 and 153600 */
4567             }
4568 #endif
4569             break;
4570         }
4571
4572         return count;
4573 }
4574
4575 static void
4576 pc98_set_baud_rate( struct com_s *com, int count )
4577 {
4578         int     if_type, io, s;
4579
4580         if_type = com->pc98_if_type & 0x0f;
4581         io = com->iobase & 0xff00;
4582
4583         switch (com->pc98_if_type) {
4584         case COM_IF_INTERNAL:
4585             if (PC98SIO_baud_rate_port(if_type) != -1) {
4586                 if (count & COM1_EXT_CLOCK) {
4587                     outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff);
4588                     break;
4589                 } else {
4590                     outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09);
4591                 }
4592             }
4593
4594             if ( count < 0 ) {
4595                 printf( "[ Illegal count : %d ]", count );
4596                 return;
4597             } else if ( count == 0 )
4598                 return;
4599             /* set i8253 */
4600             s = splclock();
4601             if (count != 3)
4602                 outb( 0x77, 0xb6 );
4603             else
4604                 outb( 0x77, 0xb4 );
4605             outb( 0x5f, 0);
4606             outb( 0x75, count & 0xff );
4607             outb( 0x5f, 0);
4608             outb( 0x75, (count >> 8) & 0xff );
4609             splx(s);
4610             break;
4611         case COM_IF_IND_SS_1:
4612         case COM_IF_IND_SS_2:
4613             outb(io | PC98SIO_intr_ctrl_port(if_type), 0);
4614             outb(io | PC98SIO_baud_rate_port(if_type), 0);
4615             outb(io | PC98SIO_baud_rate_port(if_type), 0xc0);
4616             outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80);
4617             outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff);
4618             break;
4619         case COM_IF_PIO9032B_1:
4620         case COM_IF_PIO9032B_2:
4621             outb(io | PC98SIO_baud_rate_port(if_type), count);
4622             break;
4623         case COM_IF_B98_01_1:
4624         case COM_IF_B98_01_2:
4625             outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f);
4626 #ifdef B98_01_OLD
4627             /*
4628              * Some old B98_01 board should be controlled
4629              * in different way, but this hasn't been tested yet.
4630              */
4631             outb(io | PC98SIO_func_port(if_type),
4632                  (count & 0x20000) ? 0xf0 : 0xf2);
4633 #endif
4634             break;
4635         }
4636 }
4637 static int
4638 pc98_check_if_type(struct isa_device *dev, struct siodev *iod)
4639 {
4640         int     irr, io, if_type, tmp;
4641         static  short   irq_tab[2][8] = {
4642                 {  3,  5,  6,  9, 10, 12, 13, -1},
4643                 {  3, 10, 12, 13,  5,  6,  9, -1}
4644         };
4645
4646         iod->if_type = if_type = (dev->id_flags >> 24) & 0xff;
4647         if ((if_type < 0 || if_type > COM_IF_END1) &&
4648             (if_type < 0x10 || if_type > COM_IF_END2))
4649             return(-1);
4650         if_type &= 0x0f;
4651         iod->irq = 0;
4652         io = dev->id_iobase & 0xff00;
4653
4654         if (IS_8251(iod->if_type)) {
4655             if (PC98SIO_func_port(if_type) != -1) {
4656                 outb(io | PC98SIO_func_port(if_type), 0xf2);
4657                 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab);
4658                 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1)
4659                     outb(io | PC98SIO_baud_rate_port(if_type), tmp);
4660             }
4661
4662             iod->cmd  = io | PC98SIO_cmd_port(if_type);
4663             iod->sts  = io | PC98SIO_sts_port(if_type);
4664             iod->mod  = io | PC98SIO_in_modem_port(if_type);
4665             iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type);
4666
4667             if (iod->if_type == COM_IF_INTERNAL) {
4668                 iod->irq = 4;
4669
4670                 /* XXX check new internal port. */
4671                 outb(0x138, 0);
4672                 DELAY(10);
4673                 for (tmp = 0; tmp < 100; tmp++) {
4674                     if ((inb(0x138) & 1) == 0) {
4675                         PC98SIO_baud_rate_port(if_type) = 0x13a;
4676                         if_8251_type[if_type].name = " (internal fast)";
4677                         if_8251_type[if_type].speedtab = pc98fast_speedtab;
4678                         break;
4679                     }
4680                     DELAY(1);
4681                 }
4682             } else {
4683                 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask;
4684                 if ((dev->id_iobase & 0xff) == IO_COM2)
4685                     iod->irq = irq_tab[0][tmp];
4686                 else
4687                     iod->irq = irq_tab[1][tmp];
4688             }
4689         } else {
4690             irr = if_16550a_type[if_type].irr_read;
4691 #ifdef COM_MULTIPORT
4692             if (!COM_ISMULTIPORT(dev) || dev->id_unit == COM_MPMASTER(dev))
4693 #endif
4694             if (irr != -1) {
4695                 tmp = inb(io | irr);
4696                 if (dev->id_iobase & 0x01)      /* XXX depend on RSB-384 */
4697                     iod->irq = irq_tab[1][tmp >> 3];
4698                 else
4699                     iod->irq = irq_tab[0][tmp & 0x07];
4700             }
4701         }
4702         if ( iod->irq == -1 ) return -1;
4703
4704         return 0;
4705 }
4706 static int
4707 pc98_set_ioport( struct com_s *com, int id_flags )
4708 {
4709         int     io, if_type;
4710
4711         if_type = (id_flags >> 24) & 0xff;
4712         if (IS_8251(if_type)) {
4713             pc98_check_sysclock();
4714             io = com->iobase & 0xff00;
4715             com->pc98_if_type   = if_type;
4716             if_type &= 0x0f;
4717             com->data_port      = io | PC98SIO_data_port(if_type);
4718             com->cmd_port       = io | PC98SIO_cmd_port(if_type);
4719             com->sts_port       = io | PC98SIO_sts_port(if_type);
4720             com->in_modem_port  = io | PC98SIO_in_modem_port(if_type);
4721             com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type);
4722             return 0;
4723         }
4724
4725         return -1;
4726 }
4727 #endif /* PC98 defined */