cy_pci.c revision 1.8
1/*	$NetBSD: cy_pci.c,v 1.8 1998/06/08 06:55:54 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_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	if (PCI_PRODUCT(pap->pa_id) == PCI_PRODUCT_CYCLADES_CYCLOMY_1)
56		expected |= PCI_MAPREG_MEM_TYPE_32BIT_1M;
57	else
58		expected |= PCI_MAPREG_MEM_TYPE_32BIT;
59	memh_valid = (pci_mapreg_map(pap, 0x18, expected, 0,
60	    memtp, memhp, NULL, memsizep) == 0);
61
62	if (ioh_valid && memh_valid)
63		return (1);
64
65	if (ioh_valid)
66		bus_space_unmap(*iotp, *iohp, *iosizep);
67	if (memh_valid)
68		bus_space_unmap(*memtp, *memhp, *memsizep);
69	return (0);
70}
71
72static void
73cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize)
74	bus_space_tag_t iot, memt;
75	bus_space_handle_t ioh, memh;
76	bus_size_t iosize, memsize;
77
78{
79	bus_space_unmap(iot, ioh, iosize);
80	bus_space_unmap(memt, memh, memsize);
81}
82
83static int
84cy_match_pci(parent, match, aux)
85	struct device	*parent;
86	struct cfdata	*match;
87	void		*aux;
88{
89	struct pci_attach_args *pap = aux;
90	bus_space_tag_t iot, memt;
91	bus_space_handle_t ioh, memh;
92	bus_size_t iosize, memsize;
93
94	if (PCI_VENDOR(pap->pa_id) != PCI_VENDOR_CYCLADES)
95		return 0;
96
97	switch (PCI_PRODUCT(pap->pa_id)) {
98	case PCI_PRODUCT_CYCLADES_CYCLOMY_1:
99		break;
100	case PCI_PRODUCT_CYCLADES_CYCLOMY_2:
101		break;
102	default:
103		return 0;
104	}
105
106#ifdef CY_DEBUG
107	printf("cy: Found Cyclades PCI device, id = 0x%x\n", pap->pa_id);
108#endif
109
110	if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh, &memsize) == 0)
111		return (0);
112
113#if 0
114	XXX probably should do something like this, but this code is just
115	XXX too broken.
116
117#ifdef CY_DEBUG
118	printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n",
119	    sc.sc_dev.dv_xname, memaddr, memsize, iobase, iosize);
120#endif
121
122	if ((rv = cy_find(&sc)) == 0)
123		printf("%s: PCI Cyclom card with no CD1400s!?\n",
124		    sc.sc_dev.dv_xname);
125#endif /* 0 */
126
127	cy_unmap_pci(iot, ioh, iosize, memt, memh, memsize);
128	return (1);
129}
130
131
132static void
133cy_attach_pci(parent, self, aux)
134	struct device  *parent, *self;
135	void *aux;
136{
137	struct cy_softc *sc = (void *) self;
138	struct pci_attach_args *pap = aux;
139	pci_intr_handle_t intrhandle;
140	bus_space_tag_t iot, memt;
141	bus_space_handle_t ioh, memh;
142	bus_size_t iosize, memsize;
143	const char *intrstr;
144
145	sc->sc_bustype = CY_BUSTYPE_PCI;
146
147	if (cy_map_pci(pap, &iot, &ioh, &iosize, &memt, &memh,
148	    &memsize) == 0) {
149		printf(": unable to map device registers\n");
150		return;
151	}
152
153	sc->sc_memt = memt;
154	sc->sc_bsh = memh;
155
156	if (cy_find(sc) == 0) {
157		printf(": cannot find CD1400s\n");
158		return;
159	}
160
161	/* Set up interrupt handler. */
162	if (pci_intr_map(pap->pa_pc, pap->pa_intrtag, pap->pa_intrpin,
163	    pap->pa_intrline, &intrhandle) != 0) {
164		printf(": couldn't map PCI interrupt\n");
165		return;
166	}
167	intrstr = pci_intr_string(pap->pa_pc, intrhandle);
168	sc->sc_ih = pci_intr_establish(pap->pa_pc, intrhandle, IPL_TTY,
169	    cy_intr, sc);
170	if (sc->sc_ih == NULL) {
171		printf(": couldn't establish interrupt");
172		if (intrstr != NULL)
173			printf(" at %s", intrstr);
174		printf("\n");
175		return;
176	}
177	if (intrstr != NULL)
178		printf(": interrupting at %s\n%s", intrstr, self->dv_xname);
179
180	/* attach the hardware */
181	cy_attach(parent, self, aux);
182
183	/* Enable PCI card interrupts */
184	bus_space_write_2(iot, ioh, CY_PCI_INTENA,
185	    bus_space_read_2(iot, ioh, CY_PCI_INTENA) | 0x900);
186}
187