This source file includes following definitions.
- puc_pci_match
- puc_pci_intr_string
- puc_pci_intr_establish
- puc_pci_attach
- puc_common_attach
- puc_print
- puc_submatch
- puc_find_description
- puc_port_type_name
- puc_print_ports
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/device.h>
59
60 #include <dev/pci/pcireg.h>
61 #include <dev/pci/pcivar.h>
62 #include <dev/pci/pucvar.h>
63
64 #include <dev/pci/pcidevs.h>
65
66 struct puc_pci_softc {
67 struct puc_softc sc_psc;
68
69 pci_chipset_tag_t pc;
70 pci_intr_handle_t ih;
71 };
72
73 int puc_pci_match(struct device *, void *, void *);
74 void puc_pci_attach(struct device *, struct device *, void *);
75 const char *puc_pci_intr_string(struct puc_attach_args *);
76 void *puc_pci_intr_establish(struct puc_attach_args *, int,
77 int (*)(void *), void *, char *);
78
79 struct cfattach puc_pci_ca = {
80 sizeof(struct puc_pci_softc), puc_pci_match, puc_pci_attach
81 };
82
83 struct cfdriver puc_cd = {
84 NULL, "puc", DV_DULL
85 };
86
87 const char *puc_port_type_name(int);
88
89 int
90 puc_pci_match(struct device *parent, void *match, void *aux)
91 {
92 struct pci_attach_args *pa = aux;
93 const struct puc_device_description *desc;
94 pcireg_t bhlc, subsys;
95
96 bhlc = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
97 if (PCI_HDRTYPE_TYPE(bhlc) != 0)
98 return (0);
99
100 subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
101
102 desc = puc_find_description(PCI_VENDOR(pa->pa_id),
103 PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));
104 if (desc != NULL)
105 return (10);
106
107
108
109
110
111 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_COMMUNICATIONS &&
112 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_PCI)
113 return (1);
114
115 return (0);
116 }
117
118 const char *
119 puc_pci_intr_string(struct puc_attach_args *paa)
120 {
121 struct puc_pci_softc *sc = paa->puc;
122
123 return (pci_intr_string(sc->pc, sc->ih));
124 }
125
126 void *
127 puc_pci_intr_establish(struct puc_attach_args *paa, int type,
128 int (*func)(void *), void *arg, char *name)
129 {
130 struct puc_pci_softc *sc = paa->puc;
131
132 return (pci_intr_establish(sc->pc, sc->ih, type, func, arg, name));
133 }
134
135 void
136 puc_pci_attach(struct device *parent, struct device *self, void *aux)
137 {
138 struct puc_pci_softc *psc = (struct puc_pci_softc *)self;
139 struct puc_softc *sc = &psc->sc_psc;
140 struct pci_attach_args *pa = aux;
141 struct puc_attach_args paa;
142 pcireg_t subsys;
143 int i;
144
145 subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
146 sc->sc_desc = puc_find_description(PCI_VENDOR(pa->pa_id),
147 PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));
148 if (sc->sc_desc == NULL) {
149
150
151
152
153 #ifdef PUC_PRINT_REGS
154 printf(":\n");
155 pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
156 #else
157 printf(": unknown PCI communications device\n");
158 printf("%s: compile kernel with PUC_PRINT_REGS and larger\n",
159 sc->sc_dev.dv_xname);
160 printf("%s: message buffer (via 'options MSGBUFSIZE=...'),\n",
161 sc->sc_dev.dv_xname);
162 printf("%s: and report the result with sendbug(1)\n",
163 sc->sc_dev.dv_xname);
164 #endif
165 return;
166 }
167
168 puc_print_ports(sc->sc_desc);
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183 for (i = 0; i < PUC_NBARS; i++) {
184 pcireg_t type;
185 int bar;
186
187 sc->sc_bar_mappings[i].mapped = 0;
188 bar = PCI_MAPREG_START + 4 * i;
189 if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, bar, &type))
190 continue;
191
192 sc->sc_bar_mappings[i].mapped = (pci_mapreg_map(pa, bar, type,
193 0, &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h,
194 &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s, 0)
195 == 0);
196 sc->sc_bar_mappings[i].type = type;
197 if (sc->sc_bar_mappings[i].mapped)
198 continue;
199
200 printf("%s: couldn't map BAR at offset 0x%lx\n",
201 sc->sc_dev.dv_xname, (long)bar);
202 }
203
204
205 psc->pc = pa->pa_pc;
206 if (pci_intr_map(pa, &psc->ih)) {
207 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
208 return;
209 }
210
211 paa.puc = sc;
212 paa.hwtype = 0;
213 paa.intr_string = &puc_pci_intr_string;
214 paa.intr_establish = &puc_pci_intr_establish;
215
216
217
218
219
220 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_PLX &&
221 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_PLX_CRONYX_OMEGA)
222 paa.hwtype = 0x08;
223
224 puc_common_attach(sc, &paa);
225 }
226
227 void
228 puc_common_attach(struct puc_softc *sc, struct puc_attach_args *paa)
229 {
230 int i, bar;
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 for (i = 0; PUC_PORT_VALID(sc->sc_desc, i); i++) {
250
251 if (sc->sc_desc->ports[i].type != PUC_PORT_TYPE_COM &&
252 sc->sc_desc->ports[i].type != PUC_PORT_TYPE_LPT)
253 continue;
254
255 bar = PUC_PORT_BAR_INDEX(sc->sc_desc->ports[i].bar);
256 if (!sc->sc_bar_mappings[bar].mapped) {
257 printf("%s: %s port uses unmapped BAR (0x%x)\n",
258 sc->sc_dev.dv_xname,
259 puc_port_type_name(sc->sc_desc->ports[i].type),
260 sc->sc_desc->ports[i].bar);
261 continue;
262 }
263
264
265 paa->port = i;
266 paa->type = sc->sc_desc->ports[i].type;
267 paa->flags = sc->sc_desc->ports[i].flags;
268 paa->a = sc->sc_bar_mappings[bar].a;
269 paa->t = sc->sc_bar_mappings[bar].t;
270
271 if (bus_space_subregion(sc->sc_bar_mappings[bar].t,
272 sc->sc_bar_mappings[bar].h, sc->sc_desc->ports[i].offset,
273 sc->sc_bar_mappings[bar].s - sc->sc_desc->ports[i].offset,
274 &paa->h)) {
275 printf("%s: couldn't get subregion for port %d\n",
276 sc->sc_dev.dv_xname, i);
277 continue;
278 }
279
280 #if 0
281 if (autoconf_verbose)
282 printf("%s: port %d: %s @ (index %d) 0x%x "
283 "(0x%lx, 0x%lx)\n", sc->sc_dev.dv_xname, paa->port,
284 puc_port_type_name(paa->type), bar, (int)paa->a,
285 (long)paa->t, (long)paa->h);
286 #endif
287
288
289 sc->sc_ports[i].dev = config_found_sm(&sc->sc_dev, paa,
290 puc_print, puc_submatch);
291 }
292 }
293
294 int
295 puc_print(void *aux, const char *pnp)
296 {
297 struct puc_attach_args *paa = aux;
298
299 if (pnp)
300 printf("%s at %s", puc_port_type_name(paa->type), pnp);
301 printf(" port %d", paa->port);
302 return (UNCONF);
303 }
304
305 int
306 puc_submatch(struct device *parent, void *vcf, void *aux)
307 {
308 struct cfdata *cf = (struct cfdata *)vcf;
309 struct puc_attach_args *aa = aux;
310
311 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != aa->port)
312 return 0;
313 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
314 }
315
316 const struct puc_device_description *
317 puc_find_description(u_long vend, u_long prod, u_long svend, u_long sprod)
318 {
319 int i;
320
321 #define checkreg(val, index) \
322 (((val) & puc_devices[i].rmask[(index)]) == puc_devices[i].rval[(index)])
323 #define pucdevdone(idx) \
324 (puc_devices[idx].rval[0] == 0 && puc_devices[idx].rval[1] == 0 \
325 && puc_devices[idx].rval[2] == 0 && puc_devices[idx].rval[3] == 0)
326
327 for (i = 0; !pucdevdone(i); i++) {
328 if (checkreg(vend, PUC_REG_VEND) &&
329 checkreg(prod, PUC_REG_PROD) &&
330 checkreg(svend, PUC_REG_SVEND) &&
331 checkreg(sprod, PUC_REG_SPROD))
332 return (&puc_devices[i]);
333 }
334
335 #undef devdone
336 #undef checkreg
337
338 return (NULL);
339 }
340
341 const char *
342 puc_port_type_name(int type)
343 {
344
345 switch (type) {
346 case PUC_PORT_TYPE_COM:
347 return "com";
348 case PUC_PORT_TYPE_LPT:
349 return "lpt";
350 default:
351 return "unknown";
352 }
353 }
354
355 void
356 puc_print_ports(const struct puc_device_description *desc)
357 {
358 int i, ncom, nlpt;
359
360 printf(": ports: ");
361 for (i = ncom = nlpt = 0; PUC_PORT_VALID(desc, i); i++) {
362 switch (desc->ports[i].type) {
363 case PUC_PORT_TYPE_COM:
364 ncom++;
365 break;
366 case PUC_PORT_TYPE_LPT:
367 nlpt++;
368 break;
369 default:
370 printf("port %d unknown type %d ", i,
371 desc->ports[i].type);
372 }
373 }
374 if (ncom)
375 printf("%d com", ncom);
376 if (nlpt) {
377 if (ncom)
378 printf(", ");
379 printf("%d lpt", nlpt);
380 }
381 printf("\n");
382 }