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