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