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>
