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