Date: Tue, 1 Aug 2000 16:26:01 +0400 (MSD) From: vak@cronyx.ru To: FreeBSD-gnats-submit@freebsd.org Subject: kern/20341: [patch] sio driver, support for PCI multiport cards Message-ID: <200008011226.QAA00323@crox.cronyx.ru>
next in thread | raw e-mail | index | archive | help
>Number: 20341
>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 05:40:01 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:
--- siovar40.h Thu Jul 27 11:46:05 2000
+++ isa/siovar.h Fri Jul 28 14:01:20 2000
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/isa/sio.c,v 1.291 2000/03/11 20:22:09 imp Exp $
+ * from: @(#)com.c 7.5 (Berkeley) 5/16/91
+ * from: i386/isa sio.c,v 1.234
+ */
+#define SIO_MAXUNITS 64 /* max sio ports */
+#define CE_NTYPES 3
+
+/* 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];
+};
+
+int sio_attach_unit (struct com_s *com, int unit, Port_t iobase,
+ u_int flags, bool_t no_irq);
+void siointr1 (struct com_s *com);
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
+++ isa/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;
{
--- /dev/null Tue Aug 1 10:55:27 2000
+++ pci/sio_pci.c Tue Aug 1 11:38:12 2000
@@ -0,0 +1,277 @@
+/*
+ * Serial driver for non-intelligent PCI multiport adapters.
+ * Implements the probe, attach and interrupt dispatcher,
+ * and uses sio.c for the most part of work.
+ * The PCI ports get unit numbers _after_ the ISA sio ports.
+ * Option COM_MULTIPORT is not necessary.
+ *
+ * Copyright (C) 2000 Cronyx Engineering Ltd.
+ * Author: Serge Vakulenko <vak@cronyx.ru>
+ *
+ * Supports:
+ * Cronyx Omega-PCI adapter, by Serge Vakulenko <vak@cronyx.ru>
+ *
+ * This software is distributed with NO WARRANTIES, not even the implied
+ * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Authors grant any other persons or organisations permission to use
+ * or modify this software as long as this message is kept with the software,
+ * all derivative works or modified versions.
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/timepps.h>
+#include <sys/tty.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/bus.h>
+#ifndef SMP
+#include <machine/lock.h>
+#endif
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <pci/pcivar.h>
+#if __FreeBSD_version >= 400000
+#include <isa/siovar.h>
+#include <isa/sioreg.h>
+#else
+#include <sys/malloc.h>
+#include <sys/interrupt.h>
+#include <i386/isa/siovar.h>
+#include <i386/isa/sioreg.h>
+#endif
+#include <isa/ic/ns16550.h>
+
+#include "sio.h"
+
+#define MAXCHAN 8
+
+#ifndef __i386__
+#define disable_intr()
+#define enable_intr()
+#endif
+
+#ifdef SMP
+#define disable_intr() COM_DISABLE_INTR()
+#define enable_intr() COM_ENABLE_INTR()
+#endif /* SMP */
+
+typedef struct _sio_pci_t {
+ int nchan;
+ int fifo_size;
+ int base_reg;
+ int hw_rts_cts;
+ Port_t iobase;
+ Port_t iostep;
+ struct resource *res;
+ struct resource *irq;
+ void *intrhand;
+ struct com_s com [MAXCHAN];
+} sio_pci_t;
+
+static void sio_pci_intr __P((void *arg));
+
+static int sio_pci_numunits = NSIO;
+
+#if __FreeBSD_version >= 400000
+/*
+ * FreeBSD version 4.x
+ */
+static int sio_pci_probe __P((device_t));
+static int sio_pci_attach __P((device_t));
+
+static devclass_t siopci_devclass;
+
+static device_method_t sio_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, sio_pci_probe),
+ DEVMETHOD(device_attach, sio_pci_attach),
+ { 0, 0 }
+};
+
+static driver_t sio_pci_driver = {
+ "siopci",
+ sio_pci_methods,
+ sizeof(sio_pci_t)
+};
+DRIVER_MODULE(sio_pci, pci, sio_pci_driver, siopci_devclass, 0, 0);
+
+#else
+/*
+ * FreeBSD version 3.x
+ */
+static const char *sio_pci_probe __P((pcici_t, pcidi_t));
+static void sio_pci_attach __P((pcici_t, int));
+
+static u_long sio_pci_count;
+
+static struct pci_device sio_pci_device = {
+ "siopci",
+ sio_pci_probe,
+ sio_pci_attach,
+ &sio_pci_count,
+ NULL
+};
+DATA_SET(pcidevice_set, sio_pci_device);
+
+#endif /* __FreeBSD_version >= 400000 */
+
+#if __FreeBSD_version >= 400000
+static int
+sio_pci_probe(dev)
+ device_t dev;
+{
+ u_long device_id = pci_get_vendor(dev) | pci_get_device(dev) << 16;
+#else
+static const char *
+sio_pci_probe(config_id, device_id)
+ pcici_t config_id;
+ pcidi_t device_id;
+{
+#endif
+ const char *desc = 0;
+
+ if (device_id == 0xc00110b5)
+ desc = "Cronyx-Omega-PCI Serial Adapter";
+#ifdef notyet
+ /* Add your device here. */
+ else if (device_id == 0xXXXXXXXX)
+ desc = "XXX";
+#endif
+
+#if __FreeBSD_version >= 400000
+ if (! desc)
+ return ENXIO;
+ device_set_desc(dev, desc);
+ return 0;
+#else
+ return desc;
+#endif
+}
+
+#if __FreeBSD_version >= 400000
+static int
+sio_pci_attach(dev)
+ device_t dev;
+{
+ u_long device_id = pci_get_vendor(dev) |
+ pci_get_device(dev) << 16;
+ sio_pci_t *d = device_get_softc(dev);
+ int rid;
+#define PCI_READ_CONFIG(reg) pci_read_config(dev, reg, 4)
+#else
+static void
+sio_pci_attach(config_id, unit)
+ pcici_t config_id;
+ int unit;
+{
+ u_long device_id = config_id->vendor | config_id->device << 16;
+ sio_pci_t *d = malloc(sizeof *d, M_DEVBUF, M_WAITOK);
+#define PCI_READ_CONFIG(reg) pci_conf_read(config_id, reg)
+#endif
+ struct com_s *com;
+ int s, err = 0;
+
+ bzero((char*)d, sizeof(*d));
+ s = splimp();
+
+ /* Default values. */
+ d->nchan = 8; /* channels per adapter */
+ d->iostep = 8; /* addresses per channel */
+ d->base_reg = 0x18; /* pci register: base addr2 */
+
+ /* Device dependent values. */
+ if (device_id == 0xc00110b5) {
+ d->fifo_size = 64; /* fifo size in bytes */
+ d->hw_rts_cts = 1; /* hardware rts/cts support */
+ }
+#ifdef notyet
+ else if (device_id == 0xXXXXXXXX) {
+ /* Add your device here. */
+ }
+#endif
+
+#if __FreeBSD_version >= 400000
+ /* Allocate i/o region. */
+ rid = d->base_reg;
+ d->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
+ RF_ACTIVE);
+ if (! d->res) {
+ printf("sio%d: couldn't map ports/memory\n", sio_pci_numunits);
+ err = ENXIO;
+ goto fail;
+ }
+
+ /* Allocate interrupt. */
+ rid = 0;
+ d->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (! d->irq) {
+ printf("sio%d: couldn't map interrupt\n", sio_pci_numunits);
+ err = ENXIO;
+ goto fail;
+ }
+
+ /* Register the interrupt handler. */
+ err = bus_setup_intr(dev, d->irq, INTR_TYPE_TTY | INTR_TYPE_FAST,
+ sio_pci_intr, d, &d->intrhand);
+#else
+ err = ! pci_map_int_right(config_id, sio_pci_intr, d, &tty_imask,
+ INTR_FAST);
+#endif
+ if (err) {
+ printf("sio%d: couldn't set up irq\n", sio_pci_numunits);
+#if __FreeBSD_version >= 400000
+fail: if (d->res)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ d->base_reg, d->res);
+ if (d->irq)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, d->irq);
+#endif
+ goto done;
+ }
+
+ /* Attach sio ports. */
+ d->iobase = PCI_READ_CONFIG (d->base_reg) & ~3;
+ for (com=d->com; com<d->com+d->nchan; ++com) {
+ com->iobase = d->iobase + (com - d->com) * d->iostep;
+
+ /* Interrupt enable, do it _before_ sio_attach_unit. */
+ outb(com->iobase + com_mcr, MCR_IENABLE);
+
+ if (sio_attach_unit(com, sio_pci_numunits++, com->iobase,
+ d->fifo_size << 24, 0) != 0)
+ printf("sio%d: cannot attach\n", sio_pci_numunits);
+
+ /* Must do this _after_ sio_attach_unit. */
+ com->st16650a = d->hw_rts_cts;
+ }
+done:
+ splx (s);
+#if __FreeBSD_version >= 400000
+ return err;
+#endif
+}
+
+static void
+sio_pci_intr(arg)
+ void *arg;
+{
+ sio_pci_t *d = arg;
+ struct com_s *com;
+ bool_t possibly_more_intrs;
+
+ disable_intr();
+ do {
+ possibly_more_intrs = FALSE;
+ for (com=d->com; com<d->com+d->nchan; ++com) {
+ if ((inb(com->int_id_port) & IIR_IMASK) != IIR_NOPEND) {
+ siointr1(com);
+ possibly_more_intrs = TRUE;
+ }
+ }
+ } while (possibly_more_intrs);
+ enable_intr();
+}
--- files40.i386 Fri Jul 28 17:11:26 2000
+++ conf/files.i386 Fri Jul 28 17:12:17 2000
@@ -389,6 +389,7 @@
isa/ppc.c optional ppc
isa/psm.c optional psm
isa/sio.c optional sio
+pci/sio_pci.c optional sio pci
isa/syscons_isa.c optional sc
isa/vga_isa.c optional vga
kern/subr_diskmbr.c standard
>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?200008011226.QAA00323>
