pucdata.c revision 222093
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 222093 2011-05-19 11:41:12Z jhb $");
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_cronyx;
52static puc_config_f puc_config_diva;
53static puc_config_f puc_config_icbook;
54static puc_config_f puc_config_quatech;
55static puc_config_f puc_config_syba;
56static puc_config_f puc_config_siig;
57static puc_config_f puc_config_timedia;
58static puc_config_f puc_config_titan;
59static puc_config_f puc_config_oxford_pcie;
60
61const 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
999static int
1000puc_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
1016static int
1017puc_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
1027static int
1028puc_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
1044static int
1045puc_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
1055static int
1056puc_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
1154static int
1155puc_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
1228static int
1229puc_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
1260static int
1261puc_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
1331static int
1332puc_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
1350		for (idx = 0; idx < sc->sc_nports; idx++) {
1351			value = bus_read_1(bar->b_res, 0x1000 + (idx << 9)
1352				+ 0x92);
1353			bus_write_1(bar->b_res, 0x1000 + (idx << 9) + 0x92,
1354				value | 0x10);
1355		}
1356
1357		return (0);
1358	case PUC_CFG_GET_LEN:
1359		*res = 0x200;
1360		return (0);
1361	case PUC_CFG_GET_NPORTS:
1362		/*
1363		 * Check if we are being called from puc_bfe_attach()
1364		 * or puc_bfe_probe(). If puc_bfe_probe(), we cannot
1365		 * puc_get_bar(), so we return a value of 16. This has cosmetic
1366		 * side-effects at worst; in PUC_CFG_GET_DESC,
1367		 * (int)sc->sc_cfg_data will not contain the true number of
1368		 * ports in PUC_CFG_GET_DESC, but we are not implementing that
1369		 * call for this device family anyway.
1370		 *
1371		 * The check is for initialisation of sc->sc_bar[idx], which is
1372		 * only done in puc_bfe_attach().
1373		 */
1374		idx = 0;
1375		do {
1376			if (sc->sc_bar[idx++].b_rid != -1) {
1377				sc->sc_cfg_data = 16;
1378				*res = sc->sc_cfg_data;
1379				return (0);
1380			}
1381		} while (idx < PUC_PCI_BARS);
1382
1383		bar = puc_get_bar(sc, cfg->rid);
1384		if (bar == NULL)
1385			return (ENXIO);
1386
1387		value = bus_read_1(bar->b_res, 0x04);
1388		if (value == 0)
1389			return (ENXIO);
1390
1391		sc->sc_cfg_data = value;
1392		*res = sc->sc_cfg_data;
1393		return (0);
1394	case PUC_CFG_GET_OFS:
1395		*res = 0x1000 + (port << 9);
1396		return (0);
1397	case PUC_CFG_GET_TYPE:
1398		*res = PUC_TYPE_SERIAL;
1399		return (0);
1400	default:
1401		break;
1402	}
1403	return (ENXIO);
1404}
1405
1406static int
1407puc_config_titan(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
1408    intptr_t *res)
1409{
1410	switch (cmd) {
1411	case PUC_CFG_GET_OFS:
1412		*res = (port < 3) ? 0 : (port - 2) << 3;
1413		return (0);
1414	case PUC_CFG_GET_RID:
1415		*res = 0x14 + ((port >= 2) ? 0x0c : port << 2);
1416		return (0);
1417	default:
1418		break;
1419	}
1420	return (ENXIO);
1421}
1422