cy_pci.c revision 1.9
1/*	$NetBSD: cy_pci.c,v 1.9 2000/05/29 12:05:41 tsubai 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_match_pci __P((struct device *, struct cfdata *, void *));
28static void cy_attach_pci  __P((struct device *, struct device *, void *));
29static int cy_map_pci __P((struct pci_attach_args *, bus_space_tag_t *,
30    bus_space_handle_t *, bus_size_t  *, bus_space_tag_t *,
31    bus_space_handle_t *, bus_size_t *));
32static void cy_unmap_pci __P((bus_space_tag_t, bus_space_handle_t,
33    bus_size_t, bus_space_tag_t, bus_space_handle_t, bus_size_t));
34
35struct cfattach cy_pci_ca = {
36	sizeof(struct cy_softc), cy_match_pci, cy_attach_pci
37};
38
39static int
40cy_map_pci(pap, iotp, iohp, iosizep, memtp, memhp, memsizep)
41	struct pci_attach_args	*pap;
42	bus_space_tag_t		*iotp, *memtp;
43	bus_space_handle_t	*iohp, *memhp;
44	bus_size_t		*iosizep, *memsizep;
45{
46	int ioh_valid, memh_valid;
47	pcireg_t expected;
48
49	/* Map I/O (if possible). */
50	ioh_valid = (pci_mapreg_map(pap, 0x14, PCI_MAPREG_TYPE_IO, 0,
51	    iotp, iohp, NULL, iosizep) == 0);
52
53	/* Map mem (if possible).  Expected mem type depends on board ID.  */
54	expected = PCI_MAPREG_TYPE_MEM;
55	switch (PCI_PRODUCT(pap->pa_id)) {
56	case PCI_PRODUCT_CYCLADES_CYCLOMY_1:
57	case PCI_PRODUCT_CYCLADES_CYCLOM4Y_1:
58	case PCI_PRODUCT_CYCLADES_CYCLOM8Y_1:
59		expected |= PCI_MAPREG_MEM_TYPE_32BIT_1M;
60		break;
61	default:
62		expected |= PCI_MAPREG_MEM_TYPE_32BIT;
63	}
64	memh_valid = (pci_mapreg_map(pap, 0x18, expected, 0,
65	    memtp, memhp, NULL, memsizep) == 0);
66
67	if (ioh_valid && memh_valid)
68		return (1);
69
70	if (ioh_valid)
71		bus_space_unmap(*iotp, *iohp, *iosizep);
72	if (memh_valid)
73		bus_space_unmap(*memtp, *memhp, *memsizep);
74	return (0);
75}
76
77static void
78cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize)
79	bus_space_tag_t iot, memt;
80	bus_space_handle_t ioh, memh;
81	bus_size_t iosize, memsize;
82
83{
84	bus_space_unmap(iot, ioh, iosize);
85	bus_space_unmap(memt, memh, memsize);
86}
87
88static int
89cy_match_pci(parent, match, aux)
90	struct device	*parent;
91	struct cfdata	*match;
92	void		*aux;
93{
94	struct pci_attach_args *pap = aux;
95	bus_space_tag_t iot, memt;
96	bus_space_handle_t ioh, memh;
97	bus_size_t iosize, memsize;
98
99	if (PCI_VENDOR(pap->pa_id) != PCI_VENDOR_CYCLADES)
100		return 0;
101
102	switch (PCI_PRODUCT(pap->pa_id)) {
103	case PCI_PRODUCT_CYCLADES_CYCLOMY_1:
104	case PCI_PRODUCT_CYCLADES_CYCLOMY_2:
105	case PCI_PRODUCT_CYCLADES_CYCLOM4Y_1:
106	case PCI_PRODUCT_CYCLADES_CYCLOM4Y_2:
107	case PCI_PRODUCT_CYCLADES_CYCLOM8Y_1:
108	case PCI_PRODUCT_CYCLADES_CYCLOM8Y_2:
109		break;
110	default:
111		return 0;
112	}
113
114#ifdef CY_DEBUG
115	printf("cy: Found Cyclades PCI device, id = 0x%x\n", pap->pa_id);
116#endif
117
118	if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh, &memsize) == 0)
119		return (0);
120
121#if 0
122	XXX probably should do something like this, but this code is just
123	XXX too broken.
124
125#ifdef CY_DEBUG
126	printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n",
127	    sc.sc_dev.dv_xname, memaddr, memsize, iobase, iosize);
128#endif
129
130	if ((rv = cy_find(&sc)) == 0)
131		printf("%s: PCI Cyclom card with no CD1400s!?\n",
132		    sc.sc_dev.dv_xname);
133#endif /* 0 */
134
135	cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize);
136	return (1);
137}
138
139
140static void
141cy_attach_pci(parent, self, aux)
142	struct device  *parent, *self;
143	void *aux;
144{
145	struct cy_softc *sc = (void *) self;
146	struct pci_attach_args *pap = aux;
147	pci_intr_handle_t intrhandle;
148	bus_space_tag_t iot, memt;
149	bus_space_handle_t ioh, memh;
150	bus_size_t iosize, memsize;
151	const char *intrstr;
152	int plx_ver;
153
154	sc->sc_bustype = CY_BUSTYPE_PCI;
155
156	if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh,
157	    &memsize) == 0) {
158		printf(": unable to map device registers\n");
159		return;
160	}
161
162	sc->sc_memt = memt;
163	sc->sc_bsh = memh;
164
165	if (cy_find(sc) == 0) {
166		printf(": cannot find CD1400s\n");
167		return;
168	}
169
170	/* Set up interrupt handler. */
171	if (pci_intr_map(pap->pa_pc, pap->pa_intrtag, pap->pa_intrpin,
172	    pap->pa_intrline, &intrhandle) != 0) {
173		printf(": couldn't map PCI interrupt\n");
174		return;
175	}
176	intrstr = pci_intr_string(pap->pa_pc, intrhandle);
177	sc->sc_ih = pci_intr_establish(pap->pa_pc, intrhandle, IPL_TTY,
178	    cy_intr, sc);
179	if (sc->sc_ih == NULL) {
180		printf(": couldn't establish interrupt");
181		if (intrstr != NULL)
182			printf(" at %s", intrstr);
183		printf("\n");
184		return;
185	}
186	if (intrstr != NULL)
187		printf(": interrupting at %s\n%s", intrstr, self->dv_xname);
188
189	/* attach the hardware */
190	cy_attach(parent, self, aux);
191
192	plx_ver = bus_space_read_1(memt, memh, CY_PLX_VER) & 0x0f;
193
194	/* Enable PCI card interrupts */
195	switch (plx_ver) {
196	case CY_PLX_9050:
197		bus_space_write_2(iot, ioh, CY_PCI_INTENA_9050,
198		    bus_space_read_2(iot, ioh, CY_PCI_INTENA_9050) | 0x40);
199		break;
200	case CY_PLX_9060:
201	case CY_PLX_9080:
202	default:
203		bus_space_write_2(iot, ioh, CY_PCI_INTENA,
204		    bus_space_read_2(iot, ioh, CY_PCI_INTENA) | 0x900);
205	}
206}
207