FreeBSD Bugzilla – Attachment 10199 Details for
Bug 20523
[sio] [patch] 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), 10.78 KB, created by
vak
on 2000-08-10 16:00:01 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
vak
Created:
2000-08-10 16:00:01 UTC
Size:
10.78 KB
patch
obsolete
>--- sio-current.c Wed Jul 5 02:17:45 2000 >+++ sio.c Thu Aug 10 18:17:55 2000 >@@ -288,17 +288,31 @@ > u_char obuf2[256]; > }; > >+#define MAXCHAN 8 /* up to 8 channels per multiport */ >+ >+struct multicom { >+ int nchan; /* channels per adapter */ >+ struct resource *res; >+ struct resource *irq; >+ void *intrhand; >+ struct com_s com [MAXCHAN]; >+}; >+ > #ifdef COM_ESP > static int espattach __P((struct com_s *com, Port_t esp_port)); > #endif > static int sioattach __P((device_t dev, int rid)); > static int sio_isa_attach __P((device_t dev)); >+static int sio_attach_unit __P((struct com_s *com, int unit, Port_t iobase, >+ u_int flags, bool_t no_irq, >+ bus_space_tag_t t, bus_space_handle_t h)); > > static timeout_t siobusycheck; > 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 sio_pci_intr __P((void *arg)); > 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)); >@@ -321,7 +335,6 @@ > > #if NPCI > 0 > static int sio_pci_attach __P((device_t dev)); >-static void sio_pci_kludge_unit __P((device_t dev)); > static int sio_pci_probe __P((device_t dev)); > #endif /* NPCI > 0 */ > >@@ -329,8 +342,9 @@ > > /* 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)) >+#define SIO_MAXUNITS 64 /* up to 64 ports */ >+#define com_addr(unit) (p_com_addr[unit]) >+static struct com_s *p_com_addr[SIO_MAXUNITS]; > > static device_method_t sio_isa_methods[] = { > /* Device interface */ >@@ -373,9 +387,9 @@ > }; > > static driver_t sio_pci_driver = { >- driver_name, >+ "siopci", > sio_pci_methods, >- sizeof(struct com_s), >+ sizeof(struct multicom), > }; > #endif /* NPCI > 0 */ > >@@ -419,6 +433,7 @@ > static struct callout_handle sio_timeout_handle > = CALLOUT_HANDLE_INITIALIZER(&sio_timeout_handle); > static int sio_numunits; >+static int sio_pci_numunits = NSIO; > > static struct speedtab comspeedtab[] = { > { 0, 0 }, >@@ -576,12 +591,17 @@ > struct pci_ids { > u_int32_t type; > const char *desc; >- int rid; >+ int rid; /* pci base address register */ >+ int nchan; /* channels per adapter */ >+ int iostep; /* addresses per channel */ >+ int fifo_size; /* fifo size in bytes */ >+ int hw_rts_cts; /* hardware rts/cts support */ > }; > > static struct pci_ids pci_ids[] = { > { 0x100812b9, "3COM PCI FaxModem", 0x10 }, > { 0x048011c1, "ActionTec 56k FAX PCI Modem", 0x14 }, >+ { 0xc00110b5, "Cronyx Omega-PCI Serial Adapter", 0x18, 8, 8, 64, 1 }, > { 0x00000000, NULL, 0 } > }; > >@@ -591,6 +611,12 @@ > { > u_int32_t type; > struct pci_ids *id; >+ struct multicom *d = device_get_softc(dev); >+ struct com_s *com; >+ Port_t iobase; >+ bus_space_tag_t bst; >+ bus_space_handle_t bsh, bsh_port; >+ int rid, offset, s, err = 0; > > type = pci_get_devid(dev); > id = pci_ids; >@@ -598,37 +624,75 @@ > id++; > if (id->desc == NULL) > return (ENXIO); >- sio_pci_kludge_unit(dev); >- return (sioattach(dev, id->rid)); >-} > >-/* >- * Don't cut and paste this to other drivers. It is a horrible kludge >- * which will fail to work and also be unnecessary in future versions. >- */ >-static void >-sio_pci_kludge_unit(dev) >- device_t dev; >-{ >- devclass_t dc; >- int err; >- int start; >- int unit; >+ bzero((char*)d, sizeof(*d)); >+ s = splimp(); >+ d->nchan = id->nchan > 1 ? id->nchan : 1; >+ >+ /* Allocate i/o region. */ >+ rid = id->rid; >+ 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; >+ } > >- unit = 0; >- start = 0; >- while (resource_int_value("sio", unit, "port", &start) == 0 && >- start > 0) >- unit++; >- if (device_get_unit(dev) < unit) { >- dc = device_get_devclass(dev); >- while (devclass_get_device(dc, unit)) >- unit++; >- device_printf(dev, "moving to sio%d\n", unit); >- err = device_set_unit(dev, unit); /* EVIL DO NOT COPY */ >- if (err) >- device_printf(dev, "error moving device %d\n", err); >+ /* 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); >+ if (err) { >+ printf("sio%d: couldn't set up irq\n", sio_pci_numunits); >+fail: if (d->res) >+ bus_release_resource(dev, SYS_RES_IOPORT, >+ id->rid, d->res); >+ if (d->irq) >+ bus_release_resource(dev, SYS_RES_IRQ, 0, d->irq); >+ goto done; >+ } >+ >+ /* Attach sio ports. */ >+ bst = rman_get_bustag(d->res); >+ bsh = rman_get_bushandle(d->res); >+ iobase = rman_get_start(d->res); >+ offset = 0; >+ for (com=d->com; com<d->com+d->nchan; ++com, offset+=id->iostep) { >+ /* Get a handle for a subregion of an already-mapped >+ * area of bus space. */ >+#if waiting_for_somebody_to_implement_bus_space_subregion >+ if (bus_space_subregion (bst, bsh, offset, 8, &bsh_port) != 0) { >+ printf("sio%d: cannot get bus subregion\n", >+ sio_pci_numunits); >+ continue; > } >+#else >+ bsh_port = bsh + offset; >+#endif >+ /* Interrupt enable, do it _before_ sio_attach_unit. */ >+ outb (iobase + offset + com_mcr, >+ d->nchan > 1 ? MCR_IENABLE : 0); >+ >+ if (sio_attach_unit(com, sio_pci_numunits++, iobase + offset, >+ id->fifo_size << 24, 0, bst, bsh_port) != 0) >+ printf("sio%d: cannot attach\n", sio_pci_numunits); >+ >+ /* Must do this _after_ sio_attach_unit. */ >+ com->st16650a = id->hw_rts_cts; >+ } >+done: >+ splx (s); >+ return err; > } > > static int >@@ -645,7 +709,7 @@ > if (id->desc == NULL) > return (ENXIO); > device_set_desc(dev, id->desc); >- return (sioprobe(dev, id->rid)); >+ return (0); > } > #endif /* NPCI > 0 */ > >@@ -1096,15 +1160,13 @@ > int xrid; > { > struct com_s *com; >-#ifdef COM_ESP >- Port_t *espp; >-#endif > Port_t iobase; > int unit; > u_int flags; > int rid; > struct resource *port; > int ret; >+ int no_irq; > > rid = xrid; > port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, >@@ -1117,6 +1179,66 @@ > 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, unit, iobase, flags, no_irq, >+ rman_get_bustag(port), rman_get_bushandle(port)); >+ >+ 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); >+ if (com->irqres) { >+ ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, >+ INTR_TYPE_TTY | INTR_TYPE_FAST, >+ siointr, com, &com->cookie); >+ if (ret) { >+ ret = BUS_SETUP_INTR(device_get_parent(dev), dev, >+ com->irqres, INTR_TYPE_TTY, >+ siointr, com, &com->cookie); >+ if (ret == 0) >+ device_printf(dev, "unable to activate interrupt in fast mode - using normal mode"); >+ } >+ if (ret) >+ device_printf(dev, "could not activate interrupt\n"); >+ } >+ com->ioportres = port; >+ return 0; >+} >+ >+int >+sio_attach_unit(com, unit, iobase, flags, no_irq, bst, bsh) >+ struct com_s *com; >+ int unit; >+ Port_t iobase; >+ u_int flags; >+ bool_t no_irq; >+ bus_space_tag_t bst; >+ bus_space_handle_t bsh; >+{ >+#ifdef COM_ESP >+ Port_t *espp; >+#endif >+ >+ if (unit >= SIO_MAXUNITS) >+ return ENXIO; > if (unit >= sio_numunits) > sio_numunits = unit + 1; > /* >@@ -1133,13 +1255,12 @@ > */ > bzero(com, sizeof *com); > com->unit = unit; >- com->ioportres = port; >- com->bst = rman_get_bustag(port); >- com->bsh = rman_get_bushandle(port); >+ com->bst = bst; >+ com->bsh = bsh; > 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; >@@ -1175,12 +1296,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(); >@@ -1287,17 +1402,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) >@@ -1306,6 +1415,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; >@@ -1326,24 +1437,6 @@ > com->pps.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; > pps_init(&com->pps); > >- rid = 0; >- com->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, >- RF_ACTIVE); >- if (com->irqres) { >- ret = BUS_SETUP_INTR(device_get_parent(dev), dev, com->irqres, >- INTR_TYPE_TTY | INTR_TYPE_FAST, >- siointr, com, &com->cookie); >- if (ret) { >- ret = BUS_SETUP_INTR(device_get_parent(dev), dev, >- com->irqres, INTR_TYPE_TTY, >- siointr, com, &com->cookie); >- if (ret == 0) >- device_printf(dev, "unable to activate interrupt in fast mode - using normal mode"); >- } >- if (ret) >- device_printf(dev, "could not activate interrupt\n"); >- } >- > return (0); > } > >@@ -1830,6 +1923,27 @@ > } while (possibly_more_intrs); > COM_UNLOCK(); > #endif /* COM_MULTIPORT */ >+} >+ >+static void >+sio_pci_intr(arg) >+ void *arg; >+{ >+ struct multicom *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(); > } > > static void
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 20523
: 10199