Deleted Added
full compact
sio.c (85426) sio.c (86909)
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

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 16 unchanged lines hidden (view full) ---

25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $FreeBSD: head/sys/dev/sio/sio.c 85426 2001-10-24 18:30:05Z jlemon $
33 * $FreeBSD: head/sys/dev/sio/sio.c 86909 2001-11-26 07:39:51Z imp $
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * from: i386/isa sio.c,v 1.234
36 */
37
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"

--- 25 unchanged lines hidden (view full) ---

67#include <sys/syslog.h>
68#include <sys/tty.h>
69#include <machine/bus_pio.h>
70#include <machine/bus.h>
71#include <sys/rman.h>
72#include <sys/timetc.h>
73#include <sys/timepps.h>
74
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * from: i386/isa sio.c,v 1.234
36 */
37
38#include "opt_comconsole.h"
39#include "opt_compat.h"
40#include "opt_ddb.h"
41#include "opt_sio.h"

--- 25 unchanged lines hidden (view full) ---

67#include <sys/syslog.h>
68#include <sys/tty.h>
69#include <machine/bus_pio.h>
70#include <machine/bus.h>
71#include <sys/rman.h>
72#include <sys/timetc.h>
73#include <sys/timepps.h>
74
75#include <machine/clock.h>
75#include <isa/isavar.h>
76
76#include <machine/resource.h>
77
78#include <dev/sio/sioreg.h>
79#include <dev/sio/siovar.h>
80
77#include <machine/resource.h>
78
79#include <dev/sio/sioreg.h>
80#include <dev/sio/siovar.h>
81
81#include <isa/isavar.h>
82
83#ifdef COM_ESP
84#include <dev/ic/esp.h>
85#endif
86#include <dev/ic/ns16550.h>
87
88#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
89
90#define CALLOUT_MASK 0x80

--- 15 unchanged lines hidden (view full) ---

106
107#define COM_CONSOLE(flags) ((flags) & 0x10)
108#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
109#define COM_LLCONSOLE(flags) ((flags) & 0x40)
110#define COM_DEBUGGER(flags) ((flags) & 0x80)
111#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
112#define COM_NOFIFO(flags) ((flags) & 0x02)
113#define COM_ST16650A(flags) ((flags) & 0x20000)
82#ifdef COM_ESP
83#include <dev/ic/esp.h>
84#endif
85#include <dev/ic/ns16550.h>
86
87#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */
88
89#define CALLOUT_MASK 0x80

--- 15 unchanged lines hidden (view full) ---

105
106#define COM_CONSOLE(flags) ((flags) & 0x10)
107#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
108#define COM_LLCONSOLE(flags) ((flags) & 0x40)
109#define COM_DEBUGGER(flags) ((flags) & 0x80)
110#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
111#define COM_NOFIFO(flags) ((flags) & 0x02)
112#define COM_ST16650A(flags) ((flags) & 0x20000)
113#define COM_C_NOPROBE (0x40000)
114#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE)
114#define COM_C_IIR_TXRDYBUG (0x80000)
115#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
116#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
117
118#define com_scr 7 /* scratch register for 16450-16550 (R/W) */
119
120#define sio_getreg(com, off) \
121 (bus_space_read_1((com)->bst, (com)->bsh, (off)))

--- 30 unchanged lines hidden (view full) ---

152#define CE_OVERRUN 0
153 "silo overflow",
154#define CE_INTERRUPT_BUF_OVERFLOW 1
155 "interrupt-level buffer overflow",
156#define CE_TTY_BUF_OVERFLOW 2
157 "tty-level buffer overflow",
158};
159
115#define COM_C_IIR_TXRDYBUG (0x80000)
116#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
117#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
118
119#define com_scr 7 /* scratch register for 16450-16550 (R/W) */
120
121#define sio_getreg(com, off) \
122 (bus_space_read_1((com)->bst, (com)->bsh, (off)))

