]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/dev/puc/pucdata.c
MFC 222093:
[FreeBSD/stable/8.git] / sys / dev / puc / pucdata.c
1 /*-
2  * Copyright (c) 2006 Marcel Moolenaar
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * PCI "universal" communications card driver configuration data (used to
32  * match/attach the cards).
33  */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/bus.h>
39
40 #include <machine/resource.h>
41 #include <machine/bus.h>
42 #include <sys/rman.h>
43
44 #include <dev/pci/pcivar.h>
45
46 #include <dev/puc/puc_bus.h>
47 #include <dev/puc/puc_cfg.h>
48 #include <dev/puc/puc_bfe.h>
49
50 static puc_config_f puc_config_amc;
51 static puc_config_f puc_config_cronyx;
52 static puc_config_f puc_config_diva;
53 static puc_config_f puc_config_icbook;
54 static puc_config_f puc_config_oxford_pcie;
55 static puc_config_f puc_config_quatech;
56 static puc_config_f puc_config_syba;
57 static puc_config_f puc_config_siig;
58 static puc_config_f puc_config_timedia;
59 static puc_config_f puc_config_titan;
60
61 const struct puc_cfg puc_pci_devices[] = {
62
63         {   0x0009, 0x7168, 0xffff, 0,
64             "Sunix SUN1889",
65             DEFAULT_RCLK * 8,
66             PUC_PORT_2S, 0x10, 0, 8,
67         },
68
69         {   0x103c, 0x1048, 0x103c, 0x1049,
70             "HP Diva Serial [GSP] Multiport UART - Tosca Console",
71             DEFAULT_RCLK,
72             PUC_PORT_3S, 0x10, 0, -1,
73             .config_function = puc_config_diva
74         },
75
76         {   0x103c, 0x1048, 0x103c, 0x104a,
77             "HP Diva Serial [GSP] Multiport UART - Tosca Secondary",
78             DEFAULT_RCLK,
79             PUC_PORT_2S, 0x10, 0, -1,
80             .config_function = puc_config_diva
81         },
82
83         {   0x103c, 0x1048, 0x103c, 0x104b,
84             "HP Diva Serial [GSP] Multiport UART - Maestro SP2",
85             DEFAULT_RCLK,
86             PUC_PORT_4S, 0x10, 0, -1,
87             .config_function = puc_config_diva
88         },
89
90         {   0x103c, 0x1048, 0x103c, 0x1223,
91             "HP Diva Serial [GSP] Multiport UART - Superdome Console",
92             DEFAULT_RCLK,
93             PUC_PORT_3S, 0x10, 0, -1,
94             .config_function = puc_config_diva
95         },
96
97         {   0x103c, 0x1048, 0x103c, 0x1226,
98             "HP Diva Serial [GSP] Multiport UART - Keystone SP2",
99             DEFAULT_RCLK,
100             PUC_PORT_3S, 0x10, 0, -1,
101             .config_function = puc_config_diva
102         },
103
104         {   0x103c, 0x1048, 0x103c, 0x1282,
105             "HP Diva Serial [GSP] Multiport UART - Everest SP2",
106             DEFAULT_RCLK,
107             PUC_PORT_3S, 0x10, 0, -1,
108             .config_function = puc_config_diva
109         },
110
111         {   0x10b5, 0x1076, 0x10b5, 0x1076,
112             "VScom PCI-800",
113             DEFAULT_RCLK * 8,
114             PUC_PORT_8S, 0x18, 0, 8,
115         },
116
117         {   0x10b5, 0x1077, 0x10b5, 0x1077,
118             "VScom PCI-400",
119             DEFAULT_RCLK * 8,
120             PUC_PORT_4S, 0x18, 0, 8,
121         },
122
123         {   0x10b5, 0x1103, 0x10b5, 0x1103,
124             "VScom PCI-200",
125             DEFAULT_RCLK * 8,
126             PUC_PORT_2S, 0x18, 4, 0,
127         },
128
129         /*
130          * Boca Research Turbo Serial 658 (8 serial port) card.
131          * Appears to be the same as Chase Research PLC PCI-FAST8
132          * and Perle PCI-FAST8 Multi-Port serial cards.
133          */
134         {   0x10b5, 0x9050, 0x12e0, 0x0021,
135             "Boca Research Turbo Serial 658",
136             DEFAULT_RCLK * 4,
137             PUC_PORT_8S, 0x18, 0, 8,
138         },
139
140         {   0x10b5, 0x9050, 0x12e0, 0x0031,
141             "Boca Research Turbo Serial 654",
142             DEFAULT_RCLK * 4,
143             PUC_PORT_4S, 0x18, 0, 8,
144         },
145
146         /*
147          * Dolphin Peripherals 4035 (dual serial port) card.  PLX 9050, with
148          * a seemingly-lame EEPROM setup that puts the Dolphin IDs
149          * into the subsystem fields, and claims that it's a
150          * network/misc (0x02/0x80) device.
151          */
152         {   0x10b5, 0x9050, 0xd84d, 0x6808,
153             "Dolphin Peripherals 4035",
154             DEFAULT_RCLK,
155             PUC_PORT_2S, 0x18, 4, 0,
156         },
157
158         /*
159          * Dolphin Peripherals 4014 (dual parallel port) card.  PLX 9050, with
160          * a seemingly-lame EEPROM setup that puts the Dolphin IDs
161          * into the subsystem fields, and claims that it's a
162          * network/misc (0x02/0x80) device.
163          */
164         {   0x10b5, 0x9050, 0xd84d, 0x6810,
165             "Dolphin Peripherals 4014",
166             0,
167             PUC_PORT_2P, 0x20, 4, 0,
168         },
169
170         {   0x10e8, 0x818e, 0xffff, 0,
171             "Applied Micro Circuits 8 Port UART",
172             DEFAULT_RCLK,
173             PUC_PORT_8S, 0x14, -1, -1,
174             .config_function = puc_config_amc
175         },
176
177         {   0x11fe, 0x8010, 0xffff, 0,
178             "Comtrol RocketPort 550/8 RJ11 part A",
179             DEFAULT_RCLK * 4,
180             PUC_PORT_4S, 0x10, 0, 8,
181         },
182
183         {   0x11fe, 0x8011, 0xffff, 0,
184             "Comtrol RocketPort 550/8 RJ11 part B",
185             DEFAULT_RCLK * 4,
186             PUC_PORT_4S, 0x10, 0, 8,
187         },
188
189         {   0x11fe, 0x8012, 0xffff, 0,
190             "Comtrol RocketPort 550/8 Octa part A",
191             DEFAULT_RCLK * 4,
192             PUC_PORT_4S, 0x10, 0, 8,
193         },
194
195         {   0x11fe, 0x8013, 0xffff, 0,
196             "Comtrol RocketPort 550/8 Octa part B",
197             DEFAULT_RCLK * 4,
198             PUC_PORT_4S, 0x10, 0, 8,
199         },
200
201         {   0x11fe, 0x8014, 0xffff, 0,
202             "Comtrol RocketPort 550/4 RJ45",
203             DEFAULT_RCLK * 4,
204             PUC_PORT_4S, 0x10, 0, 8,
205         },
206
207         {   0x11fe, 0x8015, 0xffff, 0,
208             "Comtrol RocketPort 550/Quad",
209             DEFAULT_RCLK * 4,
210             PUC_PORT_4S, 0x10, 0, 8,
211         },
212
213         {   0x11fe, 0x8016, 0xffff, 0,
214             "Comtrol RocketPort 550/16 part A",
215             DEFAULT_RCLK * 4,
216             PUC_PORT_4S, 0x10, 0, 8,
217         },
218
219         {   0x11fe, 0x8017, 0xffff, 0,
220             "Comtrol RocketPort 550/16 part B",
221             DEFAULT_RCLK * 4,
222             PUC_PORT_12S, 0x10, 0, 8,
223         },
224
225         {   0x11fe, 0x8018, 0xffff, 0,
226             "Comtrol RocketPort 550/8 part A",
227             DEFAULT_RCLK * 4,
228             PUC_PORT_4S, 0x10, 0, 8,
229         },
230
231         {   0x11fe, 0x8019, 0xffff, 0,
232             "Comtrol RocketPort 550/8 part B",
233             DEFAULT_RCLK * 4,
234             PUC_PORT_4S, 0x10, 0, 8,
235         },
236
237         /*
238          * IBM SurePOS 300 Series (481033H) serial ports
239          * Details can be found on the IBM RSS websites
240          */
241
242         {   0x1014, 0x0297, 0xffff, 0,
243             "IBM SurePOS 300 Series (481033H) serial ports",
244             DEFAULT_RCLK,
245             PUC_PORT_4S, 0x10, 4, 0
246         },
247
248         /*
249          * SIIG Boards.
250          *
251          * SIIG provides documentation for their boards at:
252          * <URL:http://www.siig.com/downloads.asp>
253          */
254
255         {   0x131f, 0x1010, 0xffff, 0,
256             "SIIG Cyber I/O PCI 16C550 (10x family)",
257             DEFAULT_RCLK,
258             PUC_PORT_1S1P, 0x18, 4, 0,
259         },
260
261         {   0x131f, 0x1011, 0xffff, 0,
262             "SIIG Cyber I/O PCI 16C650 (10x family)",
263             DEFAULT_RCLK,
264             PUC_PORT_1S1P, 0x18, 4, 0,
265         },
266
267         {   0x131f, 0x1012, 0xffff, 0,
268             "SIIG Cyber I/O PCI 16C850 (10x family)",
269             DEFAULT_RCLK,
270             PUC_PORT_1S1P, 0x18, 4, 0,
271         },
272
273         {   0x131f, 0x1021, 0xffff, 0,
274             "SIIG Cyber Parallel Dual PCI (10x family)",
275             0,
276             PUC_PORT_2P, 0x18, 8, 0,
277         },
278
279         {   0x131f, 0x1030, 0xffff, 0,
280             "SIIG Cyber Serial Dual PCI 16C550 (10x family)",
281             DEFAULT_RCLK,
282             PUC_PORT_2S, 0x18, 4, 0,
283         },
284
285         {   0x131f, 0x1031, 0xffff, 0,
286             "SIIG Cyber Serial Dual PCI 16C650 (10x family)",
287             DEFAULT_RCLK,
288             PUC_PORT_2S, 0x18, 4, 0,
289         },
290
291         {   0x131f, 0x1032, 0xffff, 0,
292             "SIIG Cyber Serial Dual PCI 16C850 (10x family)",
293             DEFAULT_RCLK,
294             PUC_PORT_2S, 0x18, 4, 0,
295         },
296
297         {   0x131f, 0x1034, 0xffff, 0,  /* XXX really? */
298             "SIIG Cyber 2S1P PCI 16C550 (10x family)",
299             DEFAULT_RCLK,
300             PUC_PORT_2S1P, 0x18, 4, 0,
301         },
302
303         {   0x131f, 0x1035, 0xffff, 0,  /* XXX really? */
304             "SIIG Cyber 2S1P PCI 16C650 (10x family)",
305             DEFAULT_RCLK,
306             PUC_PORT_2S1P, 0x18, 4, 0,
307         },
308
309         {   0x131f, 0x1036, 0xffff, 0,  /* XXX really? */
310             "SIIG Cyber 2S1P PCI 16C850 (10x family)",
311             DEFAULT_RCLK,
312             PUC_PORT_2S1P, 0x18, 4, 0,
313         },
314
315         {   0x131f, 0x1050, 0xffff, 0,
316             "SIIG Cyber 4S PCI 16C550 (10x family)",
317             DEFAULT_RCLK,
318             PUC_PORT_4S, 0x18, 4, 0,
319         },
320
321         {   0x131f, 0x1051, 0xffff, 0,
322             "SIIG Cyber 4S PCI 16C650 (10x family)",
323             DEFAULT_RCLK,
324             PUC_PORT_4S, 0x18, 4, 0,
325         },
326
327         {   0x131f, 0x1052, 0xffff, 0,
328             "SIIG Cyber 4S PCI 16C850 (10x family)",
329             DEFAULT_RCLK,
330             PUC_PORT_4S, 0x18, 4, 0,
331         },
332
333         {   0x131f, 0x2010, 0xffff, 0,
334             "SIIG Cyber I/O PCI 16C550 (20x family)",
335             DEFAULT_RCLK,
336             PUC_PORT_1S1P, 0x10, 4, 0,
337         },
338
339         {   0x131f, 0x2011, 0xffff, 0,
340             "SIIG Cyber I/O PCI 16C650 (20x family)",
341             DEFAULT_RCLK,
342             PUC_PORT_1S1P, 0x10, 4, 0,
343         },
344
345         {   0x131f, 0x2012, 0xffff, 0,
346             "SIIG Cyber I/O PCI 16C850 (20x family)",
347             DEFAULT_RCLK,
348             PUC_PORT_1S1P, 0x10, 4, 0,
349         },
350
351         {   0x131f, 0x2021, 0xffff, 0,
352             "SIIG Cyber Parallel Dual PCI (20x family)",
353             0,
354             PUC_PORT_2P, 0x10, 8, 0,
355         },
356
357         {   0x131f, 0x2030, 0xffff, 0,
358             "SIIG Cyber Serial Dual PCI 16C550 (20x family)",
359             DEFAULT_RCLK,
360             PUC_PORT_2S, 0x10, 4, 0,
361         },
362
363         {   0x131f, 0x2031, 0xffff, 0,
364             "SIIG Cyber Serial Dual PCI 16C650 (20x family)",
365             DEFAULT_RCLK,
366             PUC_PORT_2S, 0x10, 4, 0,
367         },
368
369         {   0x131f, 0x2032, 0xffff, 0,
370             "SIIG Cyber Serial Dual PCI 16C850 (20x family)",
371             DEFAULT_RCLK,
372             PUC_PORT_2S, 0x10, 4, 0,
373         },
374
375         {   0x131f, 0x2040, 0xffff, 0,
376             "SIIG Cyber 2P1S PCI 16C550 (20x family)",
377             DEFAULT_RCLK,
378             PUC_PORT_1S2P, 0x10, -1, 0,
379             .config_function = puc_config_siig
380         },
381
382         {   0x131f, 0x2041, 0xffff, 0,
383             "SIIG Cyber 2P1S PCI 16C650 (20x family)",
384             DEFAULT_RCLK,
385             PUC_PORT_1S2P, 0x10, -1, 0,
386             .config_function = puc_config_siig
387         },
388
389         {   0x131f, 0x2042, 0xffff, 0,
390             "SIIG Cyber 2P1S PCI 16C850 (20x family)",
391             DEFAULT_RCLK,
392             PUC_PORT_1S2P, 0x10, -1, 0,
393             .config_function = puc_config_siig
394         },
395
396         {   0x131f, 0x2050, 0xffff, 0,
397             "SIIG Cyber 4S PCI 16C550 (20x family)",
398             DEFAULT_RCLK,
399             PUC_PORT_4S, 0x10, 4, 0,
400         },
401
402         {   0x131f, 0x2051, 0xffff, 0,
403             "SIIG Cyber 4S PCI 16C650 (20x family)",
404             DEFAULT_RCLK,
405             PUC_PORT_4S, 0x10, 4, 0,
406         },
407
408         {   0x131f, 0x2052, 0xffff, 0,
409             "SIIG Cyber 4S PCI 16C850 (20x family)",
410             DEFAULT_RCLK,
411             PUC_PORT_4S, 0x10, 4, 0,
412         },
413
414         {   0x131f, 0x2060, 0xffff, 0,
415             "SIIG Cyber 2S1P PCI 16C550 (20x family)",
416             DEFAULT_RCLK,
417             PUC_PORT_2S1P, 0x10, 4, 0,
418         },
419
420         {   0x131f, 0x2061, 0xffff, 0,
421             "SIIG Cyber 2S1P PCI 16C650 (20x family)",
422             DEFAULT_RCLK,
423             PUC_PORT_2S1P, 0x10, 4, 0,
424         },
425
426         {   0x131f, 0x2062, 0xffff, 0,
427             "SIIG Cyber 2S1P PCI 16C850 (20x family)",
428             DEFAULT_RCLK,
429             PUC_PORT_2S1P, 0x10, 4, 0,
430         },
431
432         {   0x131f, 0x2081, 0xffff, 0,
433             "SIIG PS8000 8S PCI 16C650 (20x family)",
434             DEFAULT_RCLK,
435             PUC_PORT_8S, 0x10, -1, -1,
436             .config_function = puc_config_siig
437         },
438
439         {   0x135c, 0x0010, 0xffff, 0,
440             "Quatech QSC-100",
441             -3, /* max 8x clock rate */
442             PUC_PORT_4S, 0x14, 0, 8,
443             .config_function = puc_config_quatech
444         },
445
446         {   0x135c, 0x0020, 0xffff, 0,
447             "Quatech DSC-100",
448             -1, /* max 2x clock rate */
449             PUC_PORT_2S, 0x14, 0, 8,
450             .config_function = puc_config_quatech
451         },
452
453         {   0x135c, 0x0030, 0xffff, 0,
454             "Quatech DSC-200/300",
455             -1, /* max 2x clock rate */
456             PUC_PORT_2S, 0x14, 0, 8,
457             .config_function = puc_config_quatech
458         },
459
460         {   0x135c, 0x0040, 0xffff, 0,
461             "Quatech QSC-200/300",
462             -3, /* max 8x clock rate */
463             PUC_PORT_4S, 0x14, 0, 8,
464             .config_function = puc_config_quatech
465         },
466
467         {   0x135c, 0x0050, 0xffff, 0,
468             "Quatech ESC-100D",
469             -3, /* max 8x clock rate */
470             PUC_PORT_8S, 0x14, 0, 8,
471             .config_function = puc_config_quatech
472         },
473
474         {   0x135c, 0x0060, 0xffff, 0,
475             "Quatech ESC-100M",
476             -3, /* max 8x clock rate */
477             PUC_PORT_8S, 0x14, 0, 8,
478             .config_function = puc_config_quatech
479         },
480
481         {   0x135c, 0x0170, 0xffff, 0,
482             "Quatech QSCLP-100",
483             -1, /* max 2x clock rate */
484             PUC_PORT_4S, 0x18, 0, 8,
485             .config_function = puc_config_quatech
486         },
487
488         {   0x135c, 0x0180, 0xffff, 0,
489             "Quatech DSCLP-100",
490             -1, /* max 3x clock rate */
491             PUC_PORT_2S, 0x18, 0, 8,
492             .config_function = puc_config_quatech
493         },
494
495         {   0x135c, 0x01b0, 0xffff, 0,
496             "Quatech DSCLP-200/300",
497             -1, /* max 2x clock rate */
498             PUC_PORT_2S, 0x18, 0, 8,
499             .config_function = puc_config_quatech
500         },
501
502         {   0x135c, 0x01e0, 0xffff, 0,
503             "Quatech ESCLP-100",
504             -3, /* max 8x clock rate */
505             PUC_PORT_8S, 0x10, 0, 8,
506             .config_function = puc_config_quatech
507         },
508
509         {   0x1393, 0x1040, 0xffff, 0,
510             "Moxa Technologies, Smartio C104H/PCI",
511             DEFAULT_RCLK * 8,
512             PUC_PORT_4S, 0x18, 0, 8,
513         },
514
515         {   0x1393, 0x1041, 0xffff, 0,
516             "Moxa Technologies, Smartio CP-104UL/PCI",
517             DEFAULT_RCLK * 8,
518             PUC_PORT_4S, 0x18, 0, 8,
519         },
520
521         {   0x1393, 0x1043, 0xffff, 0,
522             "Moxa Technologies, Smartio CP-104EL/PCIe",
523             DEFAULT_RCLK * 8,
524             PUC_PORT_4S, 0x18, 0, 8,
525         },
526
527         {   0x1393, 0x1141, 0xffff, 0,
528             "Moxa Technologies, Industio CP-114",
529             DEFAULT_RCLK * 8,
530             PUC_PORT_4S, 0x18, 0, 8,
531         },
532
533         {   0x1393, 0x1680, 0xffff, 0,
534             "Moxa Technologies, C168H/PCI",
535             DEFAULT_RCLK * 8,
536             PUC_PORT_8S, 0x18, 0, 8,
537         },
538
539         {   0x1393, 0x1681, 0xffff, 0,
540             "Moxa Technologies, C168U/PCI",
541             DEFAULT_RCLK * 8,
542             PUC_PORT_8S, 0x18, 0, 8,
543         },
544
545         {   0x1393, 0x1682, 0xffff, 0,
546             "Moxa Technologies, CP-168EL/PCIe",
547             DEFAULT_RCLK * 8,
548             PUC_PORT_8S, 0x18, 0, 8,
549         },
550
551         {   0x13a8, 0x0158, 0xffff, 0,
552             "Cronyx Omega2-PCI",
553             DEFAULT_RCLK * 8,
554             PUC_PORT_8S, 0x10, 0, -1,
555             .config_function = puc_config_cronyx
556         },
557
558         {   0x13a8, 0x0258, 0xffff, 0,
559             "Exar XR17V258IV",
560             DEFAULT_RCLK * 8,
561             PUC_PORT_8S, 0x10, 0, -1,
562         },
563
564         {   0x1407, 0x0100, 0xffff, 0,
565             "Lava Computers Dual Serial",
566             DEFAULT_RCLK,
567             PUC_PORT_2S, 0x10, 4, 0,
568         },
569
570         {   0x1407, 0x0101, 0xffff, 0,
571             "Lava Computers Quatro A",
572             DEFAULT_RCLK,
573             PUC_PORT_2S, 0x10, 4, 0,
574         },
575
576         {   0x1407, 0x0102, 0xffff, 0,
577             "Lava Computers Quatro B",
578             DEFAULT_RCLK,
579             PUC_PORT_2S, 0x10, 4, 0,
580         },
581
582         {   0x1407, 0x0120, 0xffff, 0,
583             "Lava Computers Quattro-PCI A",
584             DEFAULT_RCLK,
585             PUC_PORT_2S, 0x10, 4, 0,
586         },
587
588         {   0x1407, 0x0121, 0xffff, 0,
589             "Lava Computers Quattro-PCI B",
590             DEFAULT_RCLK,
591             PUC_PORT_2S, 0x10, 4, 0,
592         },
593
594         {   0x1407, 0x0180, 0xffff, 0,
595             "Lava Computers Octo A",
596             DEFAULT_RCLK,
597             PUC_PORT_4S, 0x10, 4, 0,
598         },
599
600         {   0x1407, 0x0181, 0xffff, 0,
601             "Lava Computers Octo B",
602             DEFAULT_RCLK,
603             PUC_PORT_4S, 0x10, 4, 0,
604         },
605
606         {   0x1409, 0x7268, 0xffff, 0,
607             "Sunix SUN1888",
608             0,
609             PUC_PORT_2P, 0x10, 0, 8,
610         },
611
612         {   0x1409, 0x7168, 0xffff, 0,
613             NULL,
614             DEFAULT_RCLK * 8,
615             PUC_PORT_NONSTANDARD, 0x10, -1, -1,
616             .config_function = puc_config_timedia
617         },
618
619         /*
620          * Boards with an Oxford Semiconductor chip.
621          *
622          * Oxford Semiconductor provides documentation for their chip at:
623          * <URL:http://www.plxtech.com/products/uart/>
624          *
625          * As sold by Kouwell <URL:http://www.kouwell.com/>.
626          * I/O Flex PCI I/O Card Model-223 with 4 serial and 1 parallel ports.
627          */
628
629         {   0x1415, 0x9501, 0x131f, 0x2050,
630             "SIIG Cyber 4 PCI 16550",
631             DEFAULT_RCLK * 10,
632             PUC_PORT_4S, 0x10, 0, 8,
633         },
634
635         {   0x1415, 0x9501, 0x131f, 0x2051,
636             "SIIG Cyber 4S PCI 16C650 (20x family)",
637             DEFAULT_RCLK * 10,
638             PUC_PORT_4S, 0x10, 0, 8,
639         },
640
641         {   0x1415, 0x9501, 0x131f, 0x2052,
642             "SIIG Quartet Serial 850",
643             DEFAULT_RCLK * 10,
644             PUC_PORT_4S, 0x10, 0, 8,
645         },
646
647         {   0x1415, 0x9501, 0x14db, 0x2150,
648             "Kuroutoshikou SERIAL4P-LPPCI2",
649             DEFAULT_RCLK * 10,
650             PUC_PORT_4S, 0x10, 0, 8,
651         },
652
653         {   0x1415, 0x9501, 0xffff, 0,
654             "Oxford Semiconductor OX16PCI954 UARTs",
655             DEFAULT_RCLK,
656             PUC_PORT_4S, 0x10, 0, 8,
657         },
658
659         {   0x1415, 0x950a, 0x131f, 0x2030,
660             "SIIG Cyber 2S PCIe",
661             DEFAULT_RCLK * 10,
662             PUC_PORT_2S, 0x10, 0, 8,
663         },
664
665         {   0x1415, 0x950a, 0xffff, 0,
666             "Oxford Semiconductor OX16PCI954 UARTs",
667             DEFAULT_RCLK,
668             PUC_PORT_4S, 0x10, 0, 8,
669         },
670
671         {   0x1415, 0x9511, 0xffff, 0,
672             "Oxford Semiconductor OX9160/OX16PCI954 UARTs (function 1)",
673             DEFAULT_RCLK,
674             PUC_PORT_4S, 0x10, 0, 8,
675         },
676
677         {   0x1415, 0x9521, 0xffff, 0,
678             "Oxford Semiconductor OX16PCI952 UARTs",
679             DEFAULT_RCLK,
680             PUC_PORT_2S, 0x10, 4, 0,
681         },
682
683         {   0x1415, 0x9538, 0xffff, 0,
684             "Oxford Semiconductor OX16PCI958 UARTs",
685             DEFAULT_RCLK * 10,
686             PUC_PORT_8S, 0x18, 0, 8,
687         },
688
689         /*
690          * Perle boards use Oxford Semiconductor chips, but they store the
691          * Oxford Semiconductor device ID as a subvendor device ID and use
692          * their own device IDs.
693          */
694
695         {   0x155f, 0x0331, 0xffff, 0,
696             "Perle Speed4 LE",
697             DEFAULT_RCLK * 8,
698             PUC_PORT_4S, 0x10, 0, 8,
699         },
700
701         /*
702          * Oxford Semiconductor PCI Express Expresso family
703          *
704          * Found in many 'native' PCI Express serial boards such as:
705          *
706          * eMegatech MP954ER4 (4 port) and MP958ER8 (8 port)
707          * <URL:http://www.emegatech.com.tw/pdrs232pcie.html>
708          *
709          * Lindy 51189 (4 port)
710          * <URL:http://www.lindy.com> <URL:http://tinyurl.com/lindy-51189>
711          * 
712          * StarTech.com PEX4S952 (4 port) and PEX8S952 (8 port)
713          * <URL:http://www.startech.com>
714          */
715
716         {   0x1415, 0xc158, 0xffff, 0,
717             "Oxford Semiconductor OXPCIe952 UARTs",
718             DEFAULT_RCLK * 0x22,
719             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
720             .config_function = puc_config_oxford_pcie
721         },
722
723         {   0x1415, 0xc15d, 0xffff, 0,
724             "Oxford Semiconductor OXPCIe952 UARTs (function 1)",
725             DEFAULT_RCLK * 0x22,
726             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
727             .config_function = puc_config_oxford_pcie
728         },
729
730         {   0x1415, 0xc208, 0xffff, 0,
731             "Oxford Semiconductor OXPCIe954 UARTs",
732             DEFAULT_RCLK * 0x22,
733             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
734             .config_function = puc_config_oxford_pcie
735         },
736
737         {   0x1415, 0xc20d, 0xffff, 0,
738             "Oxford Semiconductor OXPCIe954 UARTs (function 1)",
739             DEFAULT_RCLK * 0x22,
740             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
741             .config_function = puc_config_oxford_pcie
742         },
743
744         {   0x1415, 0xc308, 0xffff, 0,
745             "Oxford Semiconductor OXPCIe958 UARTs",
746             DEFAULT_RCLK * 0x22,
747             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
748             .config_function = puc_config_oxford_pcie
749         },
750
751         {   0x1415, 0xc30d, 0xffff, 0,
752             "Oxford Semiconductor OXPCIe958 UARTs (function 1)",
753             DEFAULT_RCLK * 0x22,
754             PUC_PORT_NONSTANDARD, 0x10, 0, -1,
755             .config_function = puc_config_oxford_pcie
756         },
757
758         {   0x14d2, 0x8010, 0xffff, 0,
759             "VScom PCI-100L",
760             DEFAULT_RCLK * 8,
761             PUC_PORT_1S, 0x14, 0, 0,
762         },
763
764         {   0x14d2, 0x8020, 0xffff, 0,
765             "VScom PCI-200L",
766             DEFAULT_RCLK * 8,
767             PUC_PORT_2S, 0x14, 4, 0,
768         },
769
770         {   0x14d2, 0x8028, 0xffff, 0,
771             "VScom 200Li",
772             DEFAULT_RCLK,
773             PUC_PORT_2S, 0x20, 0, 8,
774         },
775
776         /*
777          * VScom (Titan?) PCI-800L.  More modern variant of the
778          * PCI-800.  Uses 6 discrete 16550 UARTs, plus another
779          * two of them obviously implemented as macro cells in
780          * the ASIC.  This causes the weird port access pattern
781          * below, where two of the IO port ranges each access
782          * one of the ASIC UARTs, and a block of IO addresses
783          * access the external UARTs.
784          */
785         {   0x14d2, 0x8080, 0xffff, 0,
786             "Titan VScom PCI-800L",
787             DEFAULT_RCLK * 8,
788             PUC_PORT_8S, 0x14, -1, -1,
789             .config_function = puc_config_titan
790         },
791
792         /*
793          * VScom PCI-800H. Uses 8 16950 UART, behind a PCI chips that offers
794          * 4 com port on PCI device 0 and 4 on PCI device 1. PCI device 0 has
795          * device ID 3 and PCI device 1 device ID 4.
796          */
797         {   0x14d2, 0xa003, 0xffff, 0,
798             "Titan PCI-800H",
799             DEFAULT_RCLK * 8,
800             PUC_PORT_4S, 0x10, 0, 8,
801         },
802         {   0x14d2, 0xa004, 0xffff, 0,
803             "Titan PCI-800H",
804             DEFAULT_RCLK * 8,
805             PUC_PORT_4S, 0x10, 0, 8,
806         },
807
808         {   0x14d2, 0xa005, 0xffff, 0,
809             "Titan PCI-200H",
810             DEFAULT_RCLK * 8,
811             PUC_PORT_2S, 0x10, 0, 8,
812         },
813
814         {   0x14d2, 0xe020, 0xffff, 0,
815             "Titan VScom PCI-200HV2",
816             DEFAULT_RCLK * 8,
817             PUC_PORT_2S, 0x10, 4, 0,
818         },
819
820         {   0x14db, 0x2130, 0xffff, 0,
821             "Avlab Technology, PCI IO 2S",
822             DEFAULT_RCLK,
823             PUC_PORT_2S, 0x10, 4, 0,
824         },
825
826         {   0x14db, 0x2150, 0xffff, 0,
827             "Avlab Low Profile PCI 4 Serial",
828             DEFAULT_RCLK,
829             PUC_PORT_4S, 0x10, 4, 0,
830         },
831
832         {   0x14db, 0x2152, 0xffff, 0,
833             "Avlab Low Profile PCI 4 Serial",
834             DEFAULT_RCLK,
835             PUC_PORT_4S, 0x10, 4, 0,
836         },
837
838         {   0x1592, 0x0781, 0xffff, 0,
839             "Syba Tech Ltd. PCI-4S2P-550-ECP",
840             DEFAULT_RCLK,
841             PUC_PORT_4S1P, 0x10, 0, -1,
842             .config_function = puc_config_syba
843         },
844
845         {   0x6666, 0x0001, 0xffff, 0,
846             "Decision Computer Inc, PCCOM 4-port serial",
847             DEFAULT_RCLK,
848             PUC_PORT_4S, 0x1c, 0, 8,
849         },
850
851         {   0x6666, 0x0002, 0xffff, 0,
852             "Decision Computer Inc, PCCOM 8-port serial",
853             DEFAULT_RCLK,
854             PUC_PORT_8S, 0x1c, 0, 8,
855         },
856
857         {   0x6666, 0x0004, 0xffff, 0,
858             "PCCOM dual port RS232/422/485",
859             DEFAULT_RCLK,
860             PUC_PORT_2S, 0x1c, 0, 8,
861         },
862
863         {   0x9710, 0x9815, 0xffff, 0,
864             "NetMos NM9815 Dual 1284 Printer port", 
865             0,
866             PUC_PORT_2P, 0x10, 8, 0,
867         }, 
868
869         /*
870          * This is more specific than the generic NM9835 entry that follows, and
871          * is placed here to _prevent_ puc from claiming this single port card.
872          *
873          * uart(4) will claim this device.
874          */
875         {   0x9710, 0x9835, 0x1000, 1,
876             "NetMos NM9835 based 1-port serial",
877             DEFAULT_RCLK,
878             PUC_PORT_1S, 0x10, 4, 0,
879         },
880
881         {   0x9710, 0x9835, 0x1000, 2,
882             "NetMos NM9835 based 2-port serial",
883             DEFAULT_RCLK,
884             PUC_PORT_2S, 0x10, 4, 0,
885         },
886
887         {   0x9710, 0x9835, 0xffff, 0,
888             "NetMos NM9835 Dual UART and 1284 Printer port",
889             DEFAULT_RCLK,
890             PUC_PORT_2S1P, 0x10, 4, 0,
891         },
892
893         {   0x9710, 0x9845, 0x1000, 0x0006,
894             "NetMos NM9845 6 Port UART",
895             DEFAULT_RCLK,
896             PUC_PORT_6S, 0x10, 4, 0,
897         },
898
899         {   0x9710, 0x9845, 0xffff, 0,
900             "NetMos NM9845 Quad UART and 1284 Printer port",
901             DEFAULT_RCLK,
902             PUC_PORT_4S1P, 0x10, 4, 0,
903         },
904
905         {   0x9710, 0x9865, 0xa000, 0x3002,
906             "NetMos NM9865 Dual UART",
907             DEFAULT_RCLK,
908             PUC_PORT_2S, 0x10, 4, 0,
909         },
910
911         {   0x9710, 0x9865, 0xa000, 0x3003,
912             "NetMos NM9865 Triple UART",
913             DEFAULT_RCLK,
914             PUC_PORT_3S, 0x10, 4, 0,
915         },
916
917         {   0x9710, 0x9865, 0xa000, 0x3004,
918             "NetMos NM9865 Quad UART",
919             DEFAULT_RCLK,
920             PUC_PORT_4S, 0x10, 4, 0,0
921         },
922
923         {   0x9710, 0x9865, 0xa000, 0x3011,
924             "NetMos NM9865 Single UART and 1284 Printer port",
925             DEFAULT_RCLK,
926             PUC_PORT_1S1P, 0x10, 4, 0,
927         },
928
929         {   0x9710, 0x9865, 0xa000, 0x3012,
930             "NetMos NM9865 Dual UART and 1284 Printer port",
931             DEFAULT_RCLK,
932             PUC_PORT_2S1P, 0x10, 4, 0,
933         },
934
935         {   0x9710, 0x9865, 0xa000, 0x3020,
936             "NetMos NM9865 Dual 1284 Printer port",
937             DEFAULT_RCLK,
938             PUC_PORT_2P, 0x10, 4, 0,
939         },
940
941         {   0xb00c, 0x021c, 0xffff, 0,
942             "IC Book Labs Gunboat x4 Lite",
943             DEFAULT_RCLK,
944             PUC_PORT_4S, 0x10, 0, 8,
945             .config_function = puc_config_icbook
946         },
947
948         {   0xb00c, 0x031c, 0xffff, 0,
949             "IC Book Labs Gunboat x4 Pro",
950             DEFAULT_RCLK,
951             PUC_PORT_4S, 0x10, 0, 8,
952             .config_function = puc_config_icbook
953         },
954
955         {   0xb00c, 0x041c, 0xffff, 0,
956             "IC Book Labs Ironclad x8 Lite",
957             DEFAULT_RCLK,
958             PUC_PORT_8S, 0x10, 0, 8,
959             .config_function = puc_config_icbook
960         },
961
962         {   0xb00c, 0x051c, 0xffff, 0,
963             "IC Book Labs Ironclad x8 Pro",
964             DEFAULT_RCLK,
965             PUC_PORT_8S, 0x10, 0, 8,
966             .config_function = puc_config_icbook
967         },
968
969         {   0xb00c, 0x081c, 0xffff, 0,
970             "IC Book Labs Dreadnought x16 Pro",
971             DEFAULT_RCLK * 8,
972             PUC_PORT_16S, 0x10, 0, 8,
973             .config_function = puc_config_icbook
974         },
975
976         {   0xb00c, 0x091c, 0xffff, 0,
977             "IC Book Labs Dreadnought x16 Lite",
978             DEFAULT_RCLK,
979             PUC_PORT_16S, 0x10, 0, 8,
980             .config_function = puc_config_icbook
981         },
982
983         {   0xb00c, 0x0a1c, 0xffff, 0,
984             "IC Book Labs Gunboat x2 Low Profile",
985             DEFAULT_RCLK,
986             PUC_PORT_2S, 0x10, 0, 8,
987         },
988
989         {   0xb00c, 0x0b1c, 0xffff, 0,
990             "IC Book Labs Gunboat x4 Low Profile",
991             DEFAULT_RCLK,
992             PUC_PORT_4S, 0x10, 0, 8,
993             .config_function = puc_config_icbook
994         },
995
996         { 0xffff, 0, 0xffff, 0, NULL, 0 }
997 };
998
999 static int
1000 puc_config_amc(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1001     intptr_t *res)
1002 {
1003         switch (cmd) {
1004         case PUC_CFG_GET_OFS:
1005                 *res = 8 * (port & 1);
1006                 return (0);
1007         case PUC_CFG_GET_RID:
1008                 *res = 0x14 + (port >> 1) * 4;
1009                 return (0);
1010         default:
1011                 break;
1012         }
1013         return (ENXIO);
1014 }
1015
1016 static int
1017 puc_config_cronyx(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1018     intptr_t *res)
1019 {
1020         if (cmd == PUC_CFG_GET_OFS) {
1021                 *res = port * 0x200;
1022                 return (0);
1023         }
1024         return (ENXIO);
1025 }
1026
1027 static int
1028 puc_config_diva(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1029     intptr_t *res)
1030 {
1031         const struct puc_cfg *cfg = sc->sc_cfg;
1032
1033         if (cmd == PUC_CFG_GET_OFS) {
1034                 if (cfg->subdevice == 0x1282)           /* Everest SP */
1035                         port <<= 1;
1036                 else if (cfg->subdevice == 0x104b)      /* Maestro SP2 */
1037                         port = (port == 3) ? 4 : port;
1038                 *res = port * 8 + ((port > 2) ? 0x18 : 0);
1039                 return (0);
1040         }
1041         return (ENXIO);
1042 }
1043
1044 static int
1045 puc_config_icbook(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1046     intptr_t *res)
1047 {
1048         if (cmd == PUC_CFG_GET_ILR) {
1049                 *res = PUC_ILR_DIGI;
1050                 return (0);
1051         }
1052         return (ENXIO);
1053 }
1054
1055 static int
1056 puc_config_quatech(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1057     intptr_t *res)
1058 {
1059         const struct puc_cfg *cfg = sc->sc_cfg;
1060         struct puc_bar *bar;
1061         uint8_t v0, v1;
1062
1063         switch (cmd) {
1064         case PUC_CFG_SETUP:
1065                 /*
1066                  * Check if the scratchpad register is enabled or if the
1067                  * interrupt status and options registers are active.
1068                  */
1069                 bar = puc_get_bar(sc, cfg->rid);
1070                 if (bar == NULL)
1071                         return (ENXIO);
1072                 /* Set DLAB in the LCR register of UART 0. */
1073                 bus_write_1(bar->b_res, 3, 0x80);
1074                 /* Write 0 to the SPR register of UART 0. */
1075                 bus_write_1(bar->b_res, 7, 0);
1076                 /* Read back the contents of the SPR register of UART 0. */
1077                 v0 = bus_read_1(bar->b_res, 7);
1078                 /* Write a specific value to the SPR register of UART 0. */
1079                 bus_write_1(bar->b_res, 7, 0x80 + -cfg->clock);
1080                 /* Read back the contents of the SPR register of UART 0. */
1081                 v1 = bus_read_1(bar->b_res, 7);
1082                 /* Clear DLAB in the LCR register of UART 0. */
1083                 bus_write_1(bar->b_res, 3, 0);
1084                 /* Save the two values read-back from the SPR register. */
1085                 sc->sc_cfg_data = (v0 << 8) | v1;
1086                 if (v0 == 0 && v1 == 0x80 + -cfg->clock) {
1087                         /*
1088                          * The SPR register echoed the two values written
1089                          * by us. This means that the SPAD jumper is set.
1090                          */
1091                         device_printf(sc->sc_dev, "warning: extra features "
1092                             "not usable -- SPAD compatibility enabled\n");
1093                         return (0);
1094                 }
1095                 if (v0 != 0) {
1096                         /*
1097                          * The first value doesn't match. This can only mean
1098                          * that the SPAD jumper is not set and that a non-
1099                          * standard fixed clock multiplier jumper is set.
1100                          */
1101                         if (bootverbose)
1102                                 device_printf(sc->sc_dev, "fixed clock rate "
1103                                     "multiplier of %d\n", 1 << v0);
1104                         if (v0 < -cfg->clock)
1105                                 device_printf(sc->sc_dev, "warning: "
1106                                     "suboptimal fixed clock rate multiplier "
1107                                     "setting\n");
1108                         return (0);
1109                 }
1110                 /*
1111                  * The first value matched, but the second didn't. We know
1112                  * that the SPAD jumper is not set. We also know that the
1113                  * clock rate multiplier is software controlled *and* that
1114                  * we just programmed it to the maximum allowed.
1115                  */
1116                 if (bootverbose)
1117                         device_printf(sc->sc_dev, "clock rate multiplier of "
1118                             "%d selected\n", 1 << -cfg->clock);
1119                 return (0);
1120         case PUC_CFG_GET_CLOCK:
1121                 v0 = (sc->sc_cfg_data >> 8) & 0xff;
1122                 v1 = sc->sc_cfg_data & 0xff;
1123                 if (v0 == 0 && v1 == 0x80 + -cfg->clock) {
1124                         /*
1125                          * XXX With the SPAD jumper applied, there's no
1126                          * easy way of knowing if there's also a clock
1127                          * rate multiplier jumper installed. Let's hope
1128                          * not...
1129                          */
1130                         *res = DEFAULT_RCLK;
1131                 } else if (v0 == 0) {
1132                         /*
1133                          * No clock rate multiplier jumper installed,
1134                          * so we programmed the board with the maximum
1135                          * multiplier allowed as given to us in the
1136                          * clock field of the config record (negated).
1137                          */
1138                         *res = DEFAULT_RCLK << -cfg->clock;
1139                 } else
1140                         *res = DEFAULT_RCLK << v0;
1141                 return (0);
1142         case PUC_CFG_GET_ILR:
1143                 v0 = (sc->sc_cfg_data >> 8) & 0xff;
1144                 v1 = sc->sc_cfg_data & 0xff;
1145                 *res = (v0 == 0 && v1 == 0x80 + -cfg->clock)
1146                     ? PUC_ILR_NONE : PUC_ILR_QUATECH;
1147                 return (0);
1148         default:
1149                 break;
1150         }
1151         return (ENXIO);
1152 }
1153
1154 static int
1155 puc_config_syba(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1156     intptr_t *res)
1157 {
1158         static int base[] = { 0x251, 0x3f0, 0 };
1159         const struct puc_cfg *cfg = sc->sc_cfg;
1160         struct puc_bar *bar;
1161         int efir, idx, ofs;
1162         uint8_t v;
1163
1164         switch (cmd) {
1165         case PUC_CFG_SETUP:
1166                 bar = puc_get_bar(sc, cfg->rid);
1167                 if (bar == NULL)
1168                         return (ENXIO);
1169
1170                 /* configure both W83877TFs */
1171                 bus_write_1(bar->b_res, 0x250, 0x89);
1172                 bus_write_1(bar->b_res, 0x3f0, 0x87);
1173                 bus_write_1(bar->b_res, 0x3f0, 0x87);
1174                 idx = 0;
1175                 while (base[idx] != 0) {
1176                         efir = base[idx];
1177                         bus_write_1(bar->b_res, efir, 0x09);
1178                         v = bus_read_1(bar->b_res, efir + 1);
1179                         if ((v & 0x0f) != 0x0c)
1180                                 return (ENXIO);
1181                         bus_write_1(bar->b_res, efir, 0x16);
1182                         v = bus_read_1(bar->b_res, efir + 1);
1183                         bus_write_1(bar->b_res, efir, 0x16);
1184                         bus_write_1(bar->b_res, efir + 1, v | 0x04);
1185                         bus_write_1(bar->b_res, efir, 0x16);
1186                         bus_write_1(bar->b_res, efir + 1, v & ~0x04);
1187                         ofs = base[idx] & 0x300;
1188                         bus_write_1(bar->b_res, efir, 0x23);
1189                         bus_write_1(bar->b_res, efir + 1, (ofs + 0x78) >> 2);
1190                         bus_write_1(bar->b_res, efir, 0x24);
1191                         bus_write_1(bar->b_res, efir + 1, (ofs + 0xf8) >> 2);
1192                         bus_write_1(bar->b_res, efir, 0x25);
1193                         bus_write_1(bar->b_res, efir + 1, (ofs + 0xe8) >> 2);
1194                         bus_write_1(bar->b_res, efir, 0x17);
1195                         bus_write_1(bar->b_res, efir + 1, 0x03);
1196                         bus_write_1(bar->b_res, efir, 0x28);
1197                         bus_write_1(bar->b_res, efir + 1, 0x43);
1198                         idx++;
1199                 }
1200                 bus_write_1(bar->b_res, 0x250, 0xaa);
1201                 bus_write_1(bar->b_res, 0x3f0, 0xaa);
1202                 return (0);
1203         case PUC_CFG_GET_OFS:
1204                 switch (port) {
1205                 case 0:
1206                         *res = 0x2f8;
1207                         return (0);
1208                 case 1:
1209                         *res = 0x2e8;
1210                         return (0);
1211                 case 2:
1212                         *res = 0x3f8;
1213                         return (0);
1214                 case 3:
1215                         *res = 0x3e8;
1216                         return (0);
1217                 case 4:
1218                         *res = 0x278;
1219                         return (0);
1220                 }
1221                 break;
1222         default:
1223                 break;
1224         }
1225         return (ENXIO);
1226 }
1227
1228 static int
1229 puc_config_siig(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1230     intptr_t *res)
1231 {
1232         const struct puc_cfg *cfg = sc->sc_cfg;
1233
1234         switch (cmd) {
1235         case PUC_CFG_GET_OFS:
1236                 if (cfg->ports == PUC_PORT_8S) {
1237                         *res = (port > 4) ? 8 * (port - 4) : 0;
1238                         return (0);
1239                 }
1240                 break;
1241         case PUC_CFG_GET_RID:
1242                 if (cfg->ports == PUC_PORT_8S) {
1243                         *res = 0x10 + ((port > 4) ? 0x10 : 4 * port);
1244                         return (0);
1245                 }
1246                 if (cfg->ports == PUC_PORT_2S1P) {
1247                         switch (port) {
1248                         case 0: *res = 0x10; return (0);
1249                         case 1: *res = 0x14; return (0);
1250                         case 2: *res = 0x1c; return (0);
1251                         }
1252                 }
1253                 break;
1254         default:
1255                 break;
1256         }
1257         return (ENXIO);
1258 }
1259
1260 static int
1261 puc_config_timedia(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1262     intptr_t *res)
1263 {
1264         static uint16_t dual[] = {
1265             0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085,
1266             0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 
1267             0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, 
1268             0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079,
1269             0xD079, 0
1270         };
1271         static uint16_t quad[] = {
1272             0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 
1273             0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 
1274             0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056,
1275             0xB157, 0
1276         };
1277         static uint16_t octa[] = {
1278             0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 
1279             0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0
1280         };
1281         static struct {
1282                 int ports;
1283                 uint16_t *ids;
1284         } subdevs[] = {
1285             { 2, dual },
1286             { 4, quad },
1287             { 8, octa },
1288             { 0, NULL }
1289         };
1290         static char desc[64];
1291         int dev, id;
1292         uint16_t subdev;
1293
1294         switch (cmd) {
1295         case PUC_CFG_GET_DESC:
1296                 snprintf(desc, sizeof(desc),
1297                     "Timedia technology %d Port Serial", (int)sc->sc_cfg_data);
1298                 *res = (intptr_t)desc;
1299                 return (0);
1300         case PUC_CFG_GET_NPORTS:
1301                 subdev = pci_get_subdevice(sc->sc_dev);
1302                 dev = 0;
1303                 while (subdevs[dev].ports != 0) {
1304                         id = 0;
1305                         while (subdevs[dev].ids[id] != 0) {
1306                                 if (subdev == subdevs[dev].ids[id]) {
1307                                         sc->sc_cfg_data = subdevs[dev].ports;
1308                                         *res = sc->sc_cfg_data;
1309                                         return (0);
1310                                 }
1311                                 id++;
1312                         }
1313                         dev++;
1314                 }
1315                 return (ENXIO);
1316         case PUC_CFG_GET_OFS:
1317                 *res = (port == 1 || port == 3) ? 8 : 0;
1318                 return (0);
1319         case PUC_CFG_GET_RID:
1320                 *res = 0x10 + ((port > 3) ? port - 2 : port >> 1) * 4;
1321                 return (0);
1322         case PUC_CFG_GET_TYPE:
1323                 *res = PUC_TYPE_SERIAL;
1324                 return (0);
1325         default:
1326                 break;
1327         }
1328         return (ENXIO);
1329 }
1330
1331 static int
1332 puc_config_oxford_pcie(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1333     intptr_t *res)
1334 {
1335         const struct puc_cfg *cfg = sc->sc_cfg;
1336         int idx;
1337         struct puc_bar *bar;
1338         uint8_t value;
1339
1340         switch (cmd) {
1341         case PUC_CFG_SETUP:
1342                 device_printf(sc->sc_dev, "%d UARTs detected\n",
1343                         sc->sc_nports);
1344
1345                 /* Set UARTs to enhanced mode */
1346                 bar = puc_get_bar(sc, cfg->rid);
1347                 if (bar == NULL)
1348                         return (ENXIO);
1349                 for (idx = 0; idx < sc->sc_nports; idx++) {
1350                         value = bus_read_1(bar->b_res, 0x1000 + (idx << 9) +
1351                             0x92);
1352                         bus_write_1(bar->b_res, 0x1000 + (idx << 9) + 0x92,
1353                             value | 0x10);
1354                 }
1355                 return (0);
1356         case PUC_CFG_GET_LEN:
1357                 *res = 0x200;
1358                 return (0);
1359         case PUC_CFG_GET_NPORTS:
1360                 /*
1361                  * Check if we are being called from puc_bfe_attach()
1362                  * or puc_bfe_probe(). If puc_bfe_probe(), we cannot
1363                  * puc_get_bar(), so we return a value of 16. This has cosmetic
1364                  * side-effects at worst; in PUC_CFG_GET_DESC,
1365                  * (int)sc->sc_cfg_data will not contain the true number of
1366                  * ports in PUC_CFG_GET_DESC, but we are not implementing that
1367                  * call for this device family anyway.
1368                  *
1369                  * The check is for initialisation of sc->sc_bar[idx], which is
1370                  * only done in puc_bfe_attach().
1371                  */
1372                 idx = 0;
1373                 do {
1374                         if (sc->sc_bar[idx++].b_rid != -1) {
1375                                 sc->sc_cfg_data = 16;
1376                                 *res = sc->sc_cfg_data;
1377                                 return (0);
1378                         }
1379                 } while (idx < PUC_PCI_BARS);
1380
1381                 bar = puc_get_bar(sc, cfg->rid);
1382                 if (bar == NULL)
1383                         return (ENXIO);
1384
1385                 value = bus_read_1(bar->b_res, 0x04);
1386                 if (value == 0)
1387                         return (ENXIO);
1388
1389                 sc->sc_cfg_data = value;
1390                 *res = sc->sc_cfg_data;
1391                 return (0);
1392         case PUC_CFG_GET_OFS:
1393                 *res = 0x1000 + (port << 9);
1394                 return (0);
1395         case PUC_CFG_GET_TYPE:
1396                 *res = PUC_TYPE_SERIAL;
1397                 return (0);
1398         default:
1399                 break;
1400         }
1401         return (ENXIO);
1402 }
1403
1404 static int
1405 puc_config_titan(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1406     intptr_t *res)
1407 {
1408         switch (cmd) {
1409         case PUC_CFG_GET_OFS:
1410                 *res = (port < 3) ? 0 : (port - 2) << 3;
1411                 return (0);
1412         case PUC_CFG_GET_RID:
1413                 *res = 0x14 + ((port >= 2) ? 0x0c : port << 2);
1414                 return (0);
1415         default:
1416                 break;
1417         }
1418         return (ENXIO);
1419 }