xref: /netbsd-src/sys/dev/pci/cy_pci.c (revision 76dfffe33547c37f8bdd446e3e4ab0f3c16cea4b)
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 
27 static int cy_probe_pci __P((struct device *, void *, void *));
28 static void cy_attach_pci  __P((struct device *, struct device *, void *));
29 static int cy_map_pci __P((struct pci_attach_args *, struct cy_softc *,
30     bus_space_handle_t *, bus_size_t  *, bus_size_t *));
31 static void cy_unmap_pci __P((struct cy_softc *, bus_space_handle_t,
32     bus_size_t, bus_size_t));
33 
34 struct cfattach cy_pci_ca = {
35 	sizeof(struct cy_softc), cy_probe_pci, cy_attach_pci
36 };
37 
38 static int
39 cy_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 
74 unmapio:
75 	bus_space_unmap(sc->sc_iot, *ioh, *iosize);
76 unmapmem:
77 	bus_space_unmap(sc->sc_memt, sc->sc_bsh, *memsize);
78 	return 0;
79 }
80 
81 static void
82 cy_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 
93 static int
94 cy_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 
144 static void
145 cy_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