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