--- 30 unchanged lines hidden (view full) ---

153#define CE_OVERRUN 0
154 "silo overflow",
155#define CE_INTERRUPT_BUF_OVERFLOW 1
156 "interrupt-level buffer overflow",
157#define CE_TTY_BUF_OVERFLOW 2
158 "tty-level buffer overflow",
159};
160
161#define CE_NTYPES 3
160#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
161
162#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum])
163
164/* types. XXX - should be elsewhere */
165typedef u_int Port_t; /* hardware port */
166typedef u_char bool_t; /* boolean */
167
168/* queue of linear buffers */
169struct lbq {
170 u_char *l_head; /* next char to process */
171 u_char *l_tail; /* one past the last char to process */
172 struct lbq *l_next; /* next in queue */
173 bool_t l_queued; /* nonzero if queued */
174};
175
176/* com device structure */
177struct com_s {
178 u_int flags; /* Copy isa device flags */
179 u_char state; /* miscellaneous flag bits */
180 bool_t active_out; /* nonzero if the callout device is open */
181 u_char cfcr_image; /* copy of value written to CFCR */
162#ifdef COM_ESP
182#ifdef COM_ESP
183 bool_t esp; /* is this unit a hayes esp board? */
184#endif
185 u_char extra_state; /* more flag bits, separate for order trick */
186 u_char fifo_image; /* copy of value written to FIFO */
187 bool_t hasfifo; /* nonzero for 16550 UARTs */
188 bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */
189 bool_t loses_outints; /* nonzero if device loses output interrupts */
190 u_char mcr_image; /* copy of value written to MCR */
191#ifdef COM_MULTIPORT
192 bool_t multiport; /* is this unit part of a multiport device? */
193#endif /* COM_MULTIPORT */
194 bool_t no_irq; /* nonzero if irq is not attached */
195 bool_t gone; /* hardware disappeared */
196 bool_t poll; /* nonzero if polling is required */
197 bool_t poll_output; /* nonzero if polling for output is required */
198 int unit; /* unit number */
199 int dtr_wait; /* time to hold DTR down on close (* 1/hz) */
200 u_int tx_fifo_size;
201 u_int wopeners; /* # processes waiting for DCD in open() */
202
203 /*
204 * The high level of the driver never reads status registers directly
205 * because there would be too many side effects to handle conveniently.
206 * Instead, it reads copies of the registers stored here by the
207 * interrupt handler.
208 */
209 u_char last_modem_status; /* last MSR read by intr handler */
210 u_char prev_modem_status; /* last MSR handled by high level */
211
212 u_char hotchar; /* ldisc-specific char to be handled ASAP */
213 u_char *ibuf; /* start of input buffer */
214 u_char *ibufend; /* end of input buffer */
215 u_char *ibufold; /* old input buffer, to be freed */
216 u_char *ihighwater; /* threshold in input buffer */
217 u_char *iptr; /* next free spot in input buffer */
218 int ibufsize; /* size of ibuf (not include error bytes) */
219 int ierroff; /* offset of error bytes in ibuf */
220
221 struct lbq obufq; /* head of queue of output buffers */
222 struct lbq obufs[2]; /* output buffers */
223
224 bus_space_tag_t bst;
225 bus_space_handle_t bsh;
226
227 Port_t data_port; /* i/o ports */
228#ifdef COM_ESP
229 Port_t esp_port;
230#endif
231 Port_t int_id_port;
232 Port_t modem_ctl_port;
233 Port_t line_status_port;
234 Port_t modem_status_port;
235 Port_t intr_ctl_port; /* Ports of IIR register */
236
237 struct tty *tp; /* cross reference */
238
239 /* Initial state. */
240 struct termios it_in; /* should be in struct tty */
241 struct termios it_out;
242
243 /* Lock state. */
244 struct termios lt_in; /* should be in struct tty */
245 struct termios lt_out;
246
247 bool_t do_timestamp;
248 bool_t do_dcd_timestamp;
249 struct timeval timestamp;
250 struct timeval dcd_timestamp;
251 struct pps_state pps;
252
253 u_long bytes_in; /* statistics */
254 u_long bytes_out;
255 u_int delta_error_counts[CE_NTYPES];
256 u_long error_counts[CE_NTYPES];
257
258 struct resource *irqres;
259 struct resource *ioportres;
260 void *cookie;
261 dev_t devs[6];
262
263 /*
264 * Data area for output buffers. Someday we should build the output
265 * buffer queue without copying data.
266 */
267 u_char obuf1[256];
268 u_char obuf2[256];
269};
270
271#ifdef COM_ESP
163static int espattach __P((struct com_s *com, Port_t esp_port));
164#endif
165
166static timeout_t siobusycheck;
167static timeout_t siodtrwakeup;
168static void comhardclose __P((struct com_s *com));
169static void sioinput __P((struct com_s *com));
170static void siointr1 __P((struct com_s *com));

