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 --- |