diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2002-09-14 15:00:04 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2002-09-14 15:00:04 +0000 |
commit | ba7f64753be9b6947a6f7ced6881ff8514567111 (patch) | |
tree | f36e6570326246d8aeaa73d422ed1d03aeed0691 /sys/dev/pci | |
parent | e162a1d92ccb99d4d9189430745c97caa313f496 (diff) |
Various fixes and cleanups in the cy driver.
Finally my "Cyclades Cyclom-8Y" works correctly.
Cleanups:
- no more stupid arrays, we have softc structs, use them.
- no more global poll timeout that walks an array, timeouts are now cheap,
one poll per softc.
- sc_dev.dv_xname is the correct thing to print in diagnostic printfs.
- don't have bus-specific code in the generic attach for @#%$! sake, it
took 20 seconds to fix (I suspect that the workaround took much more
time to write).
- spltty, not splhigh.
- use pci_mapreg_map, not pci_{io,mem}_find + bus_space_map.
- use defines, not magic constants in a few places.
- KNF in a few places (much more work needed).
Now the interesting parts:
- when handling the interrupt, don't just ignore it when the tty is not
open. Read and discard the data. If we don't read it, the card will
interrupt again and again and again and ... (inspired by NetBSD).
- actually enable interrupts on PLX9050
- From FreeBSD: "Work around a PLX9050 bug that causes system lockup in
certain systems"
deraadt@ ok
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/cy_pci.c | 136 |
1 files changed, 66 insertions, 70 deletions
diff --git a/sys/dev/pci/cy_pci.c b/sys/dev/pci/cy_pci.c index e1ebbe84975..6e0fcf21ea9 100644 --- a/sys/dev/pci/cy_pci.c +++ b/sys/dev/pci/cy_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cy_pci.c,v 1.9 2002/03/14 01:26:58 millert Exp $ */ +/* $OpenBSD: cy_pci.c,v 1.10 2002/09/14 15:00:03 art Exp $ */ /* * cy_pci.c @@ -25,10 +25,23 @@ int cy_pci_match(struct device *, void *, void *); void cy_pci_attach(struct device *, struct device *, void *); +struct cy_pci_softc { + struct cy_softc sc_cy; /* real softc */ + + bus_space_tag_t sc_iot; /* PLX i/o tag */ + bus_space_handle_t sc_ioh; /* PLX i/o handle */ +}; + struct cfattach cy_pci_ca = { - sizeof(struct cy_softc), cy_pci_match, cy_pci_attach + sizeof(struct cy_pci_softc), cy_pci_match, cy_pci_attach }; +#define CY_PLX_9050_ICS_IENABLE 0x040 +#define CY_PLX_9050_ICS_LOCAL_IENABLE 0x001 +#define CY_PLX_9050_ICS_LOCAL_IPOLARITY 0x002 +#define CY_PLX_9060_ICS_IENABLE 0x100 +#define CY_PLX_9060_ICS_LOCAL_IENABLE 0x800 + int cy_pci_match(parent, match, aux) struct device *parent; @@ -63,93 +76,76 @@ cy_pci_attach(parent, self, aux) struct device *parent, *self; void *aux; { + struct cy_pci_softc *psc = (struct cy_pci_softc *)self; struct cy_softc *sc = (struct cy_softc *)self; struct pci_attach_args *pa = aux; pci_intr_handle_t ih; - bus_space_tag_t memt; - bus_space_handle_t memh; - bus_addr_t memaddr; - bus_size_t memsize; - bus_space_tag_t iot; - bus_space_handle_t ioh; - bus_addr_t iobase; - bus_size_t iosize; + pcireg_t memtype; int plx_ver; - int cacheable; - - memt = pa->pa_memt; - iot = pa->pa_iot; - if (pci_mem_find(pa->pa_pc, pa->pa_tag, 0x18, - &memaddr, &memsize, &cacheable) != 0) { - printf("%s: can't find PCI card memory", - sc->sc_dev.dv_xname); - return; - } + sc->sc_bustype = CY_BUSTYPE_PCI; - /* map the memory (non-cacheable) */ - if (bus_space_map(memt, memaddr, memsize, 0, &memh) != 0) { - printf("%s: couldn't map PCI memory region\n", - sc->sc_dev.dv_xname); - return; - } + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_CYCLADES_CYCLOMY_1: + case PCI_PRODUCT_CYCLADES_CYCLOM4Y_1: + case PCI_PRODUCT_CYCLADES_CYCLOM8Y_1: + memtype = PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT_1M; + break; + case PCI_PRODUCT_CYCLADES_CYCLOMY_2: + case PCI_PRODUCT_CYCLADES_CYCLOM4Y_2: + case PCI_PRODUCT_CYCLADES_CYCLOM8Y_2: + memtype = PCI_MAPREG_TYPE_MEM|PCI_MAPREG_MEM_TYPE_32BIT; + break; + } - /* the PCI Cyclom IO space is only used for enabling interrupts */ - if (pci_io_find(pa->pa_pc, pa->pa_tag, 0x14, &iobase, &iosize) != 0) { - bus_space_unmap(memt, memh, memsize); - printf("%s: couldn't find PCI io region\n", + if (pci_mapreg_map(pa, 0x14, PCI_MAPREG_TYPE_IO, 0, + &psc->sc_iot, &psc->sc_ioh, NULL, NULL, 0) != 0) { + printf("%s: unable to map PLX registers\n", sc->sc_dev.dv_xname); - return; - } + return; + } - if (bus_space_map(iot, iobase, iosize, 0, &ioh) != 0) { - bus_space_unmap(memt, memh, memsize); - printf("%s: couldn't map PCI io region\n", + if (pci_mapreg_map(pa, 0x18, memtype, 0, &sc->sc_memt, + &sc->sc_memh, NULL, NULL, 0) != 0) { + printf("%s: couldn't map device registers\n", sc->sc_dev.dv_xname); return; } -#ifdef CY_DEBUG - printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n", - sc->sc_dev.dv_xname, memaddr, memsize, iobase, iosize); -#endif - - if (cy_probe_common(sc->sc_dev.dv_unit, memt, memh, - CY_BUSTYPE_PCI) == 0) { - bus_space_unmap(memt, memh, memsize); - bus_space_unmap(iot, ioh, iosize); - printf("%s: PCI Cyclom card with no CD1400s!?\n", + if ((sc->sc_nr_cd1400s = cy_probe_common(sc->sc_memt, sc->sc_memh, + CY_BUSTYPE_PCI)) == 0) { + printf("%s: PCI Cyclom card with no CD1400s\n", sc->sc_dev.dv_xname); - return; - } + return; + } - cy_attach(parent, self, aux); - - /* Get PLX version */ - memt = pa->pa_memt; - iot = pa->pa_iot; - plx_ver = bus_space_read_1(memt, memh, CY_PLX_VER) & 0x0f; - - /* Enable PCI card interrupts */ - switch (plx_ver) { - case CY_PLX_9050: - bus_space_write_2(iot, ioh, CY_PCI_INTENA_9050, - bus_space_read_2(iot, ioh, CY_PCI_INTENA_9050) | 0x40); - break; - case CY_PLX_9060: - case CY_PLX_9080: - default: - bus_space_write_2(iot, ioh, CY_PCI_INTENA, - bus_space_read_2(iot, ioh, CY_PCI_INTENA) | 0x900); - } - - /* Enable PCI card interrupts */ if (pci_intr_map(pa, &ih) != 0) panic("%s: couldn't map PCI interrupt", sc->sc_dev.dv_xname); sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cy_intr, sc, sc->sc_dev.dv_xname); + if (sc->sc_ih == NULL) + panic("%s: couldn't establish interrupt", sc->sc_dev.dv_xname); + + cy_attach(parent, self); - if (sc->sc_ih == NULL) - panic("%s: couldn't establish interrupt", sc->sc_dev.dv_xname); + /* Get PLX version */ + plx_ver = bus_space_read_1(sc->sc_memt, sc->sc_memh, CY_PLX_VER) & 0x0f; + + /* Enable PCI card interrupts */ + switch (plx_ver) { + case CY_PLX_9050: + bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA_9050, + CY_PLX_9050_ICS_IENABLE | CY_PLX_9050_ICS_LOCAL_IENABLE | + CY_PLX_9050_ICS_LOCAL_IPOLARITY); + break; + + case CY_PLX_9060: + case CY_PLX_9080: + default: + bus_space_write_2(psc->sc_iot, psc->sc_ioh, CY_PCI_INTENA, + bus_space_read_2(psc->sc_iot, psc->sc_ioh, + CY_PCI_INTENA) | CY_PLX_9060_ICS_IENABLE | + CY_PLX_9060_ICS_LOCAL_IENABLE); + } } |