--- 11 unchanged lines hidden (view full) ---

182
183char sio_driver_name[] = "sio";
184static struct mtx sio_lock;
185static int sio_inited;
186
187/* table and macro for fast conversion from a unit number to its com struct */
188devclass_t sio_devclass;
189#define com_addr(unit) ((struct com_s *) \
272static int espattach __P((struct com_s *com, Port_t esp_port));
273#endif
274
275static timeout_t siobusycheck;
276static timeout_t siodtrwakeup;
277static void comhardclose __P((struct com_s *com));
278static void sioinput __P((struct com_s *com));
279static void siointr1 __P((struct com_s *com));

--- 11 unchanged lines hidden (view full) ---

291
292char sio_driver_name[] = "sio";
293static struct mtx sio_lock;
294static int sio_inited;
295
296/* table and macro for fast conversion from a unit number to its com struct */
297devclass_t sio_devclass;
298#define com_addr(unit) ((struct com_s *) \
190 devclass_get_softc(sio_devclass, unit))
299 devclass_get_softc(sio_devclass, unit)) /* XXX */
191
192static d_open_t sioopen;
193static d_close_t sioclose;
194static d_read_t sioread;
195static d_write_t siowrite;
196static d_ioctl_t sioioctl;
197
198#define CDEV_MAJOR 28

--- 54 unchanged lines hidden (view full) ---

253 { 38400, COMBRD(38400) },
254 { 57600, COMBRD(57600) },
255 { 115200, COMBRD(115200) },
256 { -1, -1 }
257};
258
259#ifdef COM_ESP
260/* XXX configure this properly. */
300
301static d_open_t sioopen;
302static d_close_t sioclose;
303static d_read_t sioread;
304static d_write_t siowrite;
305static d_ioctl_t sioioctl;
306
307#define CDEV_MAJOR 28

--- 54 unchanged lines hidden (view full) ---

