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