xref: /openbsd-src/sys/dev/pci/cy_pci.c (revision 2badd5e3f47d2d4252969cd98d7042b4e701b5ac)
1 /*	$OpenBSD: cy_pci.c,v 1.7 2001/08/20 04:41:39 smart 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 
18 #include <dev/pci/pcivar.h>
19 #include <dev/pci/pcireg.h>
20 #include <dev/pci/pcidevs.h>
21 
22 #include <dev/ic/cd1400reg.h>
23 #include <dev/ic/cyreg.h>
24 
25 int cy_pci_match __P((struct device *, void *, void *));
26 void cy_pci_attach __P((struct device *, struct device *, void *));
27 
28 struct cfattach cy_pci_ca = {
29 	sizeof(struct cy_softc), cy_pci_match, cy_pci_attach
30 };
31 
32 int
33 cy_pci_match(parent, match, aux)
34 	struct device *parent;
35 	void *match, *aux;
36 {
37 	struct pci_attach_args *pa = aux;
38 
39 	if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_CYCLADES)
40 		return (0);
41 
42 	switch (PCI_PRODUCT(pa->pa_id)) {
43 	case PCI_PRODUCT_CYCLADES_CYCLOMY_1:
44 	case PCI_PRODUCT_CYCLADES_CYCLOMY_2:
45 	case PCI_PRODUCT_CYCLADES_CYCLOM4Y_1:
46 	case PCI_PRODUCT_CYCLADES_CYCLOM4Y_2:
47 	case PCI_PRODUCT_CYCLADES_CYCLOM8Y_1:
48 	case PCI_PRODUCT_CYCLADES_CYCLOM8Y_2:
49 		break;
50 	default:
51 		return (0);
52 	}
53 
54 #ifdef CY_DEBUG
55 	printf("cy: Found Cyclades PCI device, id = 0x%x\n", pa->pa_id);
56 #endif
57 
58 	return (1);
59 }
60 
61 void
62 cy_pci_attach(parent, self, aux)
63 	struct device *parent, *self;
64 	void *aux;
65 {
66 	struct cy_softc *sc = (struct cy_softc *)self;
67 	struct pci_attach_args *pa = aux;
68 	pci_intr_handle_t ih;
69 	bus_space_tag_t memt;
70 	bus_space_handle_t memh;
71 	bus_addr_t memaddr;
72 	bus_size_t memsize;
73 	bus_space_tag_t iot;
74 	bus_space_handle_t ioh;
75 	bus_addr_t iobase;
76 	bus_size_t iosize;
77 	int plx_ver;
78 	int cacheable;
79 
80         memt = pa->pa_memt;
81         iot = pa->pa_iot;
82 
83         if (pci_mem_find(pa->pa_pc, pa->pa_tag, 0x18,
84             &memaddr, &memsize, &cacheable) != 0) {
85                 printf("%s: can't find PCI card memory",
86 		    sc->sc_dev.dv_xname);
87                 return;
88         }
89 
90         /* map the memory (non-cacheable) */
91         if (bus_space_map(memt, memaddr, memsize, 0, &memh) != 0) {
92                 printf("%s: couldn't map PCI memory region\n",
93 		    sc->sc_dev.dv_xname);
94                 return;
95         }
96 
97         /* the PCI Cyclom IO space is only used for enabling interrupts */
98         if (pci_io_find(pa->pa_pc, pa->pa_tag, 0x14, &iobase, &iosize) != 0) {
99                 bus_space_unmap(memt, memh, memsize);
100                 printf("%s: couldn't find PCI io region\n",
101 		    sc->sc_dev.dv_xname);
102                 return;
103         }
104 
105         if (bus_space_map(iot, iobase, iosize, 0, &ioh) != 0) {
106                 bus_space_unmap(memt, memh, memsize);
107                 printf("%s: couldn't map PCI io region\n",
108 		    sc->sc_dev.dv_xname);
109                 return;
110         }
111 
112 #ifdef CY_DEBUG
113         printf("%s: pci mapped mem 0x%lx (size %d), io 0x%x (size %d)\n",
114             sc->sc_dev.dv_xname, memaddr, memsize, iobase, iosize);
115 #endif
116 
117         if (cy_probe_common(sc->sc_dev.dv_unit, memt, memh,
118 	    CY_BUSTYPE_PCI) == 0) {
119                 bus_space_unmap(memt, memh, memsize);
120                 bus_space_unmap(iot, ioh, iosize);
121                 printf("%s: PCI Cyclom card with no CD1400s!?\n",
122 		    sc->sc_dev.dv_xname);
123                 return;
124         }
125 
126 	cy_attach(parent, self, aux);
127 
128         /* Get PLX version */
129 	memt = pa->pa_memt;
130 	iot = pa->pa_iot;
131         plx_ver = bus_space_read_1(memt, memh, CY_PLX_VER) & 0x0f;
132 
133         /* Enable PCI card interrupts */
134         switch (plx_ver) {
135         case CY_PLX_9050:
136                 bus_space_write_2(iot, ioh, CY_PCI_INTENA_9050,
137                 bus_space_read_2(iot, ioh, CY_PCI_INTENA_9050) | 0x40);
138                 break;
139         case CY_PLX_9060:
140         case CY_PLX_9080:
141         default:
142                 bus_space_write_2(iot, ioh, CY_PCI_INTENA,
143                 bus_space_read_2(iot, ioh, CY_PCI_INTENA) | 0x900);
144         }
145 
146 	/* Enable PCI card interrupts */
147 	if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
148 	    pa->pa_intrline, &ih) != 0)
149 		panic("%s: couldn't map PCI interrupt", sc->sc_dev.dv_xname);
150 
151 	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_TTY, cy_intr,
152 	    sc, sc->sc_dev.dv_xname);
153 
154         if (sc->sc_ih == NULL)
155                 panic("%s: couldn't establish interrupt", sc->sc_dev.dv_xname);
156 }
157