xref: /freebsd/sys/dev/ppc/ppc.c (revision 380a989b3223d455375b4fae70fd0b9bdd43bafb)
1 /*-
2  * Copyright (c) 1997, 1998 Nicolas Souchu
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *	$Id: ppc.c,v 1.12 1998/12/07 21:58:22 archie Exp $
27  *
28  */
29 #include "ppc.h"
30 
31 #if NPPC > 0
32 
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/malloc.h>
37 #include <sys/kernel.h>
38 
39 #include <machine/clock.h>
40 
41 #include <vm/vm.h>
42 #include <vm/vm_param.h>
43 #include <vm/pmap.h>
44 
45 #include <i386/isa/isa_device.h>
46 
47 #include <dev/ppbus/ppbconf.h>
48 #include <dev/ppbus/ppb_msq.h>
49 
50 #include <i386/isa/ppcreg.h>
51 
52 static int	ppcprobe(struct isa_device *);
53 static int	ppcattach(struct isa_device *);
54 
55 struct isa_driver ppcdriver = {
56 	ppcprobe, ppcattach, "ppc"
57 };
58 
59 static struct ppc_data *ppcdata[NPPC];
60 static int nppc = 0;
61 
62 static char *ppc_types[] = {
63 	"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
64 	"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
65 };
66 
67 /* list of available modes */
68 static char *ppc_avms[] = {
69 	"COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only",
70 	"EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only",
71 	"ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP",
72 	"ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0
73 };
74 
75 /* list of current executing modes
76  * Note that few modes do not actually exist.
77  */
78 static char *ppc_modes[] = {
79 	"COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP",
80 	"EPP", "EPP", "EPP", "ECP",
81 	"ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP",
82 	"ECP+EPP", "ECP+EPP", "ECP+EPP", 0
83 };
84 
85 static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
86 
87 /*
88  * BIOS printer list - used by BIOS probe.
89  */
90 #define	BIOS_PPC_PORTS	0x408
91 #define	BIOS_PORTS	(short *)(KERNBASE+BIOS_PPC_PORTS)
92 #define	BIOS_MAX_PPC	4
93 
94 /*
95  * All these functions are default actions for IN/OUT operations.
96  * They may be redefined if needed.
97  */
98 static void ppc_outsb_epp(int unit, char *addr, int cnt) {
99 	outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
100 static void ppc_outsw_epp(int unit, char *addr, int cnt) {
101 	outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
102 static void ppc_outsl_epp(int unit, char *addr, int cnt) {
103 	outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
104 static void ppc_insb_epp(int unit, char *addr, int cnt) {
105 	insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
106 static void ppc_insw_epp(int unit, char *addr, int cnt) {
107 	insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
108 static void ppc_insl_epp(int unit, char *addr, int cnt) {
109 	insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
110 
111 static char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); }
112 static char ppc_rstr(int unit) { return r_str(ppcdata[unit]); }
113 static char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); }
114 static char ppc_repp(int unit) { return r_epp(ppcdata[unit]); }
115 static char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); }
116 static char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); }
117 
118 static void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); }
119 static void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); }
120 static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
121 static void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); }
122 static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
123 static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
124 
125 static void ppc_reset_epp_timeout(int);
126 static void ppc_ecp_sync(int);
127 static ointhand2_t ppcintr;
128 
129 static int ppc_exec_microseq(int, struct ppb_microseq **);
130 static int ppc_generic_setmode(int, int);
131 static int ppc_smclike_setmode(int, int);
132 
133 static struct ppb_adapter ppc_smclike_adapter = {
134 
135 	0,	/* no intr handler, filled by chipset dependent code */
136 
137 	ppc_reset_epp_timeout, ppc_ecp_sync,
138 
139 	ppc_exec_microseq,
140 
141 	ppc_smclike_setmode,
142 
143 	ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
144 	ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
145 
146 	ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
147 	ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
148 };
149 
150 static struct ppb_adapter ppc_generic_adapter = {
151 
152 	0,	/* no intr handler, filled by chipset dependent code */
153 
154 	ppc_reset_epp_timeout, ppc_ecp_sync,
155 
156 	ppc_exec_microseq,
157 
158 	ppc_generic_setmode,
159 
160 	ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
161 	ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
162 
163 	ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
164 	ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
165 };
166 
167 /*
168  * ppc_ecp_sync()		XXX
169  */
170 static void
171 ppc_ecp_sync(int unit) {
172 
173 	struct ppc_data *ppc = ppcdata[unit];
174 	int i, r;
175 
176 	r = r_ecr(ppc);
177 	if ((r & 0xe0) != 0x80)
178 		return;
179 
180 	for (i = 0; i < 100; i++) {
181 		r = r_ecr(ppc);
182 		if (r & 0x1)
183 			return;
184 		DELAY(100);
185 	}
186 
187 	printf("ppc%d: ECP sync failed as data still " \
188 		"present in FIFO.\n", unit);
189 
190 	return;
191 }
192 
193 static void
194 ppcintr(int unit)
195 {
196 	/* call directly upper code */
197 	ppb_intr(&ppcdata[unit]->ppc_link);
198 
199 	return;
200 }
201 
202 static int
203 ppc_detect_port(struct ppc_data *ppc)
204 {
205 
206 	w_ctr(ppc, 0x0c);	/* To avoid missing PS2 ports */
207 	w_dtr(ppc, 0xaa);
208 	if (r_dtr(ppc) != (char) 0xaa)
209 		return (0);
210 
211 	return (1);
212 }
213 
214 /*
215  * ppc_pc873xx_detect
216  *
217  * Probe for a Natsemi PC873xx-family part.
218  *
219  * References in this function are to the National Semiconductor
220  * PC87332 datasheet TL/C/11930, May 1995 revision.
221  */
222 static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
223 static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
224 static int pc873xx_irqtab[] = {5, 7, 5, 0};
225 
226 static int pc873xx_regstab[] = {
227 	PC873_FER, PC873_FAR, PC873_PTR,
228 	PC873_FCR, PC873_PCR, PC873_PMC,
229 	PC873_TUP, PC873_SID, PC873_PNP0,
230 	PC873_PNP1, PC873_LPTBA, -1
231 };
232 
233 static char *pc873xx_rnametab[] = {
234 	"FER", "FAR", "PTR", "FCR", "PCR",
235 	"PMC", "TUP", "SID", "PNP0", "PNP1",
236 	"LPTBA", NULL
237 };
238 
239 static int
240 ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode)	/* XXX mode never forced */
241 {
242     static int	index = 0;
243     int		idport, irq;
244     int		ptr, pcr, val, i;
245 
246     while ((idport = pc873xx_basetab[index++])) {
247 
248 	/* XXX should check first to see if this location is already claimed */
249 
250 	/*
251 	 * Pull the 873xx through the power-on ID cycle (2.2,1.).
252 	 * We can't use this to locate the chip as it may already have
253 	 * been used by the BIOS.
254 	 */
255 	(void)inb(idport); (void)inb(idport);
256 	(void)inb(idport); (void)inb(idport);
257 
258 	/*
259 	 * Read the SID byte.  Possible values are :
260 	 *
261 	 * 01010xxx	PC87334
262 	 * 0001xxxx	PC87332
263 	 * 01110xxx	PC87306
264 	 */
265 	outb(idport, PC873_SID);
266 	val = inb(idport + 1);
267 	if ((val & 0xf0) == 0x10) {
268 	    ppc->ppc_type = NS_PC87332;
269 	} else if ((val & 0xf8) == 0x70) {
270 	    ppc->ppc_type = NS_PC87306;
271 	} else if ((val & 0xf8) == 0x50) {
272 	    ppc->ppc_type = NS_PC87334;
273 	} else {
274 	    if (bootverbose && (val != 0xff))
275 		printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
276 	    continue ;		/* not recognised */
277 	}
278 
279 	/* print registers */
280 	if (bootverbose) {
281 		printf("PC873xx");
282 		for (i=0; pc873xx_regstab[i] != -1; i++) {
283 			outb(idport, pc873xx_regstab[i]);
284 			printf(" %s=0x%x", pc873xx_rnametab[i],
285 						inb(idport + 1) & 0xff);
286 		}
287 		printf("\n");
288 	}
289 
290 	/*
291 	 * We think we have one.  Is it enabled and where we want it to be?
292 	 */
293 	outb(idport, PC873_FER);
294 	val = inb(idport + 1);
295 	if (!(val & PC873_PPENABLE)) {
296 	    if (bootverbose)
297 		printf("PC873xx parallel port disabled\n");
298 	    continue;
299 	}
300 	outb(idport, PC873_FAR);
301 	val = inb(idport + 1) & 0x3;
302 	/* XXX we should create a driver instance for every port found */
303 	if (pc873xx_porttab[val] != ppc->ppc_base) {
304 	    if (bootverbose)
305 		printf("PC873xx at 0x%x not for driver at port 0x%x\n",
306 		       pc873xx_porttab[val], ppc->ppc_base);
307 	    continue;
308 	}
309 
310 	outb(idport, PC873_PTR);
311         ptr = inb(idport + 1);
312 
313 	/* get irq settings */
314 	if (ppc->ppc_base == 0x378)
315 		irq = (ptr & PC873_LPTBIRQ7) ? 7 : 5;
316 	else
317 		irq = pc873xx_irqtab[val];
318 
319 	if (bootverbose)
320 		printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base);
321 
322 	/*
323 	 * Check if irq settings are correct
324 	 */
325 	if (irq != ppc->ppc_irq) {
326 		/*
327 		 * If the chipset is not locked and base address is 0x378,
328 		 * we have another chance
329 		 */
330 		if (ppc->ppc_base == 0x378 && !(ptr & PC873_CFGLOCK)) {
331 			if (ppc->ppc_irq == 7) {
332 				outb(idport + 1, (ptr | PC873_LPTBIRQ7));
333 				outb(idport + 1, (ptr | PC873_LPTBIRQ7));
334 			} else {
335 				outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
336 				outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
337 			}
338 			if (bootverbose)
339 			   printf("PC873xx irq set to %d\n", ppc->ppc_irq);
340 		} else {
341 			if (bootverbose)
342 			   printf("PC873xx sorry, can't change irq setting\n");
343 		}
344 	} else {
345 		if (bootverbose)
346 			printf("PC873xx irq settings are correct\n");
347 	}
348 
349 	outb(idport, PC873_PCR);
350 	pcr = inb(idport + 1);
351 
352 	if ((ptr & PC873_CFGLOCK) || !chipset_mode) {
353 	    if (bootverbose)
354 		printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked");
355 
356 	    ppc->ppc_avm |= PPB_NIBBLE;
357 	    if (bootverbose)
358 		printf(", NIBBLE");
359 
360 	    if (pcr & PC873_EPPEN) {
361 	        ppc->ppc_avm |= PPB_EPP;
362 
363 		if (bootverbose)
364 			printf(", EPP");
365 
366 		if (pcr & PC873_EPP19)
367 			ppc->ppc_epp = EPP_1_9;
368 		else
369 			ppc->ppc_epp = EPP_1_7;
370 
371 		if ((ppc->ppc_type == NS_PC87332) && bootverbose) {
372 			outb(idport, PC873_PTR);
373 			ptr = inb(idport + 1);
374 			if (ptr & PC873_EPPRDIR)
375 				printf(", Regular mode");
376 			else
377 				printf(", Automatic mode");
378 		}
379 	    } else if (pcr & PC873_ECPEN) {
380 		ppc->ppc_avm |= PPB_ECP;
381 		if (bootverbose)
382 			printf(", ECP");
383 
384 		if (pcr & PC873_ECPCLK)	{		/* XXX */
385 			ppc->ppc_avm |= PPB_PS2;
386 			if (bootverbose)
387 				printf(", PS/2");
388 		}
389 	    } else {
390 		outb(idport, PC873_PTR);
391 		ptr = inb(idport + 1);
392 		if (ptr & PC873_EXTENDED) {
393 			ppc->ppc_avm |= PPB_SPP;
394                         if (bootverbose)
395                                 printf(", SPP");
396 		}
397 	    }
398 	} else {
399 		if (bootverbose)
400 			printf("PC873xx unlocked");
401 
402 		if (chipset_mode & PPB_ECP) {
403 			if ((chipset_mode & PPB_EPP) && bootverbose)
404 				printf(", ECP+EPP not supported");
405 
406 			pcr &= ~PC873_EPPEN;
407 			pcr |= (PC873_ECPEN | PC873_ECPCLK);	/* XXX */
408 			outb(idport + 1, pcr);
409 			outb(idport + 1, pcr);
410 
411 			if (bootverbose)
412 				printf(", ECP");
413 
414 		} else if (chipset_mode & PPB_EPP) {
415 			pcr &= ~(PC873_ECPEN | PC873_ECPCLK);
416 			pcr |= (PC873_EPPEN | PC873_EPP19);
417 			outb(idport + 1, pcr);
418 			outb(idport + 1, pcr);
419 
420 			ppc->ppc_epp = EPP_1_9;			/* XXX */
421 
422 			if (bootverbose)
423 				printf(", EPP1.9");
424 
425 			/* enable automatic direction turnover */
426 			if (ppc->ppc_type == NS_PC87332) {
427 				outb(idport, PC873_PTR);
428 				ptr = inb(idport + 1);
429 				ptr &= ~PC873_EPPRDIR;
430 				outb(idport + 1, ptr);
431 				outb(idport + 1, ptr);
432 
433 				if (bootverbose)
434 					printf(", Automatic mode");
435 			}
436 		} else {
437 			pcr &= ~(PC873_ECPEN | PC873_ECPCLK | PC873_EPPEN);
438 			outb(idport + 1, pcr);
439 			outb(idport + 1, pcr);
440 
441 			/* configure extended bit in PTR */
442 			outb(idport, PC873_PTR);
443 			ptr = inb(idport + 1);
444 
445 			if (chipset_mode & PPB_PS2) {
446 				ptr |= PC873_EXTENDED;
447 
448 				if (bootverbose)
449 					printf(", PS/2");
450 
451 			} else {
452 				/* default to NIBBLE mode */
453 				ptr &= ~PC873_EXTENDED;
454 
455 				if (bootverbose)
456 					printf(", NIBBLE");
457 			}
458 			outb(idport + 1, ptr);
459 			outb(idport + 1, ptr);
460 		}
461 
462 		ppc->ppc_avm = chipset_mode;
463 	}
464 
465 	if (bootverbose)
466 		printf("\n");
467 
468 	ppc->ppc_link.adapter = &ppc_generic_adapter;
469 	ppc_generic_setmode(ppc->ppc_unit, chipset_mode);
470 
471 	return(chipset_mode);
472     }
473     return(-1);
474 }
475 
476 static int
477 ppc_check_epp_timeout(struct ppc_data *ppc)
478 {
479 	ppc_reset_epp_timeout(ppc->ppc_unit);
480 
481 	return (!(r_str(ppc) & TIMEOUT));
482 }
483 
484 /*
485  * ppc_smc37c66xgt_detect
486  *
487  * SMC FDC37C66xGT configuration.
488  */
489 static int
490 ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
491 {
492 	int s, i;
493 	char r;
494 	int type = -1;
495 	int csr = SMC66x_CSR;	/* initial value is 0x3F0 */
496 
497 	int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
498 
499 
500 #define cio csr+1	/* config IO port is either 0x3F1 or 0x371 */
501 
502 	/*
503 	 * Detection: enter configuration mode and read CRD register.
504 	 */
505 
506 	s = splhigh();
507 	outb(csr, SMC665_iCODE);
508 	outb(csr, SMC665_iCODE);
509 	splx(s);
510 
511 	outb(csr, 0xd);
512 	if (inb(cio) == 0x65) {
513 		type = SMC_37C665GT;
514 		goto config;
515 	}
516 
517 	for (i = 0; i < 2; i++) {
518 		s = splhigh();
519 		outb(csr, SMC666_iCODE);
520 		outb(csr, SMC666_iCODE);
521 		splx(s);
522 
523 		outb(csr, 0xd);
524 		if (inb(cio) == 0x66) {
525 			type = SMC_37C666GT;
526 			break;
527 		}
528 
529 		/* Another chance, CSR may be hard-configured to be at 0x370 */
530 		csr = SMC666_CSR;
531 	}
532 
533 config:
534 	/*
535 	 * If chipset not found, do not continue.
536 	 */
537 	if (type == -1)
538 		return (-1);
539 
540 	/* select CR1 */
541 	outb(csr, 0x1);
542 
543 	/* read the port's address: bits 0 and 1 of CR1 */
544 	r = inb(cio) & SMC_CR1_ADDR;
545 	if (port_address[r] != ppc->ppc_base)
546 		return (-1);
547 
548 	ppc->ppc_type = type;
549 
550 	/*
551 	 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
552 	 * If SPP mode is detected, try to set ECP+EPP mode
553 	 */
554 
555 	if (bootverbose) {
556 		outb(csr, 0x1);
557 		printf("ppc%d: SMC registers CR1=0x%x", ppc->ppc_unit,
558 			inb(cio) & 0xff);
559 
560 		outb(csr, 0x4);
561 		printf(" CR4=0x%x", inb(cio) & 0xff);
562 	}
563 
564 	/* select CR1 */
565 	outb(csr, 0x1);
566 
567 	if (!chipset_mode) {
568 		/* autodetect mode */
569 
570 		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
571 		if (type == SMC_37C666GT) {
572 			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
573 			if (bootverbose)
574 				printf(" configuration hardwired, supposing " \
575 					"ECP+EPP SPP");
576 
577 		} else
578 		   if ((inb(cio) & SMC_CR1_MODE) == 0) {
579 			/* already in extended parallel port mode, read CR4 */
580 			outb(csr, 0x4);
581 			r = (inb(cio) & SMC_CR4_EMODE);
582 
583 			switch (r) {
584 			case SMC_SPP:
585 				ppc->ppc_avm |= PPB_SPP;
586 				if (bootverbose)
587 					printf(" SPP");
588 				break;
589 
590 			case SMC_EPPSPP:
591 				ppc->ppc_avm |= PPB_EPP | PPB_SPP;
592 				if (bootverbose)
593 					printf(" EPP SPP");
594 				break;
595 
596 			case SMC_ECP:
597 				ppc->ppc_avm |= PPB_ECP | PPB_SPP;
598 				if (bootverbose)
599 					printf(" ECP SPP");
600 				break;
601 
602 			case SMC_ECPEPP:
603 				ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
604 				if (bootverbose)
605 					printf(" ECP+EPP SPP");
606 				break;
607 			}
608 		   } else {
609 			/* not an extended port mode */
610 			ppc->ppc_avm |= PPB_SPP;
611 			if (bootverbose)
612 				printf(" SPP");
613 		   }
614 
615 	} else {
616 		/* mode forced */
617 		ppc->ppc_avm = chipset_mode;
618 
619 		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
620 		if (type == SMC_37C666GT)
621 			goto end_detect;
622 
623 		r = inb(cio);
624 		if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) {
625 			/* do not use ECP when the mode is not forced to */
626 			outb(cio, r | SMC_CR1_MODE);
627 			if (bootverbose)
628 				printf(" SPP");
629 		} else {
630 			/* an extended mode is selected */
631 			outb(cio, r & ~SMC_CR1_MODE);
632 
633 			/* read CR4 register and reset mode field */
634 			outb(csr, 0x4);
635 			r = inb(cio) & ~SMC_CR4_EMODE;
636 
637 			if (chipset_mode & PPB_ECP) {
638 				if (chipset_mode & PPB_EPP) {
639 					outb(cio, r | SMC_ECPEPP);
640 					if (bootverbose)
641 						printf(" ECP+EPP");
642 				} else {
643 					outb(cio, r | SMC_ECP);
644 					if (bootverbose)
645 						printf(" ECP");
646 				}
647 			} else {
648 				/* PPB_EPP is set */
649 				outb(cio, r | SMC_EPPSPP);
650 				if (bootverbose)
651 					printf(" EPP SPP");
652 			}
653 		}
654 		ppc->ppc_avm = chipset_mode;
655 	}
656 
657 end_detect:
658 
659 	if (bootverbose)
660 		printf ("\n");
661 
662 	if (ppc->ppc_avm & PPB_EPP) {
663 		/* select CR4 */
664 		outb(csr, 0x4);
665 		r = inb(cio);
666 
667 		/*
668 		 * Set the EPP protocol...
669 		 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
670 		 */
671 		if (ppc->ppc_epp == EPP_1_9)
672 			outb(cio, (r & ~SMC_CR4_EPPTYPE));
673 		else
674 			outb(cio, (r | SMC_CR4_EPPTYPE));
675 	}
676 
677 	/* end config mode */
678 	outb(csr, 0xaa);
679 
680 	ppc->ppc_link.adapter = &ppc_smclike_adapter;
681 	ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
682 
683 	return (chipset_mode);
684 }
685 
686 /*
687  * Winbond W83877F stuff
688  *
689  * EFER: extended function enable register
690  * EFIR: extended function index register
691  * EFDR: extended function data register
692  */
693 #define efir ((efer == 0x250) ? 0x251 : 0x3f0)
694 #define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
695 
696 static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 };
697 static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 };
698 static int w83877f_keyiter[] = { 1, 2, 2, 1 };
699 static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 };
700 
701 static int
702 ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
703 {
704 	int i, j, efer;
705 	unsigned char r, hefere, hefras;
706 
707 	for (i = 0; i < 4; i ++) {
708 		/* first try to enable configuration registers */
709 		efer = w83877f_efers[i];
710 
711 		/* write the key to the EFER */
712 		for (j = 0; j < w83877f_keyiter[i]; j ++)
713 			outb (efer, w83877f_keys[i]);
714 
715 		/* then check HEFERE and HEFRAS bits */
716 		outb (efir, 0x0c);
717 		hefere = inb(efdr) & WINB_HEFERE;
718 
719 		outb (efir, 0x16);
720 		hefras = inb(efdr) & WINB_HEFRAS;
721 
722 		/*
723 		 * HEFRAS	HEFERE
724 		 *   0		   1	write 89h to 250h (power-on default)
725 		 *   1		   0	write 86h twice to 3f0h
726 		 *   1		   1	write 87h twice to 3f0h
727 		 *   0		   0	write 88h to 250h
728 		 */
729 		if ((hefere | hefras) == w83877f_hefs[i])
730 			goto found;
731 	}
732 
733 	return (-1);	/* failed */
734 
735 found:
736 	/* check base port address - read from CR23 */
737 	outb(efir, 0x23);
738 	if (ppc->ppc_base != inb(efdr) * 4)		/* 4 bytes boundaries */
739 		return (-1);
740 
741 	/* read CHIP ID from CR9/bits0-3 */
742 	outb(efir, 0x9);
743 
744 	switch (inb(efdr) & WINB_CHIPID) {
745 		case WINB_W83877F_ID:
746 			ppc->ppc_type = WINB_W83877F;
747 			break;
748 
749 		case WINB_W83877AF_ID:
750 			ppc->ppc_type = WINB_W83877AF;
751 			break;
752 
753 		default:
754 			ppc->ppc_type = WINB_UNKNOWN;
755 	}
756 
757 	if (bootverbose) {
758 		/* dump of registers */
759 		printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]);
760 		for (i = 0; i <= 0xd; i ++) {
761 			outb(efir, i);
762 			printf("0x%x ", inb(efdr));
763 		}
764 		for (i = 0x10; i <= 0x17; i ++) {
765 			outb(efir, i);
766 			printf("0x%x ", inb(efdr));
767 		}
768 		outb(efir, 0x1e);
769 		printf("0x%x ", inb(efdr));
770 		for (i = 0x20; i <= 0x29; i ++) {
771 			outb(efir, i);
772 			printf("0x%x ", inb(efdr));
773 		}
774 		printf("\n");
775 		printf("ppc%d:", ppc->ppc_unit);
776 	}
777 
778 	ppc->ppc_link.adapter = &ppc_generic_adapter;
779 
780 	if (!chipset_mode) {
781 		/* autodetect mode */
782 
783 		/* select CR0 */
784 		outb(efir, 0x0);
785 		r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
786 
787 		/* select CR9 */
788 		outb(efir, 0x9);
789 		r |= (inb(efdr) & WINB_PRTMODS2);
790 
791 		switch (r) {
792 		case WINB_W83757:
793 			if (bootverbose)
794 				printf("ppc%d: W83757 compatible mode\n",
795 					ppc->ppc_unit);
796 			return (-1);	/* generic or SMC-like */
797 
798 		case WINB_EXTFDC:
799 		case WINB_EXTADP:
800 		case WINB_EXT2FDD:
801 		case WINB_JOYSTICK:
802 			if (bootverbose)
803 				printf(" not in parallel port mode\n");
804 			return (-1);
805 
806 		case (WINB_PARALLEL | WINB_EPP_SPP):
807 			ppc->ppc_avm |= PPB_EPP | PPB_SPP;
808 			if (bootverbose)
809 				printf(" EPP SPP");
810 			break;
811 
812 		case (WINB_PARALLEL | WINB_ECP):
813 			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
814 			if (bootverbose)
815 				printf(" ECP SPP");
816 			break;
817 
818 		case (WINB_PARALLEL | WINB_ECP_EPP):
819 			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
820 			ppc->ppc_link.adapter = &ppc_smclike_adapter;
821 
822 			if (bootverbose)
823 				printf(" ECP+EPP SPP");
824 			break;
825 		default:
826 			printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r);
827 		}
828 
829 	} else {
830 		/* mode forced */
831 
832 		/* select CR9 and set PRTMODS2 bit */
833 		outb(efir, 0x9);
834 		outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
835 
836 		/* select CR0 and reset PRTMODSx bits */
837 		outb(efir, 0x0);
838 		outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
839 
840 		if (chipset_mode & PPB_ECP) {
841 			if (chipset_mode & PPB_EPP) {
842 				outb(efdr, inb(efdr) | WINB_ECP_EPP);
843 				if (bootverbose)
844 					printf(" ECP+EPP");
845 
846 				ppc->ppc_link.adapter = &ppc_smclike_adapter;
847 
848 			} else {
849 				outb(efdr, inb(efdr) | WINB_ECP);
850 				if (bootverbose)
851 					printf(" ECP");
852 			}
853 		} else {
854 			/* select EPP_SPP otherwise */
855 			outb(efdr, inb(efdr) | WINB_EPP_SPP);
856 			if (bootverbose)
857 				printf(" EPP SPP");
858 		}
859 		ppc->ppc_avm = chipset_mode;
860 	}
861 
862 	if (bootverbose)
863 		printf("\n");
864 
865 	/* exit configuration mode */
866 	outb(efer, 0xaa);
867 
868 	ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
869 
870 	return (chipset_mode);
871 }
872 
873 /*
874  * ppc_generic_detect
875  */
876 static int
877 ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
878 {
879 	/* default to generic */
880 	ppc->ppc_link.adapter = &ppc_generic_adapter;
881 
882 	if (bootverbose)
883 		printf("ppc%d:", ppc->ppc_unit);
884 
885 	if (!chipset_mode) {
886 		/* first, check for ECP */
887 		w_ecr(ppc, 0x20);
888 		if ((r_ecr(ppc) & 0xe0) == 0x20) {
889 			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
890 			if (bootverbose)
891 				printf(" ECP SPP");
892 
893 			/* search for SMC style ECP+EPP mode */
894 			w_ecr(ppc, 0x80);
895 		}
896 
897 		/* try to reset EPP timeout bit */
898 		if (ppc_check_epp_timeout(ppc)) {
899 			ppc->ppc_avm |= PPB_EPP;
900 
901 			if (ppc->ppc_avm & PPB_ECP) {
902 				/* SMC like chipset found */
903 				ppc->ppc_type = SMC_LIKE;
904 				ppc->ppc_link.adapter = &ppc_smclike_adapter;
905 
906 				if (bootverbose)
907 					printf(" ECP+EPP");
908 			} else {
909 				if (bootverbose)
910 					printf(" EPP");
911 			}
912 		} else {
913 			/* restore to standard mode */
914 			w_ecr(ppc, 0x0);
915 		}
916 
917 		/* XXX try to detect NIBBLE and PS2 modes */
918 		ppc->ppc_avm |= PPB_NIBBLE;
919 
920 		if (bootverbose)
921 			printf(" SPP");
922 
923 	} else {
924 		ppc->ppc_avm = chipset_mode;
925 	}
926 
927 	if (bootverbose)
928 		printf("\n");
929 
930 	ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
931 
932 	return (chipset_mode);
933 }
934 
935 /*
936  * ppc_detect()
937  *
938  * mode is the mode suggested at boot
939  */
940 static int
941 ppc_detect(struct ppc_data *ppc, int chipset_mode) {
942 
943 	int i, mode;
944 
945 	/* list of supported chipsets */
946 	int (*chipset_detect[])(struct ppc_data *, int) = {
947 		ppc_pc873xx_detect,
948 		ppc_smc37c66xgt_detect,
949 		ppc_w83877f_detect,
950 		ppc_generic_detect,
951 		NULL
952 	};
953 
954 	/* if can't find the port and mode not forced return error */
955 	if (!ppc_detect_port(ppc) && chipset_mode == 0)
956 		return (EIO);			/* failed, port not present */
957 
958 	/* assume centronics compatible mode is supported */
959 	ppc->ppc_avm = PPB_COMPATIBLE;
960 
961 	/* we have to differenciate available chipset modes,
962 	 * chipset running modes and IEEE-1284 operating modes
963 	 *
964 	 * after detection, the port must support running in compatible mode
965 	 */
966 	if (ppc->ppc_flags & 0x40) {
967 		if (bootverbose)
968 			printf("ppc: chipset forced to generic\n");
969 
970 		ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
971 
972 	} else {
973 		for (i=0; chipset_detect[i] != NULL; i++) {
974 			if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
975 				ppc->ppc_mode = mode;
976 				break;
977 			}
978 		}
979 	}
980 
981 	return (0);
982 }
983 
984 /*
985  * ppc_exec_microseq()
986  *
987  * Execute a microsequence.
988  * Microsequence mechanism is supposed to handle fast I/O operations.
989  */
990 static int
991 ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
992 {
993 	struct ppc_data	*ppc = ppcdata[unit];
994 	struct ppb_microseq *mi;
995 	char cc, *p;
996 	int i, iter, len;
997 	int error;
998 
999 	register int reg;
1000 	register char mask;
1001 	register int accum = 0;
1002 	register char *ptr = 0;
1003 
1004 	struct ppb_microseq *stack = 0;
1005 
1006 /* microsequence registers are equivalent to PC-like port registers */
1007 #define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register))
1008 #define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
1009 
1010 #define INCR_PC (mi ++)		/* increment program counter */
1011 
1012 	mi = *p_msq;
1013 	for (;;) {
1014 		switch (mi->opcode) {
1015 		case MS_OP_RSET:
1016 			cc = r_reg(mi->arg[0].i, ppc);
1017 			cc &= (char)mi->arg[2].i;	/* clear mask */
1018 			cc |= (char)mi->arg[1].i;	/* assert mask */
1019                         w_reg(mi->arg[0].i, ppc, cc);
1020 			INCR_PC;
1021                         break;
1022 
1023 		case MS_OP_RASSERT_P:
1024 			reg = mi->arg[1].i;
1025 			ptr = ppc->ppc_ptr;
1026 
1027 			if ((len = mi->arg[0].i) == MS_ACCUM) {
1028 				accum = ppc->ppc_accum;
1029 				for (; accum; accum--)
1030 					w_reg(reg, ppc, *ptr++);
1031 				ppc->ppc_accum = accum;
1032 			} else
1033 				for (i=0; i<len; i++)
1034 					w_reg(reg, ppc, *ptr++);
1035 			ppc->ppc_ptr = ptr;
1036 
1037 			INCR_PC;
1038 			break;
1039 
1040                 case MS_OP_RFETCH_P:
1041 			reg = mi->arg[1].i;
1042 			mask = (char)mi->arg[2].i;
1043 			ptr = ppc->ppc_ptr;
1044 
1045 			if ((len = mi->arg[0].i) == MS_ACCUM) {
1046 				accum = ppc->ppc_accum;
1047 				for (; accum; accum--)
1048 					*ptr++ = r_reg(reg, ppc) & mask;
1049 				ppc->ppc_accum = accum;
1050 			} else
1051 				for (i=0; i<len; i++)
1052 					*ptr++ = r_reg(reg, ppc) & mask;
1053 			ppc->ppc_ptr = ptr;
1054 
1055 			INCR_PC;
1056                         break;
1057 
1058                 case MS_OP_RFETCH:
1059 			*((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
1060 							(char)mi->arg[1].i;
1061 			INCR_PC;
1062                         break;
1063 
1064 		case MS_OP_RASSERT:
1065                 case MS_OP_DELAY:
1066 
1067 		/* let's suppose the next instr. is the same */
1068 		prefetch:
1069 			for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
1070 				w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i);
1071 
1072 			if (mi->opcode == MS_OP_DELAY) {
1073 				DELAY(mi->arg[0].i);
1074 				INCR_PC;
1075 				goto prefetch;
1076 			}
1077 			break;
1078 
1079 		case MS_OP_ADELAY:
1080 			if (mi->arg[0].i)
1081 				tsleep(NULL, PPBPRI, "ppbdelay",
1082 						mi->arg[0].i * (hz/1000));
1083 			INCR_PC;
1084 			break;
1085 
1086 		case MS_OP_TRIG:
1087 			reg = mi->arg[0].i;
1088 			iter = mi->arg[1].i;
1089 			p = (char *)mi->arg[2].p;
1090 
1091 			/* XXX delay limited to 255 us */
1092 			for (i=0; i<iter; i++) {
1093 				w_reg(reg, ppc, *p++);
1094 				DELAY((unsigned char)*p++);
1095 			}
1096 			INCR_PC;
1097 			break;
1098 
1099                 case MS_OP_SET:
1100                         ppc->ppc_accum = mi->arg[0].i;
1101 			INCR_PC;
1102                         break;
1103 
1104                 case MS_OP_DBRA:
1105                         if (--ppc->ppc_accum > 0)
1106                                 mi += mi->arg[0].i;
1107 			else
1108 				INCR_PC;
1109                         break;
1110 
1111                 case MS_OP_BRSET:
1112                         cc = r_str(ppc);
1113                         if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i)
1114                                 mi += mi->arg[1].i;
1115 			else
1116 				INCR_PC;
1117                         break;
1118 
1119                 case MS_OP_BRCLEAR:
1120                         cc = r_str(ppc);
1121                         if ((cc & (char)mi->arg[0].i) == 0)
1122                                 mi += mi->arg[1].i;
1123 			else
1124 				INCR_PC;
1125                         break;
1126 
1127 		case MS_OP_BRSTAT:
1128 			cc = r_str(ppc);
1129 			if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) ==
1130 							(char)mi->arg[0].i)
1131 				mi += mi->arg[2].i;
1132 			else
1133 				INCR_PC;
1134 			break;
1135 
1136 		case MS_OP_C_CALL:
1137 			/*
1138 			 * If the C call returns !0 then end the microseq.
1139 			 * The current state of ptr is passed to the C function
1140 			 */
1141 			if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr)))
1142 				return (error);
1143 
1144 			INCR_PC;
1145 			break;
1146 
1147 		case MS_OP_PTR:
1148 			ppc->ppc_ptr = (char *)mi->arg[0].p;
1149 			INCR_PC;
1150 			break;
1151 
1152 		case MS_OP_CALL:
1153 			if (stack)
1154 				panic("%s: too much calls", __FUNCTION__);
1155 
1156 			if (mi->arg[0].p) {
1157 				/* store the state of the actual
1158 				 * microsequence
1159 				 */
1160 				stack = mi;
1161 
1162 				/* jump to the new microsequence */
1163 				mi = (struct ppb_microseq *)mi->arg[0].p;
1164 			} else
1165 				INCR_PC;
1166 
1167 			break;
1168 
1169 		case MS_OP_SUBRET:
1170 			/* retrieve microseq and pc state before the call */
1171 			mi = stack;
1172 
1173 			/* reset the stack */
1174 			stack = 0;
1175 
1176 			/* XXX return code */
1177 
1178 			INCR_PC;
1179 			break;
1180 
1181                 case MS_OP_PUT:
1182                 case MS_OP_GET:
1183                 case MS_OP_RET:
1184 			/* can't return to ppb level during the execution
1185 			 * of a submicrosequence */
1186 			if (stack)
1187 				panic("%s: can't return to ppb level",
1188 								__FUNCTION__);
1189 
1190 			/* update pc for ppb level of execution */
1191 			*p_msq = mi;
1192 
1193 			/* return to ppb level of execution */
1194 			return (0);
1195 
1196                 default:
1197                         panic("%s: unknown microsequence opcode 0x%x",
1198                                 __FUNCTION__, mi->opcode);
1199                 }
1200 	}
1201 
1202 	/* unreached */
1203 }
1204 
1205 /*
1206  * Configure current operating mode
1207  */
1208 static int
1209 ppc_generic_setmode(int unit, int mode)
1210 {
1211 	struct ppc_data *ppc = ppcdata[unit];
1212 
1213 	/* back to compatible mode, XXX don't know yet what to do here */
1214 	if (mode == 0) {
1215 		ppc->ppc_mode = PPB_COMPATIBLE;
1216 		return (0);
1217 	}
1218 
1219 	/* check if mode is available */
1220 	if (!(ppc->ppc_avm & mode))
1221 		return (EOPNOTSUPP);
1222 
1223 	/* if ECP mode, configure ecr register */
1224 	if (ppc->ppc_avm & PPB_ECP) {
1225 
1226 		/* XXX disable DMA, enable interrupts */
1227 		if (mode & PPB_EPP)
1228 			return (EOPNOTSUPP);
1229 		else if (mode & PPB_PS2)
1230 			/* select PS2 mode with ECP */
1231 			w_ecr(ppc, 0x20);
1232 		else if (mode & PPB_ECP)
1233 			/* select ECP mode */
1234 			w_ecr(ppc, 0x60);
1235 		else
1236 			/* select standard parallel port mode */
1237 			w_ecr(ppc, 0x00);
1238 	}
1239 
1240 	ppc->ppc_mode = mode;
1241 
1242 	return (0);
1243 }
1244 
1245 int
1246 ppc_smclike_setmode(int unit, int mode)
1247 {
1248 	struct ppc_data *ppc = ppcdata[unit];
1249 
1250 	/* back to compatible mode, XXX don't know yet what to do here */
1251 	if (mode == 0) {
1252 		ppc->ppc_mode = PPB_COMPATIBLE;
1253 		return (0);
1254 	}
1255 
1256 	/* check if mode is available */
1257 	if (!(ppc->ppc_avm & mode))
1258 		return (EOPNOTSUPP);
1259 
1260 	/* if ECP mode, configure ecr register */
1261 	if (ppc->ppc_avm & PPB_ECP) {
1262 
1263 		/* XXX disable DMA, enable interrupts */
1264 		if (mode & PPB_EPP)
1265 			/* select EPP mode */
1266 			w_ecr(ppc, 0x80);
1267 		else if (mode & PPB_PS2)
1268 			/* select PS2 mode with ECP */
1269 			w_ecr(ppc, 0x20);
1270 		else if (mode & PPB_ECP)
1271 			/* select ECP mode */
1272 			w_ecr(ppc, 0x60);
1273 		else
1274 			/* select standard parallel port mode */
1275 			w_ecr(ppc, 0x00);
1276 	}
1277 
1278 	ppc->ppc_mode = mode;
1279 
1280 
1281 	return (0);
1282 }
1283 
1284 /*
1285  * EPP timeout, according to the PC87332 manual
1286  * Semantics of clearing EPP timeout bit.
1287  * PC87332	- reading SPP_STR does it...
1288  * SMC		- write 1 to EPP timeout bit			XXX
1289  * Others	- (?) write 0 to EPP timeout bit
1290  */
1291 static void
1292 ppc_reset_epp_timeout(int unit)
1293 {
1294 	struct ppc_data *ppc = ppcdata[unit];
1295 	register char r;
1296 
1297 	r = r_str(ppc);
1298 	w_str(ppc, r | 0x1);
1299 	w_str(ppc, r & 0xfe);
1300 
1301 	return;
1302 }
1303 
1304 static int
1305 ppcprobe(struct isa_device *dvp)
1306 {
1307 	static short next_bios_ppc = 0;
1308 	struct ppc_data *ppc;
1309 
1310 	/*
1311 	 * If port not specified, use bios list.
1312 	 */
1313 	if(dvp->id_iobase < 0) {
1314 		if((next_bios_ppc < BIOS_MAX_PPC) &&
1315 				(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
1316 			dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
1317 			printf("ppc: parallel port found at 0x%x\n",
1318 							dvp->id_iobase);
1319 		} else
1320 			return (0);
1321 	}
1322 
1323 	/*
1324 	 * Port was explicitly specified.
1325 	 * This allows probing of ports unknown to the BIOS.
1326 	 */
1327 
1328 	/*
1329 	 * Allocate the ppc_data structure.
1330 	 */
1331 	ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
1332 	if (!ppc) {
1333 		printf("ppc: cannot malloc!\n");
1334 		goto error;
1335 	}
1336 	bzero(ppc, sizeof(struct ppc_data));
1337 
1338 	ppc->ppc_base = dvp->id_iobase;
1339 	ppc->ppc_unit = dvp->id_unit;
1340 	ppc->ppc_type = GENERIC;
1341 
1342 	/* store boot flags */
1343 	ppc->ppc_flags = dvp->id_flags;
1344 
1345 	ppc->ppc_mode = PPB_COMPATIBLE;
1346 	ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
1347 
1348 	/*
1349 	 * XXX Try and detect if interrupts are working
1350 	 */
1351 	if (!(dvp->id_flags & 0x20))
1352 		ppc->ppc_irq = ffs(dvp->id_irq) - 1;
1353 
1354 	ppcdata[ppc->ppc_unit] = ppc;
1355 	nppc ++;
1356 
1357 	/*
1358 	 * Link the Parallel Port Chipset (adapter) to
1359 	 * the future ppbus. Default to a generic chipset
1360 	 */
1361 	ppc->ppc_link.adapter_unit = ppc->ppc_unit;
1362 	ppc->ppc_link.adapter = &ppc_generic_adapter;
1363 
1364 	/*
1365 	 * Try to detect the chipset and its mode.
1366 	 */
1367 	if (ppc_detect(ppc, dvp->id_flags & 0xf))
1368 		goto error;
1369 
1370 	return (1);
1371 
1372 error:
1373 	return (0);
1374 }
1375 
1376 static int
1377 ppcattach(struct isa_device *isdp)
1378 {
1379 	struct ppc_data *ppc = ppcdata[isdp->id_unit];
1380 	struct ppb_data *ppbus;
1381 
1382 	printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
1383 		ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
1384 		ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
1385 			ppc_epp_protocol[ppc->ppc_epp] : "");
1386 
1387 	isdp->id_ointr = ppcintr;
1388 
1389 	/*
1390 	 * Prepare ppbus data area for upper level code.
1391 	 */
1392 	ppbus = ppb_alloc_bus();
1393 
1394 	if (!ppbus)
1395 		return (0);
1396 
1397 	ppc->ppc_link.ppbus = ppbus;
1398 	ppbus->ppb_link = &ppc->ppc_link;
1399 
1400 	/*
1401 	 * Probe the ppbus and attach devices found.
1402 	 */
1403 	ppb_attachdevs(ppbus);
1404 
1405 	return (1);
1406 }
1407 #endif
1408