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