FreeBSD Bugzilla – Attachment 10074 Details for
Bug 20341
Support for PCI multiport cards for sio driver
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 15.32 KB, created by
vak
on 2000-08-01 13:40:01 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
vak
Created:
2000-08-01 13:40:01 UTC
Size:
15.32 KB
patch
obsolete
>--- 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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 20341
:
10073
| 10074