362 { 38400, COMBRD(38400) },
363 { 57600, COMBRD(57600) },
364 { 115200, COMBRD(115200) },
365 { -1, -1 }
366};
367
368#ifdef COM_ESP
369/* XXX configure this properly. */
370/* XXX quite broken for new-bus. */
261static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
262static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
263#endif
264
265/*
266 * handle sysctl read/write requests for console speed
267 *
268 * In addition to setting comdefaultrate for I/O through /dev/console,

--- 48 unchanged lines hidden (view full) ---

317 splx(s);
318 }
319 return error;
320}
321
322SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
323 0, 0, sysctl_machdep_comdefaultrate, "I", "");
324
371static Port_t likely_com_ports[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, };
372static Port_t likely_esp_ports[] = { 0x140, 0x180, 0x280, 0 };
373#endif
374
375/*
376 * handle sysctl read/write requests for console speed
377 *
378 * In addition to setting comdefaultrate for I/O through /dev/console,

--- 48 unchanged lines hidden (view full) ---

427 splx(s);
428 }
429 return error;
430}
431
432SYSCTL_PROC(_machdep, OID_AUTO, conspeed, CTLTYPE_INT | CTLFLAG_RW,
433 0, 0, sysctl_machdep_comdefaultrate, "I", "");
434
435#define SET_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) | (bit))
436#define CLR_FLAG(dev, bit) device_set_flags(dev, device_get_flags(dev) & ~(bit))
437
438/*
439 * Unload the driver and clear the table.
440 * XXX this is mostly wrong.
441 * XXX TODO:
442 * This is usually called when the card is ejected, but
443 * can be caused by a modunload of a controller driver.
444 * The idea is to reset the driver's view of the device
445 * and ensure that any driver entry points such as
446 * read and write do not hang.
447 */
325int
326siodetach(dev)
327 device_t dev;
328{
329 struct com_s *com;
330 int i;
331
332 com = (struct com_s *) device_get_softc(dev);

--- 15 unchanged lines hidden (view full) ---

348 (*linesw[com->tp->t_line].l_close)(com->tp, 0);
349 com->tp->t_gen++;
350 ttyclose(com->tp);
351 ttwakeup(com->tp);
352 ttwwakeup(com->tp);
353 } else {
354 if (com->ibuf != NULL)
355 free(com->ibuf, M_DEVBUF);
448int
449siodetach(dev)
450 device_t dev;
451{
452 struct com_s *com;
453 int i;
454
455 com = (struct com_s *) device_get_softc(dev);

--- 15 unchanged lines hidden (view full) ---

471 (*linesw[com->tp->t_line].l_close)(com->tp, 0);
472 com->tp->t_gen++;
473 ttyclose(com->tp);
474 ttwakeup(com->tp);
475 ttwwakeup(com->tp);
476 } else {
477 if (com->ibuf != NULL)
478 free(com->ibuf, M_DEVBUF);
479 device_set_softc(dev, NULL);
480 free(com, M_DEVBUF);
356 }
357 return (0);
358}
359
360int
361sioprobe(dev, xrid, noprobe)
362 device_t dev;
363 int xrid;

--- 18 unchanged lines hidden (view full) ---

382 struct resource *port;
383
384 rid = xrid;
385 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
386 0, ~0, IO_COMSIZE, RF_ACTIVE);
387 if (!port)
388 return (ENXIO);
389
481 }
482 return (0);
483}
484
485int
486sioprobe(dev, xrid, noprobe)
487 device_t dev;
488 int xrid;

--- 18 unchanged lines hidden (view full) ---

