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