cy_pci.c revision 1.4
1/*	$NetBSD: cy_pci.c,v 1.4 1996/10/21 22:56:29 thorpej Exp $	*/
2
3/*
4 * cy_pci.c
5 *
6 * Driver for Cyclades Cyclom-8/16/32 multiport serial cards
7 * (currently not tested with Cyclom-32 cards)
8 *
9 * Timo Rossi, 1996
10 *
11 */
12#include <sys/param.h>
13#include <sys/systm.h>
14#include <sys/device.h>
15
16#include <machine/bus.h>
17#include <machine/intr.h>
18
19#include <dev/pci/pcivar.h>
20#include <dev/pci/pcireg.h>
21#include <dev/pci/pcidevs.h>
22
23#include <dev/ic/cd1400reg.h>
24#include <dev/ic/cyreg.h>
25#include <dev/ic/cyvar.h>
26
27static int cy_probe_pci __P((struct device *, void *, void *));
28static void cy_attach_pci  __P((struct device *, struct device *, void *));
29static int cy_map_pci __P((struct pci_attach_args *, struct cy_softc *,
30    bus_space_handle_t *, bus_size_t  *, bus_size_t *));
31static void cy_unmap_pci __P((struct cy_softc *, bus_space_handle_t,
32    bus_size_t, bus_size_t));
33
34struct cfattach cy_pci_ca = {
35	sizeof(struct cy_softc), cy_probe_pci, cy_attach_pci
36};
37
38static int
39cy_map_pci(pa, sc, ioh, iosize, memsize)
40	struct pci_attach_args *pa;
41	struct cy_softc *sc;
42	bus_space_handle_t *ioh;
43	bus_size_t  *memsize;
44	bus_size_t *iosize;
45{
46	bus_addr_t iobase;
47	bus_addr_t  memaddr;
48	int cacheable;
49
50	if (pci_mem_find(pa->pa_pc, pa->pa_tag, 0x18, &memaddr, memsize,
51	    &cacheable) != 0) {
52		printf("%s: can't find PCI card memory", sc->sc_dev.dv_xname);
53		return 0;
54	}
55	/* map the memory (non-cacheable) */
56	if (bus_space_map(sc->sc_memt, memaddr, *memsize, 0,
57	    &sc->sc_bsh) != 0) {
58		printf("%s: couldn't map PCI memory region\n",
59		    sc->sc_dev.dv_xname);
60		return 0;
61	}
62	/* the PCI Cyclom IO space is only used for enabling interrupts */
63	if (pci_io_find(pa->pa_pc, pa->pa_tag, 0x14, &iobase, iosize) != 0) {
64		printf("%s: couldn't find PCI io region\n",
65		    sc->sc_dev.dv_xname);
66		goto unmapmem;
67	}
68	if (bus_space_map(sc->sc_iot, iobase, *iosize, 0, ioh) != 0) {
69		printf("%s: couldn't map PCI io region\n", sc->sc_dev.dv_xname);
70		goto unmapio;
71	}
72	return 1;
73
74unmapio:
75	bus_space_unmap(sc->sc_iot, *ioh, *iosize);
76unmapmem:
77	bus_space_unmap(sc->sc_memt, sc->sc_bsh, *memsize);
78	return 0;
79}
80
81static void
82cy_unmap_pci(sc, ioh, iosize, memsize)
83	struct cy_softc *sc;
84	bus_space_handle_t ioh;
85	bus_size_t iosize;
86	bus_size_t  memsize;
87
88{
89	bus_space_unmap(sc->sc_iot, ioh, iosize);
90	bus_space_unmap(sc->sc_memt, sc->sc_bsh, memsize);
91}
92
93static int
94cy_probe_pci(parent, match, aux)
95	struct device  *parent;
96	void           *match, *aux;
97{
98	struct pci_attach_args *pa = aux;
99	bus_space_handle_t ioh;
100	bus_size_t  memsize;
101	bus_size_t iosize;
102	int rv = 0;
103	struct cy_softc sc;
104
105	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CYCLADES)
106		return 0;
107
108	switch (PCI_PRODUCT(pa->pa_id)) {
109	case PCI_PRODUCT_CYCLADES_CYCLOMY_1:
110		break;
111	case PCI_PRODUCT_CYCLADES_CYCLOMY_2:
112		break;
113	default:
114		return 0;
115	}
116
117#ifdef CY_DEBUG
118	printf("cy: Found Cyclades PCI device, id = 0x%x\n", pa->pa_id);
119#endif
120	/* XXX THIS IS TOTALLY WRONG! XXX */
121	memcpy(&sc.sc_dev, match, sizeof(struct device));
122
123	sc.sc_iot = pa->pa_iot;
124	sc.sc_memt = pa->pa_memt;
125	sc.sc_bustype = CY_BUSTYPE_PCI;
126
127	if (cy_map_pci(pa, &sc, &ioh, &iosize, &memsize) == 0)
128		return 0;
129
130#ifdef CY_DEBUG
131	printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n",
132	    sc.sc_dev.dv_xname, memaddr, memsize, iobase, iosize);
133#endif
134
135	if ((rv = cy_find(&sc)) == 0)
136		printf("%s: PCI Cyclom card with no CD1400s!?\n",
137		    sc.sc_dev.dv_xname);
138
139	cy_unmap_pci(&sc, ioh, iosize, memsize);
140	return rv;
141}
142
143
144static void
145cy_attach_pci(parent, self, aux)
146	struct device  *parent, *self;
147	void *aux;
148{
149	struct cy_softc *sc = (void *) self;
150	pci_intr_handle_t intrhandle;
151	bus_space_handle_t ioh;
152	bus_size_t  memsize;
153	bus_size_t iosize;
154	struct pci_attach_args *pa = aux;
155
156	sc->sc_iot = pa->pa_iot;
157	sc->sc_memt = pa->pa_memt;
158	sc->sc_bustype = CY_BUSTYPE_PCI;
159
160	if (cy_map_pci(pa, sc, &ioh, &iosize, &memsize) == 0)
161		panic("%s: mapping failed", sc->sc_dev.dv_xname);
162
163	if (cy_find(sc) == 0)
164		panic("%s: Cannot find card", sc->sc_dev.dv_xname);
165
166	cy_attach(parent, self, aux);
167
168	/* Enable PCI card interrupts */
169	bus_space_write_2(sc->sc_iot, ioh, CY_PCI_INTENA,
170	    bus_space_read_2(sc->sc_iot, ioh, CY_PCI_INTENA) | 0x900);
171
172	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
173	    pa->pa_intrline, &intrhandle) != 0)
174		panic("%s: couldn't map PCI interrupt", sc->sc_dev.dv_xname);
175
176
177	sc->sc_ih = pci_intr_establish(pa->pa_pc, intrhandle,
178	    IPL_TTY, cy_intr, sc);
179
180	if (sc->sc_ih == NULL)
181		panic("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
182}
183