diff options
author | Joshua Stein <jcs@cvs.openbsd.org> | 2018-04-15 15:07:26 +0000 |
---|---|---|
committer | Joshua Stein <jcs@cvs.openbsd.org> | 2018-04-15 15:07:26 +0000 |
commit | 7b3722a75dfb4c9076931aac499a2f91133c0d60 (patch) | |
tree | dba91b5ce2fdb93be4fe35b7878228e97f68d46c /sys/dev/pci/puc.c | |
parent | e4d715a9eb7c4dad4d9d80590f18ca457119f220 (diff) |
The Exar XR17V354 has 4 com ports that have a 256-byte FIFO, use a
frequency of 125Mhz, and have a unique sleep register. A custom
interrupt handler is setup in puc for these ports so it can check a
register which reports which ports triggered the interrupt, rather
than having to run comintr for every port every time.
ok mlarkin deraadt
Diffstat (limited to 'sys/dev/pci/puc.c')
-rw-r--r-- | sys/dev/pci/puc.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/sys/dev/pci/puc.c b/sys/dev/pci/puc.c index ff65cafd26a..bbd05098395 100644 --- a/sys/dev/pci/puc.c +++ b/sys/dev/pci/puc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: puc.c,v 1.24 2015/03/14 03:38:49 jsg Exp $ */ +/* $OpenBSD: puc.c,v 1.25 2018/04/15 15:07:25 jcs Exp $ */ /* $NetBSD: puc.c,v 1.3 1999/02/06 06:29:54 cgd Exp $ */ /* @@ -61,6 +61,7 @@ #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> #include <dev/pci/pucvar.h> +#include <dev/pci/pcidevs.h> #include <dev/ic/comreg.h> #include <dev/ic/comvar.h> @@ -78,6 +79,7 @@ int puc_pci_detach(struct device *, int); const char *puc_pci_intr_string(struct puc_attach_args *); void *puc_pci_intr_establish(struct puc_attach_args *, int, int (*)(void *), void *, char *); +int puc_pci_xr17v35x_intr(void *arg); struct cfattach puc_pci_ca = { sizeof(struct puc_pci_softc), puc_pci_match, @@ -125,9 +127,20 @@ puc_pci_intr_establish(struct puc_attach_args *paa, int type, { struct puc_pci_softc *sc = paa->puc; struct puc_softc *psc = &sc->sc_psc; - - psc->sc_ports[paa->port].intrhand = - pci_intr_establish(sc->pc, sc->ih, type, func, arg, name); + + if (psc->sc_xr17v35x) { + psc->sc_ports[paa->port].real_intrhand = func; + psc->sc_ports[paa->port].real_intrhand_arg = arg; + if (paa->port == 0) + psc->sc_ports[paa->port].intrhand = + pci_intr_establish(sc->pc, sc->ih, type, + puc_pci_xr17v35x_intr, sc, name); + return (psc->sc_ports[paa->port].real_intrhand); + } else { + psc->sc_ports[paa->port].intrhand = + pci_intr_establish(sc->pc, sc->ih, type, func, arg, name); + return (psc->sc_ports[paa->port].intrhand); + } return (psc->sc_ports[paa->port].intrhand); } @@ -146,6 +159,10 @@ puc_pci_attach(struct device *parent, struct device *self, void *aux) sc->sc_desc = puc_find_description(PCI_VENDOR(pa->pa_id), PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys)); + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_EXAR && + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_EXAR_XR17V354) + sc->sc_xr17v35x = 1; + puc_print_ports(sc->sc_desc); for (i = 0; i < PUC_NBARS; i++) { @@ -319,7 +336,6 @@ puc_find_description(u_int16_t vend, u_int16_t prod, const char * puc_port_type_name(int type) { - if (PUC_IS_COM(type)) return "com"; if (PUC_IS_LPT(type)) @@ -348,3 +364,22 @@ puc_print_ports(const struct puc_device_description *desc) } printf("\n"); } + +int +puc_pci_xr17v35x_intr(void *arg) +{ + struct puc_pci_softc *sc = arg; + struct puc_softc *psc = &sc->sc_psc; + int ports, i; + + ports = bus_space_read_1(psc->sc_bar_mappings[0].t, + psc->sc_bar_mappings[0].h, UART_EXAR_INT0); + + for (i = 0; i < 8; i++) { + if ((ports & (1 << i)) && psc->sc_ports[i].real_intrhand) + (*(psc->sc_ports[i].real_intrhand))( + psc->sc_ports[i].real_intrhand_arg); + } + + return (1); +} |