Deleted Added
full compact
sio.c (51202) sio.c (51654)
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 *
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: head/sys/pc98/cbus/sio.c 51202 1999-09-12 13:44:54Z nyan $
33 * $FreeBSD: head/sys/pc98/cbus/sio.c 51654 1999-09-25 16:21:39Z phk $
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
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())
256 * comstop())
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
274static 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 */
287typedef u_int Port_t; /* hardware port */
288typedef u_char bool_t; /* boolean */
289
290/* queue of linear buffers */
291struct 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 */
299struct 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
413static int espattach __P((struct com_s *com, Port_t esp_port));
414#endif
415static int sioattach __P((device_t dev));
416
417static timeout_t siobusycheck;
418static timeout_t siodtrwakeup;
419static void comhardclose __P((struct com_s *com));
420static void sioinput __P((struct com_s *com));
421static void siointr1 __P((struct com_s *com));
422static void siointr __P((void *arg));
423static int commctl __P((struct com_s *com, int bits, int how));
424static int comparam __P((struct tty *tp, struct termios *t));
425static swihand_t siopoll;
426static int sioprobe __P((device_t dev));
427static void siosettimeout __P((void));
428static int siosetwater __P((struct com_s *com, speed_t speed));
429static void comstart __P((struct tty *tp));
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
274static 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 */
287typedef u_int Port_t; /* hardware port */
288typedef u_char bool_t; /* boolean */
289
290/* queue of linear buffers */
291struct 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 */
299struct 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
413static int espattach __P((struct com_s *com, Port_t esp_port));
414#endif
415static int sioattach __P((device_t dev));
416
417static timeout_t siobusycheck;
418static timeout_t siodtrwakeup;
419static void comhardclose __P((struct com_s *com));
420static void sioinput __P((struct com_s *com));
421static void siointr1 __P((struct com_s *com));
422static void siointr __P((void *arg));
423static int commctl __P((struct com_s *com, int bits, int how));
424static int comparam __P((struct tty *tp, struct termios *t));
425static swihand_t siopoll;
426static int sioprobe __P((device_t dev));
427static void siosettimeout __P((void));
428static int siosetwater __P((struct com_s *com, speed_t speed));
429static void comstart __P((struct tty *tp));
430static void comstop __P((struct tty *tp, int rw));
430static timeout_t comwakeup;
431static void disc_optim __P((struct tty *tp, struct termios *t,
432 struct com_s *com));
433
434
435static char driver_name[] = "sio";
436
437/* table and macro for fast conversion from a unit number to its com struct */
438static devclass_t sio_devclass;
439#define com_addr(unit) ((struct com_s *) \
440 devclass_get_softc(sio_devclass, unit))
441
442static device_method_t sio_methods[] = {
443 /* Device interface */
444 DEVMETHOD(device_probe, sioprobe),
445 DEVMETHOD(device_attach, sioattach),
446
447 { 0, 0 }
448};
449
450static driver_t sio_driver = {
451 driver_name,
452 sio_methods,
453 sizeof(struct com_s),
454};
455
456static d_open_t sioopen;
457static d_close_t sioclose;
458static d_read_t sioread;
459static d_write_t siowrite;
460static d_ioctl_t sioioctl;
431static timeout_t comwakeup;
432static void disc_optim __P((struct tty *tp, struct termios *t,
433 struct com_s *com));
434
435
436static char driver_name[] = "sio";
437
438/* table and macro for fast conversion from a unit number to its com struct */
439static devclass_t sio_devclass;
440#define com_addr(unit) ((struct com_s *) \
441 devclass_get_softc(sio_devclass, unit))
442
443static device_method_t sio_methods[] = {
444 /* Device interface */
445 DEVMETHOD(device_probe, sioprobe),
446 DEVMETHOD(device_attach, sioattach),
447
448 { 0, 0 }
449};
450
451static driver_t sio_driver = {
452 driver_name,
453 sio_methods,
454 sizeof(struct com_s),
455};
456
457static d_open_t sioopen;
458static d_close_t sioclose;
459static d_read_t sioread;
460static d_write_t siowrite;
461static d_ioctl_t sioioctl;
461static d_stop_t siostop;
462static d_devtotty_t siodevtotty;
463
464#define CDEV_MAJOR 28
465static struct cdevsw sio_cdevsw = {
466 /* open */ sioopen,
467 /* close */ sioclose,
468 /* read */ sioread,
469 /* write */ siowrite,
470 /* ioctl */ sioioctl,
462
463#define CDEV_MAJOR 28
464static struct cdevsw sio_cdevsw = {
465 /* open */ sioopen,
466 /* close */ sioclose,
467 /* read */ sioread,
468 /* write */ siowrite,
469 /* ioctl */ sioioctl,
471 /* stop */ siostop,
470 /* stop */ nostop,
472 /* reset */ noreset,
471 /* reset */ noreset,
473 /* devtotty */ siodevtotty,
474 /* poll */ ttpoll,
472 /* devtotty */ nodevtotty,
473 /* poll */ ttypoll,
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
487int comconsole = -1;
488static volatile speed_t comdefaultrate = CONSPEED;
489#ifdef __alpha__
490static volatile speed_t gdbdefaultrate = CONSPEED;
491#endif
492static u_int com_events; /* input chars + weighted output completions */
493static Port_t siocniobase;
494static int siocnunit;
495static Port_t siogdbiobase;
496static int siogdbunit = -1;
497static bool_t sio_registered;
498static int sio_timeout;
499static int sio_timeouts_until_log;
500static struct callout_handle sio_timeout_handle
501 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
502
503#ifdef PC98
504struct siodev {
505 short if_type;
506 short irq;
507 Port_t cmd, sts, ctrl, mod;
508};
509static 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
522static void commint __P((dev_t dev));
523static void com_tiocm_set __P((struct com_s *com, int msr));
524static void com_tiocm_bis __P((struct com_s *com, int msr));
525static void com_tiocm_bic __P((struct com_s *com, int msr));
526static int com_tiocm_get __P((struct com_s *com));
527static int com_tiocm_get_delta __P((struct com_s *com));
528static void pc98_msrint_start __P((dev_t dev));
529static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed));
530static int pc98_ttspeedtab __P((struct com_s *com, int speed));
531static int pc98_get_modem_status __P((struct com_s *com));
532static timeout_t pc98_check_msr;
533static void pc98_set_baud_rate __P((struct com_s *com, int count));
534static void pc98_i8251_reset __P((struct com_s *com, int mode, int command));
535static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod));
536static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod));
537static int pc98_check_i8251_interrupt __P((struct com_s *com));
538static int pc98_i8251_get_cmd __P((struct com_s *com));
539static int pc98_i8251_get_mod __P((struct com_s *com));
540static void pc98_i8251_set_cmd __P((struct com_s *com, int x));
541static void pc98_i8251_or_cmd __P((struct com_s *com, int x));
542static void pc98_i8251_clear_cmd __P((struct com_s *com, int x));
543static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x));
544static int pc98_check_if_type __P((device_t dev, struct siodev *iod));
545static void pc98_check_sysclock __P((void));
546static 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
565static 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};
587static 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};
595static 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};
606static 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};
621static 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};
637static 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};
658static 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
684static 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
707struct {
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
750struct {
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. */
785static Port_t likely_com_ports[] = { 0, 0xb0, 0xb1, 0 };
786static 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. */
796static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
797static 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
812static int
813sysctl_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
859SYSCTL_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 */
866static int sioinit __P((struct pccard_devinfo *));
867static void siounload __P((struct pccard_devinfo *));
868static int card_intr __P((struct pccard_devinfo *));
869
870PCCARD_MODULE(sio, sioinit, siounload, card_intr, 0, tty_imask);
871
872/*
873 * Initialize the device - called from Slot manager.
874 */
875int
876sioinit(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 */
907static void
908siounload(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 */
944static int
945card_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
961static 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
971static int
972sioprobe(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
1435static int
1436espattach(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
1514static int
1515sioattach(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);
1812determined_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
1866static int
1867sioopen(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 */
1903open_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;
474 /* mmap */ nommap,
475 /* strategy */ nostrategy,
476 /* name */ driver_name,
477 /* parms */ noparms,
478 /* maj */ CDEV_MAJOR,
479 /* dump */ nodump,
480 /* psize */ nopsize,
481 /* flags */ D_TTY,
482 /* maxio */ 0,
483 /* bmaj */ -1
484};
485
486int comconsole = -1;
487static volatile speed_t comdefaultrate = CONSPEED;
488#ifdef __alpha__
489static volatile speed_t gdbdefaultrate = CONSPEED;
490#endif
491static u_int com_events; /* input chars + weighted output completions */
492static Port_t siocniobase;
493static int siocnunit;
494static Port_t siogdbiobase;
495static int siogdbunit = -1;
496static bool_t sio_registered;
497static int sio_timeout;
498static int sio_timeouts_until_log;
499static struct callout_handle sio_timeout_handle
500 = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle);
501
502#ifdef PC98
503struct siodev {
504 short if_type;
505 short irq;
506 Port_t cmd, sts, ctrl, mod;
507};
508static int sysclock;
509
510#define COM_INT_DISABLE {int previpri; previpri=spltty();
511#define COM_INT_ENABLE splx(previpri);}
512#define IEN_TxFLAG IEN_Tx
513
514#define COM_CARRIER_DETECT_EMULATE 0
515#define PC98_CHECK_MODEM_INTERVAL (hz/10)
516#define DCD_OFF_TOLERANCE 2
517#define DCD_ON_RECOGNITION 2
518#define IS_8251(if_type) (!(if_type & 0x10))
519#define COM1_EXT_CLOCK 0x40000
520
521static void commint __P((dev_t dev));
522static void com_tiocm_set __P((struct com_s *com, int msr));
523static void com_tiocm_bis __P((struct com_s *com, int msr));
524static void com_tiocm_bic __P((struct com_s *com, int msr));
525static int com_tiocm_get __P((struct com_s *com));
526static int com_tiocm_get_delta __P((struct com_s *com));
527static void pc98_msrint_start __P((dev_t dev));
528static void com_cflag_and_speed_set __P((struct com_s *com, int cflag, int speed));
529static int pc98_ttspeedtab __P((struct com_s *com, int speed));
530static int pc98_get_modem_status __P((struct com_s *com));
531static timeout_t pc98_check_msr;
532static void pc98_set_baud_rate __P((struct com_s *com, int count));
533static void pc98_i8251_reset __P((struct com_s *com, int mode, int command));
534static void pc98_disable_i8251_interrupt __P((struct com_s *com, int mod));
535static void pc98_enable_i8251_interrupt __P((struct com_s *com, int mod));
536static int pc98_check_i8251_interrupt __P((struct com_s *com));
537static int pc98_i8251_get_cmd __P((struct com_s *com));
538static int pc98_i8251_get_mod __P((struct com_s *com));
539static void pc98_i8251_set_cmd __P((struct com_s *com, int x));
540static void pc98_i8251_or_cmd __P((struct com_s *com, int x));
541static void pc98_i8251_clear_cmd __P((struct com_s *com, int x));
542static void pc98_i8251_clear_or_cmd __P((struct com_s *com, int clr, int x));
543static int pc98_check_if_type __P((device_t dev, struct siodev *iod));
544static void pc98_check_sysclock __P((void));
545static int pc98_set_ioport __P((struct com_s *com, int id_flags));
546
547#define com_int_Tx_disable(com) \
548 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP)
549#define com_int_Tx_enable(com) \
550 pc98_enable_i8251_interrupt(com,IEN_TxFLAG)
551#define com_int_Rx_disable(com) \
552 pc98_disable_i8251_interrupt(com,IEN_Rx)
553#define com_int_Rx_enable(com) \
554 pc98_enable_i8251_interrupt(com,IEN_Rx)
555#define com_int_TxRx_disable(com) \
556 pc98_disable_i8251_interrupt(com,IEN_Tx|IEN_TxEMP|IEN_Rx)
557#define com_int_TxRx_enable(com) \
558 pc98_enable_i8251_interrupt(com,IEN_TxFLAG|IEN_Rx)
559#define com_send_break_on(com) \
560 pc98_i8251_or_cmd(com,CMD8251_SBRK)
561#define com_send_break_off(com) \
562 pc98_i8251_clear_cmd(com,CMD8251_SBRK)
563
564static struct speedtab pc98speedtab[] = { /* internal RS232C interface */
565 { 0, 0, },
566 { 50, 50, },
567 { 75, 75, },
568 { 150, 150, },
569 { 200, 200, },
570 { 300, 300, },
571 { 600, 600, },
572 { 1200, 1200, },
573 { 2400, 2400, },
574 { 4800, 4800, },
575 { 9600, 9600, },
576 { 19200, 19200, },
577 { 38400, 38400, },
578 { 51200, 51200, },
579 { 76800, 76800, },
580 { 20800, 20800, },
581 { 31200, 31200, },
582 { 41600, 41600, },
583 { 62400, 62400, },
584 { -1, -1 }
585};
586static struct speedtab pc98fast_speedtab[] = {
587 { 9600, 0x80 | COMBRD(9600), },
588 { 19200, 0x80 | COMBRD(19200), },
589 { 38400, 0x80 | COMBRD(38400), },
590 { 57600, 0x80 | COMBRD(57600), },
591 { 115200, 0x80 | COMBRD(115200), },
592 { -1, -1 }
593};
594static struct speedtab comspeedtab_pio9032b[] = {
595 { 300, 6, },
596 { 600, 5, },
597 { 1200, 4, },
598 { 2400, 3, },
599 { 4800, 2, },
600 { 9600, 1, },
601 { 19200, 0, },
602 { 38400, 7, },
603 { -1, -1 }
604};
605static struct speedtab comspeedtab_b98_01[] = {
606 { 75, 11, },
607 { 150, 10, },
608 { 300, 9, },
609 { 600, 8, },
610 { 1200, 7, },
611 { 2400, 6, },
612 { 4800, 5, },
613 { 9600, 4, },
614 { 19200, 3, },
615 { 38400, 2, },
616 { 76800, 1, },
617 { 153600, 0, },
618 { -1, -1 }
619};
620static struct speedtab comspeedtab_mc16550[] = {
621 { 300, 1536, },
622 { 600, 768, },
623 { 1200, 384, },
624 { 2400, 192, },
625 { 4800, 96, },
626 { 9600, 48, },
627 { 19200, 24, },
628 { 38400, 12, },
629 { 57600, 8, },
630 { 115200, 4, },
631 { 153600, 3, },
632 { 230400, 2, },
633 { 460800, 1, },
634 { -1, -1 }
635};
636static struct speedtab comspeedtab_rsb384[] = {
637 { 300, 3840, },
638 { 600, 1920, },
639 { 1200, 960, },
640 { 2400, 480, },
641 { 4800, 240, },
642 { 9600, 120, },
643 { 19200, 60, },
644 { 38400, 30, },
645 { 57600, 20, },
646 { 115200, 10, },
647 { 128000, 9, },
648 { 144000, 8, },
649 { 192000, 6, },
650 { 230400, 5, },
651 { 288000, 4, },
652 { 384000, 3, },
653 { 576000, 2, },
654 { 1152000, 1, },
655 { -1, -1 }
656};
657static struct speedtab comspeedtab_rsa[] = {
658 { 0, 0 },
659 { 50, COMBRD_RSA(50) },
660 { 75, COMBRD_RSA(75) },
661 { 110, COMBRD_RSA(110) },
662 { 134, COMBRD_RSA(134) },
663 { 150, COMBRD_RSA(150) },
664 { 200, COMBRD_RSA(200) },
665 { 300, COMBRD_RSA(300) },
666 { 600, COMBRD_RSA(600) },
667 { 1200, COMBRD_RSA(1200) },
668 { 1800, COMBRD_RSA(1800) },
669 { 2400, COMBRD_RSA(2400) },
670 { 4800, COMBRD_RSA(4800) },
671 { 9600, COMBRD_RSA(9600) },
672 { 19200, COMBRD_RSA(19200) },
673 { 38400, COMBRD_RSA(38400) },
674 { 57600, COMBRD_RSA(57600) },
675 { 115200, COMBRD_RSA(115200) },
676 { 230400, COMBRD_RSA(230400) },
677 { 460800, COMBRD_RSA(460800) },
678 { 921600, COMBRD_RSA(921600) },
679 { -1, -1 }
680};
681#endif /* PC98 */
682
683static struct speedtab comspeedtab[] = {
684 { 0, 0 },
685 { 50, COMBRD(50) },
686 { 75, COMBRD(75) },
687 { 110, COMBRD(110) },
688 { 134, COMBRD(134) },
689 { 150, COMBRD(150) },
690 { 200, COMBRD(200) },
691 { 300, COMBRD(300) },
692 { 600, COMBRD(600) },
693 { 1200, COMBRD(1200) },
694 { 1800, COMBRD(1800) },
695 { 2400, COMBRD(2400) },
696 { 4800, COMBRD(4800) },
697 { 9600, COMBRD(9600) },
698 { 19200, COMBRD(19200) },
699 { 38400, COMBRD(38400) },
700 { 57600, COMBRD(57600) },
701 { 115200, COMBRD(115200) },
702 { -1, -1 }
703};
704
705#ifdef PC98
706struct {
707 char *name;
708 short port_table[7];
709 short irr_mask;
710 struct speedtab *speedtab;
711 short check_irq;
712} if_8251_type[] = {
713 /* COM_IF_INTERNAL */
714 { " (internal)", {0x30, 0x32, 0x32, 0x33, 0x35, -1, -1},
715 -1, pc98speedtab, 1 },
716 /* COM_IF_PC9861K_1 */
717 { " (PC9861K)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, -1, -1},
718 3, NULL, 1 },
719 /* COM_IF_PC9861K_2 */
720 { " (PC9861K)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, -1, -1},
721 3, NULL, 1 },
722 /* COM_IF_IND_SS_1 */
723 { " (IND-SS)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb3, -1},
724 3, comspeedtab_mc16550, 1 },
725 /* COM_IF_IND_SS_2 */
726 { " (IND-SS)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xbb, -1},
727 3, comspeedtab_mc16550, 1 },
728 /* COM_IF_PIO9032B_1 */
729 { " (PIO9032B)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xb8, -1},
730 7, comspeedtab_pio9032b, 1 },
731 /* COM_IF_PIO9032B_2 */
732 { " (PIO9032B)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xba, -1},
733 7, comspeedtab_pio9032b, 1 },
734 /* COM_IF_B98_01_1 */
735 { " (B98-01)", {0xb1, 0xb3, 0xb3, 0xb0, 0xb0, 0xd1, 0xd3},
736 7, comspeedtab_b98_01, 0 },
737 /* COM_IF_B98_01_2 */
738 { " (B98-01)", {0xb9, 0xbb, 0xbb, 0xb2, 0xb2, 0xd5, 0xd7},
739 7, comspeedtab_b98_01, 0 },
740};
741#define PC98SIO_data_port(type) (if_8251_type[type].port_table[0])
742#define PC98SIO_cmd_port(type) (if_8251_type[type].port_table[1])
743#define PC98SIO_sts_port(type) (if_8251_type[type].port_table[2])
744#define PC98SIO_in_modem_port(type) (if_8251_type[type].port_table[3])
745#define PC98SIO_intr_ctrl_port(type) (if_8251_type[type].port_table[4])
746#define PC98SIO_baud_rate_port(type) (if_8251_type[type].port_table[5])
747#define PC98SIO_func_port(type) (if_8251_type[type].port_table[6])
748
749struct {
750 char *name;
751 short irr_read;
752 short irr_write;
753 short port_shift;
754 short io_size;
755 struct speedtab *speedtab;
756} if_16550a_type[] = {
757 /* COM_IF_RSA98 */
758 { " (RSA-98)", -1, -1, 0, IO_COMSIZE, comspeedtab },
759 /* COM_IF_NS16550 */
760 { "", -1, -1, 0, IO_COMSIZE, comspeedtab },
761 /* COM_IF_SECOND_CCU */
762 { "", -1, -1, 0, IO_COMSIZE, comspeedtab },
763 /* COM_IF_MC16550II */
764 { " (MC16550II)", -1, 0x1000, 8, 1, comspeedtab_mc16550 },
765 /* COM_IF_MCRS98 */
766 { " (MC-RS98)", -1, 0x1000, 8, 1, comspeedtab_mc16550 },
767 /* COM_IF_RSB3000 */
768 { " (RSB-3000)", 0xbf, -1, 1, 1, comspeedtab_rsb384 },
769 /* COM_IF_RSB384 */
770 { " (RSB-384)", 0xbf, -1, 1, 1, comspeedtab_rsb384 },
771 /* COM_IF_MODEM_CARD */
772 { "", -1, -1, 0, IO_COMSIZE, comspeedtab },
773 /* COM_IF_RSA98III */
774 { " (RSA-98III)", -1, -1, 0, 16, comspeedtab_rsa },
775 /* COM_IF_ESP98 */
776 { " (ESP98)", -1, -1, 1, 1, comspeedtab_mc16550 },
777};
778#endif /* PC98 */
779
780#ifdef COM_ESP
781#ifdef PC98
782
783/* XXX configure this properly. */
784static Port_t likely_com_ports[] = { 0, 0xb0, 0xb1, 0 };
785static Port_t likely_esp_ports[] = { 0xc0d0, 0 };
786
787#define ESP98_CMD1 (ESP_CMD1 * 0x100)
788#define ESP98_CMD2 (ESP_CMD2 * 0x100)
789#define ESP98_STATUS1 (ESP_STATUS1 * 0x100)
790#define ESP98_STATUS2 (ESP_STATUS2 * 0x100)
791
792#else /* PC98 */
793
794/* XXX configure this properly. */
795static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
796static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
797
798#endif /* PC98 */
799#endif
800
801/*
802 * handle sysctl read/write requests for console speed
803 *
804 * In addition to setting comdefaultrate for I/O through /dev/console,
805 * also set the initial and lock values for the /dev/ttyXX device
806 * if there is one associated with the console. Finally, if the /dev/tty
807 * device has already been open, change the speed on the open running port
808 * itself.
809 */
810
811static int
812sysctl_machdep_comdefaultrate SYSCTL_HANDLER_ARGS
813{
814 int error, s;
815 speed_t newspeed;
816 struct com_s *com;
817 struct tty *tp;
818
819 newspeed = comdefaultrate;
820
821 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
822 if (error || !req->newptr)
823 return (error);
824
825 comdefaultrate = newspeed;
826
827 if (comconsole < 0) /* serial console not selected? */
828 return (0);
829
830 com = com_addr(comconsole);
831 if (!com)
832 return (ENXIO);
833
834 /*
835 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
836 * (note, the lock rates really are boolean -- if non-zero, disallow
837 * speed changes)
838 */
839 com->it_in.c_ispeed = com->it_in.c_ospeed =
840 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
841 com->it_out.c_ispeed = com->it_out.c_ospeed =
842 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
843
844 /*
845 * if we're open, change the running rate too
846 */
847 tp = com->tp;
848 if (tp && (tp->t_state & TS_ISOPEN)) {
849 tp->t_termios.c_ispeed =
850 tp->t_termios.c_ospeed = comdefaultrate;
851 s = spltty();
852 error = comparam(tp, &tp->t_termios);
853 splx(s);
854 }
855 return error;
856}
857
858SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
859 0, 0, sysctl_machdep_comdefaultrate, "I", "");
860
861#if NCARD > 0
862/*
863 * PC-Card (PCMCIA) specific code.
864 */
865static int sioinit __P((struct pccard_devinfo *));
866static void siounload __P((struct pccard_devinfo *));
867static int card_intr __P((struct pccard_devinfo *));
868
869PCCARD_MODULE(sio, sioinit, siounload, card_intr, 0, tty_imask);
870
871/*
872 * Initialize the device - called from Slot manager.
873 */
874int
875sioinit(struct pccard_devinfo *devi)
876{
877
878 /* validate unit number. */
879 if (devi->isahd.id_unit >= (NSIOTOT))
880 return(ENODEV);
881 /* Make sure it isn't already probed. */
882 if (com_addr(devi->isahd.id_unit))
883 return(EBUSY);
884
885 /* It's already probed as serial by Upper */
886 devi->isahd.id_flags |= COM_C_NOPROBE;
887
888 /*
889 * attach the device.
890 */
891 if (sioattach(devi->isahd.id_device) == 0)
892 return(ENXIO);
893
894 return(0);
895}
896
897/*
898 * siounload - unload the driver and clear the table.
899 * XXX TODO:
900 * This is usually called when the card is ejected, but
901 * can be caused by a modunload of a controller driver.
902 * The idea is to reset the driver's view of the device
903 * and ensure that any driver entry points such as
904 * read and write do not hang.
905 */
906static void
907siounload(struct pccard_devinfo *devi)
908{
909 struct com_s *com;
910
911 if (!devi) {
912 printf("NULL devi in siounload\n");
913 return;
914 }
915 com = com_addr(devi->isahd.id_unit);
916 if (!com) {
917 printf("NULL com in siounload\n");
918 return;
919 }
920 if (!com->iobase) {
921 printf("sio%d already unloaded!\n",devi->isahd.id_unit);
922 return;
923 }
924 if (com->tp && (com->tp->t_state & TS_ISOPEN)) {
925 com->gone = 1;
926 printf("sio%d: unload\n", devi->isahd.id_unit);
927 com->tp->t_gen++;
928 ttyclose(com->tp);
929 ttwakeup(com->tp);
930 ttwwakeup(com->tp);
931 } else {
932 if (com->ibuf != NULL)
933 free(com->ibuf, M_DEVBUF);
934 free(com, M_DEVBUF);
935 printf("sio%d: unload,gone\n", devi->isahd.id_unit);
936 }
937}
938
939/*
940 * card_intr - Shared interrupt called from
941 * front end of PC-Card handler.
942 */
943static int
944card_intr(struct pccard_devinfo *devi)
945{
946 struct com_s *com;
947
948 COM_LOCK();
949 com = com_addr(devi->isahd.id_unit);
950 if (com && !com->gone)
951 siointr1(com_addr(devi->isahd.id_unit));
952 COM_UNLOCK();
953 return(1);
954}
955#endif /* NCARD > 0 */
956
957#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
958#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
959
960static struct isa_pnp_id sio_ids[] = {
961 {0x0005d041, "Standard PC COM port"}, /* PNP0500 */
962 {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */
963 {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */
964 {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */
965 {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */
966 {0x31307256, "USR3031"}, /* USR3031 */
967 {0}
968};
969
970static int
971sioprobe(dev)
972 device_t dev;
973{
974 static bool_t already_init;
975 bool_t failures[10];
976 int fn;
977 device_t idev;
978 Port_t iobase;
979 intrmask_t irqmap[4];
980 intrmask_t irqs;
981 u_char mcr_image;
982 int result;
983 device_t xdev;
984 u_int flags = device_get_flags(dev);
985 int rid;
986 struct resource *port;
987#ifdef PC98
988 int irqout=0;
989 int tmp;
990 int port_shift = 0;
991 struct siodev iod;
992 Port_t rsabase = NULL;
993#endif
994
995 /* Check isapnp ids */
996 if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO)
997 return (ENXIO);
998
999 rid = 0;
1000#ifdef PC98
1001 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1002 0, ~0, 1, RF_ACTIVE); /* XXX */
1003#else
1004 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1005 0, ~0, IO_COMSIZE, RF_ACTIVE);
1006#endif
1007 if (!port)
1008 return ENXIO;
1009
1010 if (!already_init) {
1011 /*
1012 * Turn off MCR_IENABLE for all likely serial ports. An unused
1013 * port with its MCR_IENABLE gate open will inhibit interrupts
1014 * from any used port that shares the interrupt vector.
1015 * XXX the gate enable is elsewhere for some multiports.
1016 */
1017 device_t *devs;
1018 int count, i;
1019
1020 devclass_get_devices(sio_devclass, &devs, &count);
1021#ifdef PC98
1022 for (i = 0; i < count; i++) {
1023 xdev = devs[i];
1024 if (device_is_enabled(xdev)) {
1025 tmp = (flags >> 24) & 0xff;
1026 if (IS_8251(tmp))
1027 outb((isa_get_port(xdev) & 0xff00) | PC98SIO_cmd_port(tmp & 0x0f), 0xf2);
1028 else
1029 if (tmp == COM_IF_RSA98III) {
1030 rsabase = isa_get_port(xdev) & 0xfff0;
1031 outb(isa_get_port(xdev) + 8 + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0);
1032 } else
1033 outb(isa_get_port(xdev) + (com_mcr << if_16550a_type[tmp & 0x0f].port_shift), 0);
1034 }
1035 }
1036#else
1037 for (i = 0; i < count; i++) {
1038 xdev = devs[i];
1039 if (device_is_enabled(xdev))
1040 outb(isa_get_port(xdev) + com_mcr, 0);
1041 }
1042#endif
1043 free(devs, M_TEMP);
1044 already_init = TRUE;
1045 }
1046
1047 if (COM_LLCONSOLE(flags)) {
1048 printf("sio%d: reserved for low-level i/o\n",
1049 device_get_unit(dev));
1050 return (ENXIO);
1051 }
1052
1053#ifdef PC98
1054 DELAY(10);
1055
1056 /*
1057 * If the port is i8251 UART (internal, B98_01)
1058 */
1059 if (pc98_check_if_type(dev, &iod) == -1)
1060 return ENXIO;
1061 if (iod.irq > 0)
1062 isa_set_irq(dev, iod.irq);
1063 if (IS_8251(iod.if_type)) {
1064 outb(iod.cmd, 0);
1065 DELAY(10);
1066 outb(iod.cmd, 0);
1067 DELAY(10);
1068 outb(iod.cmd, 0);
1069 DELAY(10);
1070 outb(iod.cmd, CMD8251_RESET);
1071 DELAY(1000); /* for a while...*/
1072 outb(iod.cmd, 0xf2); /* MODE (dummy) */
1073 DELAY(10);
1074 outb(iod.cmd, 0x01); /* CMD (dummy) */
1075 DELAY(1000); /* for a while...*/
1076 if (( inb(iod.sts) & STS8251_TxEMP ) == 0 ) {
1077 result = ENXIO;
1078 }
1079 if (if_8251_type[iod.if_type & 0x0f].check_irq) {
1080 COM_INT_DISABLE
1081 tmp = ( inb( iod.ctrl ) & ~(IEN_Rx|IEN_TxEMP|IEN_Tx));
1082 outb( iod.ctrl, tmp|IEN_TxEMP );
1083 DELAY(10);
1084 result = isa_irq_pending() ? 0 : ENXIO;
1085 outb( iod.ctrl, tmp );
1086 COM_INT_ENABLE
1087 } else {
1088 /*
1089 * B98_01 doesn't activate TxEMP interrupt line
1090 * when being reset, so we can't check irq pending.
1091 */
1092 result = 0;
1093 }
1094 if (epson_machine_id==0x20) { /* XXX */
1095 result = 0;
1096 }
1097 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1098 return result;
1099 }
1100#endif /* PC98 */
1101 /*
1102 * If the device is on a multiport card and has an AST/4
1103 * compatible interrupt control register, initialize this
1104 * register and prepare to leave MCR_IENABLE clear in the mcr.
1105 * Otherwise, prepare to set MCR_IENABLE in the mcr.
1106 * Point idev to the device struct giving the correct id_irq.
1107 * This is the struct for the master device if there is one.
1108 */
1109 idev = dev;
1110 mcr_image = MCR_IENABLE;
1111#ifdef PC98
1112 if (iod.if_type == COM_IF_RSA98III) {
1113 mcr_image = 0;
1114 rsabase = isa_get_port(idev) & 0xfff0;
1115 if (rsabase != isa_get_port(idev))
1116 return(0);
1117 outb(rsabase + rsa_msr, 0x04);
1118 outb(rsabase + rsa_frr, 0x00);
1119 if ((inb(rsabase + rsa_srr) & 0x36) != 0x36)
1120 return (0);
1121 outb(rsabase + rsa_ier, 0x00);
1122 outb(rsabase + rsa_frr, 0x00);
1123 outb(rsabase + rsa_tivsr, 0x00);
1124 outb(rsabase + rsa_tcr, 0x00);
1125 }
1126#endif /* PC98 */
1127#ifdef COM_MULTIPORT
1128 if (COM_ISMULTIPORT(flags)) {
1129 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
1130 if (idev == NULL) {
1131 printf("sio%d: master device %d not configured\n",
1132 device_get_unit(dev), COM_MPMASTER(flags));
1133 idev = dev;
1134 }
1135#ifndef PC98
1136 if (!COM_NOTAST4(flags)) {
1137 outb(isa_get_port(idev) + com_scr,
1138 isa_get_irq(idev) >= 0 ? 0x80 : 0);
1139 mcr_image = 0;
1140 }
1141#endif /* !PC98 */
1142 }
1143#endif /* COM_MULTIPORT */
1144 if (isa_get_irq(idev) < 0)
1145 mcr_image = 0;
1146
1147#ifdef PC98
1148 tmp = if_16550a_type[iod.if_type & 0x0f].irr_write;
1149 if (tmp != -1) {
1150 /* MC16550II */
1151 switch (isa_get_irq(idev)) {
1152 case 3: irqout = 4; break;
1153 case 5: irqout = 5; break;
1154 case 6: irqout = 6; break;
1155 case 12: irqout = 7; break;
1156 default:
1157 printf("sio%d: irq configuration error\n",
1158 device_get_unit(dev));
1159 return (0);
1160 }
1161 outb((isa_get_port(dev) & 0x00ff) | tmp, irqout);
1162 }
1163 port_shift = if_16550a_type[iod.if_type & 0x0f].port_shift;
1164#endif
1165 bzero(failures, sizeof failures);
1166 iobase = rman_get_start(port);
1167#ifdef PC98
1168 if (iod.if_type == COM_IF_RSA98III)
1169 iobase += 8;
1170#endif
1171
1172 /*
1173 * We don't want to get actual interrupts, just masked ones.
1174 * Interrupts from this line should already be masked in the ICU,
1175 * but mask them in the processor as well in case there are some
1176 * (misconfigured) shared interrupts.
1177 */
1178 disable_intr();
1179/* EXTRA DELAY? */
1180
1181 /*
1182 * Initialize the speed and the word size and wait long enough to
1183 * drain the maximum of 16 bytes of junk in device output queues.
1184 * The speed is undefined after a master reset and must be set
1185 * before relying on anything related to output. There may be
1186 * junk after a (very fast) soft reboot and (apparently) after
1187 * master reset.
1188 * XXX what about the UART bug avoided by waiting in comparam()?
1189 * We don't want to to wait long enough to drain at 2 bps.
1190 */
1191 if (iobase == siocniobase)
1192 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
1193 else {
1194#ifdef PC98
1195 tmp = ttspeedtab(SIO_TEST_SPEED,
1196 if_16550a_type[iod.if_type & 0x0f].speedtab);
1197 outb(iobase + (com_cfcr << port_shift), CFCR_DLAB|CFCR_8BITS);
1198 outb(iobase + (com_dlbl << port_shift), tmp & 0xff);
1199 outb(iobase + (com_dlbh << port_shift), (tmp >> 8) & 0xff);
1200 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS);
1201#else
1202 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
1203 outb(iobase + com_dlbl, COMBRD(SIO_TEST_SPEED) & 0xff);
1204 outb(iobase + com_dlbh, (u_int) COMBRD(SIO_TEST_SPEED) >> 8);
1205 outb(iobase + com_cfcr, CFCR_8BITS);
1206#endif
1207 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
1208 }
1209
1210 /*
1211 * Enable the interrupt gate and disable device interupts. This
1212 * should leave the device driving the interrupt line low and
1213 * guarantee an edge trigger if an interrupt can be generated.
1214 */
1215/* EXTRA DELAY? */
1216#ifdef PC98
1217 outb(iobase + (com_mcr << port_shift), mcr_image);
1218 outb(iobase + (com_ier << port_shift), 0);
1219#else
1220 outb(iobase + com_mcr, mcr_image);
1221 outb(iobase + com_ier, 0);
1222#endif
1223 DELAY(1000); /* XXX */
1224 irqmap[0] = isa_irq_pending();
1225
1226 /*
1227 * Attempt to set loopback mode so that we can send a null byte
1228 * without annoying any external device.
1229 */
1230/* EXTRA DELAY? */
1231#ifdef PC98
1232 outb(iobase + (com_mcr << port_shift), mcr_image | MCR_LOOPBACK);
1233#else
1234 outb(iobase + com_mcr, mcr_image | MCR_LOOPBACK);
1235#endif
1236
1237 /*
1238 * Attempt to generate an output interrupt. On 8250's, setting
1239 * IER_ETXRDY generates an interrupt independent of the current
1240 * setting and independent of whether the THR is empty. On 16450's,
1241 * setting IER_ETXRDY generates an interrupt independent of the
1242 * current setting. On 16550A's, setting IER_ETXRDY only
1243 * generates an interrupt when IER_ETXRDY is not already set.
1244 */
1245#ifdef PC98
1246 outb(iobase + (com_ier << port_shift), IER_ETXRDY);
1247 if (iod.if_type == COM_IF_RSA98III)
1248 outb(rsabase + rsa_ier, 0x04);
1249#else
1250 outb(iobase + com_ier, IER_ETXRDY);
1251#endif /* PC98 */
1252
1253 /*
1254 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
1255 * an interrupt. They'd better generate one for actually doing
1256 * output. Loopback may be broken on the same incompatibles but
1257 * it's unlikely to do more than allow the null byte out.
1258 */
1259#ifdef PC98
1260 outb(iobase + (com_data << port_shift), 0);
1261#else
1262 outb(iobase + com_data, 0);
1263#endif
1264 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
1265
1266 /*
1267 * Turn off loopback mode so that the interrupt gate works again
1268 * (MCR_IENABLE was hidden). This should leave the device driving
1269 * an interrupt line high. It doesn't matter if the interrupt
1270 * line oscillates while we are not looking at it, since interrupts
1271 * are disabled.
1272 */
1273/* EXTRA DELAY? */
1274#ifdef PC98
1275 outb(iobase + (com_mcr << port_shift), mcr_image);
1276#else
1277 outb(iobase + com_mcr, mcr_image);
1278#endif /* PC98 */
1279
1280 /*
1281 * It's a definitly Serial PCMCIA(16550A), but still be required
1282 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
1283 */
1284 if ( COM_NOPROBE(flags) ) {
1285 /* Reading IIR register twice */
1286 for ( fn = 0; fn < 2; fn ++ ) {
1287 DELAY(10000);
1288#ifdef PC98
1289 failures[6] = inb(iobase + (com_iir << port_shift));
1290#else
1291 failures[6] = inb(iobase + com_iir);
1292#endif
1293 }
1294 /* Check IIR_TXRDY clear ? */
1295 result = 0;
1296 if ( failures[6] & IIR_TXRDY ) {
1297 /* Nop, Double check with clearing IER */
1298#ifdef PC98
1299 outb(iobase + (com_ier << port_shift), 0);
1300 if (inb(iobase +
1301 (com_iir << port_shift)) & IIR_NOPEND) {
1302#else
1303 outb(iobase + com_ier, 0);
1304 if ( inb(iobase + com_iir) & IIR_NOPEND ) {
1305#endif
1306 /* Ok. we're familia this gang */
1307 SET_FLAG(dev, COM_C_IIR_TXRDYBUG); /* Set IIR_TXRDYBUG */
1308 } else {
1309 /* Unknown, Just omit this chip.. XXX */
1310 result = ENXIO;
1311 }
1312 } else {
1313 /* OK. this is well-known guys */
1314 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG); /*Clear IIR_TXRDYBUG*/
1315 }
1316#ifdef PC98
1317 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS);
1318#else
1319 outb(iobase + com_cfcr, CFCR_8BITS);
1320#endif
1321 enable_intr();
1322 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1323 return (iobase == siocniobase ? 0 : result);
1324 }
1325
1326 /*
1327 * Check that
1328 * o the CFCR, IER and MCR in UART hold the values written to them
1329 * (the values happen to be all distinct - this is good for
1330 * avoiding false positive tests from bus echoes).
1331 * o an output interrupt is generated and its vector is correct.
1332 * o the interrupt goes away when the IIR in the UART is read.
1333 */
1334/* EXTRA DELAY? */
1335#ifdef PC98
1336 failures[0] = inb(iobase + (com_cfcr << port_shift)) - CFCR_8BITS;
1337 failures[1] = inb(iobase + (com_ier << port_shift)) - IER_ETXRDY;
1338 failures[2] = inb(iobase + (com_mcr << port_shift)) - mcr_image;
1339#else
1340 failures[0] = inb(iobase + com_cfcr) - CFCR_8BITS;
1341 failures[1] = inb(iobase + com_ier) - IER_ETXRDY;
1342 failures[2] = inb(iobase + com_mcr) - mcr_image;
1343#endif
1344 DELAY(10000); /* Some internal modems need this time */
1345 irqmap[1] = isa_irq_pending();
1346#ifdef PC98
1347 failures[4] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK)
1348 - IIR_TXRDY;
1349 if (iod.if_type == COM_IF_RSA98III)
1350 inb(rsabase + rsa_srr);
1351#else
1352 failures[4] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_TXRDY;
1353#endif
1354 DELAY(1000); /* XXX */
1355 irqmap[2] = isa_irq_pending();
1356#ifdef PC98
1357 failures[6] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK)
1358 - IIR_NOPEND;
1359 if (iod.if_type == COM_IF_RSA98III)
1360 inb(rsabase + rsa_srr);
1361#else
1362 failures[6] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
1363#endif
1364
1365 /*
1366 * Turn off all device interrupts and check that they go off properly.
1367 * Leave MCR_IENABLE alone. For ports without a master port, it gates
1368 * the OUT2 output of the UART to
1369 * the ICU input. Closing the gate would give a floating ICU input
1370 * (unless there is another device driving it) and spurious interrupts.
1371 * (On the system that this was first tested on, the input floats high
1372 * and gives a (masked) interrupt as soon as the gate is closed.)
1373 */
1374#ifdef PC98
1375 outb(iobase + (com_ier << port_shift), 0);
1376 outb(iobase + (com_cfcr << port_shift), CFCR_8BITS);
1377 failures[7] = inb(iobase + (com_ier << port_shift));
1378 if (iod.if_type == COM_IF_RSA98III)
1379 outb(rsabase + rsa_ier, 0x00);
1380#else
1381 outb(iobase + com_ier, 0);
1382 outb(iobase + com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
1383 failures[7] = inb(iobase + com_ier);
1384#endif
1385 DELAY(1000); /* XXX */
1386 irqmap[3] = isa_irq_pending();
1387#ifdef PC98
1388 failures[9] = (inb(iobase + (com_iir << port_shift)) & IIR_IMASK)
1389 - IIR_NOPEND;
1390 if (iod.if_type == COM_IF_RSA98III) {
1391 inb(rsabase + rsa_srr);
1392 outb(rsabase + rsa_frr, 0x00);
1393 }
1394#else
1395 failures[9] = (inb(iobase + com_iir) & IIR_IMASK) - IIR_NOPEND;
1396#endif
1397
1398 enable_intr();
1399
1400 irqs = irqmap[1] & ~irqmap[0];
1401 if (isa_get_irq(idev) >= 0 && ((1 << isa_get_irq(idev)) & irqs) == 0)
1402 printf(
1403 "sio%d: configured irq %d not in bitmap of probed irqs %#x\n",
1404 device_get_unit(dev), isa_get_irq(idev), irqs);
1405 if (bootverbose)
1406 printf("sio%d: irq maps: %#x %#x %#x %#x\n",
1407 device_get_unit(dev),
1408 irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
1409
1410 result = 0;
1411 for (fn = 0; fn < sizeof failures; ++fn)
1412 if (failures[fn]) {
1413#ifdef PC98
1414 outb(iobase + (com_mcr << port_shift), 0);
1415#else
1416 outb(iobase + com_mcr, 0);
1417#endif
1418 result = ENXIO;
1419 if (bootverbose) {
1420 printf("sio%d: probe failed test(s):",
1421 device_get_unit(dev));
1422 for (fn = 0; fn < sizeof failures; ++fn)
1423 if (failures[fn])
1424 printf(" %d", fn);
1425 printf("\n");
1426 }
1427 break;
1428 }
1429 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1430 return (iobase == siocniobase ? 0 : result);
1431}
1432
1433#ifdef COM_ESP
1434static int
1435espattach(com, esp_port)
1436 struct com_s *com;
1437 Port_t esp_port;
1438{
1439 u_char dips;
1440 u_char val;
1441
1442 /*
1443 * Check the ESP-specific I/O port to see if we're an ESP
1444 * card. If not, return failure immediately.
1445 */
1446 if ((inb(esp_port) & 0xf3) == 0) {
1447 printf(" port 0x%x is not an ESP board?\n", esp_port);
1448 return (0);
1449 }
1450
1451 /*
1452 * We've got something that claims to be a Hayes ESP card.
1453 * Let's hope so.
1454 */
1455
1456 /* Get the dip-switch configuration */
1457#ifdef PC98
1458 outb(esp_port + ESP98_CMD1, ESP_GETDIPS);
1459 dips = inb(esp_port + ESP98_STATUS1);
1460#else
1461 outb(esp_port + ESP_CMD1, ESP_GETDIPS);
1462 dips = inb(esp_port + ESP_STATUS1);
1463#endif
1464
1465 /*
1466 * Bits 0,1 of dips say which COM port we are.
1467 */
1468#ifdef PC98
1469 if ((com->iobase & 0xff) == likely_com_ports[dips & 0x03])
1470#else
1471 if (com->iobase == likely_com_ports[dips & 0x03])
1472#endif
1473 printf(" : ESP");
1474 else {
1475 printf(" esp_port has com %d\n", dips & 0x03);
1476 return (0);
1477 }
1478
1479 /*
1480 * Check for ESP version 2.0 or later: bits 4,5,6 = 010.
1481 */
1482#ifdef PC98
1483 outb(esp_port + ESP98_CMD1, ESP_GETTEST);
1484 val = inb(esp_port + ESP98_STATUS1); /* clear reg 1 */
1485 val = inb(esp_port + ESP98_STATUS2);
1486#else
1487 outb(esp_port + ESP_CMD1, ESP_GETTEST);
1488 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */
1489 val = inb(esp_port + ESP_STATUS2);
1490#endif
1491 if ((val & 0x70) < 0x20) {
1492 printf("-old (%o)", val & 0x70);
1493 return (0);
1494 }
1495
1496 /*
1497 * Check for ability to emulate 16550: bit 7 == 1
1498 */
1499 if ((dips & 0x80) == 0) {
1500 printf(" slave");
1501 return (0);
1502 }
1503
1504 /*
1505 * Okay, we seem to be a Hayes ESP card. Whee.
1506 */
1507 com->esp = TRUE;
1508 com->esp_port = esp_port;
1509 return (1);
1510}
1511#endif /* COM_ESP */
1512
1513static int
1514sioattach(dev)
1515 device_t dev;
1516{
1517 struct com_s *com;
1518#ifdef COM_ESP
1519 Port_t *espp;
1520#endif
1521 Port_t iobase;
1522 int unit;
1523 void *ih;
1524 u_int flags = device_get_flags(dev);
1525 int rid;
1526 struct resource *port;
1527#ifdef PC98
1528 int port_shift = 0;
1529 u_char *obuf;
1530 u_long obufsize;
1531#endif
1532
1533 rid = 0;
1534#ifdef PC98
1535 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1536 0, ~0, 1, RF_ACTIVE); /* XXX */
1537#else
1538 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1539 0, ~0, IO_COMSIZE, RF_ACTIVE);
1540#endif
1541 if (!port)
1542 return ENXIO;
1543
1544 iobase = rman_get_start(port);
1545#ifdef PC98
1546 if (((flags >> 24) & 0xff) == COM_IF_RSA98III)
1547 iobase += 8;
1548#endif
1549 unit = device_get_unit(dev);
1550 com = device_get_softc(dev);
1551#ifdef PC98
1552 obufsize = 256;
1553 if (((flags >> 24) & 0xff) == COM_IF_RSA98III)
1554 obufsize = 2048;
1555 if ((obuf = malloc(obufsize * 2, M_DEVBUF, M_NOWAIT)) == NULL)
1556 return (0);
1557 bzero(obuf, obufsize * 2);
1558#endif
1559
1560 /*
1561 * sioprobe() has initialized the device registers as follows:
1562 * o cfcr = CFCR_8BITS.
1563 * It is most important that CFCR_DLAB is off, so that the
1564 * data port is not hidden when we enable interrupts.
1565 * o ier = 0.
1566 * Interrupts are only enabled when the line is open.
1567 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1568 * interrupt control register or the config specifies no irq.
1569 * Keeping MCR_DTR and MCR_RTS off might stop the external
1570 * device from sending before we are ready.
1571 */
1572 bzero(com, sizeof *com);
1573#ifdef PC98
1574 com->obufsize = obufsize;
1575 com->obuf1 = obuf;
1576 com->obuf2 = obuf + obufsize;
1577#endif
1578 com->unit = unit;
1579 com->ioportres = port;
1580 com->cfcr_image = CFCR_8BITS;
1581 com->dtr_wait = 3 * hz;
1582 com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1583 com->no_irq = isa_get_irq(dev) < 0;
1584 com->tx_fifo_size = 1;
1585 com->obufs[0].l_head = com->obuf1;
1586 com->obufs[1].l_head = com->obuf2;
1587
1588 com->iobase = iobase;
1589#ifdef PC98
1590 if (pc98_set_ioport(com, device_get_flags(dev)) == -1) {
1591 com->pc98_if_type = (device_get_flags(dev) >> 24) & 0xff;
1592 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
1593 com->data_port = iobase + (com_data << port_shift);
1594 com->int_id_port = iobase + (com_iir << port_shift);
1595 com->modem_ctl_port = iobase + (com_mcr << port_shift);
1596 com->mcr_image = inb(com->modem_ctl_port);
1597 com->line_status_port = iobase + (com_lsr << port_shift);
1598 com->modem_status_port = iobase + (com_msr << port_shift);
1599 com->intr_ctl_port = iobase + (com_ier << port_shift);
1600 }
1601#else /* not PC98 */
1602 com->data_port = iobase + com_data;
1603 com->int_id_port = iobase + com_iir;
1604 com->modem_ctl_port = iobase + com_mcr;
1605 com->mcr_image = inb(com->modem_ctl_port);
1606 com->line_status_port = iobase + com_lsr;
1607 com->modem_status_port = iobase + com_msr;
1608 com->intr_ctl_port = iobase + com_ier;
1609#endif
1610
1611 /*
1612 * We don't use all the flags from <sys/ttydefaults.h> since they
1613 * are only relevant for logins. It's important to have echo off
1614 * initially so that the line doesn't start blathering before the
1615 * echo flag can be turned off.
1616 */
1617 com->it_in.c_iflag = 0;
1618 com->it_in.c_oflag = 0;
1619 com->it_in.c_cflag = TTYDEF_CFLAG;
1620 com->it_in.c_lflag = 0;
1621 if (unit == comconsole) {
1622#ifdef PC98
1623 if (IS_8251(com->pc98_if_type))
1624 DELAY(100000);
1625#endif
1626 com->it_in.c_iflag = TTYDEF_IFLAG;
1627 com->it_in.c_oflag = TTYDEF_OFLAG;
1628 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1629 com->it_in.c_lflag = TTYDEF_LFLAG;
1630 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1631 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1632 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1633 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1634 } else
1635 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1636 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1637 enable_intr();
1638 free(com, M_DEVBUF);
1639 return (0);
1640 }
1641 enable_intr();
1642 termioschars(&com->it_in);
1643 com->it_out = com->it_in;
1644
1645 /* attempt to determine UART type */
1646 printf("sio%d: type", unit);
1647
1648
1649#ifndef PC98
1650#ifdef COM_MULTIPORT
1651 if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
1652#else
1653 if (!COM_IIR_TXRDYBUG(flags))
1654#endif
1655 {
1656 u_char scr;
1657 u_char scr1;
1658 u_char scr2;
1659
1660 scr = inb(iobase + com_scr);
1661 outb(iobase + com_scr, 0xa5);
1662 scr1 = inb(iobase + com_scr);
1663 outb(iobase + com_scr, 0x5a);
1664 scr2 = inb(iobase + com_scr);
1665 outb(iobase + com_scr, scr);
1666 if (scr1 != 0xa5 || scr2 != 0x5a) {
1667 printf(" 8250");
1668 goto determined_type;
1669 }
1670 }
1671#endif /* !PC98 */
1672#ifdef PC98
1673 if (IS_8251(com->pc98_if_type)) {
1674 com_int_TxRx_disable( com );
1675 com_cflag_and_speed_set( com, com->it_in.c_cflag, comdefaultrate );
1676 com_tiocm_bic( com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE );
1677 com_send_break_off( com );
1678 printf(" 8251%s", if_8251_type[com->pc98_if_type & 0x0f].name);
1679 } else {
1680 outb(iobase + (com_fifo << port_shift), FIFO_ENABLE | FIFO_RX_HIGH);
1681#else
1682 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1683#endif /* PC98 */
1684 DELAY(100);
1685 com->st16650a = 0;
1686 switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1687 case FIFO_RX_LOW:
1688 printf(" 16450");
1689 break;
1690 case FIFO_RX_MEDL:
1691 printf(" 16450?");
1692 break;
1693 case FIFO_RX_MEDH:
1694 printf(" 16550?");
1695 break;
1696 case FIFO_RX_HIGH:
1697 if (COM_NOFIFO(flags)) {
1698 printf(" 16550A fifo disabled");
1699 } else {
1700 com->hasfifo = TRUE;
1701#ifdef PC98
1702 com->tx_fifo_size = 0; /* XXX flag conflicts. */
1703 printf(" 16550A");
1704#else
1705 if (COM_ST16650A(flags)) {
1706 com->st16650a = 1;
1707 com->tx_fifo_size = 32;
1708 printf(" ST16650A");
1709 } else {
1710 com->tx_fifo_size = COM_FIFOSIZE(flags);
1711 printf(" 16550A");
1712 }
1713#endif
1714 }
1715#ifdef PC98
1716 if (com->pc98_if_type == COM_IF_RSA98III) {
1717 com->tx_fifo_size = 2048;
1718 com->rsabase = isa_get_port(dev);
1719 outb(com->rsabase + rsa_ier, 0x00);
1720 outb(com->rsabase + rsa_frr, 0x00);
1721 }
1722#endif
1723
1724#ifdef COM_ESP
1725#ifdef PC98
1726 if (com->pc98_if_type == COM_IF_ESP98)
1727#endif
1728 for (espp = likely_esp_ports; *espp != 0; espp++)
1729 if (espattach(com, *espp)) {
1730 com->tx_fifo_size = 1024;
1731 break;
1732 }
1733#endif
1734 if (!com->st16650a) {
1735 if (!com->tx_fifo_size)
1736 com->tx_fifo_size = 16;
1737 else
1738 printf(" lookalike with %d bytes FIFO",
1739 com->tx_fifo_size);
1740 }
1741
1742 break;
1743 }
1744
1745#ifdef PC98
1746 if (com->pc98_if_type == COM_IF_RSB3000) {
1747 /* Set RSB-2000/3000 Extended Buffer mode. */
1748 u_char lcr;
1749 lcr = inb(iobase + (com_cfcr << port_shift));
1750 outb(iobase + (com_cfcr << port_shift), lcr | CFCR_DLAB);
1751 outb(iobase + (com_emr << port_shift), EMR_EXBUFF | EMR_EFMODE);
1752 outb(iobase + (com_cfcr << port_shift), lcr);
1753 }
1754#endif
1755
1756#ifdef COM_ESP
1757 if (com->esp) {
1758 /*
1759 * Set 16550 compatibility mode.
1760 * We don't use the ESP_MODE_SCALE bit to increase the
1761 * fifo trigger levels because we can't handle large
1762 * bursts of input.
1763 * XXX flow control should be set in comparam(), not here.
1764 */
1765#ifdef PC98
1766 outb(com->esp_port + ESP98_CMD1, ESP_SETMODE);
1767 outb(com->esp_port + ESP98_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1768#else
1769 outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1770 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1771#endif
1772
1773 /* Set RTS/CTS flow control. */
1774#ifdef PC98
1775 outb(com->esp_port + ESP98_CMD1, ESP_SETFLOWTYPE);
1776 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_RTS);
1777 outb(com->esp_port + ESP98_CMD2, ESP_FLOW_CTS);
1778#else
1779 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1780 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1781 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1782#endif
1783
1784 /* Set flow-control levels. */
1785#ifdef PC98
1786 outb(com->esp_port + ESP98_CMD1, ESP_SETRXFLOW);
1787 outb(com->esp_port + ESP98_CMD2, HIBYTE(768));
1788 outb(com->esp_port + ESP98_CMD2, LOBYTE(768));
1789 outb(com->esp_port + ESP98_CMD2, HIBYTE(512));
1790 outb(com->esp_port + ESP98_CMD2, LOBYTE(512));
1791#else
1792 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1793 outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1794 outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1795 outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1796 outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1797#endif
1798
1799#ifdef PC98
1800 /* Set UART clock prescaler. */
1801 outb(com->esp_port + ESP98_CMD1, ESP_SETCLOCK);
1802 outb(com->esp_port + ESP98_CMD2, 2); /* 4 times */
1803#endif
1804 }
1805#endif /* COM_ESP */
1806#ifdef PC98
1807 printf("%s", if_16550a_type[com->pc98_if_type & 0x0f].name);
1808 outb(iobase + (com_fifo << port_shift), 0);
1809#else
1810 outb(iobase + com_fifo, 0);
1811determined_type: ;
1812#endif
1813
1814#ifdef COM_MULTIPORT
1815 if (COM_ISMULTIPORT(flags)) {
1816 com->multiport = TRUE;
1817 printf(" (multiport");
1818 if (unit == COM_MPMASTER(flags))
1819 printf(" master");
1820 printf(")");
1821 com->no_irq =
1822 isa_get_irq(devclass_get_device
1823 (sio_devclass, COM_MPMASTER(flags))) < 0;
1824 }
1825#endif /* COM_MULTIPORT */
1826#ifdef PC98
1827 }
1828#endif
1829 if (unit == comconsole)
1830 printf(", console");
1831 if ( COM_IIR_TXRDYBUG(flags) )
1832 printf(" with a bogus IIR_TXRDY register");
1833 printf("\n");
1834
1835 if (!sio_registered) {
1836 register_swi(SWI_TTY, siopoll);
1837 sio_registered = TRUE;
1838 }
1839 make_dev(&sio_cdevsw, unit,
1840 UID_ROOT, GID_WHEEL, 0600, "ttyd%r", unit);
1841 make_dev(&sio_cdevsw, unit | CONTROL_INIT_STATE,
1842 UID_ROOT, GID_WHEEL, 0600, "ttyid%r", unit);
1843 make_dev(&sio_cdevsw, unit | CONTROL_LOCK_STATE,
1844 UID_ROOT, GID_WHEEL, 0600, "ttyld%r", unit);
1845 make_dev(&sio_cdevsw, unit | CALLOUT_MASK,
1846 UID_UUCP, GID_DIALER, 0660, "cuaa%r", unit);
1847 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_INIT_STATE,
1848 UID_UUCP, GID_DIALER, 0660, "cuaia%r", unit);
1849 make_dev(&sio_cdevsw, unit | CALLOUT_MASK | CONTROL_LOCK_STATE,
1850 UID_UUCP, GID_DIALER, 0660, "cuala%r", unit);
1851 com->flags = flags;
1852 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1853 pps_init(&com->pps);
1854
1855 rid = 0;
1856 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1857 RF_SHAREABLE | RF_ACTIVE);
1858 BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres,
1859 INTR_TYPE_TTY | INTR_TYPE_FAST,
1860 siointr, com, &ih);
1861
1862 return (0);
1863}
1864
1865static int
1866sioopen(dev, flag, mode, p)
1867 dev_t dev;
1868 int flag;
1869 int mode;
1870 struct proc *p;
1871{
1872 struct com_s *com;
1873 int error;
1874 Port_t iobase;
1875 int mynor;
1876 int s;
1877 struct tty *tp;
1878 int unit;
1879#ifdef PC98
1880 int port_shift = 0;
1881#endif
1882
1883 mynor = minor(dev);
1884 unit = MINOR_TO_UNIT(mynor);
1885 if ((u_int) unit >= NSIOTOT || (com = com_addr(unit)) == NULL)
1886 return (ENXIO);
1887 if (com->gone)
1888 return (ENXIO);
1889 if (mynor & CONTROL_MASK)
1890 return (0);
1891 tp = dev->si_tty = com->tp = ttymalloc(com->tp);
1892 s = spltty();
1893
1894#ifdef PC98
1895 if (!IS_8251(com->pc98_if_type))
1896 port_shift = if_16550a_type[com->pc98_if_type & 0x0f].port_shift;
1897#endif
1898 /*
1899 * We jump to this label after all non-interrupted sleeps to pick
1900 * up any changes of the device state.
1901 */
1902open_top:
1903 while (com->state & CS_DTR_OFF) {
1904 error = tsleep(&com->dtr_wait, TTIPRI | PCATCH, "siodtr", 0);
1905 if (com_addr(unit) == NULL)
1906 return (ENXIO);
1907 if (error != 0 || com->gone)
1908 goto out;
1909 }
1910 if (tp->t_state & TS_ISOPEN) {
1911 /*
1912 * The device is open, so everything has been initialized.
1913 * Handle conflicts.
1914 */
1915 if (mynor & CALLOUT_MASK) {
1916 if (!com->active_out) {
1917 error = EBUSY;
1918 goto out;
1919 }
1920 } else {
1921 if (com->active_out) {
1922 if (flag & O_NONBLOCK) {
1923 error = EBUSY;
1924 goto out;
1925 }
1926 error = tsleep(&com->active_out,
1927 TTIPRI | PCATCH, "siobi", 0);
1928 if (com_addr(unit) == NULL)
1929 return (ENXIO);
1930 if (error != 0 || com->gone)
1931 goto out;
1932 goto open_top;
1933 }
1934 }
1935 if (tp->t_state & TS_XCLUDE &&
1936 suser(p)) {
1937 error = EBUSY;
1938 goto out;
1939 }
1940 } else {
1941 /*
1942 * The device isn't open, so there are no conflicts.
1943 * Initialize it. Initialization is done twice in many
1944 * cases: to preempt sleeping callin opens if we are
1945 * callout, and to complete a callin open after DCD rises.
1946 */
1947 tp->t_oproc = comstart;
1948 tp->t_stop = comstop;
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();
2100out:
2101 splx(s);
2102 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
2103 comhardclose(com);
2104 return (error);
2105}
2106
2107static int
2108sioclose(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);
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();
2100out:
2101 splx(s);
2102 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
2103 comhardclose(com);
2104 return (error);
2105}
2106
2107static int
2108sioclose(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);
2130 comstop(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
2147static void
2148comhardclose(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
2250static int
2251sioread(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
2268static int
2269siowrite(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
2297static void
2298siobusycheck(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
2335static void
2336siodtrwakeup(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
2346static void
2347sioinput(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
2444void
2445siointr(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
2511static void
2512siointr1(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
2536status_read:;
2537 if (IS_8251(com->pc98_if_type)) {
2538 tmp = inb(com->sts_port);
2539more_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 */
2646if (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 }
2664cont:
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
2823static int
2824sioioctl(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
3054static void
3055siopoll()
3056{
3057 int unit;
3058
3059 if (com_events == 0)
3060 return;
3061repeat:
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
3131static int
3132comparam(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
3410static int
3411siosetwater(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
3484static void
3485comstart(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
3614static void
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
2147static void
2148comhardclose(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
2250static int
2251sioread(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
2268static int
2269siowrite(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
2297static void
2298siobusycheck(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
2335static void
2336siodtrwakeup(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
2346static void
2347sioinput(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
2444void
2445siointr(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
2511static void
2512siointr1(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
2536status_read:;
2537 if (IS_8251(com->pc98_if_type)) {
2538 tmp = inb(com->sts_port);
2539more_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 */
2646if (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 }
2664cont:
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
2823static int
2824sioioctl(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
3054static void
3055siopoll()
3056{
3057 int unit;
3058
3059 if (com_events == 0)
3060 return;
3061repeat:
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
3131static int
3132comparam(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
3410static int
3411siosetwater(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
3484static void
3485comstart(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
3614static void
3615siostop(tp, rw)
3615comstop(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
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
3681static struct tty *
3682siodevtotty(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
3697static int
3698commctl(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
3753static void
3754siosettimeout()
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
3791static void
3792comwakeup(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 */
3848static void
3849commint(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
3884static void
3885disc_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
3907struct siocnstate {
3908 u_char dlbl;
3909 u_char dlbh;
3910 u_char ier;
3911 u_char cfcr;
3912 u_char mcr;
3913};
3914
3915static speed_t siocngetspeed __P((Port_t, struct speedtab *));
3916static void siocnclose __P((struct siocnstate *sp, Port_t iobase));
3917static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed));
3918static void siocntxwait __P((Port_t iobase));
3919
3920static cn_probe_t siocnprobe;
3921static cn_init_t siocninit;
3922static cn_checkc_t siocncheckc;
3923static cn_getc_t siocngetc;
3924static cn_putc_t siocnputc;
3925
3926#ifdef __i386__
3927CONS_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
3936static void
3937siocntxwait(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
3962static speed_t
3963siocngetspeed(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
3989static void
3990siocnopen(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
4034static void
4035siocnclose(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
4056static void
4057siocnprobe(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
4168CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc);
4169
4170int
4171siocnattach(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
4210int
4211siogdbattach(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
4249static void
4250siocninit(cp)
4251 struct consdev *cp;
4252{
4253 comconsole = DEV_TO_UNIT(cp->cn_dev);
4254}
4255
4256static int
4257siocncheckc(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
4281int
4282siocngetc(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
4304void
4305siocnputc(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__
4326int
4327siogdbgetc()
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
4345void
4346siogdbputc(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
4361DEV_DRIVER_MODULE(sio, isa, sio_driver, sio_devclass, sio_cdevsw, 0, 0);
4362
4363#ifdef PC98
4364/*
4365 * pc98 local function
4366 */
4367
4368static void
4369com_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
4385static void
4386com_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
4401static void
4402com_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
4416static int
4417com_tiocm_get(struct com_s *com)
4418{
4419 return( com->pc98_prev_modem_status );
4420}
4421
4422static int
4423com_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 ) */
4433static int
4434pc98_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
4455static void
4456pc98_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
4503static void
4504pc98_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
4525static void
4526pc98_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
4538static void
4539pc98_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
4549static int
4550pc98_check_i8251_interrupt(struct com_s *com)
4551{
4552 return ( com->intr_enable & 0x07 );
4553}
4554
4555static void
4556pc98_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
4567static void
4568pc98_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
4579static void
4580pc98_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
4591static void
4592pc98_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
4603static int
4604pc98_i8251_get_cmd(struct com_s *com)
4605{
4606 return com->pc98_prev_siocmd;
4607}
4608
4609static int
4610pc98_i8251_get_mod(struct com_s *com)
4611{
4612 return com->pc98_prev_siomod;
4613}
4614
4615static void
4616pc98_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
4632static void
4633pc98_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
4645static void
4646com_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
4699static int
4700pc98_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
4760static void
4761pc98_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}
4822static int
4823pc98_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}
4892static int
4893pc98_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 */
3681static int
3682commctl(com, bits, how)
3683 struct com_s *com;
3684 int bits;
3685 int how;
3686{
3687 int mcr;
3688 int msr;
3689
3690 if (how == DMGET) {
3691 bits = TIOCM_LE; /* XXX - always enabled while open */
3692 mcr = com->mcr_image;
3693 if (mcr & MCR_DTR)
3694 bits |= TIOCM_DTR;
3695 if (mcr & MCR_RTS)
3696 bits |= TIOCM_RTS;
3697 msr = com->prev_modem_status;
3698 if (msr & MSR_CTS)
3699 bits |= TIOCM_CTS;
3700 if (msr & MSR_DCD)
3701 bits |= TIOCM_CD;
3702 if (msr & MSR_DSR)
3703 bits |= TIOCM_DSR;
3704 /*
3705 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
3706 * more volatile by reading the modem status a lot. Perhaps
3707 * we should latch both bits until the status is read here.
3708 */
3709 if (msr & (MSR_RI | MSR_TERI))
3710 bits |= TIOCM_RI;
3711 return (bits);
3712 }
3713 mcr = 0;
3714 if (bits & TIOCM_DTR)
3715 mcr |= MCR_DTR;
3716 if (bits & TIOCM_RTS)
3717 mcr |= MCR_RTS;
3718 if (com->gone)
3719 return(0);
3720 disable_intr();
3721 switch (how) {
3722 case DMSET:
3723 outb(com->modem_ctl_port,
3724 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
3725 break;
3726 case DMBIS:
3727 outb(com->modem_ctl_port, com->mcr_image |= mcr);
3728 break;
3729 case DMBIC:
3730 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
3731 break;
3732 }
3733 enable_intr();
3734 return (0);
3735}
3736
3737static void
3738siosettimeout()
3739{
3740 struct com_s *com;
3741 bool_t someopen;
3742 int unit;
3743
3744 /*
3745 * Set our timeout period to 1 second if no polled devices are open.
3746 * Otherwise set it to max(1/200, 1/hz).
3747 * Enable timeouts iff some device is open.
3748 */
3749 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3750 sio_timeout = hz;
3751 someopen = FALSE;
3752 for (unit = 0; unit < NSIOTOT; ++unit) {
3753 com = com_addr(unit);
3754 if (com != NULL && com->tp != NULL
3755 && com->tp->t_state & TS_ISOPEN && !com->gone) {
3756 someopen = TRUE;
3757 if (com->poll || com->poll_output) {
3758 sio_timeout = hz > 200 ? hz / 200 : 1;
3759 break;
3760 }
3761 }
3762 }
3763 if (someopen) {
3764 sio_timeouts_until_log = hz / sio_timeout;
3765 sio_timeout_handle = timeout(comwakeup, (void *)NULL,
3766 sio_timeout);
3767 } else {
3768 /* Flush error messages, if any. */
3769 sio_timeouts_until_log = 1;
3770 comwakeup((void *)NULL);
3771 untimeout(comwakeup, (void *)NULL, sio_timeout_handle);
3772 }
3773}
3774
3775static void
3776comwakeup(chan)
3777 void *chan;
3778{
3779 struct com_s *com;
3780 int unit;
3781
3782 sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
3783
3784 /*
3785 * Recover from lost output interrupts.
3786 * Poll any lines that don't use interrupts.
3787 */
3788 for (unit = 0; unit < NSIOTOT; ++unit) {
3789 com = com_addr(unit);
3790 if (com != NULL && !com->gone
3791 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
3792 disable_intr();
3793 siointr1(com);
3794 enable_intr();
3795 }
3796 }
3797
3798 /*
3799 * Check for and log errors, but not too often.
3800 */
3801 if (--sio_timeouts_until_log > 0)
3802 return;
3803 sio_timeouts_until_log = hz / sio_timeout;
3804 for (unit = 0; unit < NSIOTOT; ++unit) {
3805 int errnum;
3806
3807 com = com_addr(unit);
3808 if (com == NULL)
3809 continue;
3810 if (com->gone)
3811 continue;
3812 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
3813 u_int delta;
3814 u_long total;
3815
3816 disable_intr();
3817 delta = com->delta_error_counts[errnum];
3818 com->delta_error_counts[errnum] = 0;
3819 enable_intr();
3820 if (delta == 0)
3821 continue;
3822 total = com->error_counts[errnum] += delta;
3823 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
3824 unit, delta, error_desc[errnum],
3825 delta == 1 ? "" : "s", total);
3826 }
3827 }
3828}
3829
3830#ifdef PC98
3831/* commint is called when modem control line changes */
3832static void
3833commint(dev_t dev)
3834{
3835 register struct tty *tp;
3836 int stat,delta;
3837 struct com_s *com;
3838 int mynor,unit;
3839
3840 mynor = minor(dev);
3841 unit = MINOR_TO_UNIT(mynor);
3842 com = com_addr(unit);
3843 tp = com->tp;
3844
3845 stat = com_tiocm_get(com);
3846 delta = com_tiocm_get_delta(com);
3847
3848 if (com->state & CS_CTS_OFLOW) {
3849 if (stat & TIOCM_CTS)
3850 com->state |= CS_ODEVREADY;
3851 else
3852 com->state &= ~CS_ODEVREADY;
3853 }
3854 if ((delta & TIOCM_CAR) && (mynor & CALLOUT_MASK) == 0) {
3855 if (stat & TIOCM_CAR )
3856 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
3857 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
3858 /* negate DTR, RTS */
3859 com_tiocm_bic(com, (tp->t_cflag & HUPCL) ?
3860 TIOCM_DTR|TIOCM_RTS|TIOCM_LE : TIOCM_LE );
3861 /* disable IENABLE */
3862 com_int_TxRx_disable( com );
3863 }
3864 }
3865}
3866#endif
3867
3868static void
3869disc_optim(tp, t, com)
3870 struct tty *tp;
3871 struct termios *t;
3872 struct com_s *com;
3873{
3874 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
3875 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
3876 && (!(t->c_iflag & PARMRK)
3877 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
3878 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
3879 && linesw[tp->t_line].l_rint == ttyinput)
3880 tp->t_state |= TS_CAN_BYPASS_L_RINT;
3881 else
3882 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
3883 com->hotchar = linesw[tp->t_line].l_hotchar;
3884}
3885
3886/*
3887 * Following are all routines needed for SIO to act as console
3888 */
3889#include <sys/cons.h>
3890
3891struct siocnstate {
3892 u_char dlbl;
3893 u_char dlbh;
3894 u_char ier;
3895 u_char cfcr;
3896 u_char mcr;
3897};
3898
3899static speed_t siocngetspeed __P((Port_t, struct speedtab *));
3900static void siocnclose __P((struct siocnstate *sp, Port_t iobase));
3901static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed));
3902static void siocntxwait __P((Port_t iobase));
3903
3904static cn_probe_t siocnprobe;
3905static cn_init_t siocninit;
3906static cn_checkc_t siocncheckc;
3907static cn_getc_t siocngetc;
3908static cn_putc_t siocnputc;
3909
3910#ifdef __i386__
3911CONS_DRIVER(sio, siocnprobe, siocninit, NULL, siocngetc, siocncheckc, siocnputc);
3912
3913#endif
3914
3915/* To get the GDB related variables */
3916#if DDB > 0
3917#include <ddb/ddb.h>
3918#endif
3919
3920static void
3921siocntxwait(iobase)
3922 Port_t iobase;
3923{
3924 int timo;
3925
3926 /*
3927 * Wait for any pending transmission to finish. Required to avoid
3928 * the UART lockup bug when the speed is changed, and for normal
3929 * transmits.
3930 */
3931 timo = 100000;
3932 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
3933 != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
3934 ;
3935}
3936
3937/*
3938 * Read the serial port specified and try to figure out what speed
3939 * it's currently running at. We're assuming the serial port has
3940 * been initialized and is basicly idle. This routine is only intended
3941 * to be run at system startup.
3942 *
3943 * If the value read from the serial port doesn't make sense, return 0.
3944 */
3945
3946static speed_t
3947siocngetspeed(iobase, table)
3948 Port_t iobase;
3949 struct speedtab *table;
3950{
3951 int code;
3952 u_char dlbh;
3953 u_char dlbl;
3954 u_char cfcr;
3955
3956 cfcr = inb(iobase + com_cfcr);
3957 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3958
3959 dlbl = inb(iobase + com_dlbl);
3960 dlbh = inb(iobase + com_dlbh);
3961
3962 outb(iobase + com_cfcr, cfcr);
3963
3964 code = dlbh << 8 | dlbl;
3965
3966 for ( ; table->sp_speed != -1; table++)
3967 if (table->sp_code == code)
3968 return (table->sp_speed);
3969
3970 return 0; /* didn't match anything sane */
3971}
3972
3973static void
3974siocnopen(sp, iobase, speed)
3975 struct siocnstate *sp;
3976 Port_t iobase;
3977 int speed;
3978{
3979 int divisor;
3980 u_char dlbh;
3981 u_char dlbl;
3982
3983 /*
3984 * Save all the device control registers except the fifo register
3985 * and set our default ones (cs8 -parenb speed=comdefaultrate).
3986 * We can't save the fifo register since it is read-only.
3987 */
3988 sp->ier = inb(iobase + com_ier);
3989 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */
3990 siocntxwait(iobase);
3991 sp->cfcr = inb(iobase + com_cfcr);
3992 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
3993 sp->dlbl = inb(iobase + com_dlbl);
3994 sp->dlbh = inb(iobase + com_dlbh);
3995 /*
3996 * Only set the divisor registers if they would change, since on
3997 * some 16550 incompatibles (Startech), setting them clears the
3998 * data input register. This also reduces the effects of the
3999 * UMC8669F bug.
4000 */
4001 divisor = ttspeedtab(speed, comspeedtab);
4002 dlbl = divisor & 0xFF;
4003 if (sp->dlbl != dlbl)
4004 outb(iobase + com_dlbl, dlbl);
4005 dlbh = (u_int) divisor >> 8;
4006 if (sp->dlbh != dlbh)
4007 outb(iobase + com_dlbh, dlbh);
4008 outb(iobase + com_cfcr, CFCR_8BITS);
4009 sp->mcr = inb(iobase + com_mcr);
4010 /*
4011 * We don't want interrupts, but must be careful not to "disable"
4012 * them by clearing the MCR_IENABLE bit, since that might cause
4013 * an interrupt by floating the IRQ line.
4014 */
4015 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
4016}
4017
4018static void
4019siocnclose(sp, iobase)
4020 struct siocnstate *sp;
4021 Port_t iobase;
4022{
4023 /*
4024 * Restore the device control registers.
4025 */
4026 siocntxwait(iobase);
4027 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
4028 if (sp->dlbl != inb(iobase + com_dlbl))
4029 outb(iobase + com_dlbl, sp->dlbl);
4030 if (sp->dlbh != inb(iobase + com_dlbh))
4031 outb(iobase + com_dlbh, sp->dlbh);
4032 outb(iobase + com_cfcr, sp->cfcr);
4033 /*
4034 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
4035 */
4036 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
4037 outb(iobase + com_ier, sp->ier);
4038}
4039
4040static void
4041siocnprobe(cp)
4042 struct consdev *cp;
4043{
4044 speed_t boot_speed;
4045 u_char cfcr;
4046 int s, unit;
4047 struct siocnstate sp;
4048
4049 /*
4050 * Find our first enabled console, if any. If it is a high-level
4051 * console device, then initialize it and return successfully.
4052 * If it is a low-level console device, then initialize it and
4053 * return unsuccessfully. It must be initialized in both cases
4054 * for early use by console drivers and debuggers. Initializing
4055 * the hardware is not necessary in all cases, since the i/o
4056 * routines initialize it on the fly, but it is necessary if
4057 * input might arrive while the hardware is switched back to an
4058 * uninitialized state. We can't handle multiple console devices
4059 * yet because our low-level routines don't take a device arg.
4060 * We trust the user to set the console flags properly so that we
4061 * don't need to probe.
4062 */
4063 cp->cn_pri = CN_DEAD;
4064
4065 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
4066 int flags;
4067 int disabled;
4068 if (resource_int_value("sio", unit, "disabled", &disabled) == 0) {
4069 if (disabled)
4070 continue;
4071 }
4072 if (resource_int_value("sio", unit, "flags", &flags))
4073 continue;
4074 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
4075 int port;
4076 Port_t iobase;
4077
4078 if (resource_int_value("sio", unit, "port", &port))
4079 continue;
4080 iobase = port;
4081 s = spltty();
4082 if (boothowto & RB_SERIAL) {
4083 boot_speed = siocngetspeed(iobase, comspeedtab);
4084 if (boot_speed)
4085 comdefaultrate = boot_speed;
4086 }
4087
4088 /*
4089 * Initialize the divisor latch. We can't rely on
4090 * siocnopen() to do this the first time, since it
4091 * avoids writing to the latch if the latch appears
4092 * to have the correct value. Also, if we didn't
4093 * just read the speed from the hardware, then we
4094 * need to set the speed in hardware so that
4095 * switching it later is null.
4096 */
4097 cfcr = inb(iobase + com_cfcr);
4098 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
4099 outb(iobase + com_dlbl,
4100 COMBRD(comdefaultrate) & 0xff);
4101 outb(iobase + com_dlbh,
4102 (u_int) COMBRD(comdefaultrate) >> 8);
4103 outb(iobase + com_cfcr, cfcr);
4104
4105 siocnopen(&sp, iobase, comdefaultrate);
4106
4107 splx(s);
4108 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
4109 cp->cn_dev = makedev(CDEV_MAJOR, unit);
4110 cp->cn_pri = COM_FORCECONSOLE(flags)
4111 || boothowto & RB_SERIAL
4112 ? CN_REMOTE : CN_NORMAL;
4113 siocniobase = iobase;
4114 siocnunit = unit;
4115 }
4116 if (COM_DEBUGGER(flags)) {
4117 printf("sio%d: gdb debugging port\n", unit);
4118 siogdbiobase = iobase;
4119 siogdbunit = unit;
4120#if DDB > 0
4121 gdbdev = makedev(CDEV_MAJOR, unit);
4122 gdb_getc = siocngetc;
4123 gdb_putc = siocnputc;
4124#endif
4125 }
4126 }
4127 }
4128#ifdef __i386__
4129#if DDB > 0
4130 /*
4131 * XXX Ugly Compatability.
4132 * If no gdb port has been specified, set it to be the console
4133 * as some configuration files don't specify the gdb port.
4134 */
4135 if (gdbdev == NODEV && (boothowto & RB_GDB)) {
4136 printf("Warning: no GDB port specified. Defaulting to sio%d.\n",
4137 siocnunit);
4138 printf("Set flag 0x80 on desired GDB port in your\n");
4139 printf("configuration file (currently sio only).\n");
4140 siogdbiobase = siocniobase;
4141 siogdbunit = siocnunit;
4142 gdbdev = makedev(CDEV_MAJOR, siocnunit);
4143 gdb_getc = siocngetc;
4144 gdb_putc = siocnputc;
4145 }
4146#endif
4147#endif
4148}
4149
4150#ifdef __alpha__
4151
4152CONS_DRIVER(sio, NULL, NULL, NULL, siocngetc, siocncheckc, siocnputc);
4153
4154int
4155siocnattach(port, speed)
4156 int port;
4157 int speed;
4158{
4159 int s;
4160 u_char cfcr;
4161 struct siocnstate sp;
4162
4163 siocniobase = port;
4164 comdefaultrate = speed;
4165 sio_consdev.cn_pri = CN_NORMAL;
4166 sio_consdev.cn_dev = makedev(CDEV_MAJOR, 0);
4167
4168 s = spltty();
4169
4170 /*
4171 * Initialize the divisor latch. We can't rely on
4172 * siocnopen() to do this the first time, since it
4173 * avoids writing to the latch if the latch appears
4174 * to have the correct value. Also, if we didn't
4175 * just read the speed from the hardware, then we
4176 * need to set the speed in hardware so that
4177 * switching it later is null.
4178 */
4179 cfcr = inb(siocniobase + com_cfcr);
4180 outb(siocniobase + com_cfcr, CFCR_DLAB | cfcr);
4181 outb(siocniobase + com_dlbl,
4182 COMBRD(comdefaultrate) & 0xff);
4183 outb(siocniobase + com_dlbh,
4184 (u_int) COMBRD(comdefaultrate) >> 8);
4185 outb(siocniobase + com_cfcr, cfcr);
4186
4187 siocnopen(&sp, siocniobase, comdefaultrate);
4188 splx(s);
4189
4190 cn_tab = &sio_consdev;
4191 return 0;
4192}
4193
4194int
4195siogdbattach(port, speed)
4196 int port;
4197 int speed;
4198{
4199 int s;
4200 u_char cfcr;
4201 struct siocnstate sp;
4202
4203 siogdbiobase = port;
4204 gdbdefaultrate = speed;
4205
4206 s = spltty();
4207
4208 /*
4209 * Initialize the divisor latch. We can't rely on
4210 * siocnopen() to do this the first time, since it
4211 * avoids writing to the latch if the latch appears
4212 * to have the correct value. Also, if we didn't
4213 * just read the speed from the hardware, then we
4214 * need to set the speed in hardware so that
4215 * switching it later is null.
4216 */
4217 cfcr = inb(siogdbiobase + com_cfcr);
4218 outb(siogdbiobase + com_cfcr, CFCR_DLAB | cfcr);
4219 outb(siogdbiobase + com_dlbl,
4220 COMBRD(gdbdefaultrate) & 0xff);
4221 outb(siogdbiobase + com_dlbh,
4222 (u_int) COMBRD(gdbdefaultrate) >> 8);
4223 outb(siogdbiobase + com_cfcr, cfcr);
4224
4225 siocnopen(&sp, siogdbiobase, gdbdefaultrate);
4226 splx(s);
4227
4228 return 0;
4229}
4230
4231#endif
4232
4233static void
4234siocninit(cp)
4235 struct consdev *cp;
4236{
4237 comconsole = DEV_TO_UNIT(cp->cn_dev);
4238}
4239
4240static int
4241siocncheckc(dev)
4242 dev_t dev;
4243{
4244 int c;
4245 Port_t iobase;
4246 int s;
4247 struct siocnstate sp;
4248
4249 if (minor(dev) == siogdbunit)
4250 iobase = siogdbiobase;
4251 else
4252 iobase = siocniobase;
4253 s = spltty();
4254 siocnopen(&sp, iobase, comdefaultrate);
4255 if (inb(iobase + com_lsr) & LSR_RXRDY)
4256 c = inb(iobase + com_data);
4257 else
4258 c = -1;
4259 siocnclose(&sp, iobase);
4260 splx(s);
4261 return (c);
4262}
4263
4264
4265int
4266siocngetc(dev)
4267 dev_t dev;
4268{
4269 int c;
4270 Port_t iobase;
4271 int s;
4272 struct siocnstate sp;
4273
4274 if (minor(dev) == siogdbunit)
4275 iobase = siogdbiobase;
4276 else
4277 iobase = siocniobase;
4278 s = spltty();
4279 siocnopen(&sp, iobase, comdefaultrate);
4280 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4281 ;
4282 c = inb(iobase + com_data);
4283 siocnclose(&sp, iobase);
4284 splx(s);
4285 return (c);
4286}
4287
4288void
4289siocnputc(dev, c)
4290 dev_t dev;
4291 int c;
4292{
4293 int s;
4294 struct siocnstate sp;
4295 Port_t iobase;
4296
4297 if (minor(dev) == siogdbunit)
4298 iobase = siogdbiobase;
4299 else
4300 iobase = siocniobase;
4301 s = spltty();
4302 siocnopen(&sp, iobase, comdefaultrate);
4303 siocntxwait(iobase);
4304 outb(iobase + com_data, c);
4305 siocnclose(&sp, iobase);
4306 splx(s);
4307}
4308
4309#ifdef __alpha__
4310int
4311siogdbgetc()
4312{
4313 int c;
4314 Port_t iobase;
4315 int s;
4316 struct siocnstate sp;
4317
4318 iobase = siogdbiobase;
4319 s = spltty();
4320 siocnopen(&sp, iobase, gdbdefaultrate);
4321 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
4322 ;
4323 c = inb(iobase + com_data);
4324 siocnclose(&sp, iobase);
4325 splx(s);
4326 return (c);
4327}
4328
4329void
4330siogdbputc(c)
4331 int c;
4332{
4333 int s;
4334 struct siocnstate sp;
4335
4336 s = spltty();
4337 siocnopen(&sp, siogdbiobase, gdbdefaultrate);
4338 siocntxwait(siogdbiobase);
4339 outb(siogdbiobase + com_data, c);
4340 siocnclose(&sp, siogdbiobase);
4341 splx(s);
4342}
4343#endif
4344
4345DEV_DRIVER_MODULE(sio, isa, sio_driver, sio_devclass, sio_cdevsw, 0, 0);
4346
4347#ifdef PC98
4348/*
4349 * pc98 local function
4350 */
4351
4352static void
4353com_tiocm_set(struct com_s *com, int msr)
4354{
4355 int s;
4356 int tmp = 0;
4357 int mask = CMD8251_TxEN|CMD8251_RxEN|CMD8251_DTR|CMD8251_RTS;
4358
4359 s=spltty();
4360 com->pc98_prev_modem_status = ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) )
4361 | ( com->pc98_prev_modem_status & ~(TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4362 tmp |= (CMD8251_TxEN|CMD8251_RxEN);
4363 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4364 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4365 pc98_i8251_clear_or_cmd( com, mask, tmp );
4366 splx(s);
4367}
4368
4369static void
4370com_tiocm_bis(struct com_s *com, int msr)
4371{
4372 int s;
4373 int tmp = 0;
4374
4375 s=spltty();
4376 com->pc98_prev_modem_status |= ( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4377 tmp |= CMD8251_TxEN|CMD8251_RxEN;
4378 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4379 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4380
4381 pc98_i8251_or_cmd( com, tmp );
4382 splx(s);
4383}
4384
4385static void
4386com_tiocm_bic(struct com_s *com, int msr)
4387{
4388 int s;
4389 int tmp = msr;
4390
4391 s=spltty();
4392 com->pc98_prev_modem_status &= ~( msr & (TIOCM_LE|TIOCM_DTR|TIOCM_RTS) );
4393 if ( msr & TIOCM_DTR ) tmp |= CMD8251_DTR;
4394 if ( msr & TIOCM_RTS ) tmp |= CMD8251_RTS;
4395
4396 pc98_i8251_clear_cmd( com, tmp );
4397 splx(s);
4398}
4399
4400static int
4401com_tiocm_get(struct com_s *com)
4402{
4403 return( com->pc98_prev_modem_status );
4404}
4405
4406static int
4407com_tiocm_get_delta(struct com_s *com)
4408{
4409 int tmp;
4410
4411 tmp = com->pc98_modem_delta;
4412 com->pc98_modem_delta = 0;
4413 return( tmp );
4414}
4415
4416/* convert to TIOCM_?? ( ioctl.h ) */
4417static int
4418pc98_get_modem_status(struct com_s *com)
4419{
4420 int stat, stat2;
4421 register int msr;
4422
4423 stat = inb(com->sts_port);
4424 stat2 = inb(com->in_modem_port);
4425 msr = com->pc98_prev_modem_status
4426 & ~(TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4427 if ( !(stat2 & CICSCD_CD) ) msr |= TIOCM_CAR;
4428 if ( !(stat2 & CICSCD_CI) ) msr |= TIOCM_RI;
4429 if ( stat & STS8251_DSR ) msr |= TIOCM_DSR;
4430 if ( !(stat2 & CICSCD_CS) ) msr |= TIOCM_CTS;
4431#if COM_CARRIER_DETECT_EMULATE
4432 if ( msr & (TIOCM_DSR|TIOCM_CTS) ) {
4433 msr |= TIOCM_CAR;
4434 }
4435#endif
4436 return(msr);
4437}
4438
4439static void
4440pc98_check_msr(void* chan)
4441{
4442 int msr, delta;
4443 int s;
4444 register struct tty *tp;
4445 struct com_s *com;
4446 int mynor;
4447 int unit;
4448 dev_t dev;
4449
4450 dev=(dev_t)chan;
4451 mynor = minor(dev);
4452 unit = MINOR_TO_UNIT(mynor);
4453 com = com_addr(unit);
4454 tp = com->tp;
4455
4456 s = spltty();
4457 msr = pc98_get_modem_status(com);
4458 /* make change flag */
4459 delta = msr ^ com->pc98_prev_modem_status;
4460 if ( delta & TIOCM_CAR ) {
4461 if ( com->modem_car_chg_timer ) {
4462 if ( -- com->modem_car_chg_timer )
4463 msr ^= TIOCM_CAR;
4464 } else {
4465 if ((com->modem_car_chg_timer = (msr & TIOCM_CAR) ?
4466 DCD_ON_RECOGNITION : DCD_OFF_TOLERANCE) != 0)
4467 msr ^= TIOCM_CAR;
4468 }
4469 } else
4470 com->modem_car_chg_timer = 0;
4471 delta = ( msr ^ com->pc98_prev_modem_status ) &
4472 (TIOCM_CAR|TIOCM_RI|TIOCM_DSR|TIOCM_CTS);
4473 com->pc98_prev_modem_status = msr;
4474 delta = ( com->pc98_modem_delta |= delta );
4475 splx(s);
4476 if ( com->modem_checking || (tp->t_state & (TS_ISOPEN)) ) {
4477 if ( delta ) {
4478 commint(dev);
4479 }
4480 timeout(pc98_check_msr, (caddr_t)dev,
4481 PC98_CHECK_MODEM_INTERVAL);
4482 } else {
4483 com->modem_checking = 0;
4484 }
4485}
4486
4487static void
4488pc98_msrint_start(dev_t dev)
4489{
4490 struct com_s *com;
4491 int mynor;
4492 int unit;
4493 int s = spltty();
4494
4495 mynor = minor(dev);
4496 unit = MINOR_TO_UNIT(mynor);
4497 com = com_addr(unit);
4498 /* modem control line check routine envoke interval is 1/10 sec */
4499 if ( com->modem_checking == 0 ) {
4500 com->pc98_prev_modem_status = pc98_get_modem_status(com);
4501 com->pc98_modem_delta = 0;
4502 timeout(pc98_check_msr, (caddr_t)dev,
4503 PC98_CHECK_MODEM_INTERVAL);
4504 com->modem_checking = 1;
4505 }
4506 splx(s);
4507}
4508
4509static void
4510pc98_disable_i8251_interrupt(struct com_s *com, int mod)
4511{
4512 /* disable interrupt */
4513 register int tmp;
4514
4515 mod |= ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4516 COM_INT_DISABLE
4517 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4518 outb( com->intr_ctrl_port, (com->intr_enable&=~mod) | tmp );
4519 COM_INT_ENABLE
4520}
4521
4522static void
4523pc98_enable_i8251_interrupt(struct com_s *com, int mod)
4524{
4525 register int tmp;
4526
4527 COM_INT_DISABLE
4528 tmp = inb( com->intr_ctrl_port ) & ~(IEN_Tx|IEN_TxEMP|IEN_Rx);
4529 outb( com->intr_ctrl_port, (com->intr_enable|=mod) | tmp );
4530 COM_INT_ENABLE
4531}
4532
4533static int
4534pc98_check_i8251_interrupt(struct com_s *com)
4535{
4536 return ( com->intr_enable & 0x07 );
4537}
4538
4539static void
4540pc98_i8251_clear_cmd(struct com_s *com, int x)
4541{
4542 int tmp;
4543
4544 COM_INT_DISABLE
4545 tmp = com->pc98_prev_siocmd & ~(x);
4546 outb(com->cmd_port, tmp);
4547 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4548 COM_INT_ENABLE
4549}
4550
4551static void
4552pc98_i8251_or_cmd(struct com_s *com, int x)
4553{
4554 int tmp;
4555
4556 COM_INT_DISABLE
4557 tmp = com->pc98_prev_siocmd | (x);
4558 outb(com->cmd_port, tmp);
4559 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4560 COM_INT_ENABLE
4561}
4562
4563static void
4564pc98_i8251_set_cmd(struct com_s *com, int x)
4565{
4566 int tmp;
4567
4568 COM_INT_DISABLE
4569 tmp = (x);
4570 outb(com->cmd_port, tmp);
4571 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4572 COM_INT_ENABLE
4573}
4574
4575static void
4576pc98_i8251_clear_or_cmd(struct com_s *com, int clr, int x)
4577{
4578 int tmp;
4579 COM_INT_DISABLE
4580 tmp = com->pc98_prev_siocmd & ~(clr);
4581 tmp |= (x);
4582 outb(com->cmd_port, tmp);
4583 com->pc98_prev_siocmd = tmp & ~(CMD8251_ER|CMD8251_RESET|CMD8251_EH);
4584 COM_INT_ENABLE
4585}
4586
4587static int
4588pc98_i8251_get_cmd(struct com_s *com)
4589{
4590 return com->pc98_prev_siocmd;
4591}
4592
4593static int
4594pc98_i8251_get_mod(struct com_s *com)
4595{
4596 return com->pc98_prev_siomod;
4597}
4598
4599static void
4600pc98_i8251_reset(struct com_s *com, int mode, int command)
4601{
4602 outb(com->cmd_port, 0); /* dummy */
4603 DELAY(2);
4604 outb(com->cmd_port, 0); /* dummy */
4605 DELAY(2);
4606 outb(com->cmd_port, 0); /* dummy */
4607 DELAY(2);
4608 outb(com->cmd_port, CMD8251_RESET); /* internal reset */
4609 DELAY(2);
4610 outb(com->cmd_port, mode ); /* mode register */
4611 com->pc98_prev_siomod = mode;
4612 DELAY(2);
4613 pc98_i8251_set_cmd( com, (command|CMD8251_ER) );
4614}
4615
4616static void
4617pc98_check_sysclock(void)
4618{
4619 /* get system clock from port */
4620 if ( pc98_machine_type & M_8M ) {
4621 /* 8 MHz system & H98 */
4622 sysclock = 8;
4623 } else {
4624 /* 5 MHz system */
4625 sysclock = 5;
4626 }
4627}
4628
4629static void
4630com_cflag_and_speed_set( struct com_s *com, int cflag, int speed)
4631{
4632 int cfcr=0, count;
4633 int previnterrupt;
4634
4635 count = pc98_ttspeedtab( com, speed );
4636 if ( count < 0 ) return;
4637
4638 previnterrupt = pc98_check_i8251_interrupt(com);
4639 pc98_disable_i8251_interrupt( com, IEN_Tx|IEN_TxEMP|IEN_Rx );
4640
4641 switch ( cflag&CSIZE ) {
4642 case CS5:
4643 cfcr = MOD8251_5BITS; break;
4644 case CS6:
4645 cfcr = MOD8251_6BITS; break;
4646 case CS7:
4647 cfcr = MOD8251_7BITS; break;
4648 case CS8:
4649 cfcr = MOD8251_8BITS; break;
4650 }
4651 if ( cflag&PARENB ) {
4652 if ( cflag&PARODD )
4653 cfcr |= MOD8251_PODD;
4654 else
4655 cfcr |= MOD8251_PEVEN;
4656 } else
4657 cfcr |= MOD8251_PDISAB;
4658
4659 if ( cflag&CSTOPB )
4660 cfcr |= MOD8251_STOP2;
4661 else
4662 cfcr |= MOD8251_STOP1;
4663
4664 if ( count & 0x10000 )
4665 cfcr |= MOD8251_CLKX1;
4666 else
4667 cfcr |= MOD8251_CLKX16;
4668
4669 if (epson_machine_id != 0x20) { /* XXX */
4670 int tmp;
4671 while (!((tmp = inb(com->sts_port)) & STS8251_TxEMP))
4672 ;
4673 }
4674 /* set baud rate from ospeed */
4675 pc98_set_baud_rate( com, count );
4676
4677 if ( cfcr != pc98_i8251_get_mod(com) )
4678 pc98_i8251_reset(com, cfcr, pc98_i8251_get_cmd(com) );
4679
4680 pc98_enable_i8251_interrupt( com, previnterrupt );
4681}
4682
4683static int
4684pc98_ttspeedtab(struct com_s *com, int speed)
4685{
4686 int if_type, effect_sp, count = -1, mod;
4687
4688 if_type = com->pc98_if_type & 0x0f;
4689
4690 switch (com->pc98_if_type) {
4691 case COM_IF_INTERNAL:
4692 if (PC98SIO_baud_rate_port(if_type) != -1) {
4693 count = ttspeedtab(speed, if_8251_type[if_type].speedtab);
4694 if (count > 0) {
4695 count |= COM1_EXT_CLOCK;
4696 break;
4697 }
4698 }
4699
4700 /* for *1CLK asynchronous! mode, TEFUTEFU */
4701 mod = (sysclock == 5) ? 2457600 : 1996800;
4702 effect_sp = ttspeedtab( speed, pc98speedtab );
4703 if ( effect_sp < 0 ) /* XXX */
4704 effect_sp = ttspeedtab( (speed - 1), pc98speedtab );
4705 if ( effect_sp <= 0 )
4706 return effect_sp;
4707 if ( effect_sp == speed )
4708 mod /= 16;
4709 if ( mod % effect_sp )
4710 return(-1);
4711 count = mod / effect_sp;
4712 if ( count > 65535 )
4713 return(-1);
4714 if ( effect_sp != speed )
4715 count |= 0x10000;
4716 break;
4717 case COM_IF_PC9861K_1:
4718 case COM_IF_PC9861K_2:
4719 count = 1;
4720 break;
4721 case COM_IF_IND_SS_1:
4722 case COM_IF_IND_SS_2:
4723 case COM_IF_PIO9032B_1:
4724 case COM_IF_PIO9032B_2:
4725 if ( speed == 0 ) return 0;
4726 count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4727 break;
4728 case COM_IF_B98_01_1:
4729 case COM_IF_B98_01_2:
4730 if ( speed == 0 ) return 0;
4731 count = ttspeedtab( speed, if_8251_type[if_type].speedtab );
4732#ifdef B98_01_OLD
4733 if (count == 0 || count == 1) {
4734 count += 4;
4735 count |= 0x20000; /* x1 mode for 76800 and 153600 */
4736 }
4737#endif
4738 break;
4739 }
4740
4741 return count;
4742}
4743
4744static void
4745pc98_set_baud_rate( struct com_s *com, int count )
4746{
4747 int if_type, io, s;
4748
4749 if_type = com->pc98_if_type & 0x0f;
4750 io = com->iobase & 0xff00;
4751
4752 switch (com->pc98_if_type) {
4753 case COM_IF_INTERNAL:
4754 if (PC98SIO_baud_rate_port(if_type) != -1) {
4755 if (count & COM1_EXT_CLOCK) {
4756 outb((Port_t)PC98SIO_baud_rate_port(if_type), count & 0xff);
4757 break;
4758 } else {
4759 outb((Port_t)PC98SIO_baud_rate_port(if_type), 0x09);
4760 }
4761 }
4762
4763 if ( count < 0 ) {
4764 printf( "[ Illegal count : %d ]", count );
4765 return;
4766 } else if ( count == 0 )
4767 return;
4768 /* set i8253 */
4769 s = splclock();
4770 if (count != 3)
4771 outb( 0x77, 0xb6 );
4772 else
4773 outb( 0x77, 0xb4 );
4774 outb( 0x5f, 0);
4775 outb( 0x75, count & 0xff );
4776 outb( 0x5f, 0);
4777 outb( 0x75, (count >> 8) & 0xff );
4778 splx(s);
4779 break;
4780 case COM_IF_IND_SS_1:
4781 case COM_IF_IND_SS_2:
4782 outb(io | PC98SIO_intr_ctrl_port(if_type), 0);
4783 outb(io | PC98SIO_baud_rate_port(if_type), 0);
4784 outb(io | PC98SIO_baud_rate_port(if_type), 0xc0);
4785 outb(io | PC98SIO_baud_rate_port(if_type), (count >> 8) | 0x80);
4786 outb(io | PC98SIO_baud_rate_port(if_type), count & 0xff);
4787 break;
4788 case COM_IF_PIO9032B_1:
4789 case COM_IF_PIO9032B_2:
4790 outb(io | PC98SIO_baud_rate_port(if_type), count);
4791 break;
4792 case COM_IF_B98_01_1:
4793 case COM_IF_B98_01_2:
4794 outb(io | PC98SIO_baud_rate_port(if_type), count & 0x0f);
4795#ifdef B98_01_OLD
4796 /*
4797 * Some old B98_01 board should be controlled
4798 * in different way, but this hasn't been tested yet.
4799 */
4800 outb(io | PC98SIO_func_port(if_type),
4801 (count & 0x20000) ? 0xf0 : 0xf2);
4802#endif
4803 break;
4804 }
4805}
4806static int
4807pc98_check_if_type(device_t dev, struct siodev *iod)
4808{
4809 int irr, io, if_type, tmp;
4810 static short irq_tab[2][8] = {
4811 { 3, 5, 6, 9, 10, 12, 13, -1},
4812 { 3, 10, 12, 13, 5, 6, 9, -1}
4813 };
4814
4815 iod->if_type = if_type = (device_get_flags(dev) >> 24) & 0xff;
4816 if ((if_type < 0 || if_type > COM_IF_END1) &&
4817 (if_type < 0x10 || if_type > COM_IF_END2))
4818 return(-1);
4819 if_type &= 0x0f;
4820 iod->irq = 0;
4821 io = isa_get_port(dev) & 0xff00;
4822
4823 if (IS_8251(iod->if_type)) {
4824 if (PC98SIO_func_port(if_type) != -1) {
4825 outb(io | PC98SIO_func_port(if_type), 0xf2);
4826 tmp = ttspeedtab(9600, if_8251_type[if_type].speedtab);
4827 if (tmp != -1 && PC98SIO_baud_rate_port(if_type) != -1)
4828 outb(io | PC98SIO_baud_rate_port(if_type), tmp);
4829 }
4830
4831 iod->cmd = io | PC98SIO_cmd_port(if_type);
4832 iod->sts = io | PC98SIO_sts_port(if_type);
4833 iod->mod = io | PC98SIO_in_modem_port(if_type);
4834 iod->ctrl = io | PC98SIO_intr_ctrl_port(if_type);
4835
4836 if (iod->if_type == COM_IF_INTERNAL) {
4837 iod->irq = 4;
4838
4839 /* XXX check new internal port. */
4840 outb(0x13a, 0);
4841 DELAY(10);
4842 for (tmp = 0; tmp < 100; tmp++) {
4843 if ((inb(0x13a) & 0x80) == 0) {
4844 PC98SIO_baud_rate_port(if_type) = 0x13a;
4845 if_8251_type[if_type].name = " (internal fast)";
4846 if_8251_type[if_type].speedtab = pc98fast_speedtab;
4847 break;
4848 }
4849 DELAY(1);
4850 }
4851 } else {
4852 tmp = inb( iod->mod ) & if_8251_type[if_type].irr_mask;
4853 if ((isa_get_port(dev) & 0xff) == IO_COM2)
4854 iod->irq = irq_tab[0][tmp];
4855 else
4856 iod->irq = irq_tab[1][tmp];
4857 }
4858 } else {
4859 irr = if_16550a_type[if_type].irr_read;
4860#ifdef COM_MULTIPORT
4861 if (!COM_ISMULTIPORT(device_get_flags(dev)) ||
4862 device_get_unit(dev) == COM_MPMASTER(device_get_flags(dev)))
4863#endif
4864 if (irr != -1) {
4865 tmp = inb(io | irr);
4866 if (isa_get_port(dev) & 0x01) /* XXX depend on RSB-384 */
4867 iod->irq = irq_tab[1][tmp >> 3];
4868 else
4869 iod->irq = irq_tab[0][tmp & 0x07];
4870 }
4871 }
4872 if ( iod->irq == -1 ) return -1;
4873
4874 return 0;
4875}
4876static int
4877pc98_set_ioport( struct com_s *com, int id_flags )
4878{
4879 int io, if_type;
4880
4881 if_type = (id_flags >> 24) & 0xff;
4882 if (IS_8251(if_type)) {
4883 pc98_check_sysclock();
4884 io = com->iobase & 0xff00;
4885 com->pc98_if_type = if_type;
4886 if_type &= 0x0f;
4887 com->data_port = io | PC98SIO_data_port(if_type);
4888 com->cmd_port = io | PC98SIO_cmd_port(if_type);
4889 com->sts_port = io | PC98SIO_sts_port(if_type);
4890 com->in_modem_port = io | PC98SIO_in_modem_port(if_type);
4891 com->intr_ctrl_port = io | PC98SIO_intr_ctrl_port(if_type);
4892 return 0;
4893 }
4894
4895 return -1;
4896}
4897#endif /* PC98 defined */