1 /*-
2 * (MPSAFE)
3 *
4 * Copyright (c) 1991 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: src/sys/isa/sio.c,v 1.291.2.35 2003/05/18 08:51:15 murray Exp $
32 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
33 * from: i386/isa sio.c,v 1.234
34 */
35
36 #include "opt_comconsole.h"
37 #include "opt_ddb.h"
38 #include "opt_sio.h"
39 #include "use_pci.h"
40 #include "use_puc.h"
41
42 /*
43 * Serial driver, based on 386BSD-0.1 com driver.
44 * Mostly rewritten to use pseudo-DMA.
45 * Works for National Semiconductor NS8250-NS16550AF UARTs.
46 * COM driver, based on HP dca driver.
47 *
48 * Changes for PC-Card integration:
49 * - Added PC-Card driver table and handlers
50 */
51 #include <sys/param.h>
52 #include <sys/systm.h>
53 #include <sys/reboot.h>
54 #include <sys/malloc.h>
55 #include <sys/tty.h>
56 #include <sys/ttydefaults.h> /* for TTYDEF_* */
57 #include <sys/proc.h>
58 #include <sys/caps.h>
59 #include <sys/module.h>
60 #include <sys/conf.h>
61 #include <sys/dkstat.h>
62 #include <sys/fcntl.h>
63 #include <sys/interrupt.h>
64 #include <sys/kernel.h>
65 #include <sys/syslog.h>
66 #include <sys/sysctl.h>
67 #include <sys/bus.h>
68 #include <sys/rman.h>
69 #include <sys/timepps.h>
70 #include <sys/thread2.h>
71 #include <sys/devfs.h>
72 #include <sys/consio.h>
73
74 #include <machine/limits.h>
75
76 #include <bus/isa/isareg.h>
77 #include <bus/isa/isavar.h>
78 #if NPCI > 0
79 #include <bus/pci/pcireg.h>
80 #include <bus/pci/pcivar.h>
81 #endif
82 #if NPUC > 0
83 #include <dev/misc/puc/pucvar.h>
84 #endif
85 #include <machine/lock.h>
86
87 #include <machine/clock.h>
88
89 #include "sioreg.h"
90 #include "sio_private.h"
91
92 #ifdef COM_ESP
93 #include "../ic_layer/esp.h"
94 #endif
95
96 #define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
97
98 #define CALLOUT_MASK 0x80
99 #define CONTROL_MASK 0x60
100 #define CONTROL_INIT_STATE 0x20
101 #define CONTROL_LOCK_STATE 0x40
102 #define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev)))
103 #define MINOR_TO_UNIT(mynor) ((((mynor) & ~0xffffU) >> (8 + 3)) \
104 | ((mynor) & 0x1f))
105 #define UNIT_TO_MINOR(unit) ((((unit) & ~0x1fU) << (8 + 3)) \
106 | ((unit) & 0x1f))
107
108 #define com_scr 7 /* scratch register for 16450-16550 (R/W) */
109
110 #define sio_getreg(com, off) \
111 (bus_space_read_1((com)->bst, (com)->bsh, (off)))
112 #define sio_setreg(com, off, value) \
113 (bus_space_write_1((com)->bst, (com)->bsh, (off), (value)))
114
115 /*
116 * com state bits.
117 * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher
118 * than the other bits so that they can be tested as a group without masking
119 * off the low bits.
120 *
121 * The following com and tty flags correspond closely:
122 * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and
123 * comstop())
124 * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart())
125 * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam())
126 * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam())
127 * TS_FLUSH is not used.
128 * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON.
129 * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state).
130 */
131 #define CS_BUSY 0x80 /* output in progress */
132 #define CS_TTGO 0x40 /* output not stopped by XOFF */
133 #define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */
134 #define CS_CHECKMSR 1 /* check of MSR scheduled */
135 #define CS_CTS_OFLOW 2 /* use CTS output flow control */
136 #define CS_DTR_OFF 0x10 /* DTR held off */
137 #define CS_ODONE 4 /* output completed */
138 #define CS_RTS_IFLOW 8 /* use RTS input flow control */
139 #define CSE_BUSYCHECK 1 /* siobusycheck() scheduled */
140
141 static char const * const error_desc[] = {
142 #define CE_OVERRUN 0
143 "silo overflow",
144 #define CE_INTERRUPT_BUF_OVERFLOW 1
145 "interrupt-level buffer overflow",
146 #define CE_TTY_BUF_OVERFLOW 2
147 "tty-level buffer overflow",
148 };
149
150 #ifdef COM_ESP
151 static int espattach (struct com_s *com, Port_t esp_port);
152 #endif
153 static int sio_isa_attach (device_t dev);
154
155 static timeout_t siobusycheck;
156 static u_int siodivisor (u_long rclk, speed_t speed);
157 static timeout_t siodtrwakeup;
158 static void comhardclose (struct com_s *com);
159 static void sioinput (struct com_s *com);
160 static void siointr1 (struct com_s *com);
161 static void siointr (void *arg);
162 static int commctl (struct com_s *com, int bits, int how);
163 static int comparam (struct tty *tp, struct termios *t);
164 static inthand2_t siopoll;
165 static int sio_isa_probe (device_t dev);
166 static void siosettimeout (void);
167 static int siosetwater (struct com_s *com, speed_t speed);
168 static void comstart (struct tty *tp);
169 static void comstop (struct tty *tp, int rw);
170 static timeout_t comwakeup;
171 static void disc_optim (struct tty *tp, struct termios *t,
172 struct com_s *com);
173 static void siocntxwait (Port_t iobase);
174
175 #if NPCI > 0
176 static int sio_pci_attach (device_t dev);
177 static void sio_pci_kludge_unit (device_t dev);
178 static int sio_pci_probe (device_t dev);
179 #endif /* NPCI > 0 */
180
181 #if NPUC > 0
182 static int sio_puc_attach (device_t dev);
183 static int sio_puc_probe (device_t dev);
184 #endif /* NPUC > 0 */
185
186 static char driver_name[] = "sio";
187
188 /* table and macro for fast conversion from a unit number to its com struct */
189 devclass_t sio_devclass;
190 #define com_addr(unit) ((struct com_s *) \
191 devclass_get_softc(sio_devclass, unit))
192
193 static device_method_t sio_isa_methods[] = {
194 /* Device interface */
195 DEVMETHOD(device_probe, sio_isa_probe),
196 DEVMETHOD(device_attach, sio_isa_attach),
197
198 DEVMETHOD_END
199 };
200
201 static driver_t sio_isa_driver = {
202 driver_name,
203 sio_isa_methods,
204 sizeof(struct com_s),
205 };
206
207 #if NPCI > 0
208 static device_method_t sio_pci_methods[] = {
209 /* Device interface */
210 DEVMETHOD(device_probe, sio_pci_probe),
211 DEVMETHOD(device_attach, sio_pci_attach),
212
213 DEVMETHOD_END
214 };
215
216 static driver_t sio_pci_driver = {
217 driver_name,
218 sio_pci_methods,
219 sizeof(struct com_s),
220 };
221 #endif /* NPCI > 0 */
222
223 #if NPUC > 0
224 static device_method_t sio_puc_methods[] = {
225 /* Device interface */
226 DEVMETHOD(device_probe, sio_puc_probe),
227 DEVMETHOD(device_attach, sio_puc_attach),
228
229 DEVMETHOD_END
230 };
231
232 static driver_t sio_puc_driver = {
233 driver_name,
234 sio_puc_methods,
235 sizeof(struct com_s),
236 };
237 #endif /* NPUC > 0 */
238
239 static d_open_t sioopen;
240 static d_close_t sioclose;
241 static d_read_t sioread;
242 static d_write_t siowrite;
243 static d_ioctl_t sioioctl;
244
245 static struct dev_ops sio_ops = {
246 { driver_name, 0, D_TTY },
247 .d_open = sioopen,
248 .d_close = sioclose,
249 .d_read = sioread,
250 .d_write = siowrite,
251 .d_ioctl = sioioctl,
252 .d_kqfilter = ttykqfilter,
253 .d_revoke = ttyrevoke
254 };
255
256 int comconsole = -1;
257 static volatile speed_t comdefaultrate = CONSPEED;
258 static u_long comdefaultrclk = DEFAULT_RCLK;
259 SYSCTL_ULONG(_machdep, OID_AUTO, conrclk, CTLFLAG_RW, &comdefaultrclk, 0, "");
260 static Port_t siocniobase;
261 static int siocnunit;
262 static Port_t siogdbiobase;
263 static int siogdbunit = -1;
264 static bool_t sio_registered;
265 static int sio_timeout;
266 static int sio_timeouts_until_log;
267 static struct callout sio_timeout_handle;
268 static int sio_numunits;
269
270 #ifdef COM_ESP
271 /* XXX configure this properly. */
272 static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
273 static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
274 #endif
275
276 /*
277 * handle sysctl read/write requests for console speed
278 *
279 * In addition to setting comdefaultrate for I/O through /dev/console,
280 * also set the initial and lock values for the /dev/ttyXX device
281 * if there is one associated with the console. Finally, if the /dev/tty
282 * device has already been open, change the speed on the open running port
283 * itself.
284 */
285
286 static int
sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)287 sysctl_machdep_comdefaultrate(SYSCTL_HANDLER_ARGS)
288 {
289 int error;
290 speed_t newspeed;
291 struct com_s *com;
292 struct tty *tp;
293
294 lwkt_gettoken(&tty_token);
295 newspeed = comdefaultrate;
296
297 error = sysctl_handle_opaque(oidp, &newspeed, sizeof newspeed, req);
298 if (error || !req->newptr) {
299 lwkt_reltoken(&tty_token);
300 return (error);
301 }
302
303 comdefaultrate = newspeed;
304
305 if (comconsole < 0) { /* serial console not selected? */
306 lwkt_reltoken(&tty_token);
307 return (0);
308 }
309
310 com = com_addr(comconsole);
311 if (com == NULL) {
312 lwkt_reltoken(&tty_token);
313 return (ENXIO);
314 }
315
316 /*
317 * set the initial and lock rates for /dev/ttydXX and /dev/cuaXX
318 * (note, the lock rates really are boolean -- if non-zero, disallow
319 * speed changes)
320 */
321 com->it_in.c_ispeed = com->it_in.c_ospeed =
322 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
323 com->it_out.c_ispeed = com->it_out.c_ospeed =
324 com->lt_out.c_ispeed = com->lt_out.c_ospeed = comdefaultrate;
325
326 /*
327 * if we're open, change the running rate too
328 */
329 tp = com->tp;
330 if (tp && (tp->t_state & TS_ISOPEN)) {
331 tp->t_termios.c_ispeed =
332 tp->t_termios.c_ospeed = comdefaultrate;
333 crit_enter();
334 error = comparam(tp, &tp->t_termios);
335 crit_exit();
336 }
337 lwkt_reltoken(&tty_token);
338 return error;
339 }
340
341 SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
342 0, 0, sysctl_machdep_comdefaultrate, "I", "");
343
344 #if NPCI > 0
345 struct pci_ids {
346 u_int32_t type;
347 const char *desc;
348 int rid;
349 };
350
351 static struct pci_ids pci_ids[] = {
352 { 0x100812b9, "3COM PCI FaxModem", 0x10 },
353 { 0x2000131f, "CyberSerial (1-port) 16550", 0x10 },
354 { 0x01101407, "Koutech IOFLEX-2S PCI Dual Port Serial", 0x10 },
355 { 0x01111407, "Koutech IOFLEX-2S PCI Dual Port Serial", 0x10 },
356 { 0x048011c1, "Lucent kermit based PCI Modem", 0x14 },
357 { 0x95211415, "Oxford Semiconductor PCI Dual Port Serial", 0x10 },
358 { 0x7101135e, "SeaLevel Ultra 530.PCI Single Port Serial", 0x18 },
359 { 0x0000151f, "SmartLink 5634PCV SurfRider", 0x10 },
360 { 0x98459710, "Netmos Nm9845 PCI Bridge with Dual UART", 0x10 },
361 { 0x99229710, "MCS9922 PCIe Multi-I/O Controller", 0x10 },
362 { 0x8c3d8086, "Intel Lynx Point KT Controller", 0x10 },
363 { 0x9c3d8086, "Intel Lynx Point-LP HECI KT", 0x10 },
364 { 0x8cbd8086, "Intel Wildcat Point KT Controller", 0x10 },
365 { 0x9cbd8086, "Intel Wildcat Point-LP KT Controller", 0x10 },
366 { 0x00000000, NULL, 0 }
367 };
368
369 static int
sio_pci_attach(device_t dev)370 sio_pci_attach(device_t dev)
371 {
372 u_int32_t type;
373 struct pci_ids *id;
374
375 type = pci_get_devid(dev);
376 id = pci_ids;
377 while (id->type && id->type != type)
378 id++;
379 if (id->desc == NULL)
380 return (ENXIO);
381 sio_pci_kludge_unit(dev);
382 return (sioattach(dev, id->rid, 0UL));
383 }
384
385 /*
386 * Don't cut and paste this to other drivers. It is a horrible kludge
387 * which will fail to work and also be unnecessary in future versions.
388 */
389 static void
sio_pci_kludge_unit(device_t dev)390 sio_pci_kludge_unit(device_t dev)
391 {
392 devclass_t dc;
393 int err;
394 int start;
395 int unit;
396
397 unit = 0;
398 start = 0;
399 while (resource_int_value("sio", unit, "port", &start) == 0 &&
400 start > 0)
401 unit++;
402 if (device_get_unit(dev) < unit) {
403 dc = device_get_devclass(dev);
404 while (devclass_get_device(dc, unit))
405 unit++;
406 device_printf(dev, "moving to sio%d\n", unit);
407 err = device_set_unit(dev, unit); /* EVIL DO NOT COPY */
408 if (err)
409 device_printf(dev, "error moving device %d\n", err);
410 }
411 }
412
413 static int
sio_pci_probe(device_t dev)414 sio_pci_probe(device_t dev)
415 {
416 u_int32_t type;
417 struct pci_ids *id;
418
419 type = pci_get_devid(dev);
420 id = pci_ids;
421 while (id->type && id->type != type)
422 id++;
423 if (id->desc == NULL)
424 return (ENXIO);
425 device_set_desc(dev, id->desc);
426 return (sioprobe(dev, id->rid, 0UL));
427 }
428 #endif /* NPCI > 0 */
429
430 #if NPUC > 0
431 static int
sio_puc_attach(device_t dev)432 sio_puc_attach(device_t dev)
433 {
434 uintptr_t rclk;
435
436 if (BUS_READ_IVAR(device_get_parent(dev), dev, PUC_IVAR_FREQ,
437 &rclk) != 0)
438 rclk = DEFAULT_RCLK;
439 return (sioattach(dev, 0, rclk));
440 }
441
442 static int
sio_puc_probe(device_t dev)443 sio_puc_probe(device_t dev)
444 {
445 uintptr_t rclk;
446
447 if (BUS_READ_IVAR(device_get_parent(dev), dev, PUC_IVAR_FREQ,
448 &rclk) != 0)
449 rclk = DEFAULT_RCLK;
450 return (sioprobe(dev, 0, rclk));
451 }
452 #endif /* NPUC */
453
454 static struct isa_pnp_id sio_ids[] = {
455 {0x0005d041, "Standard PC COM port"}, /* PNP0500 */
456 {0x0105d041, "16550A-compatible COM port"}, /* PNP0501 */
457 {0x0205d041, "Multiport serial device (non-intelligent 16550)"}, /* PNP0502 */
458 {0x1005d041, "Generic IRDA-compatible device"}, /* PNP0510 */
459 {0x1105d041, "Generic IRDA-compatible device"}, /* PNP0511 */
460 /* Devices that do not have a compatid */
461 {0x12206804, NULL}, /* ACH2012 - 5634BTS 56K Video Ready Modem */
462 {0x7602a904, NULL}, /* AEI0276 - 56K v.90 Fax Modem (LKT) */
463 {0x00007905, NULL}, /* AKY0000 - 56K Plug&Play Modem */
464 {0x21107905, NULL}, /* AKY1021 - 56K Plug&Play Modem */
465 {0x01405407, NULL}, /* AZT4001 - AZT3000 PnP SOUND DEVICE, MODEM */
466 {0x56039008, NULL}, /* BDP0356 - Best Data 56x2 */
467 {0x56159008, NULL}, /* BDP1556 - B.D. Smart One 56SPS,Voice Modem*/
468 {0x36339008, NULL}, /* BDP3336 - Best Data Prods. 336F */
469 {0x0014490a, NULL}, /* BRI1400 - Boca 33.6 PnP */
470 {0x0015490a, NULL}, /* BRI1500 - Internal Fax Data */
471 {0x0034490a, NULL}, /* BRI3400 - Internal ACF Modem */
472 {0x0094490a, NULL}, /* BRI9400 - Boca K56Flex PnP */
473 {0x00b4490a, NULL}, /* BRIB400 - Boca 56k PnP */
474 {0x0030320d, NULL}, /* CIR3000 - Cirrus Logic V43 */
475 {0x0100440e, NULL}, /* CRD0001 - Cardinal MVP288IV ? */
476 {0x01308c0e, NULL}, /* CTL3001 - Creative Labs Phoneblaster */
477 {0x36033610, NULL}, /* DAV0336 - DAVICOM 336PNP MODEM */
478 {0x01009416, NULL}, /* ETT0001 - E-Tech Bullet 33k6 PnP */
479 {0x0000aa1a, NULL}, /* FUJ0000 - FUJITSU Modem 33600 PNP/I2 */
480 {0x1200c31e, NULL}, /* GVC0012 - VF1128HV-R9 (win modem?) */
481 {0x0303c31e, NULL}, /* GVC0303 - MaxTech 33.6 PnP D/F/V */
482 {0x0505c31e, NULL}, /* GVC0505 - GVC 56k Faxmodem */
483 {0x0116c31e, NULL}, /* GVC1601 - Rockwell V.34 Plug & Play Modem */
484 {0x0050c31e, NULL}, /* GVC5000 - some GVC modem */
485 {0x3800f91e, NULL}, /* GWY0038 - Telepath with v.90 */
486 {0x9062f91e, NULL}, /* GWY6290 - Telepath with x2 Technology */
487 {0x8100e425, NULL}, /* IOD0081 - I-O DATA DEVICE,INC. IFML-560 */
488 {0x21002534, NULL}, /* MAE0021 - Jetstream Int V.90 56k Voice Series 2*/
489 {0x0000f435, NULL}, /* MOT0000 - Motorola ModemSURFR 33.6 Intern */
490 {0x5015f435, NULL}, /* MOT1550 - Motorola ModemSURFR 56K Modem */
491 {0xf015f435, NULL}, /* MOT15F0 - Motorola VoiceSURFR 56K Modem */
492 {0x6045f435, NULL}, /* MOT4560 - Motorola ? */
493 {0x61e7a338, NULL}, /* NECE761 - 33.6Modem */
494 {0x08804f3f, NULL}, /* OZO8008 - Zoom (33.6k Modem) */
495 {0x0f804f3f, NULL}, /* OZO800f - Zoom 2812 (56k Modem) */
496 {0x39804f3f, NULL}, /* OZO8039 - Zoom 56k flex */
497 {0x00914f3f, NULL}, /* OZO9100 - Zoom 2919 (K56 Faxmodem) */
498 {0x3024a341, NULL}, /* PMC2430 - Pace 56 Voice Internal Modem */
499 {0x1000eb49, NULL}, /* ROK0010 - Rockwell ? */
500 {0x1200b23d, NULL}, /* RSS0012 - OMRON ME5614ISA */
501 {0x5002734a, NULL}, /* RSS0250 - 5614Jx3(G) Internal Modem */
502 {0x6202734a, NULL}, /* RSS0262 - 5614Jx3[G] V90+K56Flex Modem */
503 {0x1010104d, NULL}, /* SHP1010 - Rockwell 33600bps Modem */
504 {0xc100ad4d, NULL}, /* SMM00C1 - Leopard 56k PnP */
505 {0x9012b04e, NULL}, /* SUP1290 - Supra ? */
506 {0x1013b04e, NULL}, /* SUP1310 - SupraExpress 336i PnP */
507 {0x8013b04e, NULL}, /* SUP1380 - SupraExpress 288i PnP Voice */
508 {0x8113b04e, NULL}, /* SUP1381 - SupraExpress 336i PnP Voice */
509 {0x5016b04e, NULL}, /* SUP1650 - Supra 336i Sp Intl */
510 {0x7016b04e, NULL}, /* SUP1670 - Supra 336i V+ Intl */
511 {0x7420b04e, NULL}, /* SUP2070 - Supra ? */
512 {0x8020b04e, NULL}, /* SUP2080 - Supra ? */
513 {0x8420b04e, NULL}, /* SUP2084 - SupraExpress 56i PnP */
514 {0x7121b04e, NULL}, /* SUP2171 - SupraExpress 56i Sp? */
515 {0x8024b04e, NULL}, /* SUP2480 - Supra ? */
516 {0x01007256, NULL}, /* USR0001 - U.S. Robotics Inc., Sportster W */
517 {0x02007256, NULL}, /* USR0002 - U.S. Robotics Inc. Sportster 33. */
518 {0x04007256, NULL}, /* USR0004 - USR Sportster 14.4k */
519 {0x06007256, NULL}, /* USR0006 - USR Sportster 33.6k */
520 {0x11007256, NULL}, /* USR0011 - USR ? */
521 {0x01017256, NULL}, /* USR0101 - USR ? */
522 {0x30207256, NULL}, /* USR2030 - U.S.Robotics Inc. Sportster 560 */
523 {0x50207256, NULL}, /* USR2050 - U.S.Robotics Inc. Sportster 33. */
524 {0x70207256, NULL}, /* USR2070 - U.S.Robotics Inc. Sportster 560 */
525 {0x30307256, NULL}, /* USR3030 - U.S. Robotics 56K FAX INT */
526 {0x31307256, NULL}, /* USR3031 - U.S. Robotics 56K FAX INT */
527 {0x50307256, NULL}, /* USR3050 - U.S. Robotics 56K FAX INT */
528 {0x70307256, NULL}, /* USR3070 - U.S. Robotics 56K Voice INT */
529 {0x90307256, NULL}, /* USR3090 - USR ? */
530 {0x70917256, NULL}, /* USR9170 - U.S. Robotics 56K FAX INT */
531 {0x90917256, NULL}, /* USR9190 - USR 56k Voice INT */
532 {0x0300695c, NULL}, /* WCI0003 - Fax/Voice/Modem/Speakphone/Asvd */
533 {0x01a0896a, NULL}, /* ZTIA001 - Zoom Internal V90 Faxmodem */
534 {0x61f7896a, NULL}, /* ZTIF761 - Zoom ComStar 33.6 */
535 {0}
536 };
537
538
539
540 static int
sio_isa_probe(device_t dev)541 sio_isa_probe(device_t dev)
542 {
543 /* Check isapnp ids */
544 if (ISA_PNP_PROBE(device_get_parent(dev), dev, sio_ids) == ENXIO)
545 return (ENXIO);
546 return (sioprobe(dev, 0, 0UL));
547 }
548
549 int
sioprobe(device_t dev,int xrid,u_long rclk)550 sioprobe(device_t dev, int xrid, u_long rclk)
551 {
552 #if 0
553 static bool_t already_init;
554 device_t xdev;
555 #endif
556 struct com_s *com;
557 u_int divisor;
558 bool_t failures[10];
559 int fn;
560 device_t idev;
561 Port_t iobase;
562 intrmask_t irqmap[4];
563 intrmask_t irqs;
564 u_char mcr_image;
565 int result;
566 u_long xirq;
567 u_int flags = device_get_flags(dev);
568 int rid;
569 struct resource *port;
570
571 rid = xrid;
572 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
573 0, ~0, IO_COMSIZE, RF_ACTIVE);
574 if (!port)
575 return (ENXIO);
576
577 lwkt_gettoken(&tty_token);
578 com = device_get_softc(dev);
579 com->bst = rman_get_bustag(port);
580 com->bsh = rman_get_bushandle(port);
581 if (rclk == 0)
582 rclk = DEFAULT_RCLK;
583 com->rclk = rclk;
584
585 #if 0
586 /*
587 * XXX this is broken - when we are first called, there are no
588 * previously configured IO ports. We could hard code
589 * 0x3f8, 0x2f8, 0x3e8, 0x2e8 etc but that's probably worse.
590 * This code has been doing nothing since the conversion since
591 * "count" is zero the first time around.
592 */
593 if (!already_init) {
594 /*
595 * Turn off MCR_IENABLE for all likely serial ports. An unused
596 * port with its MCR_IENABLE gate open will inhibit interrupts
597 * from any used port that shares the interrupt vector.
598 * XXX the gate enable is elsewhere for some multiports.
599 */
600 device_t *devs;
601 int count, i, xioport;
602
603 devclass_get_devices(sio_devclass, &devs, &count);
604 for (i = 0; i < count; i++) {
605 xdev = devs[i];
606 if (device_is_enabled(xdev) &&
607 bus_get_resource(xdev, SYS_RES_IOPORT, 0, &xioport,
608 NULL) == 0)
609 outb(xioport + com_mcr, 0);
610 }
611 kfree(devs, M_TEMP);
612 already_init = TRUE;
613 }
614 #endif
615
616 if (COM_LLCONSOLE(flags)) {
617 kprintf("sio%d: reserved for low-level i/o\n",
618 device_get_unit(dev));
619 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
620 lwkt_reltoken(&tty_token);
621 return (ENXIO);
622 }
623
624 /*
625 * If the device is on a multiport card and has an AST/4
626 * compatible interrupt control register, initialize this
627 * register and prepare to leave MCR_IENABLE clear in the mcr.
628 * Otherwise, prepare to set MCR_IENABLE in the mcr.
629 * Point idev to the device struct giving the correct id_irq.
630 * This is the struct for the master device if there is one.
631 */
632 idev = dev;
633 mcr_image = MCR_IENABLE;
634 #ifdef COM_MULTIPORT
635 if (COM_ISMULTIPORT(flags)) {
636 Port_t xiobase;
637 u_long io;
638
639 idev = devclass_get_device(sio_devclass, COM_MPMASTER(flags));
640 if (idev == NULL) {
641 kprintf("sio%d: master device %d not configured\n",
642 device_get_unit(dev), COM_MPMASTER(flags));
643 idev = dev;
644 }
645 if (!COM_NOTAST4(flags)) {
646 if (bus_get_resource(idev, SYS_RES_IOPORT, 0, &io,
647 NULL) == 0) {
648 xiobase = io;
649 if (bus_get_resource(idev, SYS_RES_IRQ, 0,
650 NULL, NULL) == 0)
651 outb(xiobase + com_scr, 0x80);
652 else
653 outb(xiobase + com_scr, 0);
654 }
655 mcr_image = 0;
656 }
657 }
658 #endif /* COM_MULTIPORT */
659 if (bus_get_resource(idev, SYS_RES_IRQ, 0, NULL, NULL) != 0)
660 mcr_image = 0;
661
662 bzero(failures, sizeof failures);
663 iobase = rman_get_start(port);
664
665 /*
666 * We don't want to get actual interrupts, just masked ones.
667 * Interrupts from this line should already be masked in the ICU,
668 * but mask them in the processor as well in case there are some
669 * (misconfigured) shared interrupts.
670 */
671 com_lock();
672 /* EXTRA DELAY? */
673
674 /*
675 * For the TI16754 chips, set prescaler to 1 (4 is often the
676 * default after-reset value) as otherwise it's impossible to
677 * get highest baudrates.
678 */
679 if (COM_TI16754(flags)) {
680 u_char cfcr, efr;
681
682 cfcr = sio_getreg(com, com_cfcr);
683 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
684 efr = sio_getreg(com, com_efr);
685 /* Unlock extended features to turn off prescaler. */
686 sio_setreg(com, com_efr, efr | EFR_EFE);
687 /* Disable EFR. */
688 sio_setreg(com, com_cfcr, (cfcr != CFCR_EFR_ENABLE) ? cfcr : 0);
689 /* Turn off prescaler. */
690 sio_setreg(com, com_mcr,
691 sio_getreg(com, com_mcr) & ~MCR_PRESCALE);
692 sio_setreg(com, com_cfcr, CFCR_EFR_ENABLE);
693 sio_setreg(com, com_efr, efr);
694 sio_setreg(com, com_cfcr, cfcr);
695 }
696
697 /*
698 * Initialize the speed and the word size and wait long enough to
699 * drain the maximum of 16 bytes of junk in device output queues.
700 * The speed is undefined after a master reset and must be set
701 * before relying on anything related to output. There may be
702 * junk after a (very fast) soft reboot and (apparently) after
703 * master reset.
704 * XXX what about the UART bug avoided by waiting in comparam()?
705 * We don't want to to wait long enough to drain at 2 bps.
706 */
707 if (iobase == siocniobase) {
708 DELAY((16 + 1) * 1000000 / (comdefaultrate / 10));
709 } else {
710 sio_setreg(com, com_cfcr, CFCR_DLAB | CFCR_8BITS);
711 divisor = siodivisor(rclk, SIO_TEST_SPEED);
712 sio_setreg(com, com_dlbl, divisor & 0xff);
713 sio_setreg(com, com_dlbh, divisor >> 8);
714 sio_setreg(com, com_cfcr, CFCR_8BITS);
715 DELAY((16 + 1) * 1000000 / (SIO_TEST_SPEED / 10));
716 }
717
718 /*
719 * Make sure we can drain the receiver. If we can't, the serial
720 * port may not exist.
721 */
722 for (fn = 0; fn < 256; ++fn) {
723 if ((sio_getreg(com, com_lsr) & LSR_RXRDY) == 0)
724 break;
725 (void)sio_getreg(com, com_data);
726 }
727 if (fn == 256) {
728 /*
729 * Serial port might be probed but not exist, disable
730 * if so. Clear console flags if the serial port does
731 * not exist. This is very common for sio0 and sio1
732 * now and avoids unnecessary user confusion (user does
733 * not have to clear the sio0 console flag if sio0 does
734 * not exist and the user wants the console on another
735 * sio).
736 *
737 * Also set the sioN.disabled resource to prevent console
738 * probing of the non-existent serial port. sio0.flags
739 * typically defaults to 0x10 (from the kernel config).
740 */
741 com_unlock();
742 lwkt_reltoken(&tty_token);
743 kprintf("sio%d: can't drain, serial port might "
744 "not exist, disabling\n", device_get_unit(dev));
745 com->flags &= ~0x30;
746 resource_set_int("sio", device_get_unit(dev), "disabled", 1);
747
748 return (ENXIO);
749 }
750
751 /*
752 * Enable the interrupt gate and disable device interupts. This
753 * should leave the device driving the interrupt line low and
754 * guarantee an edge trigger if an interrupt can be generated.
755 */
756 /* EXTRA DELAY? */
757 sio_setreg(com, com_mcr, mcr_image);
758 sio_setreg(com, com_ier, 0);
759 DELAY(1000); /* XXX */
760 irqmap[0] = isa_irq_pending();
761
762 /*
763 * Attempt to set loopback mode so that we can send a null byte
764 * without annoying any external device.
765 */
766 /* EXTRA DELAY? */
767 sio_setreg(com, com_mcr, mcr_image | MCR_LOOPBACK);
768
769 /*
770 * Attempt to generate an output interrupt. On 8250's, setting
771 * IER_ETXRDY generates an interrupt independent of the current
772 * setting and independent of whether the THR is empty. On 16450's,
773 * setting IER_ETXRDY generates an interrupt independent of the
774 * current setting. On 16550A's, setting IER_ETXRDY only
775 * generates an interrupt when IER_ETXRDY is not already set.
776 */
777 sio_setreg(com, com_ier, IER_ETXRDY);
778
779 /*
780 * On some 16x50 incompatibles, setting IER_ETXRDY doesn't generate
781 * an interrupt. They'd better generate one for actually doing
782 * output. Loopback may be broken on the same incompatibles but
783 * it's unlikely to do more than allow the null byte out.
784 */
785 sio_setreg(com, com_data, 0);
786 DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
787
788 /*
789 * Turn off loopback mode so that the interrupt gate works again
790 * (MCR_IENABLE was hidden). This should leave the device driving
791 * an interrupt line high. It doesn't matter if the interrupt
792 * line oscillates while we are not looking at it, since interrupts
793 * are disabled.
794 */
795 /* EXTRA DELAY? */
796 sio_setreg(com, com_mcr, mcr_image);
797
798 /*
799 * Some pcmcia cards have the "TXRDY bug", so we check everyone
800 * for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
801 */
802 if (COM_NOPROBE(flags)) {
803 /* Reading IIR register twice */
804 for (fn = 0; fn < 2; fn ++) {
805 DELAY(10000);
806 failures[6] = sio_getreg(com, com_iir);
807 }
808 /* Check IIR_TXRDY clear ? */
809 result = 0;
810 if (failures[6] & IIR_TXRDY) {
811 /* Nop, Double check with clearing IER */
812 sio_setreg(com, com_ier, 0);
813 if (sio_getreg(com, com_iir) & IIR_NOPEND) {
814 /* Ok. we're familia this gang */
815 SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
816 } else {
817 /* Unknown, Just omit this chip.. XXX */
818 result = ENXIO;
819 sio_setreg(com, com_mcr, 0);
820 }
821 } else {
822 /* OK. this is well-known guys */
823 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
824 }
825 sio_setreg(com, com_ier, 0);
826 sio_setreg(com, com_cfcr, CFCR_8BITS);
827 com_unlock();
828 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
829 lwkt_reltoken(&tty_token);
830 return (iobase == siocniobase ? 0 : result);
831 }
832
833 /*
834 * Check that
835 * o the CFCR, IER and MCR in UART hold the values written to them
836 * (the values happen to be all distinct - this is good for
837 * avoiding false positive tests from bus echoes).
838 * o an output interrupt is generated and its vector is correct.
839 * o the interrupt goes away when the IIR in the UART is read.
840 */
841 /* EXTRA DELAY? */
842 failures[0] = sio_getreg(com, com_cfcr) - CFCR_8BITS;
843 failures[1] = sio_getreg(com, com_ier) - IER_ETXRDY;
844 failures[2] = sio_getreg(com, com_mcr) - mcr_image;
845 DELAY(10000); /* Some internal modems need this time */
846 irqmap[1] = isa_irq_pending();
847 failures[4] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_TXRDY;
848 DELAY(1000); /* XXX */
849 irqmap[2] = isa_irq_pending();
850 failures[6] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
851
852 /*
853 * Turn off all device interrupts and check that they go off properly.
854 * Leave MCR_IENABLE alone. For ports without a master port, it gates
855 * the OUT2 output of the UART to
856 * the ICU input. Closing the gate would give a floating ICU input
857 * (unless there is another device driving it) and spurious interrupts.
858 * (On the system that this was first tested on, the input floats high
859 * and gives a (masked) interrupt as soon as the gate is closed.)
860 */
861 sio_setreg(com, com_ier, 0);
862 sio_setreg(com, com_cfcr, CFCR_8BITS); /* dummy to avoid bus echo */
863 failures[7] = sio_getreg(com, com_ier);
864 DELAY(1000); /* XXX */
865 irqmap[3] = isa_irq_pending();
866 failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
867
868 com_unlock();
869
870 irqs = irqmap[1] & ~irqmap[0];
871 if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
872 ((1 << xirq) & irqs) == 0)
873 kprintf(
874 "sio%d: configured irq %ld not in bitmap of probed irqs %#x\n",
875 device_get_unit(dev), xirq, irqs);
876 if (bootverbose)
877 kprintf("sio%d: irq maps: %#x %#x %#x %#x\n",
878 device_get_unit(dev),
879 irqmap[0], irqmap[1], irqmap[2], irqmap[3]);
880
881 result = 0;
882 for (fn = 0; fn < sizeof failures; ++fn)
883 if (failures[fn]) {
884 sio_setreg(com, com_mcr, 0);
885 result = ENXIO;
886 if (bootverbose) {
887 kprintf("sio%d: probe failed test(s):",
888 device_get_unit(dev));
889 for (fn = 0; fn < sizeof failures; ++fn)
890 if (failures[fn])
891 kprintf(" %d", fn);
892 kprintf("\n");
893 }
894 break;
895 }
896 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
897 lwkt_reltoken(&tty_token);
898 return (iobase == siocniobase ? 0 : result);
899 }
900
901 #ifdef COM_ESP
902 static int
espattach(struct com_s * com,Port_t esp_port)903 espattach(struct com_s *com, Port_t esp_port)
904 {
905 u_char dips;
906 u_char val;
907
908 /*
909 * Check the ESP-specific I/O port to see if we're an ESP
910 * card. If not, return failure immediately.
911 */
912 if ((inb(esp_port) & 0xf3) == 0) {
913 kprintf(" port 0x%x is not an ESP board?\n", esp_port);
914 return (0);
915 }
916
917 lwkt_gettoken(&tty_token);
918 /*
919 * We've got something that claims to be a Hayes ESP card.
920 * Let's hope so.
921 */
922
923 /* Get the dip-switch configuration */
924 outb(esp_port + ESP_CMD1, ESP_GETDIPS);
925 dips = inb(esp_port + ESP_STATUS1);
926
927 /*
928 * Bits 0,1 of dips say which COM port we are.
929 */
930 if (rman_get_start(com->ioportres) == likely_com_ports[dips & 0x03])
931 kprintf(" : ESP");
932 else {
933 kprintf(" esp_port has com %d\n", dips & 0x03);
934 lwkt_reltoken(&tty_token);
935 return (0);
936 }
937
938 /*
939 * Check for ESP version 2.0 or later: bits 4,5,6 = 010.
940 */
941 outb(esp_port + ESP_CMD1, ESP_GETTEST);
942 val = inb(esp_port + ESP_STATUS1); /* clear reg 1 */
943 val = inb(esp_port + ESP_STATUS2);
944 if ((val & 0x70) < 0x20) {
945 kprintf("-old (%o)", val & 0x70);
946 lwkt_reltoken(&tty_token);
947 return (0);
948 }
949
950 /*
951 * Check for ability to emulate 16550: bit 7 == 1
952 */
953 if ((dips & 0x80) == 0) {
954 kprintf(" slave");
955 lwkt_reltoken(&tty_token);
956 return (0);
957 }
958
959 /*
960 * Okay, we seem to be a Hayes ESP card. Whee.
961 */
962 com->esp = TRUE;
963 com->esp_port = esp_port;
964 lwkt_reltoken(&tty_token);
965 return (1);
966 }
967 #endif /* COM_ESP */
968
969 static int
sio_isa_attach(device_t dev)970 sio_isa_attach(device_t dev)
971 {
972 return (sioattach(dev, 0, 0UL));
973 }
974
975 int
sioattach(device_t dev,int xrid,u_long rclk)976 sioattach(device_t dev, int xrid, u_long rclk)
977 {
978 struct com_s *com;
979 #ifdef COM_ESP
980 Port_t *espp;
981 #endif
982 Port_t iobase;
983 int minorbase;
984 int unit;
985 u_int flags;
986 int rid;
987 struct resource *port;
988 int ret;
989 char tbuf[MAKEDEV_MINNBUF];
990 char *unit_in_base32;
991 static int did_init;
992
993 lwkt_gettoken(&tty_token);
994 if (did_init == 0) {
995 did_init = 1;
996 callout_init_mp(&sio_timeout_handle);
997 }
998
999 rid = xrid;
1000 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
1001 0, ~0, IO_COMSIZE, RF_ACTIVE);
1002 if (!port) {
1003 lwkt_reltoken(&tty_token);
1004 return (ENXIO);
1005 }
1006
1007 iobase = rman_get_start(port);
1008 unit = device_get_unit(dev);
1009 com = device_get_softc(dev);
1010 flags = device_get_flags(dev);
1011
1012 if (unit >= sio_numunits)
1013 sio_numunits = unit + 1;
1014 /*
1015 * sioprobe() has initialized the device registers as follows:
1016 * o cfcr = CFCR_8BITS.
1017 * It is most important that CFCR_DLAB is off, so that the
1018 * data port is not hidden when we enable interrupts.
1019 * o ier = 0.
1020 * Interrupts are only enabled when the line is open.
1021 * o mcr = MCR_IENABLE, or 0 if the port has AST/4 compatible
1022 * interrupt control register or the config specifies no irq.
1023 * Keeping MCR_DTR and MCR_RTS off might stop the external
1024 * device from sending before we are ready.
1025 */
1026 bzero(com, sizeof *com);
1027 com->unit = unit;
1028 com->ioportres = port;
1029 com->bst = rman_get_bustag(port);
1030 com->bsh = rman_get_bushandle(port);
1031 com->cfcr_image = CFCR_8BITS;
1032 com->dtr_wait = 3 * hz;
1033 callout_init_mp(&com->dtr_ch);
1034 callout_init_mp(&com->busy_ch);
1035 com->loses_outints = COM_LOSESOUTINTS(flags) != 0;
1036 com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0;
1037 com->tx_fifo_size = 1;
1038 com->obufs[0].l_head = com->obuf1;
1039 com->obufs[1].l_head = com->obuf2;
1040
1041 com->data_port = iobase + com_data;
1042 com->int_id_port = iobase + com_iir;
1043 com->modem_ctl_port = iobase + com_mcr;
1044 com->mcr_image = inb(com->modem_ctl_port);
1045 com->line_status_port = iobase + com_lsr;
1046 com->modem_status_port = iobase + com_msr;
1047 com->intr_ctl_port = iobase + com_ier;
1048
1049 if (rclk == 0)
1050 rclk = DEFAULT_RCLK;
1051 com->rclk = rclk;
1052
1053 /*
1054 * We don't use all the flags from <sys/ttydefaults.h> since they
1055 * are only relevant for logins. It's important to have echo off
1056 * initially so that the line doesn't start blathering before the
1057 * echo flag can be turned off.
1058 */
1059 com->it_in.c_iflag = 0;
1060 com->it_in.c_oflag = 0;
1061 com->it_in.c_cflag = TTYDEF_CFLAG;
1062 com->it_in.c_lflag = 0;
1063 if (unit == comconsole) {
1064 com->it_in.c_iflag = TTYDEF_IFLAG;
1065 com->it_in.c_oflag = TTYDEF_OFLAG;
1066 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
1067 com->it_in.c_lflag = TTYDEF_LFLAG;
1068 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
1069 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
1070 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
1071 com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
1072 } else
1073 com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
1074 if (siosetwater(com, com->it_in.c_ispeed) != 0) {
1075 /*
1076 * Leave i/o resources allocated if this is a `cn'-level
1077 * console, so that other devices can't snarf them.
1078 */
1079 if (iobase != siocniobase)
1080 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
1081 lwkt_reltoken(&tty_token);
1082 return (ENOMEM);
1083 }
1084 termioschars(&com->it_in);
1085 com->it_out = com->it_in;
1086
1087 /* attempt to determine UART type */
1088 kprintf("sio%d: type", unit);
1089
1090
1091 #ifdef COM_MULTIPORT
1092 if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
1093 #else
1094 if (!COM_IIR_TXRDYBUG(flags))
1095 #endif
1096 {
1097 u_char scr;
1098 u_char scr1;
1099 u_char scr2;
1100
1101 scr = sio_getreg(com, com_scr);
1102 sio_setreg(com, com_scr, 0xa5);
1103 scr1 = sio_getreg(com, com_scr);
1104 sio_setreg(com, com_scr, 0x5a);
1105 scr2 = sio_getreg(com, com_scr);
1106 sio_setreg(com, com_scr, scr);
1107 if (scr1 != 0xa5 || scr2 != 0x5a) {
1108 kprintf(" 8250");
1109 goto determined_type;
1110 }
1111 }
1112 sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
1113 DELAY(100);
1114 com->st16650a = 0;
1115 switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
1116 case FIFO_RX_LOW:
1117 kprintf(" 16450");
1118 break;
1119 case FIFO_RX_MEDL:
1120 kprintf(" 16450?");
1121 break;
1122 case FIFO_RX_MEDH:
1123 kprintf(" 16550?");
1124 break;
1125 case FIFO_RX_HIGH:
1126 if (COM_NOFIFO(flags)) {
1127 kprintf(" 16550A fifo disabled");
1128 } else {
1129 com->hasfifo = TRUE;
1130 if (COM_ST16650A(flags)) {
1131 com->st16650a = 1;
1132 com->tx_fifo_size = 32;
1133 kprintf(" ST16650A");
1134 } else if (COM_TI16754(flags)) {
1135 com->tx_fifo_size = 64;
1136 kprintf(" TI16754");
1137 } else {
1138 com->tx_fifo_size = COM_FIFOSIZE(flags);
1139 kprintf(" 16550A");
1140 }
1141 }
1142 #ifdef COM_ESP
1143 for (espp = likely_esp_ports; *espp != 0; espp++)
1144 if (espattach(com, *espp)) {
1145 com->tx_fifo_size = 1024;
1146 break;
1147 }
1148 #endif
1149 if (!com->st16650a && !COM_TI16754(flags)) {
1150 if (!com->tx_fifo_size)
1151 com->tx_fifo_size = 16;
1152 else
1153 kprintf(" lookalike with %d bytes FIFO",
1154 com->tx_fifo_size);
1155 }
1156
1157 break;
1158 }
1159 #ifdef COM_ESP
1160 if (com->esp) {
1161 /*
1162 * Set 16550 compatibility mode.
1163 * We don't use the ESP_MODE_SCALE bit to increase the
1164 * fifo trigger levels because we can't handle large
1165 * bursts of input.
1166 * XXX flow control should be set in comparam(), not here.
1167 */
1168 outb(com->esp_port + ESP_CMD1, ESP_SETMODE);
1169 outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO);
1170
1171 /* Set RTS/CTS flow control. */
1172 outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE);
1173 outb(com->esp_port + ESP_CMD2, ESP_FLOW_RTS);
1174 outb(com->esp_port + ESP_CMD2, ESP_FLOW_CTS);
1175
1176 /* Set flow-control levels. */
1177 outb(com->esp_port + ESP_CMD1, ESP_SETRXFLOW);
1178 outb(com->esp_port + ESP_CMD2, HIBYTE(768));
1179 outb(com->esp_port + ESP_CMD2, LOBYTE(768));
1180 outb(com->esp_port + ESP_CMD2, HIBYTE(512));
1181 outb(com->esp_port + ESP_CMD2, LOBYTE(512));
1182 }
1183 #endif /* COM_ESP */
1184 sio_setreg(com, com_fifo, 0);
1185 determined_type: ;
1186
1187 #ifdef COM_MULTIPORT
1188 if (COM_ISMULTIPORT(flags)) {
1189 device_t masterdev;
1190
1191 com->multiport = TRUE;
1192 kprintf(" (multiport");
1193 if (unit == COM_MPMASTER(flags))
1194 kprintf(" master");
1195 kprintf(")");
1196 masterdev = devclass_get_device(sio_devclass,
1197 COM_MPMASTER(flags));
1198 com->no_irq = (masterdev == NULL || bus_get_resource(masterdev,
1199 SYS_RES_IRQ, 0, NULL, NULL) != 0);
1200 }
1201 #endif /* COM_MULTIPORT */
1202 if (unit == comconsole)
1203 kprintf(", console");
1204 if (COM_IIR_TXRDYBUG(flags))
1205 kprintf(" with a bogus IIR_TXRDY register");
1206 kprintf("\n");
1207
1208 if (!sio_registered) {
1209 register_swi_mp(SWI_TTY, siopoll, NULL,
1210 "swi_siopoll", NULL, -1);
1211 sio_registered = TRUE;
1212 }
1213 minorbase = UNIT_TO_MINOR(unit);
1214 unit_in_base32 = makedev_unit_b32(tbuf, unit);
1215 make_dev(&sio_ops, minorbase,
1216 UID_ROOT, GID_WHEEL, 0600, "ttyd%s", unit_in_base32);
1217 make_dev(&sio_ops, minorbase | CONTROL_INIT_STATE,
1218 UID_ROOT, GID_WHEEL, 0600, "ttyid%s", unit_in_base32);
1219 make_dev(&sio_ops, minorbase | CONTROL_LOCK_STATE,
1220 UID_ROOT, GID_WHEEL, 0600, "ttyld%s", unit_in_base32);
1221 make_dev(&sio_ops, minorbase | CALLOUT_MASK,
1222 UID_UUCP, GID_DIALER, 0660, "cuaa%s", unit_in_base32);
1223 make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE,
1224 UID_UUCP, GID_DIALER, 0660, "cuaia%s", unit_in_base32);
1225 make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE,
1226 UID_UUCP, GID_DIALER, 0660, "cuala%s", unit_in_base32);
1227 com->flags = flags;
1228 com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR;
1229 pps_init(&com->pps);
1230
1231 rid = 0;
1232 com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
1233 RF_ACTIVE);
1234 if (com->irqres) {
1235 ret = BUS_SETUP_INTR(device_get_parent(dev), dev,
1236 com->irqres, INTR_MPSAFE, siointr, com,
1237 &com->cookie, NULL, NULL);
1238 if (ret)
1239 device_printf(dev, "could not activate interrupt\n");
1240 #if defined(DDB)
1241 /*
1242 * Enable interrupts for early break-to-debugger support
1243 * on the console.
1244 */
1245 if (ret == 0 && unit == comconsole &&
1246 (break_to_debugger || alt_break_to_debugger)) {
1247 inb(siocniobase + com_data);
1248 outb(siocniobase + com_ier,
1249 IER_ERXRDY | IER_ERLS | IER_EMSC);
1250 }
1251 #endif
1252 }
1253
1254 lwkt_reltoken(&tty_token);
1255 return (0);
1256 }
1257
1258 static int
sioopen(struct dev_open_args * ap)1259 sioopen(struct dev_open_args *ap)
1260 {
1261 cdev_t dev = ap->a_head.a_dev;
1262 struct com_s *com;
1263 int error;
1264 int mynor;
1265 struct tty *tp;
1266 int unit;
1267
1268 mynor = minor(dev);
1269 unit = MINOR_TO_UNIT(mynor);
1270 com = com_addr(unit);
1271 if (com == NULL)
1272 return (ENXIO);
1273 if (com->gone)
1274 return (ENXIO);
1275 if (mynor & CONTROL_MASK)
1276 return (0);
1277 lwkt_gettoken(&tty_token);
1278 tp = ttymalloc(&com->tp);
1279 dev->si_tty = tp;
1280 crit_enter();
1281 /*
1282 * We jump to this label after all non-interrupted sleeps to pick
1283 * up any changes of the device state.
1284 */
1285 open_top:
1286 while (com->state & CS_DTR_OFF) {
1287 error = tsleep(&com->dtr_wait, PCATCH, "siodtr", 0);
1288 if (com_addr(unit) == NULL) {
1289 crit_exit();
1290 lwkt_reltoken(&tty_token);
1291 return (ENXIO);
1292 }
1293 if (error != 0 || com->gone)
1294 goto out;
1295 }
1296 if (tp->t_state & TS_ISOPEN) {
1297 /*
1298 * The device is open, so everything has been initialized.
1299 * Handle conflicts.
1300 */
1301 if (mynor & CALLOUT_MASK) {
1302 if (!com->active_out) {
1303 error = EBUSY;
1304 goto out;
1305 }
1306 } else {
1307 if (com->active_out) {
1308 if (ap->a_oflags & O_NONBLOCK) {
1309 error = EBUSY;
1310 goto out;
1311 }
1312 error = tsleep(&com->active_out,
1313 PCATCH, "siobi", 0);
1314 if (com_addr(unit) == NULL) {
1315 crit_exit();
1316 lwkt_reltoken(&tty_token);
1317 return (ENXIO);
1318 }
1319 if (error != 0 || com->gone)
1320 goto out;
1321 goto open_top;
1322 }
1323 }
1324 if ((tp->t_state & TS_XCLUDE) &&
1325 caps_priv_check(ap->a_cred, SYSCAP_RESTRICTEDROOT))
1326 {
1327 error = EBUSY;
1328 goto out;
1329 }
1330 } else {
1331 /*
1332 * The device isn't open, so there are no conflicts.
1333 * Initialize it. Initialization is done twice in many
1334 * cases: to preempt sleeping callin opens if we are
1335 * callout, and to complete a callin open after DCD rises.
1336 */
1337 tp->t_oproc = comstart;
1338 tp->t_param = comparam;
1339 tp->t_stop = comstop;
1340 tp->t_dev = dev;
1341 tp->t_termios = mynor & CALLOUT_MASK
1342 ? com->it_out : com->it_in;
1343 (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET);
1344 com->poll = com->no_irq;
1345 com->poll_output = com->loses_outints;
1346 ++com->wopeners;
1347 error = comparam(tp, &tp->t_termios);
1348 --com->wopeners;
1349 if (error != 0)
1350 goto out;
1351 /*
1352 * XXX we should goto open_top if comparam() slept.
1353 */
1354 if (com->hasfifo) {
1355 /*
1356 * (Re)enable and drain fifos.
1357 *
1358 * Certain SMC chips cause problems if the fifos
1359 * are enabled while input is ready. Turn off the
1360 * fifo if necessary to clear the input. We test
1361 * the input ready bit after enabling the fifos
1362 * since we've already enabled them in comparam()
1363 * and to handle races between enabling and fresh
1364 * input.
1365 */
1366 while (TRUE) {
1367 sio_setreg(com, com_fifo,
1368 FIFO_RCV_RST | FIFO_XMT_RST
1369 | com->fifo_image);
1370 /*
1371 * XXX the delays are for superstitious
1372 * historical reasons. It must be less than
1373 * the character time at the maximum
1374 * supported speed (87 usec at 115200 bps
1375 * 8N1). Otherwise we might loop endlessly
1376 * if data is streaming in. We used to use
1377 * delays of 100. That usually worked
1378 * because DELAY(100) used to usually delay
1379 * for about 85 usec instead of 100.
1380 */
1381 DELAY(50);
1382 if (!(inb(com->line_status_port) & LSR_RXRDY))
1383 break;
1384 sio_setreg(com, com_fifo, 0);
1385 DELAY(50);
1386 (void) inb(com->data_port);
1387 }
1388 }
1389
1390 com_lock();
1391 (void) inb(com->line_status_port);
1392 (void) inb(com->data_port);
1393 com->prev_modem_status = com->last_modem_status
1394 = inb(com->modem_status_port);
1395 if (COM_IIR_TXRDYBUG(com->flags)) {
1396 outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
1397 | IER_EMSC);
1398 } else {
1399 outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
1400 | IER_ERLS | IER_EMSC);
1401 }
1402 com_unlock();
1403 /*
1404 * Handle initial DCD. Callout devices get a fake initial
1405 * DCD (trapdoor DCD). If we are callout, then any sleeping
1406 * callin opens get woken up and resume sleeping on "siobi"
1407 * instead of "siodcd".
1408 */
1409 /*
1410 * XXX `mynor & CALLOUT_MASK' should be
1411 * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where
1412 * TRAPDOOR_CARRIER is the default initial state for callout
1413 * devices and SOFT_CARRIER is like CLOCAL except it hides
1414 * the true carrier.
1415 */
1416 if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK)
1417 (*linesw[tp->t_line].l_modem)(tp, 1);
1418 }
1419 /*
1420 * Wait for DCD if necessary.
1421 */
1422 if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK)
1423 && !(tp->t_cflag & CLOCAL) && !(ap->a_oflags & O_NONBLOCK)) {
1424 ++com->wopeners;
1425 error = tsleep(TSA_CARR_ON(tp), PCATCH, "siodcd", 0);
1426 if (com_addr(unit) == NULL) {
1427 crit_exit();
1428 lwkt_reltoken(&tty_token);
1429 return (ENXIO);
1430 }
1431 --com->wopeners;
1432 if (error != 0 || com->gone)
1433 goto out;
1434 goto open_top;
1435 }
1436 error = (*linesw[tp->t_line].l_open)(dev, tp);
1437 disc_optim(tp, &tp->t_termios, com);
1438 if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK)
1439 com->active_out = TRUE;
1440 siosettimeout();
1441 out:
1442 crit_exit();
1443 if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0)
1444 comhardclose(com);
1445 lwkt_reltoken(&tty_token);
1446 return (error);
1447 }
1448
1449 static int
sioclose(struct dev_close_args * ap)1450 sioclose(struct dev_close_args *ap)
1451 {
1452 cdev_t dev = ap->a_head.a_dev;
1453 struct com_s *com;
1454 int mynor;
1455 struct tty *tp;
1456
1457 mynor = minor(dev);
1458 if (mynor & CONTROL_MASK)
1459 return (0);
1460 lwkt_gettoken(&tty_token);
1461 com = com_addr(MINOR_TO_UNIT(mynor));
1462 if (com == NULL) {
1463 lwkt_reltoken(&tty_token);
1464 return (ENODEV);
1465 }
1466 tp = com->tp;
1467 crit_enter();
1468 (*linesw[tp->t_line].l_close)(tp, ap->a_fflag);
1469 disc_optim(tp, &tp->t_termios, com);
1470 comstop(tp, FREAD | FWRITE);
1471 comhardclose(com);
1472 ttyclose(tp);
1473 siosettimeout();
1474 crit_exit();
1475 if (com->gone) {
1476 kprintf("sio%d: gone\n", com->unit);
1477 crit_enter();
1478 if (com->ibuf != NULL)
1479 kfree(com->ibuf, M_DEVBUF);
1480 bzero(tp, sizeof *tp);
1481 crit_exit();
1482 }
1483 lwkt_reltoken(&tty_token);
1484 return (0);
1485 }
1486
1487 static void
comhardclose(struct com_s * com)1488 comhardclose(struct com_s *com)
1489 {
1490 struct tty *tp;
1491 crit_enter();
1492 lwkt_gettoken(&tty_token);
1493 com->poll = FALSE;
1494 com->poll_output = FALSE;
1495 com->do_timestamp = FALSE;
1496 com->do_dcd_timestamp = FALSE;
1497 com->pps.ppsparam.mode = 0;
1498 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
1499 tp = com->tp;
1500
1501 #if defined(DDB)
1502 /*
1503 * Leave interrupts enabled and don't clear DTR if this is the
1504 * console. This allows us to detect break-to-debugger events
1505 * while the console device is closed.
1506 */
1507 if (com->unit != comconsole ||
1508 (break_to_debugger == 0 && alt_break_to_debugger == 0))
1509 #endif
1510 {
1511 sio_setreg(com, com_ier, 0);
1512 if (tp->t_cflag & HUPCL
1513 /*
1514 * XXX we will miss any carrier drop between here and the
1515 * next open. Perhaps we should watch DCD even when the
1516 * port is closed; it is not sufficient to check it at
1517 * the next open because it might go up and down while
1518 * we're not watching.
1519 */
1520 || (!com->active_out
1521 && !(com->prev_modem_status & MSR_DCD)
1522 && !(com->it_in.c_cflag & CLOCAL))
1523 || !(tp->t_state & TS_ISOPEN)) {
1524 (void)commctl(com, TIOCM_DTR, DMBIC);
1525 if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) {
1526 callout_reset(&com->dtr_ch, com->dtr_wait,
1527 siodtrwakeup, com);
1528 com->state |= CS_DTR_OFF;
1529 }
1530 }
1531 }
1532 if (com->hasfifo) {
1533 /*
1534 * Disable fifos so that they are off after controlled
1535 * reboots. Some BIOSes fail to detect 16550s when the
1536 * fifos are enabled.
1537 */
1538 sio_setreg(com, com_fifo, 0);
1539 }
1540 com->active_out = FALSE;
1541 wakeup(&com->active_out);
1542 wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */
1543 lwkt_reltoken(&tty_token);
1544 crit_exit();
1545 }
1546
1547 static int
sioread(struct dev_read_args * ap)1548 sioread(struct dev_read_args *ap)
1549 {
1550 cdev_t dev = ap->a_head.a_dev;
1551 int mynor, ret;
1552 struct com_s *com;
1553
1554 lwkt_gettoken(&tty_token);
1555 mynor = minor(dev);
1556 if (mynor & CONTROL_MASK) {
1557 lwkt_reltoken(&tty_token);
1558 return (ENODEV);
1559 }
1560 com = com_addr(MINOR_TO_UNIT(mynor));
1561 if (com == NULL || com->gone) {
1562 lwkt_reltoken(&tty_token);
1563 return (ENODEV);
1564 }
1565 ret = ((*linesw[com->tp->t_line].l_read)(com->tp, ap->a_uio, ap->a_ioflag));
1566 lwkt_reltoken(&tty_token);
1567 return ret;
1568 }
1569
1570 static int
siowrite(struct dev_write_args * ap)1571 siowrite(struct dev_write_args *ap)
1572 {
1573 cdev_t dev = ap->a_head.a_dev;
1574 int mynor;
1575 struct com_s *com;
1576 int unit, ret;
1577
1578 lwkt_gettoken(&tty_token);
1579 mynor = minor(dev);
1580 if (mynor & CONTROL_MASK) {
1581 lwkt_reltoken(&tty_token);
1582 return (ENODEV);
1583 }
1584
1585 unit = MINOR_TO_UNIT(mynor);
1586 com = com_addr(unit);
1587 if (com == NULL || com->gone) {
1588 lwkt_reltoken(&tty_token);
1589 return (ENODEV);
1590 }
1591 /*
1592 * (XXX) We disallow virtual consoles if the physical console is
1593 * a serial port. This is in case there is a display attached that
1594 * is not the console. In that situation we don't need/want the X
1595 * server taking over the console.
1596 */
1597 if (constty != NULL && unit == comconsole)
1598 constty = NULL;
1599 ret = ((*linesw[com->tp->t_line].l_write)(com->tp, ap->a_uio, ap->a_ioflag));
1600 lwkt_reltoken(&tty_token);
1601 return ret;
1602 }
1603
1604 static void
siobusycheck(void * chan)1605 siobusycheck(void *chan)
1606 {
1607 struct com_s *com;
1608
1609 lwkt_gettoken(&tty_token);
1610 com = (struct com_s *)chan;
1611
1612 /*
1613 * Clear TS_BUSY if low-level output is complete.
1614 * spl locking is sufficient because siointr1() does not set CS_BUSY.
1615 * If siointr1() clears CS_BUSY after we look at it, then we'll get
1616 * called again. Reading the line status port outside of siointr1()
1617 * is safe because CS_BUSY is clear so there are no output interrupts
1618 * to lose.
1619 */
1620 crit_enter();
1621 if (com->state & CS_BUSY)
1622 com->extra_state &= ~CSE_BUSYCHECK; /* False alarm. */
1623 else if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
1624 == (LSR_TSRE | LSR_TXRDY)) {
1625 com->tp->t_state &= ~TS_BUSY;
1626 ttwwakeup(com->tp);
1627 com->extra_state &= ~CSE_BUSYCHECK;
1628 } else {
1629 callout_reset(&com->busy_ch, hz / 100, siobusycheck, com);
1630 }
1631 crit_exit();
1632 lwkt_reltoken(&tty_token);
1633 }
1634
1635 static u_int
siodivisor(u_long rclk,speed_t speed)1636 siodivisor(u_long rclk, speed_t speed)
1637 {
1638 long actual_speed;
1639 u_int divisor;
1640 int error;
1641
1642 if (speed == 0 || speed > ((speed_t)-1 - 1) / 8)
1643 return (0);
1644 divisor = (rclk / (8UL * speed) + 1) / 2;
1645 if (divisor == 0 || divisor >= 65536)
1646 return (0);
1647 actual_speed = rclk / (16UL * divisor);
1648
1649 /* 10 times error in percent: */
1650 error = ((actual_speed - (long)speed) * 2000 / (long)speed + 1) / 2;
1651
1652 /* 3.0% maximum error tolerance: */
1653 if (error < -30 || error > 30)
1654 return (0);
1655
1656 return (divisor);
1657 }
1658
1659 static void
siodtrwakeup(void * chan)1660 siodtrwakeup(void *chan)
1661 {
1662 struct com_s *com;
1663
1664 lwkt_gettoken(&tty_token);
1665 com = (struct com_s *)chan;
1666 com->state &= ~CS_DTR_OFF;
1667 wakeup(&com->dtr_wait);
1668 lwkt_reltoken(&tty_token);
1669 }
1670
1671 /*
1672 * NOTE: Normally called with tty_token held but might not be when
1673 * operating as the console.
1674 *
1675 * Must be called with com_lock
1676 */
1677 #define SIOCOPYSIZE 64
1678
1679 static void
sioinput(struct com_s * com)1680 sioinput(struct com_s *com)
1681 {
1682 u_char line_status;
1683 int recv_data;
1684 int incc;
1685 int i;
1686 struct tty *tp;
1687 uint8_t buf[SIOCOPYSIZE];
1688
1689 /*
1690 * Process a block of data queued by siointr1() and shift the buffer
1691 * in order to allow the interrupt to continue to pipeline data as
1692 * we process each block. This is a retrofit of old code, otherwise
1693 * I'd just use a rollover FIFO.
1694 */
1695 tp = com->tp;
1696 again:
1697 if (!(tp->t_state & TS_ISOPEN) || !(tp->t_cflag & CREAD)) {
1698 com->iptr = com->ibuf;
1699 return;
1700 }
1701 incc = com->iptr - com->ibuf;
1702 if (incc > SIOCOPYSIZE) {
1703 bcopy(com->ibuf, buf, SIOCOPYSIZE);
1704 bcopy(com->ibuf + SIOCOPYSIZE, com->ibuf, incc - SIOCOPYSIZE);
1705 com->iptr = com->ibuf + incc - SIOCOPYSIZE;
1706 incc = SIOCOPYSIZE;
1707 } else {
1708 bcopy(com->ibuf, buf, incc);
1709 com->iptr = com->ibuf;
1710 }
1711 line_status = com->iptr[com->ierroff];
1712
1713 /*
1714 * There is now room for another low-level buffer full of input,
1715 * so enable RTS if it is now disabled and there is room in the
1716 * high-level buffer.
1717 */
1718 if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & MCR_RTS) &&
1719 !(tp->t_state & TS_TBLOCK)) {
1720 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
1721 }
1722 com_unlock();
1723
1724 /*
1725 * Process the input block
1726 */
1727 for (i = 0; i < incc; ++i) {
1728 recv_data = buf[i];
1729 if (line_status
1730 & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) {
1731 if (line_status & LSR_BI)
1732 recv_data |= TTY_BI;
1733 if (line_status & LSR_FE)
1734 recv_data |= TTY_FE;
1735 if (line_status & LSR_OE)
1736 recv_data |= TTY_OE;
1737 if (line_status & LSR_PE)
1738 recv_data |= TTY_PE;
1739 }
1740 (*linesw[tp->t_line].l_rint)(recv_data, tp);
1741 line_status = 0;
1742 }
1743 com_lock();
1744
1745 if (com->iptr != com->ibuf)
1746 goto again;
1747 }
1748
1749 static void
siointr(void * arg)1750 siointr(void *arg)
1751 {
1752 lwkt_gettoken(&tty_token);
1753 #ifndef COM_MULTIPORT
1754 com_lock();
1755 siointr1((struct com_s *) arg);
1756 com_unlock();
1757 #else /* COM_MULTIPORT */
1758 bool_t possibly_more_intrs;
1759 int unit;
1760 struct com_s *com;
1761
1762 /*
1763 * Loop until there is no activity on any port. This is necessary
1764 * to get an interrupt edge more than to avoid another interrupt.
1765 * If the IRQ signal is just an OR of the IRQ signals from several
1766 * devices, then the edge from one may be lost because another is
1767 * on.
1768 */
1769 com_lock();
1770 do {
1771 possibly_more_intrs = FALSE;
1772 for (unit = 0; unit < sio_numunits; ++unit) {
1773 com = com_addr(unit);
1774 /*
1775 * XXX com_lock();
1776 * would it work here, or be counter-productive?
1777 */
1778 if (com != NULL
1779 && !com->gone
1780 && (inb(com->int_id_port) & IIR_IMASK)
1781 != IIR_NOPEND) {
1782 siointr1(com);
1783 possibly_more_intrs = TRUE;
1784 }
1785 /* XXX com_unlock(); */
1786 }
1787 } while (possibly_more_intrs);
1788 com_unlock();
1789 #endif /* COM_MULTIPORT */
1790 lwkt_reltoken(&tty_token);
1791 }
1792
1793 /*
1794 * Called with tty_token held and com_lock held.
1795 */
1796 static void
siointr1(struct com_s * com)1797 siointr1(struct com_s *com)
1798 {
1799 u_char line_status;
1800 u_char modem_status;
1801 u_char *ioptr;
1802 u_char recv_data;
1803 u_char int_ctl;
1804 u_char int_ctl_new;
1805 sysclock_t count;
1806
1807 int_ctl = inb(com->intr_ctl_port);
1808 int_ctl_new = int_ctl;
1809
1810 while (!com->gone) {
1811 if (com->pps.ppsparam.mode & PPS_CAPTUREBOTH) {
1812 modem_status = inb(com->modem_status_port);
1813 if ((modem_status ^ com->last_modem_status) & MSR_DCD) {
1814 count = sys_cputimer->count();
1815 pps_event(&com->pps, count,
1816 (modem_status & MSR_DCD) ?
1817 PPS_CAPTUREASSERT : PPS_CAPTURECLEAR);
1818 }
1819 }
1820 line_status = inb(com->line_status_port);
1821
1822 /* input event? (check first to help avoid overruns) */
1823 while (line_status & LSR_RCV_MASK) {
1824 /* break/unnattached error bits or real input? */
1825 if (!(line_status & LSR_RXRDY))
1826 recv_data = 0;
1827 else
1828 recv_data = inb(com->data_port);
1829 #if defined(DDB)
1830 /*
1831 * Solaris implements a new BREAK which is initiated
1832 * by a character sequence CR ~ ^b which is similar
1833 * to a familiar pattern used on Sun servers by the
1834 * Remote Console.
1835 */
1836 #define KEY_CRTLB 2 /* ^B */
1837 #define KEY_CR 13 /* CR '\r' */
1838 #define KEY_TILDE 126 /* ~ */
1839
1840 if (com->unit == comconsole && alt_break_to_debugger) {
1841 static int brk_state1 = 0, brk_state2 = 0;
1842 if (recv_data == KEY_CR) {
1843 brk_state1 = recv_data;
1844 brk_state2 = 0;
1845 } else if (brk_state1 == KEY_CR && (recv_data == KEY_TILDE || recv_data == KEY_CRTLB)) {
1846 if (recv_data == KEY_TILDE)
1847 brk_state2 = recv_data;
1848 else if (brk_state2 == KEY_TILDE && recv_data == KEY_CRTLB) {
1849 com_unlock();
1850 breakpoint();
1851 com_lock();
1852 brk_state1 = brk_state2 = 0;
1853 goto cont;
1854 } else
1855 brk_state2 = 0;
1856 } else
1857 brk_state1 = 0;
1858 }
1859 #endif
1860 if (line_status & (LSR_BI | LSR_FE | LSR_PE)) {
1861 /*
1862 * Don't store BI if IGNBRK or FE/PE if IGNPAR.
1863 * Otherwise, push the work to a higher level
1864 * (to handle PARMRK) if we're bypassing.
1865 * Otherwise, convert BI/FE and PE+INPCK to 0.
1866 *
1867 * This makes bypassing work right in the
1868 * usual "raw" case (IGNBRK set, and IGNPAR
1869 * and INPCK clear).
1870 *
1871 * Note: BI together with FE/PE means just BI.
1872 */
1873 if (line_status & LSR_BI) {
1874 #if defined(DDB)
1875 if (com->unit == comconsole &&
1876 break_to_debugger) {
1877 com_unlock();
1878 breakpoint();
1879 com_lock();
1880 goto cont;
1881 }
1882 #endif
1883 if (com->tp == NULL
1884 || com->tp->t_iflag & IGNBRK)
1885 goto cont;
1886 } else {
1887 if (com->tp == NULL
1888 || com->tp->t_iflag & IGNPAR)
1889 goto cont;
1890 }
1891 if (com->tp->t_state & TS_CAN_BYPASS_L_RINT
1892 && (line_status & (LSR_BI | LSR_FE)
1893 || com->tp->t_iflag & INPCK))
1894 recv_data = 0;
1895 }
1896 ++com->bytes_in;
1897 if (com->hotchar != 0 && recv_data == com->hotchar)
1898 setsofttty();
1899 ioptr = com->iptr;
1900 if (ioptr >= com->ibufend) {
1901 CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW);
1902 } else {
1903 if (com->do_timestamp)
1904 microtime(&com->timestamp);
1905 schedsofttty();
1906 #if 0 /* for testing input latency vs efficiency */
1907 if (com->iptr - com->ibuf == 8)
1908 setsofttty();
1909 #endif
1910 ioptr[0] = recv_data;
1911 ioptr[com->ierroff] = line_status;
1912 com->iptr = ++ioptr;
1913 if (ioptr == com->ihighwater
1914 && com->state & CS_RTS_IFLOW)
1915 outb(com->modem_ctl_port,
1916 com->mcr_image &= ~MCR_RTS);
1917 if (line_status & LSR_OE)
1918 CE_RECORD(com, CE_OVERRUN);
1919 }
1920 cont:
1921 /*
1922 * "& 0x7F" is to avoid the gcc-1.40 generating a slow
1923 * jump from the top of the loop to here
1924 */
1925 line_status = inb(com->line_status_port) & 0x7F;
1926 }
1927
1928 /* modem status change? (always check before doing output) */
1929 modem_status = inb(com->modem_status_port);
1930 if (modem_status != com->last_modem_status) {
1931 if (com->do_dcd_timestamp
1932 && !(com->last_modem_status & MSR_DCD)
1933 && modem_status & MSR_DCD)
1934 microtime(&com->dcd_timestamp);
1935
1936 /*
1937 * Schedule high level to handle DCD changes. Note
1938 * that we don't use the delta bits anywhere. Some
1939 * UARTs mess them up, and it's easy to remember the
1940 * previous bits and calculate the delta.
1941 */
1942 com->last_modem_status = modem_status;
1943 if (!(com->state & CS_CHECKMSR)) {
1944 com->state |= CS_CHECKMSR;
1945 setsofttty();
1946 }
1947
1948 /* handle CTS change immediately for crisp flow ctl */
1949 if (com->state & CS_CTS_OFLOW) {
1950 if (modem_status & MSR_CTS)
1951 com->state |= CS_ODEVREADY;
1952 else
1953 com->state &= ~CS_ODEVREADY;
1954 }
1955 }
1956
1957 /* output queued and everything ready? */
1958 if ((line_status & LSR_TXRDY)
1959 && com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) {
1960 ioptr = com->obufq.l_head;
1961 if (com->tx_fifo_size > 1) {
1962 u_int ocount;
1963
1964 ocount = com->obufq.l_tail - ioptr;
1965 if (ocount > com->tx_fifo_size)
1966 ocount = com->tx_fifo_size;
1967 com->bytes_out += ocount;
1968 do
1969 outb(com->data_port, *ioptr++);
1970 while (--ocount != 0);
1971 } else {
1972 outb(com->data_port, *ioptr++);
1973 ++com->bytes_out;
1974 }
1975 com->obufq.l_head = ioptr;
1976 if (COM_IIR_TXRDYBUG(com->flags)) {
1977 int_ctl_new = int_ctl | IER_ETXRDY;
1978 }
1979 if (ioptr >= com->obufq.l_tail) {
1980 struct lbq *qp;
1981
1982 qp = com->obufq.l_next;
1983 qp->l_queued = FALSE;
1984 qp = qp->l_next;
1985 if (qp != NULL) {
1986 com->obufq.l_head = qp->l_head;
1987 com->obufq.l_tail = qp->l_tail;
1988 com->obufq.l_next = qp;
1989 } else {
1990 /* output just completed */
1991 if (COM_IIR_TXRDYBUG(com->flags)) {
1992 int_ctl_new = int_ctl & ~IER_ETXRDY;
1993 }
1994 com->state &= ~CS_BUSY;
1995 }
1996 if (!(com->state & CS_ODONE)) {
1997 com->state |= CS_ODONE;
1998 setsofttty(); /* handle at high level ASAP */
1999 }
2000 }
2001 if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
2002 outb(com->intr_ctl_port, int_ctl_new);
2003 }
2004 }
2005
2006 /* finished? */
2007 #ifdef COM_MULTIPORT
2008 return;
2009 #else
2010 if (inb(com->int_id_port) & IIR_NOPEND)
2011 return;
2012 #endif
2013 }
2014 }
2015
2016 static int
sioioctl(struct dev_ioctl_args * ap)2017 sioioctl(struct dev_ioctl_args *ap)
2018 {
2019 cdev_t dev = ap->a_head.a_dev;
2020 caddr_t data = ap->a_data;
2021 struct com_s *com;
2022 int error;
2023 int mynor;
2024 struct tty *tp;
2025
2026 lwkt_gettoken(&tty_token);
2027 mynor = minor(dev);
2028
2029 com = com_addr(MINOR_TO_UNIT(mynor));
2030 if (com == NULL || com->gone) {
2031 lwkt_reltoken(&tty_token);
2032 return (ENODEV);
2033 }
2034 if (mynor & CONTROL_MASK) {
2035 struct termios *ct;
2036
2037 switch (mynor & CONTROL_MASK) {
2038 case CONTROL_INIT_STATE:
2039 ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in;
2040 break;
2041 case CONTROL_LOCK_STATE:
2042 ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in;
2043 break;
2044 default:
2045 lwkt_reltoken(&tty_token);
2046 return (ENODEV); /* /dev/nodev */
2047 }
2048 switch (ap->a_cmd) {
2049 case TIOCSETA:
2050 error = caps_priv_check(ap->a_cred,
2051 SYSCAP_RESTRICTEDROOT);
2052 if (error != 0) {
2053 lwkt_reltoken(&tty_token);
2054 return (error);
2055 }
2056 *ct = *(struct termios *)data;
2057 lwkt_reltoken(&tty_token);
2058 return (0);
2059 case TIOCGETA:
2060 *(struct termios *)data = *ct;
2061 lwkt_reltoken(&tty_token);
2062 return (0);
2063 case TIOCGETD:
2064 *(int *)data = TTYDISC;
2065 lwkt_reltoken(&tty_token);
2066 return (0);
2067 case TIOCGWINSZ:
2068 bzero(data, sizeof(struct winsize));
2069 lwkt_reltoken(&tty_token);
2070 return (0);
2071 default:
2072 lwkt_reltoken(&tty_token);
2073 return (ENOTTY);
2074 }
2075 }
2076 tp = com->tp;
2077 if (ap->a_cmd == TIOCSETA || ap->a_cmd == TIOCSETAW ||
2078 ap->a_cmd == TIOCSETAF) {
2079 int cc;
2080 struct termios *dt = (struct termios *)data;
2081 struct termios *lt = mynor & CALLOUT_MASK
2082 ? &com->lt_out : &com->lt_in;
2083
2084 dt->c_iflag = (tp->t_iflag & lt->c_iflag)
2085 | (dt->c_iflag & ~lt->c_iflag);
2086 dt->c_oflag = (tp->t_oflag & lt->c_oflag)
2087 | (dt->c_oflag & ~lt->c_oflag);
2088 dt->c_cflag = (tp->t_cflag & lt->c_cflag)
2089 | (dt->c_cflag & ~lt->c_cflag);
2090 dt->c_lflag = (tp->t_lflag & lt->c_lflag)
2091 | (dt->c_lflag & ~lt->c_lflag);
2092 for (cc = 0; cc < NCCS; ++cc)
2093 if (lt->c_cc[cc] != 0)
2094 dt->c_cc[cc] = tp->t_cc[cc];
2095 if (lt->c_ispeed != 0)
2096 dt->c_ispeed = tp->t_ispeed;
2097 if (lt->c_ospeed != 0)
2098 dt->c_ospeed = tp->t_ospeed;
2099 }
2100 error = (*linesw[tp->t_line].l_ioctl)(tp, ap->a_cmd, data, ap->a_fflag, ap->a_cred);
2101 if (error != ENOIOCTL) {
2102 lwkt_reltoken(&tty_token);
2103 return (error);
2104 }
2105 crit_enter();
2106 error = ttioctl(tp, ap->a_cmd, data, ap->a_fflag);
2107 disc_optim(tp, &tp->t_termios, com);
2108 if (error != ENOIOCTL) {
2109 crit_exit();
2110 lwkt_reltoken(&tty_token);
2111 return (error);
2112 }
2113 switch (ap->a_cmd) {
2114 case TIOCSBRK:
2115 sio_setreg(com, com_cfcr, com->cfcr_image |= CFCR_SBREAK);
2116 break;
2117 case TIOCCBRK:
2118 sio_setreg(com, com_cfcr, com->cfcr_image &= ~CFCR_SBREAK);
2119 break;
2120 case TIOCSDTR:
2121 (void)commctl(com, TIOCM_DTR, DMBIS);
2122 break;
2123 case TIOCCDTR:
2124 (void)commctl(com, TIOCM_DTR, DMBIC);
2125 break;
2126 /*
2127 * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The
2128 * changes get undone on the next call to comparam().
2129 */
2130 case TIOCMSET:
2131 (void)commctl(com, *(int *)data, DMSET);
2132 break;
2133 case TIOCMBIS:
2134 (void)commctl(com, *(int *)data, DMBIS);
2135 break;
2136 case TIOCMBIC:
2137 (void)commctl(com, *(int *)data, DMBIC);
2138 break;
2139 case TIOCMGET:
2140 *(int *)data = commctl(com, 0, DMGET);
2141 break;
2142 case TIOCMSDTRWAIT:
2143 /* must be root since the wait applies to following logins */
2144 error = caps_priv_check(ap->a_cred, SYSCAP_RESTRICTEDROOT);
2145 if (error != 0) {
2146 crit_exit();
2147 lwkt_reltoken(&tty_token);
2148 return (error);
2149 }
2150 com->dtr_wait = *(int *)data * hz / 100;
2151 break;
2152 case TIOCMGDTRWAIT:
2153 *(int *)data = com->dtr_wait * 100 / hz;
2154 break;
2155 case TIOCTIMESTAMP:
2156 com->do_timestamp = TRUE;
2157 *(struct timeval *)data = com->timestamp;
2158 break;
2159 case TIOCDCDTIMESTAMP:
2160 com->do_dcd_timestamp = TRUE;
2161 *(struct timeval *)data = com->dcd_timestamp;
2162 break;
2163 default:
2164 crit_exit();
2165 error = pps_ioctl(ap->a_cmd, data, &com->pps);
2166 if (error == ENODEV)
2167 error = ENOTTY;
2168 lwkt_reltoken(&tty_token);
2169 return (error);
2170 }
2171 crit_exit();
2172 lwkt_reltoken(&tty_token);
2173 return (0);
2174 }
2175
2176 static void
siopoll(void * dummy,void * frame)2177 siopoll(void *dummy, void *frame)
2178 {
2179 int unit;
2180 int any;
2181
2182 lwkt_gettoken(&tty_token);
2183 repeat:
2184 any = 0;
2185 for (unit = 0; unit < sio_numunits; ++unit) {
2186 struct com_s *com;
2187 int incc;
2188 struct tty *tp;
2189
2190 com = com_addr(unit);
2191 if (com == NULL)
2192 continue;
2193 tp = com->tp;
2194 if (tp == NULL || com->gone) {
2195 /*
2196 * Discard any events related to never-opened or
2197 * going-away devices.
2198 */
2199 com_lock();
2200 incc = com->iptr - com->ibuf;
2201 com->iptr = com->ibuf;
2202 if (com->state & CS_CHECKMSR) {
2203 incc += LOTS_OF_EVENTS;
2204 com->state &= ~CS_CHECKMSR;
2205 }
2206 com_unlock();
2207 continue;
2208 }
2209 if (com->iptr != com->ibuf) {
2210 com_lock();
2211 sioinput(com);
2212 com_unlock();
2213 any = 1;
2214 }
2215 if (com->state & CS_CHECKMSR) {
2216 u_char delta_modem_status;
2217
2218 com_lock();
2219 delta_modem_status = com->last_modem_status
2220 ^ com->prev_modem_status;
2221 com->prev_modem_status = com->last_modem_status;
2222 com->state &= ~CS_CHECKMSR;
2223 com_unlock();
2224 if (delta_modem_status)
2225 any = 1;
2226 if (delta_modem_status & MSR_DCD) {
2227 (*linesw[tp->t_line].l_modem)
2228 (tp, com->prev_modem_status & MSR_DCD);
2229 }
2230 }
2231 if (com->state & CS_ODONE) {
2232 com_lock();
2233 com->state &= ~CS_ODONE;
2234 com_unlock();
2235 if (!(com->state & CS_BUSY)
2236 && !(com->extra_state & CSE_BUSYCHECK)) {
2237 callout_reset(&com->busy_ch, hz / 100,
2238 siobusycheck, com);
2239 com->extra_state |= CSE_BUSYCHECK;
2240 }
2241 (*linesw[tp->t_line].l_start)(tp);
2242 }
2243 }
2244 if (any)
2245 goto repeat;
2246 lwkt_reltoken(&tty_token);
2247 }
2248
2249 /*
2250 * Called with tty_token held but no com_lock
2251 */
2252 static int
comparam(struct tty * tp,struct termios * t)2253 comparam(struct tty *tp, struct termios *t)
2254 {
2255 u_int cfcr;
2256 int cflag;
2257 struct com_s *com;
2258 u_int divisor;
2259 u_char dlbh;
2260 u_char dlbl;
2261 int unit;
2262
2263 unit = DEV_TO_UNIT(tp->t_dev);
2264 com = com_addr(unit);
2265 if (com == NULL) {
2266 return (ENODEV);
2267 }
2268
2269 /* do historical conversions */
2270 if (t->c_ispeed == 0)
2271 t->c_ispeed = t->c_ospeed;
2272
2273 /* check requested parameters */
2274 if (t->c_ospeed == 0) {
2275 divisor = 0;
2276 } else {
2277 if (t->c_ispeed != t->c_ospeed)
2278 return (EINVAL);
2279 divisor = siodivisor(com->rclk, t->c_ispeed);
2280 if (divisor == 0)
2281 return (EINVAL);
2282 }
2283
2284 /* parameters are OK, convert them to the com struct and the device */
2285 crit_enter();
2286 if (divisor == 0)
2287 (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
2288 else
2289 (void)commctl(com, TIOCM_DTR, DMBIS);
2290 cflag = t->c_cflag;
2291 switch (cflag & CSIZE) {
2292 case CS5:
2293 cfcr = CFCR_5BITS;
2294 break;
2295 case CS6:
2296 cfcr = CFCR_6BITS;
2297 break;
2298 case CS7:
2299 cfcr = CFCR_7BITS;
2300 break;
2301 default:
2302 cfcr = CFCR_8BITS;
2303 break;
2304 }
2305 if (cflag & PARENB) {
2306 cfcr |= CFCR_PENAB;
2307 if (!(cflag & PARODD))
2308 cfcr |= CFCR_PEVEN;
2309 }
2310 if (cflag & CSTOPB)
2311 cfcr |= CFCR_STOPB;
2312
2313 if (com->hasfifo && divisor != 0) {
2314 /*
2315 * Use a fifo trigger level low enough so that the input
2316 * latency from the fifo is less than about 16 msec and
2317 * the total latency is less than about 30 msec. These
2318 * latencies are reasonable for humans. Serial comms
2319 * protocols shouldn't expect anything better since modem
2320 * latencies are larger.
2321 *
2322 * Interrupts can be held up for long periods of time
2323 * due to inefficiencies in other parts of the kernel,
2324 * certain video cards, etc. Setting the FIFO trigger
2325 * point to MEDH instead of HIGH gives us 694uS of slop
2326 * (8 character times) instead of 173uS (2 character times)
2327 * @ 115200 bps.
2328 */
2329 com->fifo_image = t->c_ospeed <= 4800
2330 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
2331 #ifdef COM_ESP
2332 /*
2333 * The Hayes ESP card needs the fifo DMA mode bit set
2334 * in compatibility mode. If not, it will interrupt
2335 * for each character received.
2336 */
2337 if (com->esp)
2338 com->fifo_image |= FIFO_DMA_MODE;
2339 #endif
2340 sio_setreg(com, com_fifo, com->fifo_image);
2341 }
2342
2343 /*
2344 * This returns with interrupts disabled so that we can complete
2345 * the speed change atomically. Keeping interrupts disabled is
2346 * especially important while com_data is hidden.
2347 */
2348 siocntxwait(com->bsh);
2349 (void) siosetwater(com, t->c_ispeed);
2350
2351 if (divisor != 0) {
2352 sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
2353 /*
2354 * Only set the divisor registers if they would change,
2355 * since on some 16550 incompatibles (UMC8669F), setting
2356 * them while input is arriving them loses sync until
2357 * data stops arriving.
2358 */
2359 dlbl = divisor & 0xFF;
2360 if (sio_getreg(com, com_dlbl) != dlbl)
2361 sio_setreg(com, com_dlbl, dlbl);
2362 dlbh = divisor >> 8;
2363 if (sio_getreg(com, com_dlbh) != dlbh)
2364 sio_setreg(com, com_dlbh, dlbh);
2365 }
2366 sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
2367
2368 if (!(tp->t_state & TS_TTSTOP))
2369 com->state |= CS_TTGO;
2370
2371 if (cflag & CRTS_IFLOW) {
2372 if (com->st16650a) {
2373 sio_setreg(com, com_cfcr, 0xbf);
2374 sio_setreg(com, com_fifo,
2375 sio_getreg(com, com_fifo) | 0x40);
2376 }
2377 com->state |= CS_RTS_IFLOW;
2378 /*
2379 * If CS_RTS_IFLOW just changed from off to on, the change
2380 * needs to be propagated to MCR_RTS. This isn't urgent,
2381 * so do it later by calling comstart() instead of repeating
2382 * a lot of code from comstart() here.
2383 */
2384 } else if (com->state & CS_RTS_IFLOW) {
2385 com->state &= ~CS_RTS_IFLOW;
2386 /*
2387 * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS
2388 * on here, since comstart() won't do it later.
2389 */
2390 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2391 if (com->st16650a) {
2392 sio_setreg(com, com_cfcr, 0xbf);
2393 sio_setreg(com, com_fifo,
2394 sio_getreg(com, com_fifo) & ~0x40);
2395 }
2396 }
2397
2398 /*
2399 * Set up state to handle output flow control.
2400 * XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
2401 * Now has 10+ msec latency, while CTS flow has 50- usec latency.
2402 */
2403 com->state |= CS_ODEVREADY;
2404 com->state &= ~CS_CTS_OFLOW;
2405 if (cflag & CCTS_OFLOW) {
2406 com->state |= CS_CTS_OFLOW;
2407 if (!(com->last_modem_status & MSR_CTS))
2408 com->state &= ~CS_ODEVREADY;
2409 if (com->st16650a) {
2410 sio_setreg(com, com_cfcr, 0xbf);
2411 sio_setreg(com, com_fifo,
2412 sio_getreg(com, com_fifo) | 0x80);
2413 }
2414 } else {
2415 if (com->st16650a) {
2416 sio_setreg(com, com_cfcr, 0xbf);
2417 sio_setreg(com, com_fifo,
2418 sio_getreg(com, com_fifo) & ~0x80);
2419 }
2420 }
2421
2422 sio_setreg(com, com_cfcr, com->cfcr_image);
2423
2424 /* XXX shouldn't call functions while intrs are disabled. */
2425 disc_optim(tp, t, com);
2426 /*
2427 * Recover from fiddling with CS_TTGO. We used to call siointr1()
2428 * unconditionally, but that defeated the careful discarding of
2429 * stale input in sioopen().
2430 */
2431 if (com->state >= (CS_BUSY | CS_TTGO)) {
2432 com_lock();
2433 siointr1(com);
2434 com_unlock();
2435 }
2436 crit_exit();
2437 comstart(tp);
2438 if (com->ibufold != NULL) {
2439 kfree(com->ibufold, M_DEVBUF);
2440 com->ibufold = NULL;
2441 }
2442 return (0);
2443 }
2444
2445 /*
2446 * called with tty_token held
2447 */
2448 static int
siosetwater(struct com_s * com,speed_t speed)2449 siosetwater(struct com_s *com, speed_t speed)
2450 {
2451 int cp4ticks;
2452 u_char *ibuf;
2453 int ibufsize;
2454 struct tty *tp;
2455
2456 /*
2457 * Make the buffer size large enough to handle a softtty interrupt
2458 * latency of about 2 ticks without loss of throughput or data
2459 * (about 3 ticks if input flow control is not used or not honoured,
2460 * but a bit less for CS5-CS7 modes).
2461 */
2462 cp4ticks = speed / 10 / hz * 4;
2463 for (ibufsize = 128; ibufsize < cp4ticks;)
2464 ibufsize <<= 1;
2465 if (ibufsize == com->ibufsize)
2466 return (0);
2467
2468 /*
2469 * Allocate input buffer. The extra factor of 2 in the size is
2470 * to allow for an error byte for each input byte.
2471 */
2472 ibuf = kmalloc(2 * ibufsize, M_DEVBUF, M_WAITOK | M_ZERO);
2473
2474 /* Initialize non-critical variables. */
2475 com->ibufold = com->ibuf;
2476 com->ibufsize = ibufsize;
2477 tp = com->tp;
2478 if (tp != NULL) {
2479 tp->t_ififosize = 2 * ibufsize;
2480 tp->t_ispeedwat = (speed_t)-1;
2481 tp->t_ospeedwat = (speed_t)-1;
2482 }
2483
2484 /*
2485 * Read current input buffer.
2486 */
2487 com_lock();
2488 if (com->iptr != com->ibuf)
2489 sioinput(com);
2490
2491 /*-
2492 * Initialize critical variables, including input buffer watermarks.
2493 * The external device is asked to stop sending when the buffer
2494 * exactly reaches high water, or when the high level requests it.
2495 * The high level is notified immediately (rather than at a later
2496 * clock tick) when this watermark is reached.
2497 * The buffer size is chosen so the watermark should almost never
2498 * be reached.
2499 * The low watermark is invisibly 0 since the buffer is always
2500 * emptied all at once.
2501 */
2502 com->iptr = com->ibuf = ibuf;
2503 com->ibufend = ibuf + ibufsize;
2504 com->ierroff = ibufsize;
2505 com->ihighwater = ibuf + 3 * ibufsize / 4;
2506 com_unlock();
2507 return (0);
2508 }
2509
2510 static void
comstart(struct tty * tp)2511 comstart(struct tty *tp)
2512 {
2513 struct com_s *com;
2514 int unit;
2515
2516 lwkt_gettoken(&tty_token);
2517 unit = DEV_TO_UNIT(tp->t_dev);
2518 com = com_addr(unit);
2519 if (com == NULL) {
2520 lwkt_reltoken(&tty_token);
2521 return;
2522 }
2523 crit_enter();
2524 com_lock();
2525 if (tp->t_state & TS_TTSTOP)
2526 com->state &= ~CS_TTGO;
2527 else
2528 com->state |= CS_TTGO;
2529 if (tp->t_state & TS_TBLOCK) {
2530 if (com->mcr_image & MCR_RTS && com->state & CS_RTS_IFLOW)
2531 outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS);
2532 } else {
2533 if (!(com->mcr_image & MCR_RTS) && com->iptr < com->ihighwater
2534 && com->state & CS_RTS_IFLOW)
2535 outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
2536 }
2537 com_unlock();
2538 if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
2539 ttwwakeup(tp);
2540 crit_exit();
2541 lwkt_reltoken(&tty_token);
2542 return;
2543 }
2544 if (tp->t_outq.c_cc != 0) {
2545 struct lbq *qp;
2546 struct lbq *next;
2547
2548 if (!com->obufs[0].l_queued) {
2549 com->obufs[0].l_tail
2550 = com->obuf1 + clist_qtob(&tp->t_outq, com->obuf1,
2551 sizeof com->obuf1);
2552 com->obufs[0].l_next = NULL;
2553 com->obufs[0].l_queued = TRUE;
2554 com_lock();
2555 if (com->state & CS_BUSY) {
2556 qp = com->obufq.l_next;
2557 while ((next = qp->l_next) != NULL)
2558 qp = next;
2559 qp->l_next = &com->obufs[0];
2560 } else {
2561 com->obufq.l_head = com->obufs[0].l_head;
2562 com->obufq.l_tail = com->obufs[0].l_tail;
2563 com->obufq.l_next = &com->obufs[0];
2564 com->state |= CS_BUSY;
2565 }
2566 com_unlock();
2567 }
2568 if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
2569 com->obufs[1].l_tail
2570 = com->obuf2 + clist_qtob(&tp->t_outq, com->obuf2,
2571 sizeof com->obuf2);
2572 com->obufs[1].l_next = NULL;
2573 com->obufs[1].l_queued = TRUE;
2574 com_lock();
2575 if (com->state & CS_BUSY) {
2576 qp = com->obufq.l_next;
2577 while ((next = qp->l_next) != NULL)
2578 qp = next;
2579 qp->l_next = &com->obufs[1];
2580 } else {
2581 com->obufq.l_head = com->obufs[1].l_head;
2582 com->obufq.l_tail = com->obufs[1].l_tail;
2583 com->obufq.l_next = &com->obufs[1];
2584 com->state |= CS_BUSY;
2585 }
2586 com_unlock();
2587 }
2588 tp->t_state |= TS_BUSY;
2589 }
2590 com_lock();
2591 if (com->state >= (CS_BUSY | CS_TTGO))
2592 siointr1(com); /* fake interrupt to start output */
2593 com_unlock();
2594 ttwwakeup(tp);
2595 crit_exit();
2596 lwkt_reltoken(&tty_token);
2597 }
2598
2599 static void
comstop(struct tty * tp,int rw)2600 comstop(struct tty *tp, int rw)
2601 {
2602 struct com_s *com;
2603
2604 lwkt_gettoken(&tty_token);
2605 com = com_addr(DEV_TO_UNIT(tp->t_dev));
2606 if (com == NULL || com->gone) {
2607 lwkt_reltoken(&tty_token);
2608 return;
2609 }
2610 com_lock();
2611 if (rw & FWRITE) {
2612 if (com->hasfifo)
2613 #ifdef COM_ESP
2614 /* XXX avoid h/w bug. */
2615 if (!com->esp)
2616 #endif
2617 sio_setreg(com, com_fifo,
2618 FIFO_XMT_RST | com->fifo_image);
2619 com->obufs[0].l_queued = FALSE;
2620 com->obufs[1].l_queued = FALSE;
2621 com->state &= ~(CS_ODONE | CS_BUSY);
2622 com->tp->t_state &= ~TS_BUSY;
2623 }
2624 if (rw & FREAD) {
2625 if (com->hasfifo)
2626 #ifdef COM_ESP
2627 /* XXX avoid h/w bug. */
2628 if (!com->esp)
2629 #endif
2630 sio_setreg(com, com_fifo,
2631 FIFO_RCV_RST | com->fifo_image);
2632 com->iptr = com->ibuf;
2633 }
2634 com_unlock();
2635 comstart(tp);
2636 lwkt_reltoken(&tty_token);
2637 }
2638
2639 static int
commctl(struct com_s * com,int bits,int how)2640 commctl(struct com_s *com, int bits, int how)
2641 {
2642 int mcr;
2643 int msr;
2644
2645 lwkt_gettoken(&tty_token);
2646 if (how == DMGET) {
2647 bits = TIOCM_LE; /* XXX - always enabled while open */
2648 mcr = com->mcr_image;
2649 if (mcr & MCR_DTR)
2650 bits |= TIOCM_DTR;
2651 if (mcr & MCR_RTS)
2652 bits |= TIOCM_RTS;
2653 msr = com->prev_modem_status;
2654 if (msr & MSR_CTS)
2655 bits |= TIOCM_CTS;
2656 if (msr & MSR_DCD)
2657 bits |= TIOCM_CD;
2658 if (msr & MSR_DSR)
2659 bits |= TIOCM_DSR;
2660 /*
2661 * XXX - MSR_RI is naturally volatile, and we make MSR_TERI
2662 * more volatile by reading the modem status a lot. Perhaps
2663 * we should latch both bits until the status is read here.
2664 */
2665 if (msr & (MSR_RI | MSR_TERI))
2666 bits |= TIOCM_RI;
2667 lwkt_reltoken(&tty_token);
2668 return (bits);
2669 }
2670 mcr = 0;
2671 if (bits & TIOCM_DTR)
2672 mcr |= MCR_DTR;
2673 if (bits & TIOCM_RTS)
2674 mcr |= MCR_RTS;
2675 if (com->gone) {
2676 lwkt_reltoken(&tty_token);
2677 return(0);
2678 }
2679 com_lock();
2680 switch (how) {
2681 case DMSET:
2682 outb(com->modem_ctl_port,
2683 com->mcr_image = mcr | (com->mcr_image & MCR_IENABLE));
2684 break;
2685 case DMBIS:
2686 outb(com->modem_ctl_port, com->mcr_image |= mcr);
2687 break;
2688 case DMBIC:
2689 outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
2690 break;
2691 }
2692 com_unlock();
2693 lwkt_reltoken(&tty_token);
2694 return (0);
2695 }
2696
2697 /*
2698 * NOTE: Must be called with tty_token held
2699 */
2700 static void
siosettimeout(void)2701 siosettimeout(void)
2702 {
2703 struct com_s *com;
2704 bool_t someopen;
2705 int unit;
2706
2707 ASSERT_LWKT_TOKEN_HELD(&tty_token);
2708 /*
2709 * Set our timeout period to 1 second if no polled devices are open.
2710 * Otherwise set it to max(1/200, 1/hz).
2711 * Enable timeouts iff some device is open.
2712 */
2713 callout_stop(&sio_timeout_handle);
2714 sio_timeout = hz;
2715 someopen = FALSE;
2716 for (unit = 0; unit < sio_numunits; ++unit) {
2717 com = com_addr(unit);
2718 if (com != NULL && com->tp != NULL
2719 && com->tp->t_state & TS_ISOPEN && !com->gone) {
2720 someopen = TRUE;
2721 if (com->poll || com->poll_output) {
2722 sio_timeout = hz > 200 ? hz / 200 : 1;
2723 break;
2724 }
2725 }
2726 }
2727 if (someopen) {
2728 sio_timeouts_until_log = hz / sio_timeout;
2729 callout_reset(&sio_timeout_handle, sio_timeout,
2730 comwakeup, NULL);
2731 } else {
2732 /* Flush error messages, if any. */
2733 sio_timeouts_until_log = 1;
2734 comwakeup(NULL);
2735 callout_stop(&sio_timeout_handle);
2736 }
2737 }
2738
2739 /*
2740 * NOTE: Must be called with tty_token held
2741 */
2742 static void
comwakeup(void * chan)2743 comwakeup(void *chan)
2744 {
2745 struct com_s *com;
2746 int unit;
2747
2748 /*
2749 * Can be called from a callout too so just get the token
2750 */
2751 lwkt_gettoken(&tty_token);
2752 callout_reset(&sio_timeout_handle, sio_timeout, comwakeup, NULL);
2753
2754 /*
2755 * Recover from lost output interrupts.
2756 * Poll any lines that don't use interrupts.
2757 */
2758 for (unit = 0; unit < sio_numunits; ++unit) {
2759 com = com_addr(unit);
2760 if (com != NULL && !com->gone
2761 && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
2762 com_lock();
2763 siointr1(com);
2764 com_unlock();
2765 }
2766 }
2767
2768 /*
2769 * Check for and log errors, but not too often.
2770 */
2771 if (--sio_timeouts_until_log > 0) {
2772 lwkt_reltoken(&tty_token);
2773 return;
2774 }
2775 sio_timeouts_until_log = hz / sio_timeout;
2776 for (unit = 0; unit < sio_numunits; ++unit) {
2777 int errnum;
2778
2779 com = com_addr(unit);
2780 if (com == NULL)
2781 continue;
2782 if (com->gone)
2783 continue;
2784 for (errnum = 0; errnum < CE_NTYPES; ++errnum) {
2785 u_int delta;
2786 u_long total;
2787
2788 com_lock();
2789 delta = com->delta_error_counts[errnum];
2790 com->delta_error_counts[errnum] = 0;
2791 com_unlock();
2792 if (delta == 0)
2793 continue;
2794 total = com->error_counts[errnum] += delta;
2795 log(LOG_ERR, "sio%d: %u more %s%s (total %lu)\n",
2796 unit, delta, error_desc[errnum],
2797 delta == 1 ? "" : "s", total);
2798 }
2799 }
2800 lwkt_reltoken(&tty_token);
2801 }
2802
2803 static void
disc_optim(struct tty * tp,struct termios * t,struct com_s * com)2804 disc_optim(struct tty *tp, struct termios *t, struct com_s *com)
2805 {
2806 lwkt_gettoken(&tty_token);
2807 if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON))
2808 && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK))
2809 && (!(t->c_iflag & PARMRK)
2810 || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))
2811 && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN))
2812 && linesw[tp->t_line].l_rint == ttyinput)
2813 tp->t_state |= TS_CAN_BYPASS_L_RINT;
2814 else
2815 tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
2816 com->hotchar = linesw[tp->t_line].l_hotchar;
2817 lwkt_reltoken(&tty_token);
2818 }
2819
2820 /*
2821 * Following are all routines needed for SIO to act as console
2822 */
2823 #include <sys/cons.h>
2824
2825 struct siocnstate {
2826 u_char dlbl;
2827 u_char dlbh;
2828 u_char ier;
2829 u_char cfcr;
2830 u_char mcr;
2831 };
2832
2833 static speed_t siocngetspeed (Port_t, u_long rclk);
2834 #if 0
2835 static void siocnclose (struct siocnstate *sp, Port_t iobase);
2836 #endif
2837 static void siocnopen (struct siocnstate *sp, Port_t iobase, int speed);
2838
2839 static cn_probe_t siocnprobe;
2840 static cn_init_t siocninit;
2841 static cn_init_fini_t siocninit_fini;
2842 static cn_checkc_t siocncheckc;
2843 static cn_getc_t siocngetc;
2844 static cn_putc_t siocnputc;
2845
2846 #if defined(__i386__) || defined(__x86_64__)
2847 CONS_DRIVER(sio, siocnprobe, siocninit, siocninit_fini,
2848 NULL, siocngetc, siocncheckc, siocnputc, NULL, NULL);
2849 #endif
2850
2851 /* To get the GDB related variables */
2852 #if defined(DDB)
2853 #include <ddb/ddb.h>
2854 #endif
2855
2856 static void
siocntxwait(Port_t iobase)2857 siocntxwait(Port_t iobase)
2858 {
2859 int timo;
2860
2861 /*
2862 * Wait for any pending transmission to finish. Required to avoid
2863 * the UART lockup bug when the speed is changed, and for normal
2864 * transmits.
2865 */
2866 timo = 100000;
2867 while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
2868 != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
2869 ;
2870 }
2871
2872 /*
2873 * Read the serial port specified and try to figure out what speed
2874 * it's currently running at. We're assuming the serial port has
2875 * been initialized and is basicly idle. This routine is only intended
2876 * to be run at system startup.
2877 *
2878 * If the value read from the serial port doesn't make sense, return 0.
2879 */
2880 /*
2881 * NOTE: Must be called with tty_token held
2882 */
2883 static speed_t
siocngetspeed(Port_t iobase,u_long rclk)2884 siocngetspeed(Port_t iobase, u_long rclk)
2885 {
2886 u_int divisor;
2887 u_char dlbh;
2888 u_char dlbl;
2889 u_char cfcr;
2890
2891 cfcr = inb(iobase + com_cfcr);
2892 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
2893
2894 dlbl = inb(iobase + com_dlbl);
2895 dlbh = inb(iobase + com_dlbh);
2896
2897 outb(iobase + com_cfcr, cfcr);
2898
2899 divisor = dlbh << 8 | dlbl;
2900
2901 /* XXX there should be more sanity checking. */
2902 if (divisor == 0)
2903 return (CONSPEED);
2904 return (rclk / (16UL * divisor));
2905 }
2906
2907 static void
siocnopen(struct siocnstate * sp,Port_t iobase,int speed)2908 siocnopen(struct siocnstate *sp, Port_t iobase, int speed)
2909 {
2910 u_int divisor;
2911 u_char dlbh;
2912 u_char dlbl;
2913
2914 /*
2915 * Save all the device control registers except the fifo register
2916 * and set our default ones (cs8 -parenb speed=comdefaultrate).
2917 * We can't save the fifo register since it is read-only.
2918 */
2919 sp->ier = inb(iobase + com_ier);
2920 outb(iobase + com_ier, 0); /* spltty() doesn't stop siointr() */
2921 siocntxwait(iobase);
2922 sp->cfcr = inb(iobase + com_cfcr);
2923 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2924 sp->dlbl = inb(iobase + com_dlbl);
2925 sp->dlbh = inb(iobase + com_dlbh);
2926 /*
2927 * Only set the divisor registers if they would change, since on
2928 * some 16550 incompatibles (Startech), setting them clears the
2929 * data input register. This also reduces the effects of the
2930 * UMC8669F bug.
2931 */
2932 divisor = siodivisor(comdefaultrclk, speed);
2933 dlbl = divisor & 0xFF;
2934 if (sp->dlbl != dlbl)
2935 outb(iobase + com_dlbl, dlbl);
2936 dlbh = divisor >> 8;
2937 if (sp->dlbh != dlbh)
2938 outb(iobase + com_dlbh, dlbh);
2939 outb(iobase + com_cfcr, CFCR_8BITS);
2940 sp->mcr = inb(iobase + com_mcr);
2941 /*
2942 * We don't want interrupts, but must be careful not to "disable"
2943 * them by clearing the MCR_IENABLE bit, since that might cause
2944 * an interrupt by floating the IRQ line.
2945 */
2946 outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
2947 }
2948
2949 #if 0
2950 static void
2951 siocnclose(struct siocnstate *sp, Port_t iobase)
2952 {
2953 /*
2954 * Restore the device control registers.
2955 */
2956 siocntxwait(iobase);
2957 outb(iobase + com_cfcr, CFCR_DLAB | CFCR_8BITS);
2958 if (sp->dlbl != inb(iobase + com_dlbl))
2959 outb(iobase + com_dlbl, sp->dlbl);
2960 if (sp->dlbh != inb(iobase + com_dlbh))
2961 outb(iobase + com_dlbh, sp->dlbh);
2962 outb(iobase + com_cfcr, sp->cfcr);
2963 /*
2964 * XXX damp oscillations of MCR_DTR and MCR_RTS by not restoring them.
2965 */
2966 outb(iobase + com_mcr, sp->mcr | MCR_DTR | MCR_RTS);
2967 outb(iobase + com_ier, sp->ier);
2968 }
2969 #endif
2970
2971 static void
siocnprobe(struct consdev * cp)2972 siocnprobe(struct consdev *cp)
2973 {
2974 u_char cfcr;
2975 u_int divisor;
2976 int unit;
2977 int fn;
2978 struct siocnstate sp;
2979
2980 /*
2981 * Find our first enabled console, if any. If it is a high-level
2982 * console device, then initialize it and return successfully.
2983 * If it is a low-level console device, then initialize it and
2984 * return unsuccessfully. It must be initialized in both cases
2985 * for early use by console drivers and debuggers. Initializing
2986 * the hardware is not necessary in all cases, since the i/o
2987 * routines initialize it on the fly, but it is necessary if
2988 * input might arrive while the hardware is switched back to an
2989 * uninitialized state. We can't handle multiple console devices
2990 * yet because our low-level routines don't take a device arg.
2991 * We trust the user to set the console flags properly so that we
2992 * don't need to probe.
2993 */
2994 cp->cn_pri = CN_DEAD;
2995
2996 for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
2997 int flags;
2998 int disabled;
2999
3000 if (!resource_int_value("sio", unit, "disabled", &disabled)) {
3001 if (disabled)
3002 continue;
3003 }
3004 if (resource_int_value("sio", unit, "flags", &flags))
3005 continue;
3006 if (COM_CONSOLE(flags) || COM_DEBUGGER(flags)) {
3007 int port;
3008 int baud;
3009 Port_t iobase;
3010 speed_t boot_speed;
3011 struct com_s *com;
3012
3013 /*
3014 * We need the port. For built-in serial ports
3015 * (e.g. sio0/sio1) the resources exist. For
3016 * add-on serial ports they resources might not
3017 * but the port may have been configured late
3018 * and we can find it when we re-probe.
3019 *
3020 * If the port is not specified check to see if
3021 * the device configured after the fact.
3022 */
3023 com = com_addr(unit);
3024 if (resource_int_value("sio", unit, "port", &port)) {
3025 if (com == NULL || com->ioportres == NULL)
3026 continue;
3027 port = rman_get_bushandle(com->ioportres);
3028 }
3029 if (resource_int_value("sio", unit, "baud", &baud) == 0)
3030 boot_speed = baud;
3031 else
3032 boot_speed = 0;
3033 iobase = port;
3034 crit_enter();
3035 if (boothowto & RB_SERIAL) {
3036 if (boot_speed == 0) {
3037 boot_speed = siocngetspeed(iobase,
3038 comdefaultrclk);
3039 }
3040 if (boot_speed)
3041 comdefaultrate = boot_speed;
3042 }
3043 if (boot_speed == 0)
3044 boot_speed = comdefaultrate;
3045
3046 /*
3047 * Initialize the divisor latch. We can't rely on
3048 * siocnopen() to do this the first time, since it
3049 * avoids writing to the latch if the latch appears
3050 * to have the correct value. Also, if we didn't
3051 * just read the speed from the hardware, then we
3052 * need to set the speed in hardware so that
3053 * switching it later is null.
3054 */
3055 com_lock();
3056 cfcr = inb(iobase + com_cfcr);
3057 outb(iobase + com_cfcr, CFCR_DLAB | cfcr);
3058 divisor = siodivisor(comdefaultrclk, boot_speed);
3059 outb(iobase + com_dlbl, divisor & 0xff);
3060 outb(iobase + com_dlbh, divisor >> 8);
3061 outb(iobase + com_cfcr, cfcr);
3062
3063 /*
3064 * Make sure we can drain the receiver. If we can't,
3065 * the serial port may not exist and making it the
3066 * console will implode the kernel.
3067 *
3068 * This is a failsafe, the main sio probe should have
3069 * already forced sioN.disabled to 1 and not reached
3070 * here.
3071 */
3072 for (fn = 0; fn < 256; ++fn) {
3073 if ((inb(iobase + com_lsr) & LSR_RXRDY) == 0)
3074 break;
3075 (void)inb(iobase + com_data);
3076 }
3077 if (fn == 256) {
3078 kprintf("sio%d: does not exist, "
3079 "cannot make console\n", unit);
3080 com_unlock();
3081 crit_exit();
3082 continue;
3083 }
3084
3085 /*
3086 * We want ttyopen
3087 */
3088 if (com) {
3089 com->it_in.c_iflag = TTYDEF_IFLAG;
3090 com->it_in.c_oflag = TTYDEF_OFLAG;
3091 com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL;
3092 com->it_in.c_lflag = TTYDEF_LFLAG;
3093 com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL;
3094 com->lt_out.c_ispeed = com->lt_out.c_ospeed =
3095 com->lt_in.c_ispeed = com->lt_in.c_ospeed =
3096 com->it_in.c_ispeed = com->it_in.c_ospeed =
3097 boot_speed;
3098 }
3099
3100 siocnopen(&sp, iobase, boot_speed);
3101 com_unlock();
3102
3103 crit_exit();
3104 if (COM_CONSOLE(flags) && !COM_LLCONSOLE(flags)) {
3105 cp->cn_probegood = 1;
3106 cp->cn_private = (void *)(intptr_t)unit;
3107 cp->cn_pri = (COM_FORCECONSOLE(flags)
3108 || ((boothowto & RB_SERIAL)) ?
3109 CN_REMOTE : CN_NORMAL);
3110 siocniobase = iobase;
3111 siocnunit = unit;
3112 }
3113 if (COM_DEBUGGER(flags) && gdb_tab == NULL) {
3114 kprintf("sio%d: gdb debugging port\n", unit);
3115 siogdbiobase = iobase;
3116 siogdbunit = unit;
3117 #if defined(DDB)
3118 cp->cn_gdbprivate = (void *)(intptr_t)unit;
3119 gdb_tab = cp;
3120 #endif
3121 }
3122 }
3123 }
3124 #if defined(__i386__) || defined(__x86_64__)
3125 #if defined(DDB)
3126 /*
3127 * XXX Ugly Compatibility.
3128 * If no gdb port has been specified, set it to be the console
3129 * as some configuration files don't specify the gdb port.
3130 */
3131 if (gdb_tab == NULL && (boothowto & RB_GDB)) {
3132 kprintf("Warning: no GDB port specified. Defaulting to sio%d.\n",
3133 siocnunit);
3134 kprintf("Set flag 0x80 on desired GDB port in your\n");
3135 kprintf("configuration file (currently sio only).\n");
3136 siogdbiobase = siocniobase;
3137 siogdbunit = siocnunit;
3138 cp->cn_gdbprivate = (void *)(intptr_t)siocnunit;
3139 gdb_tab = cp;
3140 }
3141 #endif
3142 #endif
3143 }
3144
3145 static void
siocninit(struct consdev * cp)3146 siocninit(struct consdev *cp)
3147 {
3148 comconsole = (int)(intptr_t)cp->cn_private;
3149 }
3150
3151 static void
siocninit_fini(struct consdev * cp)3152 siocninit_fini(struct consdev *cp)
3153 {
3154 cdev_t dev;
3155 char tbuf[MAKEDEV_MINNBUF];
3156 int unit;
3157
3158 if (cp->cn_probegood) {
3159 unit = (int)(intptr_t)cp->cn_private;
3160
3161 /*
3162 * Call devfs_find_device_by_name on ttydX to find the correct
3163 * device, as it should have been created already at this
3164 * point by the attach routine.
3165 *
3166 * If it isn't found, the serial port was not attached at all
3167 * and we shouldn't be here, so assert this case.
3168 */
3169 dev = devfs_find_device_by_name("ttyd%s",
3170 makedev_unit_b32(tbuf, unit));
3171
3172 KKASSERT(dev != NULL);
3173 cp->cn_dev = dev;
3174 }
3175 }
3176
3177 static int
siocncheckc(void * private)3178 siocncheckc(void *private)
3179 {
3180 int c;
3181 int unit = (int)(intptr_t)private;
3182 Port_t iobase;
3183 #if 0
3184 struct siocnstate sp;
3185 #endif
3186
3187 if (unit == siogdbunit)
3188 iobase = siogdbiobase;
3189 else
3190 iobase = siocniobase;
3191 crit_enter();
3192 com_lock();
3193 #if 0
3194 siocnopen(&sp, iobase, comdefaultrate);
3195 #endif
3196 if (inb(iobase + com_lsr) & LSR_RXRDY)
3197 c = inb(iobase + com_data);
3198 else
3199 c = -1;
3200 #if 0
3201 siocnclose(&sp, iobase);
3202 #endif
3203 com_unlock();
3204 crit_exit();
3205
3206 return (c);
3207 }
3208
3209
3210 static int
siocngetc(void * private)3211 siocngetc(void *private)
3212 {
3213 int c;
3214 int unit = (int)(intptr_t)private;
3215 Port_t iobase;
3216 #if 0
3217 struct siocnstate sp;
3218 #endif
3219
3220 if (unit == siogdbunit)
3221 iobase = siogdbiobase;
3222 else
3223 iobase = siocniobase;
3224 crit_enter();
3225 com_lock();
3226 #if 0
3227 siocnopen(&sp, iobase, comdefaultrate);
3228 #endif
3229 while (!(inb(iobase + com_lsr) & LSR_RXRDY))
3230 ;
3231 c = inb(iobase + com_data);
3232 #if 0
3233 siocnclose(&sp, iobase);
3234 #endif
3235 com_unlock();
3236 crit_exit();
3237 return (c);
3238 }
3239
3240 static void
siocnputc(void * private,int c)3241 siocnputc(void *private, int c)
3242 {
3243 int unit = (int)(intptr_t)private;
3244 #if 0
3245 struct siocnstate sp;
3246 #endif
3247 Port_t iobase;
3248
3249 if (unit == siogdbunit)
3250 iobase = siogdbiobase;
3251 else
3252 iobase = siocniobase;
3253 crit_enter();
3254 com_lock();
3255 #if 0
3256 siocnopen(&sp, iobase, comdefaultrate);
3257 #endif
3258 siocntxwait(iobase);
3259 outb(iobase + com_data, c);
3260 #if 0
3261 siocnclose(&sp, iobase);
3262 #endif
3263 com_unlock();
3264 crit_exit();
3265 }
3266
3267 DRIVER_MODULE(sio, isa, sio_isa_driver, sio_devclass, NULL, NULL);
3268 DRIVER_MODULE(sio, acpi, sio_isa_driver, sio_devclass, NULL, NULL);
3269 #if NPCI > 0
3270 DRIVER_MODULE(sio, pci, sio_pci_driver, sio_devclass, NULL, NULL);
3271 #endif
3272 #if NPUC > 0
3273 DRIVER_MODULE(sio, puc, sio_puc_driver, sio_devclass, NULL, NULL);
3274 #endif
3275