xref: /freebsd/sys/dev/ppc/ppc.c (revision a654d072959982a88cfbd609921641d85a8eb50c)
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.8 1998/09/13 20:57:06 nsouch 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", 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 
128 static int ppc_exec_microseq(int, struct ppb_microseq **);
129 static int ppc_generic_setmode(int, int);
130 static int ppc_smclike_setmode(int, int);
131 
132 static struct ppb_adapter ppc_smclike_adapter = {
133 
134 	0,	/* no intr handler, filled by chipset dependent code */
135 
136 	ppc_reset_epp_timeout, ppc_ecp_sync,
137 
138 	ppc_exec_microseq,
139 
140 	ppc_smclike_setmode,
141 
142 	ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
143 	ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
144 
145 	ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
146 	ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
147 };
148 
149 static struct ppb_adapter ppc_generic_adapter = {
150 
151 	0,	/* no intr handler, filled by chipset dependent code */
152 
153 	ppc_reset_epp_timeout, ppc_ecp_sync,
154 
155 	ppc_exec_microseq,
156 
157 	ppc_generic_setmode,
158 
159 	ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
160 	ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
161 
162 	ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
163 	ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
164 };
165 
166 /*
167  * ppc_ecp_sync()		XXX
168  */
169 static void
170 ppc_ecp_sync(int unit) {
171 
172 	struct ppc_data *ppc = ppcdata[unit];
173 	int i, r;
174 
175 	r = r_ecr(ppc);
176 	if ((r & 0xe0) != 0x80)
177 		return;
178 
179 	for (i = 0; i < 100; i++) {
180 		r = r_ecr(ppc);
181 		if (r & 0x1)
182 			return;
183 		DELAY(100);
184 	}
185 
186 	printf("ppc%d: ECP sync failed as data still " \
187 		"present in FIFO.\n", unit);
188 
189 	return;
190 }
191 
192 void
193 ppcintr(int unit)
194 {
195 	/* call directly upper code */
196 	ppb_intr(&ppcdata[unit]->ppc_link);
197 
198 	return;
199 }
200 
201 static int
202 ppc_detect_port(struct ppc_data *ppc)
203 {
204 
205 	w_ctr(ppc, 0x0c);	/* To avoid missing PS2 ports */
206 	w_dtr(ppc, 0xaa);
207 	if (r_dtr(ppc) != (char) 0xaa)
208 		return (0);
209 
210 	return (1);
211 }
212 
213 /*
214  * ppc_pc873xx_detect
215  *
216  * Probe for a Natsemi PC873xx-family part.
217  *
218  * References in this function are to the National Semiconductor
219  * PC87332 datasheet TL/C/11930, May 1995 revision.
220  */
221 static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
222 static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
223 
224 static int
225 ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode)	/* XXX mode never forced */
226 {
227     static int	index = 0;
228     int		base, idport;
229     int		val;
230 
231     while ((idport = pc873xx_basetab[index++])) {
232 
233 	/* XXX should check first to see if this location is already claimed */
234 
235 	/*
236 	 * Pull the 873xx through the power-on ID cycle (2.2,1.).  We can't use this
237 	 * to locate the chip as it may already have been used by the BIOS.
238 	 */
239 	(void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport);
240 
241 	/*
242 	 * Read the SID byte.  Possible values are :
243 	 *
244 	 * 0001xxxx	PC87332
245 	 * 01110xxx	PC87306
246 	 */
247 	outb(idport, PC873_SID);
248 	val = inb(idport + 1);
249 	if ((val & 0xf0) == 0x10) {
250 	    ppc->ppc_type = NS_PC87332;
251 	} else if ((val & 0xf8) == 0x70) {
252 	    ppc->ppc_type = NS_PC87306;
253 	} else {
254 	    if (bootverbose && (val != 0xff))
255 		printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
256 	    continue ;		/* not recognised */
257 	}
258 
259 	/*
260 	 * We think we have one.  Is it enabled and where we want it to be?
261 	 */
262 	outb(idport, PC873_FER);
263 	val = inb(idport + 1);
264 	if (!(val & PC873_PPENABLE)) {
265 	    if (bootverbose)
266 		printf("PC873xx parallel port disabled\n");
267 	    continue;
268 	}
269 	outb(idport, PC873_FAR);
270 	val = inb(idport + 1) & 0x3;
271 	/* XXX we should create a driver instance for every port found */
272 	if (pc873xx_porttab[val] != ppc->ppc_base) {
273 	    if (bootverbose)
274 		printf("PC873xx at 0x%x not for driver at port 0x%x\n",
275 		       pc873xx_porttab[val], ppc->ppc_base);
276 	    continue;
277 	}
278 
279 	/*
280 	 * This is the port we want.  Can we dink with it to improve
281 	 * our chances?
282 	 */
283 	outb(idport, PC873_PTR);
284 	val = inb(idport + 1);
285 	if (val & PC873_CFGLOCK) {
286 	    if (bootverbose)
287 		printf("PC873xx locked\n");
288 
289 	    /* work out what mode we're in */
290 	    ppc->ppc_avm |= PPB_NIBBLE;		/* worst case */
291 
292 	    outb(idport, PC873_PCR);
293 	    val = inb(idport + 1);
294 	    if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
295 		outb(idport, PC873_PTR);
296 		val = inb(idport + 1);
297 		if (!(val & PC873_EPPRDIR)) {
298 		    ppc->ppc_avm |= PPB_EPP;	/* As we would have done it anwyay */
299 		}
300 	    } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
301 		ppc->ppc_avm |= PPB_PS2;	/* tolerable alternative */
302 	    }
303 	} else {
304 	    if (bootverbose)
305 		printf("PC873xx unlocked, ");
306 
307 #if 0	/* broken */
308 	    /*
309 	     * Frob the zero-wait-state option if possible; it causes
310 	     * unreliable operation.
311 	     */
312 	    outb(idport, PC873_FCR);
313 	    val = inb(idport + 1);
314 	    if ((ppc->ppc_type == NS_PC87306) ||	/* we are a '306 */
315 		!(val & PC873_ZWSPWDN)) {		/* or pin _is_ ZWS */
316 		val &= ~PC873_ZWS;
317 		outb(idport + 1, val);			/* must disable ZWS */
318 		outb(idport + 1, val);
319 
320 		if (bootverbose)
321 		    printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled");
322 	    }
323 
324 #endif
325 	    if (bootverbose)
326 		printf("reconfiguring for ");
327 
328 	    /*
329 	     * if the chip is at 0x3bc, we can't use EPP as there's no room
330 	     * for the extra registers.
331 	     *
332 	     * XXX should we use ECP mode always and use the EPP submode?
333 	     */
334 	    if (ppc->ppc_base != 0x3bc) {
335 		if (bootverbose)
336 		    printf("EPP 1.9\n");
337 
338 		/* configure for EPP 1.9 operation XXX should be configurable */
339 		outb(idport, PC873_PCR);
340 		val = inb(idport + 1);
341 		val &= ~(PC873_ECPEN | PC873_ECPCLK);	/* disable ECP */
342 		val |= (PC873_EPPEN | PC873_EPP19);	/* enable EPP */
343 		outb(idport + 1, val);
344 		outb(idport + 1, val);
345 
346 		/* enable automatic direction turnover */
347 		outb(idport, PC873_PTR);
348 		val = inb(idport + 1);
349 		val &= ~PC873_EPPRDIR;			/* disable "regular" direction change */
350 		outb(idport + 1, val);
351 		outb(idport + 1, val);
352 
353 		/* we are an EPP-32 port */
354 		ppc->ppc_avm |= PPB_EPP;
355 	    } else {
356 		if (bootverbose)
357 		    printf("ECP\n");
358 
359 		/* configure as an ECP port to get bidirectional operation for now */
360 		outb(idport, PC873_PCR);
361 		outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
362 
363 		/* we look like a PS/2 port */
364 		ppc->ppc_avm |= PPB_PS2;
365 	    }
366 	}
367 
368 	return(chipset_mode);
369     }
370     return(-1);
371 }
372 
373 static int
374 ppc_check_epp_timeout(struct ppc_data *ppc)
375 {
376 	ppc_reset_epp_timeout(ppc->ppc_unit);
377 
378 	return (!(r_str(ppc) & TIMEOUT));
379 }
380 
381 /*
382  * ppc_smc37c66xgt_detect
383  *
384  * SMC FDC37C66xGT configuration.
385  */
386 static int
387 ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
388 {
389 	int s, i;
390 	char r;
391 	int type = -1;
392 	int csr = SMC66x_CSR;	/* initial value is 0x3F0 */
393 
394 	int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
395 
396 
397 #define cio csr+1	/* config IO port is either 0x3F1 or 0x371 */
398 
399 	/*
400 	 * Detection: enter configuration mode and read CRD register.
401 	 */
402 
403 	s = splhigh();
404 	outb(csr, SMC665_iCODE);
405 	outb(csr, SMC665_iCODE);
406 	splx(s);
407 
408 	outb(csr, 0xd);
409 	if (inb(cio) == 0x65) {
410 		type = SMC_37C665GT;
411 		goto config;
412 	}
413 
414 	for (i = 0; i < 2; i++) {
415 		s = splhigh();
416 		outb(csr, SMC666_iCODE);
417 		outb(csr, SMC666_iCODE);
418 		splx(s);
419 
420 		outb(csr, 0xd);
421 		if (inb(cio) == 0x66) {
422 			type = SMC_37C666GT;
423 			break;
424 		}
425 
426 		/* Another chance, CSR may be hard-configured to be at 0x370 */
427 		csr = SMC666_CSR;
428 	}
429 
430 config:
431 	/*
432 	 * If chipset not found, do not continue.
433 	 */
434 	if (type == -1)
435 		return (-1);
436 
437 	/* select CR1 */
438 	outb(csr, 0x1);
439 
440 	/* read the port's address: bits 0 and 1 of CR1 */
441 	r = inb(cio) & SMC_CR1_ADDR;
442 	if (port_address[r] != ppc->ppc_base)
443 		return (-1);
444 
445 	ppc->ppc_type = type;
446 
447 	/*
448 	 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
449 	 * If SPP mode is detected, try to set ECP+EPP mode
450 	 */
451 
452 	if (bootverbose) {
453 		outb(csr, 0x1);
454 		printf("ppc%d: SMC registers CR1=0x%x", ppc->ppc_unit,
455 			inb(cio) & 0xff);
456 
457 		outb(csr, 0x4);
458 		printf(" CR4=0x%x", inb(cio) & 0xff);
459 	}
460 
461 	/* select CR1 */
462 	outb(csr, 0x1);
463 
464 	if (!chipset_mode) {
465 		/* autodetect mode */
466 
467 		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
468 		if (type == SMC_37C666GT) {
469 			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
470 			if (bootverbose)
471 				printf(" configuration hardwired, supposing " \
472 					"ECP+EPP SPP");
473 
474 		} else
475 		   if ((inb(cio) & SMC_CR1_MODE) == 0) {
476 			/* already in extended parallel port mode, read CR4 */
477 			outb(csr, 0x4);
478 			r = (inb(cio) & SMC_CR4_EMODE);
479 
480 			switch (r) {
481 			case SMC_SPP:
482 				ppc->ppc_avm |= PPB_SPP;
483 				if (bootverbose)
484 					printf(" SPP");
485 				break;
486 
487 			case SMC_EPPSPP:
488 				ppc->ppc_avm |= PPB_EPP | PPB_SPP;
489 				if (bootverbose)
490 					printf(" EPP SPP");
491 				break;
492 
493 			case SMC_ECP:
494 				ppc->ppc_avm |= PPB_ECP | PPB_SPP;
495 				if (bootverbose)
496 					printf(" ECP SPP");
497 				break;
498 
499 			case SMC_ECPEPP:
500 				ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
501 				if (bootverbose)
502 					printf(" ECP+EPP SPP");
503 				break;
504 			}
505 		   } else {
506 			/* not an extended port mode */
507 			ppc->ppc_avm |= PPB_SPP;
508 			if (bootverbose)
509 				printf(" SPP");
510 		   }
511 
512 	} else {
513 		/* mode forced */
514 		ppc->ppc_avm = chipset_mode;
515 
516 		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
517 		if (type == SMC_37C666GT)
518 			goto end_detect;
519 
520 		r = inb(cio);
521 		if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) {
522 			/* do not use ECP when the mode is not forced to */
523 			outb(cio, r | SMC_CR1_MODE);
524 			if (bootverbose)
525 				printf(" SPP");
526 		} else {
527 			/* an extended mode is selected */
528 			outb(cio, r & ~SMC_CR1_MODE);
529 
530 			/* read CR4 register and reset mode field */
531 			outb(csr, 0x4);
532 			r = inb(cio) & ~SMC_CR4_EMODE;
533 
534 			if (chipset_mode & PPB_ECP) {
535 				if (chipset_mode & PPB_EPP) {
536 					outb(cio, r | SMC_ECPEPP);
537 					if (bootverbose)
538 						printf(" ECP+EPP");
539 				} else {
540 					outb(cio, r | SMC_ECP);
541 					if (bootverbose)
542 						printf(" ECP");
543 				}
544 			} else {
545 				/* PPB_EPP is set */
546 				outb(cio, r | SMC_EPPSPP);
547 				if (bootverbose)
548 					printf(" EPP SPP");
549 			}
550 		}
551 		ppc->ppc_avm = chipset_mode;
552 	}
553 
554 end_detect:
555 
556 	if (bootverbose)
557 		printf ("\n");
558 
559 	if (ppc->ppc_avm & PPB_EPP) {
560 		/* select CR4 */
561 		outb(csr, 0x4);
562 		r = inb(cio);
563 
564 		/*
565 		 * Set the EPP protocol...
566 		 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
567 		 */
568 		if (ppc->ppc_epp == EPP_1_9)
569 			outb(cio, (r & ~SMC_CR4_EPPTYPE));
570 		else
571 			outb(cio, (r | SMC_CR4_EPPTYPE));
572 	}
573 
574 	/* end config mode */
575 	outb(csr, 0xaa);
576 
577 	ppc->ppc_link.adapter = &ppc_smclike_adapter;
578 	ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
579 
580 	return (chipset_mode);
581 }
582 
583 /*
584  * Winbond W83877F stuff
585  *
586  * EFER: extended function enable register
587  * EFIR: extended function index register
588  * EFDR: extended function data register
589  */
590 #define efir ((efer == 0x250) ? 0x251 : 0x3f0)
591 #define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
592 
593 static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 };
594 static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 };
595 static int w83877f_keyiter[] = { 1, 2, 2, 1 };
596 static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 };
597 
598 static int
599 ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
600 {
601 	int i, j, efer, base;
602 	unsigned char r, hefere, hefras;
603 
604 	for (i = 0; i < 4; i ++) {
605 		/* first try to enable configuration registers */
606 		efer = w83877f_efers[i];
607 
608 		/* write the key to the EFER */
609 		for (j = 0; j < w83877f_keyiter[i]; j ++)
610 			outb (efer, w83877f_keys[i]);
611 
612 		/* then check HEFERE and HEFRAS bits */
613 		outb (efir, 0x0c);
614 		hefere = inb(efdr) & WINB_HEFERE;
615 
616 		outb (efir, 0x16);
617 		hefras = inb(efdr) & WINB_HEFRAS;
618 
619 		/*
620 		 * HEFRAS	HEFERE
621 		 *   0		   1	write 89h to 250h (power-on default)
622 		 *   1		   0	write 86h twice to 3f0h
623 		 *   1		   1	write 87h twice to 3f0h
624 		 *   0		   0	write 88h to 250h
625 		 */
626 		if ((hefere | hefras) == w83877f_hefs[i])
627 			goto found;
628 	}
629 
630 	return (-1);	/* failed */
631 
632 found:
633 	/* check base port address - read from CR23 */
634 	outb(efir, 0x23);
635 	if (ppc->ppc_base != inb(efdr) * 4)		/* 4 bytes boundaries */
636 		return (-1);
637 
638 	/* read CHIP ID from CR9/bits0-3 */
639 	outb(efir, 0x9);
640 
641 	switch (inb(efdr) & WINB_CHIPID) {
642 		case WINB_W83877F_ID:
643 			ppc->ppc_type = WINB_W83877F;
644 			break;
645 
646 		case WINB_W83877AF_ID:
647 			ppc->ppc_type = WINB_W83877AF;
648 			break;
649 
650 		default:
651 			ppc->ppc_type = WINB_UNKNOWN;
652 	}
653 
654 	if (bootverbose) {
655 		/* dump of registers */
656 		printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]);
657 		for (i = 0; i <= 0xd; i ++) {
658 			outb(efir, i);
659 			printf("0x%x ", inb(efdr));
660 		}
661 		for (i = 0x10; i <= 0x17; i ++) {
662 			outb(efir, i);
663 			printf("0x%x ", inb(efdr));
664 		}
665 		outb(efir, 0x1e);
666 		printf("0x%x ", inb(efdr));
667 		for (i = 0x20; i <= 0x29; i ++) {
668 			outb(efir, i);
669 			printf("0x%x ", inb(efdr));
670 		}
671 		printf("\n");
672 		printf("ppc%d:", ppc->ppc_unit);
673 	}
674 
675 	ppc->ppc_link.adapter = &ppc_generic_adapter;
676 
677 	if (!chipset_mode) {
678 		/* autodetect mode */
679 
680 		/* select CR0 */
681 		outb(efir, 0x0);
682 		r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
683 
684 		/* select CR9 */
685 		outb(efir, 0x9);
686 		r |= (inb(efdr) & WINB_PRTMODS2);
687 
688 		switch (r) {
689 		case WINB_W83757:
690 			if (bootverbose)
691 				printf("ppc%d: W83757 compatible mode\n",
692 					ppc->ppc_unit);
693 			return (-1);	/* generic or SMC-like */
694 
695 		case WINB_EXTFDC:
696 		case WINB_EXTADP:
697 		case WINB_EXT2FDD:
698 		case WINB_JOYSTICK:
699 			if (bootverbose)
700 				printf(" not in parallel port mode\n");
701 			return (-1);
702 
703 		case (WINB_PARALLEL | WINB_EPP_SPP):
704 			ppc->ppc_avm |= PPB_EPP | PPB_SPP;
705 			if (bootverbose)
706 				printf(" EPP SPP");
707 			break;
708 
709 		case (WINB_PARALLEL | WINB_ECP):
710 			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
711 			if (bootverbose)
712 				printf(" ECP SPP");
713 			break;
714 
715 		case (WINB_PARALLEL | WINB_ECP_EPP):
716 			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
717 			ppc->ppc_link.adapter = &ppc_smclike_adapter;
718 
719 			if (bootverbose)
720 				printf(" ECP+EPP SPP");
721 			break;
722 		default:
723 			printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r);
724 		}
725 
726 	} else {
727 		/* mode forced */
728 
729 		/* select CR9 and set PRTMODS2 bit */
730 		outb(efir, 0x9);
731 		outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
732 
733 		/* select CR0 and reset PRTMODSx bits */
734 		outb(efir, 0x0);
735 		outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
736 
737 		if (chipset_mode & PPB_ECP) {
738 			if (chipset_mode & PPB_EPP) {
739 				outb(efdr, inb(efdr) | WINB_ECP_EPP);
740 				if (bootverbose)
741 					printf(" ECP+EPP");
742 
743 				ppc->ppc_link.adapter = &ppc_smclike_adapter;
744 
745 			} else {
746 				outb(efdr, inb(efdr) | WINB_ECP);
747 				if (bootverbose)
748 					printf(" ECP");
749 			}
750 		} else {
751 			/* select EPP_SPP otherwise */
752 			outb(efdr, inb(efdr) | WINB_EPP_SPP);
753 			if (bootverbose)
754 				printf(" EPP SPP");
755 		}
756 		ppc->ppc_avm = chipset_mode;
757 	}
758 
759 	if (bootverbose)
760 		printf("\n");
761 
762 	/* exit configuration mode */
763 	outb(efer, 0xaa);
764 
765 	ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
766 
767 	return (chipset_mode);
768 }
769 
770 /*
771  * ppc_generic_detect
772  */
773 static int
774 ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
775 {
776 	char save_control;
777 
778 	/* default to generic */
779 	ppc->ppc_link.adapter = &ppc_generic_adapter;
780 
781 	if (bootverbose)
782 		printf("ppc%d:", ppc->ppc_unit);
783 
784 	if (!chipset_mode) {
785 		/* first, check for ECP */
786 		w_ecr(ppc, 0x20);
787 		if ((r_ecr(ppc) & 0xe0) == 0x20) {
788 			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
789 			if (bootverbose)
790 				printf(" ECP SPP");
791 
792 			/* search for SMC style ECP+EPP mode */
793 			w_ecr(ppc, 0x80);
794 		}
795 
796 		/* try to reset EPP timeout bit */
797 		if (ppc_check_epp_timeout(ppc)) {
798 			ppc->ppc_avm |= PPB_EPP;
799 
800 			if (ppc->ppc_avm & PPB_ECP) {
801 				/* SMC like chipset found */
802 				ppc->ppc_type = SMC_LIKE;
803 				ppc->ppc_link.adapter = &ppc_smclike_adapter;
804 
805 				if (bootverbose)
806 					printf(" ECP+EPP");
807 			} else {
808 				if (bootverbose)
809 					printf(" EPP");
810 			}
811 		} else {
812 			/* restore to standard mode */
813 			w_ecr(ppc, 0x0);
814 		}
815 
816 		/* XXX try to detect NIBBLE and PS2 modes */
817 		ppc->ppc_avm |= PPB_NIBBLE;
818 
819 		if (bootverbose)
820 			printf(" SPP");
821 
822 	} else {
823 		ppc->ppc_avm = chipset_mode;
824 	}
825 
826 	if (bootverbose)
827 		printf("\n");
828 
829 	ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
830 
831 	return (chipset_mode);
832 }
833 
834 /*
835  * ppc_detect()
836  *
837  * mode is the mode suggested at boot
838  */
839 static int
840 ppc_detect(struct ppc_data *ppc, int chipset_mode) {
841 
842 	int i, mode;
843 
844 	/* list of supported chipsets */
845 	int (*chipset_detect[])(struct ppc_data *, int) = {
846 		ppc_pc873xx_detect,
847 		ppc_smc37c66xgt_detect,
848 		ppc_w83877f_detect,
849 		ppc_generic_detect,
850 		NULL
851 	};
852 
853 	/* if can't find the port and mode not forced return error */
854 	if (!ppc_detect_port(ppc) && chipset_mode == 0)
855 		return (EIO);			/* failed, port not present */
856 
857 	/* assume centronics compatible mode is supported */
858 	ppc->ppc_avm = PPB_COMPATIBLE;
859 
860 	/* we have to differenciate available chipset modes,
861 	 * chipset running modes and IEEE-1284 operating modes
862 	 *
863 	 * after detection, the port must support running in compatible mode
864 	 */
865 	for (i=0; chipset_detect[i] != NULL; i++) {
866 		if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
867 			ppc->ppc_mode = mode;
868 			break;
869 		}
870 	}
871 
872 	return (0);
873 }
874 
875 /*
876  * ppc_exec_microseq()
877  *
878  * Execute a microsequence.
879  * Microsequence mechanism is supposed to handle fast I/O operations.
880  */
881 static int
882 ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
883 {
884 	struct ppc_data	*ppc = ppcdata[unit];
885 	struct ppb_microseq *mi;
886 	char cc, *p;
887 	int i, iter, len;
888 	int error;
889 
890 	register int reg;
891 	register char mask;
892 	register int accum = 0;
893 	register char *ptr = 0;
894 
895 	struct ppb_microseq *stack = 0;
896 
897 /* microsequence registers are equivalent to PC-like port registers */
898 #define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register))
899 #define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
900 
901 #define INCR_PC (mi ++)		/* increment program counter */
902 
903 	mi = *p_msq;
904 	for (;;) {
905 		switch (mi->opcode) {
906 		case MS_OP_RSET:
907 			cc = r_reg(mi->arg[0].i, ppc);
908 			cc &= (char)mi->arg[2].i;	/* clear mask */
909 			cc |= (char)mi->arg[1].i;	/* assert mask */
910                         w_reg(mi->arg[0].i, ppc, cc);
911 			INCR_PC;
912                         break;
913 
914 		case MS_OP_RASSERT_P:
915 			reg = mi->arg[1].i;
916 			ptr = ppc->ppc_ptr;
917 
918 			if ((len = mi->arg[0].i) == MS_ACCUM) {
919 				accum = ppc->ppc_accum;
920 				for (; accum; accum--)
921 					w_reg(reg, ppc, *ptr++);
922 				ppc->ppc_accum = accum;
923 			} else
924 				for (i=0; i<len; i++)
925 					w_reg(reg, ppc, *ptr++);
926 			ppc->ppc_ptr = ptr;
927 
928 			INCR_PC;
929 			break;
930 
931                 case MS_OP_RFETCH_P:
932 			reg = mi->arg[1].i;
933 			mask = (char)mi->arg[2].i;
934 			ptr = ppc->ppc_ptr;
935 
936 			if ((len = mi->arg[0].i) == MS_ACCUM) {
937 				accum = ppc->ppc_accum;
938 				for (; accum; accum--)
939 					*ptr++ = r_reg(reg, ppc) & mask;
940 				ppc->ppc_accum = accum;
941 			} else
942 				for (i=0; i<len; i++)
943 					*ptr++ = r_reg(reg, ppc) & mask;
944 			ppc->ppc_ptr = ptr;
945 
946 			INCR_PC;
947                         break;
948 
949                 case MS_OP_RFETCH:
950 			*((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
951 							(char)mi->arg[1].i;
952 			INCR_PC;
953                         break;
954 
955 		case MS_OP_RASSERT:
956                 case MS_OP_DELAY:
957 
958 		/* let's suppose the next instr. is the same */
959 		prefetch:
960 			for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
961 				w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i);
962 
963 			if (mi->opcode == MS_OP_DELAY) {
964 				DELAY(mi->arg[0].i);
965 				INCR_PC;
966 				goto prefetch;
967 			}
968 			break;
969 
970 		case MS_OP_ADELAY:
971 			if (mi->arg[0].i)
972 				tsleep(NULL, PPBPRI, "ppbdelay",
973 						mi->arg[0].i * (hz/1000));
974 			INCR_PC;
975 			break;
976 
977 		case MS_OP_TRIG:
978 			reg = mi->arg[0].i;
979 			iter = mi->arg[1].i;
980 			p = (char *)mi->arg[2].p;
981 
982 			/* XXX delay limited to 255 us */
983 			for (i=0; i<iter; i++) {
984 				w_reg(reg, ppc, *p++);
985 				DELAY((unsigned char)*p++);
986 			}
987 			INCR_PC;
988 			break;
989 
990                 case MS_OP_SET:
991                         ppc->ppc_accum = mi->arg[0].i;
992 			INCR_PC;
993                         break;
994 
995                 case MS_OP_DBRA:
996                         if (--ppc->ppc_accum > 0)
997                                 mi += mi->arg[0].i;
998 			else
999 				INCR_PC;
1000                         break;
1001 
1002                 case MS_OP_BRSET:
1003                         cc = r_str(ppc);
1004                         if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i)
1005                                 mi += mi->arg[1].i;
1006 			else
1007 				INCR_PC;
1008                         break;
1009 
1010                 case MS_OP_BRCLEAR:
1011                         cc = r_str(ppc);
1012                         if ((cc & (char)mi->arg[0].i) == 0)
1013                                 mi += mi->arg[1].i;
1014 			else
1015 				INCR_PC;
1016                         break;
1017 
1018 		case MS_OP_BRSTAT:
1019 			cc = r_str(ppc);
1020 			if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) ==
1021 							(char)mi->arg[0].i)
1022 				mi += mi->arg[2].i;
1023 			else
1024 				INCR_PC;
1025 			break;
1026 
1027 		case MS_OP_C_CALL:
1028 			/*
1029 			 * If the C call returns !0 then end the microseq.
1030 			 * The current state of ptr is passed to the C function
1031 			 */
1032 			if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr)))
1033 				return (error);
1034 
1035 			INCR_PC;
1036 			break;
1037 
1038 		case MS_OP_PTR:
1039 			ppc->ppc_ptr = (char *)mi->arg[0].p;
1040 			INCR_PC;
1041 			break;
1042 
1043 		case MS_OP_CALL:
1044 			if (stack)
1045 				panic("%s: too much calls", __FUNCTION__);
1046 
1047 			if (mi->arg[0].p) {
1048 				/* store the state of the actual
1049 				 * microsequence
1050 				 */
1051 				stack = mi;
1052 
1053 				/* jump to the new microsequence */
1054 				mi = (struct ppb_microseq *)mi->arg[0].p;
1055 			} else
1056 				INCR_PC;
1057 
1058 			break;
1059 
1060 		case MS_OP_SUBRET:
1061 			/* retrieve microseq and pc state before the call */
1062 			mi = stack;
1063 
1064 			/* reset the stack */
1065 			stack = 0;
1066 
1067 			/* XXX return code */
1068 
1069 			INCR_PC;
1070 			break;
1071 
1072                 case MS_OP_PUT:
1073                 case MS_OP_GET:
1074                 case MS_OP_RET:
1075 			/* can't return to ppb level during the execution
1076 			 * of a submicrosequence */
1077 			if (stack)
1078 				panic("%s: can't return to ppb level",
1079 								__FUNCTION__);
1080 
1081 			/* update pc for ppb level of execution */
1082 			*p_msq = mi;
1083 
1084 			/* return to ppb level of execution */
1085 			return (0);
1086 
1087                 default:
1088                         panic("%s: unknown microsequence opcode 0x%x",
1089                                 __FUNCTION__, mi->opcode);
1090                 }
1091 	}
1092 
1093 	/* unreached */
1094 }
1095 
1096 /*
1097  * Configure current operating mode
1098  */
1099 static int
1100 ppc_generic_setmode(int unit, int mode)
1101 {
1102 	struct ppc_data *ppc = ppcdata[unit];
1103 
1104 	/* back to compatible mode, XXX don't know yet what to do here */
1105 	if (mode == 0) {
1106 		ppc->ppc_mode = PPB_COMPATIBLE;
1107 		return (0);
1108 	}
1109 
1110 	/* check if mode is available */
1111 	if (!(ppc->ppc_avm & mode))
1112 		return (EOPNOTSUPP);
1113 
1114 	/* if ECP mode, configure ecr register */
1115 	if (ppc->ppc_avm & PPB_ECP) {
1116 
1117 		/* XXX disable DMA, enable interrupts */
1118 		if (mode & PPB_EPP)
1119 			return (EOPNOTSUPP);
1120 		else if (mode & PPB_PS2)
1121 			/* select PS2 mode with ECP */
1122 			w_ecr(ppc, 0x20);
1123 		else if (mode & PPB_ECP)
1124 			/* select ECP mode */
1125 			w_ecr(ppc, 0x60);
1126 		else
1127 			/* select standard parallel port mode */
1128 			w_ecr(ppc, 0x00);
1129 	}
1130 
1131 	ppc->ppc_mode = mode;
1132 
1133 	return (0);
1134 }
1135 
1136 int
1137 ppc_smclike_setmode(int unit, int mode)
1138 {
1139 	struct ppc_data *ppc = ppcdata[unit];
1140 
1141 	/* back to compatible mode, XXX don't know yet what to do here */
1142 	if (mode == 0) {
1143 		ppc->ppc_mode = PPB_COMPATIBLE;
1144 		return (0);
1145 	}
1146 
1147 	/* check if mode is available */
1148 	if (!(ppc->ppc_avm & mode))
1149 		return (EOPNOTSUPP);
1150 
1151 	/* if ECP mode, configure ecr register */
1152 	if (ppc->ppc_avm & PPB_ECP) {
1153 
1154 		/* XXX disable DMA, enable interrupts */
1155 		if (mode & PPB_EPP)
1156 			/* select EPP mode */
1157 			w_ecr(ppc, 0x80);
1158 		else if (mode & PPB_PS2)
1159 			/* select PS2 mode with ECP */
1160 			w_ecr(ppc, 0x20);
1161 		else if (mode & PPB_ECP)
1162 			/* select ECP mode */
1163 			w_ecr(ppc, 0x60);
1164 		else
1165 			/* select standard parallel port mode */
1166 			w_ecr(ppc, 0x00);
1167 	}
1168 
1169 	ppc->ppc_mode = mode;
1170 
1171 
1172 	return (0);
1173 }
1174 
1175 /*
1176  * EPP timeout, according to the PC87332 manual
1177  * Semantics of clearing EPP timeout bit.
1178  * PC87332	- reading SPP_STR does it...
1179  * SMC		- write 1 to EPP timeout bit			XXX
1180  * Others	- (???) write 0 to EPP timeout bit
1181  */
1182 static void
1183 ppc_reset_epp_timeout(int unit)
1184 {
1185 	struct ppc_data *ppc = ppcdata[unit];
1186 	register char r;
1187 
1188 	r = r_str(ppc);
1189 	w_str(ppc, r | 0x1);
1190 	w_str(ppc, r & 0xfe);
1191 
1192 	return;
1193 }
1194 
1195 static int
1196 ppcprobe(struct isa_device *dvp)
1197 {
1198 	static short next_bios_ppc = 0;
1199 	struct ppc_data *ppc;
1200 	int error;
1201 
1202 	/*
1203 	 * If port not specified, use bios list.
1204 	 */
1205 	if(dvp->id_iobase < 0) {
1206 		if((next_bios_ppc < BIOS_MAX_PPC) &&
1207 				(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
1208 			dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
1209 			printf("ppc: parallel port found at 0x%x\n",
1210 							dvp->id_iobase);
1211 		} else
1212 			return (0);
1213 	}
1214 
1215 	/*
1216 	 * Port was explicitly specified.
1217 	 * This allows probing of ports unknown to the BIOS.
1218 	 */
1219 
1220 	/*
1221 	 * Allocate the ppc_data structure.
1222 	 */
1223 	ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
1224 	if (!ppc) {
1225 		printf("ppc: cannot malloc!\n");
1226 		goto error;
1227 	}
1228 	bzero(ppc, sizeof(struct ppc_data));
1229 
1230 	ppc->ppc_base = dvp->id_iobase;
1231 	ppc->ppc_unit = dvp->id_unit;
1232 	ppc->ppc_type = GENERIC;
1233 
1234 	ppc->ppc_mode = PPB_COMPATIBLE;
1235 	ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
1236 
1237 	/*
1238 	 * XXX Try and detect if interrupts are working
1239 	 */
1240 	if (!(dvp->id_flags & 0x20))
1241 		ppc->ppc_irq = (dvp->id_irq);
1242 
1243 	ppcdata[ppc->ppc_unit] = ppc;
1244 	nppc ++;
1245 
1246 	/*
1247 	 * Link the Parallel Port Chipset (adapter) to
1248 	 * the future ppbus. Default to a generic chipset
1249 	 */
1250 	ppc->ppc_link.adapter_unit = ppc->ppc_unit;
1251 	ppc->ppc_link.adapter = &ppc_generic_adapter;
1252 
1253 	/*
1254 	 * Try to detect the chipset and its mode.
1255 	 */
1256 	if (ppc_detect(ppc, dvp->id_flags & 0xf))
1257 		goto error;
1258 
1259 end_probe:
1260 
1261 	return (1);
1262 
1263 error:
1264 	return (0);
1265 }
1266 
1267 static int
1268 ppcattach(struct isa_device *isdp)
1269 {
1270 	struct ppc_data *ppc = ppcdata[isdp->id_unit];
1271 	struct ppb_data *ppbus;
1272 	char * mode;
1273 
1274 	printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
1275 		ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
1276 		ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
1277 			ppc_epp_protocol[ppc->ppc_epp] : "");
1278 
1279 	/*
1280 	 * Prepare ppbus data area for upper level code.
1281 	 */
1282 	ppbus = ppb_alloc_bus();
1283 
1284 	if (!ppbus)
1285 		return (0);
1286 
1287 	ppc->ppc_link.ppbus = ppbus;
1288 	ppbus->ppb_link = &ppc->ppc_link;
1289 
1290 	/*
1291 	 * Probe the ppbus and attach devices found.
1292 	 */
1293 	ppb_attachdevs(ppbus);
1294 
1295 	return (1);
1296 }
1297 #endif
1298