507 struct resource *port;
508
509 rid = xrid;
510 port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
511 0, ~0, IO_COMSIZE, RF_ACTIVE);
512 if (!port)
513 return (ENXIO);
514
390 com = device_get_softc(dev);
515 com = malloc(sizeof(*com), M_DEVBUF, M_NOWAIT | M_ZERO);
516 if (com == NULL)
517 return (ENOMEM);
518 device_set_softc(dev, com);
391 com->bst = rman_get_bustag(port);
392 com->bsh = rman_get_bushandle(port);
393
394 while (sio_inited != 2)
395 if (atomic_cmpset_int(&sio_inited, 0, 1)) {
396 mtx_init(&sio_lock, sio_driver_name, (comconsole != -1) ?
397 MTX_SPIN | MTX_QUIET : MTX_SPIN);
398 atomic_store_rel_int(&sio_inited, 2);

--- 29 unchanged lines hidden (view full) ---

428 already_init = TRUE;
429 }
430#endif
431
432 if (COM_LLCONSOLE(flags)) {
433 printf("sio%d: reserved for low-level i/o\n",
434 device_get_unit(dev));
435 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
519 com->bst = rman_get_bustag(port);
520 com->bsh = rman_get_bushandle(port);
521
522 while (sio_inited != 2)
523 if (atomic_cmpset_int(&sio_inited, 0, 1)) {
524 mtx_init(&sio_lock, sio_driver_name, (comconsole != -1) ?
525 MTX_SPIN | MTX_QUIET : MTX_SPIN);
526 atomic_store_rel_int(&sio_inited, 2);

--- 29 unchanged lines hidden (view full) ---

556 already_init = TRUE;
557 }
558#endif
559
560 if (COM_LLCONSOLE(flags)) {
561 printf("sio%d: reserved for low-level i/o\n",
562 device_get_unit(dev));
563 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
564 device_set_softc(dev, NULL);
565 free(com, M_DEVBUF);
436 return (ENXIO);
437 }
438
439 /*
440 * If the device is on a multiport card and has an AST/4
441 * compatible interrupt control register, initialize this
442 * register and prepare to leave MCR_IENABLE clear in the mcr.
443 * Otherwise, prepare to set MCR_IENABLE in the mcr.

--- 135 unchanged lines hidden (view full) ---

579 } else {
580 /* OK. this is well-known guys */
581 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
582 }
583 sio_setreg(com, com_ier, 0);
584 sio_setreg(com, com_cfcr, CFCR_8BITS);
585 mtx_unlock_spin(&sio_lock);
586 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
566 return (ENXIO);
567 }
568
569 /*
570 * If the device is on a multiport card and has an AST/4
571 * compatible interrupt control register, initialize this
572 * register and prepare to leave MCR_IENABLE clear in the mcr.
573 * Otherwise, prepare to set MCR_IENABLE in the mcr.

--- 135 unchanged lines hidden (view full) ---

709 } else {
710 /* OK. this is well-known guys */
711 CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
712 }
713 sio_setreg(com, com_ier, 0);
714 sio_setreg(com, com_cfcr, CFCR_8BITS);
715 mtx_unlock_spin(&sio_lock);
716 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
587 return (iobase == siocniobase ? 0 : result);
717 if (iobase == siocniobase)
718 result = 0;
719 if (result != 0) {
720 device_set_softc(dev, NULL);
721 free(com, M_DEVBUF);
722 }
723 return (result);
588 }
589
590 /*
591 * Check that
592 * o the CFCR, IER and MCR in UART hold the values written to them
593 * (the values happen to be all distinct - this is good for
594 * avoiding false positive tests from bus echoes).
595 * o an output interrupt is generated and its vector is correct.

--- 50 unchanged lines hidden (view full) ---

646 for (fn = 0; fn < sizeof failures; ++fn)
647 if (failures[fn])
648 printf(" %d", fn);
649 printf("\n");
650 }
651 break;
652 }
653 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
724 }
725
726 /*
727 * Check that
728 * o the CFCR, IER and MCR in UART hold the values written to them
729 * (the values happen to be all distinct - this is good for
730 * avoiding false positive tests from bus echoes).
731 * o an output interrupt is generated and its vector is correct.

--- 50 unchanged lines hidden (view full) ---

782 for (fn = 0; fn < sizeof failures; ++fn)
783 if (failures[fn])
784 printf(" %d", fn);
785 printf("\n");
786 }
787 break;
788 }
789 bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
654 return (iobase == siocniobase ? 0 : result);
790 if (iobase == siocniobase)
791 result = 0;
792 if (result != 0) {
793 device_set_softc(dev, NULL);
794 free(com, M_DEVBUF);
795 }
796 return (result);
655}
656
657#ifdef COM_ESP
658static int
659espattach(com, esp_port)
660 struct com_s *com;
661 Port_t esp_port;
662{

--- 2340 unchanged lines hidden ---
797}
798
799#ifdef COM_ESP
800static int
801espattach(com, esp_port)
802 struct com_s *com;
803 Port_t esp_port;
804{

--- 2340 unchanged lines hidden ---