Date: Tue, 1 Aug 2000 12:19:22 +0400 (MSD) From: vak@cronyx.ru To: FreeBSD-gnats-submit@freebsd.org Subject: kern/20339: [patch] sio driver, support for PCI multiport cards, part 2/4 Message-ID: <200008010819.MAA01756@hanoi.cronyx.ru>
next in thread | raw e-mail | index | archive | help
>Number: 20339 >Category: kern >Synopsis: Support for PCI multiport cards for sio driver >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Tue Aug 01 01:20:03 PDT 2000 >Closed-Date: >Last-Modified: >Originator: Serge Vakulenko >Release: FreeBSD 4.0-RELEASE i386 >Organization: Cronyx Engineering Ltd. >Environment: FreeBSD 4.0, Cronyx-Omega-PCI serial multiport adapters. >Description: To handle non-intelligent multiport async adapters, the sio driver lacks the PCI detection and attachment routines. Some rearrangment of the sio.c is also required. The patch consists of four parts: 1) sys/isa/siovar.h (new file) 2) sys/isa/sio.c (patch) 3) sys/pci/sio_pci.c (new file) 4) sys/conf/files.i386 (patch) >How-To-Repeat: >Fix: Part 2 of 4. 1) Move the struct com_s definition to separate file siovar.h. 2) Split the sioattach() routine. Leave the isa-dependent part in sioattach(), and build the (public) bus-independent attachment function sio_attach_unit(). 3) Make siointr1 public. --- sio40.c Wed Jul 26 17:32:07 2000 +++ sio.c Fri Jul 28 14:01:54 2000 @@ -82,6 +82,7 @@ #include <machine/resource.h> #include <isa/sioreg.h> +#include <isa/siovar.h> #ifdef COM_ESP #include <isa/ic/esp.h> @@ -167,113 +168,8 @@ "tty-level buffer overflow", }; -#define CE_NTYPES 3 #define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) -/* types. XXX - should be elsewhere */ -typedef u_int Port_t; /* hardware port */ -typedef u_char bool_t; /* boolean */ - -/* queue of linear buffers */ -struct lbq { - u_char *l_head; /* next char to process */ - u_char *l_tail; /* one past the last char to process */ - struct lbq *l_next; /* next in queue */ - bool_t l_queued; /* nonzero if queued */ -}; - -/* com device structure */ -struct com_s { - u_int flags; /* Copy isa device flags */ - u_char state; /* miscellaneous flag bits */ - bool_t active_out; /* nonzero if the callout device is open */ - u_char cfcr_image; /* copy of value written to CFCR */ -#ifdef COM_ESP - bool_t esp; /* is this unit a hayes esp board? */ -#endif - u_char extra_state; /* more flag bits, separate for order trick */ - u_char fifo_image; /* copy of value written to FIFO */ - bool_t hasfifo; /* nonzero for 16550 UARTs */ - bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */ - bool_t loses_outints; /* nonzero if device loses output interrupts */ - u_char mcr_image; /* copy of value written to MCR */ -#ifdef COM_MULTIPORT - bool_t multiport; /* is this unit part of a multiport device? */ -#endif /* COM_MULTIPORT */ - bool_t no_irq; /* nonzero if irq is not attached */ - bool_t gone; /* hardware disappeared */ - bool_t poll; /* nonzero if polling is required */ - bool_t poll_output; /* nonzero if polling for output is required */ - int unit; /* unit number */ - int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ - u_int tx_fifo_size; - u_int wopeners; /* # processes waiting for DCD in open() */ - - /* - * The high level of the driver never reads status registers directly - * because there would be too many side effects to handle conveniently. - * Instead, it reads copies of the registers stored here by the - * interrupt handler. - */ - u_char last_modem_status; /* last MSR read by intr handler */ - u_char prev_modem_status; /* last MSR handled by high level */ - - u_char hotchar; /* ldisc-specific char to be handled ASAP */ - u_char *ibuf; /* start of input buffer */ - u_char *ibufend; /* end of input buffer */ - u_char *ibufold; /* old input buffer, to be freed */ - u_char *ihighwater; /* threshold in input buffer */ - u_char *iptr; /* next free spot in input buffer */ - int ibufsize; /* size of ibuf (not include error bytes) */ - int ierroff; /* offset of error bytes in ibuf */ - - struct lbq obufq; /* head of queue of output buffers */ - struct lbq obufs[2]; /* output buffers */ - - Port_t data_port; /* i/o ports */ -#ifdef COM_ESP - Port_t esp_port; -#endif - Port_t int_id_port; - Port_t iobase; - Port_t modem_ctl_port; - Port_t line_status_port; - Port_t modem_status_port; - Port_t intr_ctl_port; /* Ports of IIR register */ - - struct tty *tp; /* cross reference */ - - /* Initial state. */ - struct termios it_in; /* should be in struct tty */ - struct termios it_out; - - /* Lock state. */ - struct termios lt_in; /* should be in struct tty */ - struct termios lt_out; - - bool_t do_timestamp; - bool_t do_dcd_timestamp; - struct timeval timestamp; - struct timeval dcd_timestamp; - struct pps_state pps; - - u_long bytes_in; /* statistics */ - u_long bytes_out; - u_int delta_error_counts[CE_NTYPES]; - u_long error_counts[CE_NTYPES]; - - struct resource *irqres; - struct resource *ioportres; - void *cookie; - - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ - u_char obuf1[256]; - u_char obuf2[256]; -}; - #ifdef COM_ESP static int espattach __P((struct com_s *com, Port_t esp_port)); #endif @@ -284,7 +180,6 @@ static timeout_t siodtrwakeup; static void comhardclose __P((struct com_s *com)); static void sioinput __P((struct com_s *com)); -static void siointr1 __P((struct com_s *com)); static void siointr __P((void *arg)); static int commctl __P((struct com_s *com, int bits, int how)); static int comparam __P((struct tty *tp, struct termios *t)); @@ -309,8 +204,8 @@ /* table and macro for fast conversion from a unit number to its com struct */ static devclass_t sio_devclass; -#define com_addr(unit) ((struct com_s *) \ - devclass_get_softc(sio_devclass, unit)) +static struct com_s *p_com_addr[SIO_MAXUNITS]; +#define com_addr(unit) (p_com_addr[unit]) static device_method_t sio_isa_methods[] = { /* Device interface */ @@ -969,32 +864,19 @@ return (sioattach(dev)); } -static int -sioattach(dev) - device_t dev; -{ +int +sio_attach_unit(com, unit, iobase, flags, no_irq) struct com_s *com; + int unit; + Port_t iobase; + u_int flags; + bool_t no_irq; +{ #ifdef COM_ESP Port_t *espp; #endif - Port_t iobase; - int unit; - u_int flags; - int rid; - struct resource *port; - int ret; - - rid = 0; - port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0, ~0, IO_COMSIZE, RF_ACTIVE); - if (!port) - return (ENXIO); - - iobase = rman_get_start(port); - unit = device_get_unit(dev); - com = device_get_softc(dev); - flags = device_get_flags(dev); - + if (unit >= SIO_MAXUNITS) + return ENXIO; if (unit >= sio_numunits) sio_numunits = unit + 1; /* @@ -1011,11 +893,10 @@ */ bzero(com, sizeof *com); com->unit = unit; - com->ioportres = port; com->cfcr_image = CFCR_8BITS; com->dtr_wait = 3 * hz; com->loses_outints = COM_LOSESOUTINTS(flags) != 0; - com->no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; + com->no_irq = no_irq; com->tx_fifo_size = 1; com->obufs[0].l_head = com->obuf1; com->obufs[1].l_head = com->obuf2; @@ -1052,12 +933,6 @@ com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED; if (siosetwater(com, com->it_in.c_ispeed) != 0) { enable_intr(); - /* - * Leave i/o resources allocated if this is a `cn'-level - * console, so that other devices can't snarf them. - */ - if (iobase != siocniobase) - bus_release_resource(dev, SYS_RES_IOPORT, rid, port); return (ENOMEM); } enable_intr(); @@ -1164,17 +1039,11 @@ #ifdef COM_MULTIPORT if (COM_ISMULTIPORT(flags)) { - device_t masterdev; - com->multiport = TRUE; printf(" (multiport"); if (unit == COM_MPMASTER(flags)) printf(" master"); printf(")"); - masterdev = devclass_get_device(sio_devclass, - COM_MPMASTER(flags)); - com->no_irq = (masterdev == NULL || bus_get_resource(masterdev, - SYS_RES_IRQ, 0, NULL, NULL) != 0); } #endif /* COM_MULTIPORT */ if (unit == comconsole) @@ -1183,6 +1052,8 @@ printf(" with a bogus IIR_TXRDY register"); printf("\n"); + com_addr(unit) = com; + if (!sio_registered) { register_swi(SWI_TTY, siopoll); sio_registered = TRUE; @@ -1203,6 +1074,50 @@ com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; pps_init(&com->pps); + return (0); +} + +static int +sioattach(dev) + device_t dev; +{ + int rid, ret, no_irq; + struct resource *port; + struct com_s *com; + Port_t iobase; + u_int flags; + + rid = 0; + port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, IO_COMSIZE, RF_ACTIVE); + if (!port) + return (ENXIO); + + iobase = rman_get_start(port); + com = device_get_softc(dev); + flags = device_get_flags(dev); + +#ifdef COM_MULTIPORT + if (COM_ISMULTIPORT(flags)) { + device_t masterdev; + + masterdev = devclass_get_device(sio_devclass, + COM_MPMASTER(flags)); + no_irq = (masterdev == NULL || bus_get_resource(masterdev, + SYS_RES_IRQ, 0, NULL, NULL) != 0); + } else +#endif /* COM_MULTIPORT */ + no_irq = bus_get_resource(dev, SYS_RES_IRQ, 0, NULL, NULL) != 0; + + ret = sio_attach_unit(com, device_get_unit(dev), iobase, flags, no_irq); + if (ret != 0) { + /* Leave i/o resources allocated if this is a `cn'-level + * console, so that other devices can't snarf them. */ + if (iobase != siocniobase) + bus_release_resource(dev, SYS_RES_IOPORT, rid, port); + return ret; + } + rid = 0; com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_ACTIVE); @@ -1220,8 +1135,8 @@ if (ret) device_printf(dev, "could not activate interrupt\n"); } - - return (0); + com->ioportres = port; + return 0; } static int @@ -1713,7 +1628,7 @@ #endif /* COM_MULTIPORT */ } -static void +void siointr1(com) struct com_s *com; { >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200008010819.MAA01756>