ppc.c revision 38505
1184588Sdfr/*-
2184588Sdfr * Copyright (c) 1997, 1998 Nicolas Souchu
3184588Sdfr * All rights reserved.
4184588Sdfr *
5184588Sdfr * Redistribution and use in source and binary forms, with or without
6184588Sdfr * modification, are permitted provided that the following conditions
7184588Sdfr * are met:
8184588Sdfr * 1. Redistributions of source code must retain the above copyright
9184588Sdfr *    notice, this list of conditions and the following disclaimer.
10184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright
11184588Sdfr *    notice, this list of conditions and the following disclaimer in the
12184588Sdfr *    documentation and/or other materials provided with the distribution.
13184588Sdfr *
14184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17184588Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24184588Sdfr * SUCH DAMAGE.
25184588Sdfr *
26184588Sdfr *	$Id: ppc.c,v 1.4 1998/08/03 19:14:32 msmith Exp $
27184588Sdfr *
28184588Sdfr */
29184588Sdfr#include "ppc.h"
30184588Sdfr
31184588Sdfr#if NPPC > 0
32184588Sdfr
33184588Sdfr#include <sys/param.h>
34184588Sdfr#include <sys/systm.h>
35184588Sdfr#include <sys/conf.h>
36184588Sdfr#include <sys/malloc.h>
37184588Sdfr
38184588Sdfr#include <machine/clock.h>
39184588Sdfr
40184588Sdfr#include <vm/vm.h>
41184588Sdfr#include <vm/vm_param.h>
42184588Sdfr#include <vm/pmap.h>
43184588Sdfr
44184588Sdfr#include <i386/isa/isa_device.h>
45184588Sdfr
46184588Sdfr#include <dev/ppbus/ppbconf.h>
47184588Sdfr#include <dev/ppbus/ppb_msq.h>
48184588Sdfr
49184588Sdfr#include <i386/isa/ppcreg.h>
50184588Sdfr
51184588Sdfrstatic int	ppcprobe(struct isa_device *);
52184588Sdfrstatic int	ppcattach(struct isa_device *);
53184588Sdfr
54184588Sdfrstruct isa_driver ppcdriver = {
55184588Sdfr	ppcprobe, ppcattach, "ppc"
56184588Sdfr};
57184588Sdfr
58184588Sdfrstatic struct ppc_data *ppcdata[NPPC];
59184588Sdfrstatic int nppc = 0;
60184588Sdfr
61184588Sdfrstatic char *ppc_types[] = {
62184588Sdfr	"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
63184588Sdfr	"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0
64184588Sdfr};
65184588Sdfr
66184588Sdfr/* list of available modes */
67184588Sdfrstatic char *ppc_avms[] = {
68184588Sdfr	"COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only",
69184588Sdfr	"EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only",
70184588Sdfr	"ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP",
71184588Sdfr	"ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0
72184588Sdfr};
73184588Sdfr
74184588Sdfr/* list of current executing modes
75184588Sdfr * Note that few modes do not actually exist.
76184588Sdfr */
77184588Sdfrstatic char *ppc_modes[] = {
78184588Sdfr	"COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP",
79184588Sdfr	"EPP", "EPP", "EPP", "ECP",
80184588Sdfr	"ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP",
81184588Sdfr	"ECP+EPP", "ECP+EPP", "ECP+EPP", 0
82184588Sdfr};
83184588Sdfr
84184588Sdfrstatic char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
85184588Sdfr
86184588Sdfr/*
87184588Sdfr * BIOS printer list - used by BIOS probe.
88184588Sdfr */
89184588Sdfr#define	BIOS_PPC_PORTS	0x408
90184588Sdfr#define	BIOS_PORTS	(short *)(KERNBASE+BIOS_PPC_PORTS)
91184588Sdfr#define	BIOS_MAX_PPC	4
92184588Sdfr
93184588Sdfr/*
94184588Sdfr * All these functions are default actions for IN/OUT operations.
95184588Sdfr * They may be redefined if needed.
96184588Sdfr */
97184588Sdfrstatic void ppc_outsb_epp(int unit, char *addr, int cnt) {
98184588Sdfr	outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
99184588Sdfrstatic void ppc_outsw_epp(int unit, char *addr, int cnt) {
100184588Sdfr	outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
101184588Sdfrstatic void ppc_outsl_epp(int unit, char *addr, int cnt) {
102184588Sdfr	outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
103184588Sdfrstatic void ppc_insb_epp(int unit, char *addr, int cnt) {
104184588Sdfr	insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
105184588Sdfrstatic void ppc_insw_epp(int unit, char *addr, int cnt) {
106184588Sdfr	insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
107184588Sdfrstatic void ppc_insl_epp(int unit, char *addr, int cnt) {
108184588Sdfr	insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
109184588Sdfr
110184588Sdfrstatic char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); }
111184588Sdfrstatic char ppc_rstr(int unit) { return r_str(ppcdata[unit]); }
112184588Sdfrstatic char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); }
113184588Sdfrstatic char ppc_repp(int unit) { return r_epp(ppcdata[unit]); }
114184588Sdfrstatic char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); }
115184588Sdfrstatic char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); }
116184588Sdfr
117184588Sdfrstatic void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); }
118184588Sdfrstatic void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); }
119184588Sdfrstatic void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
120184588Sdfrstatic void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); }
121184588Sdfrstatic void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
122184588Sdfrstatic void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
123184588Sdfr
124184588Sdfrstatic void ppc_reset_epp_timeout(int);
125184588Sdfrstatic void ppc_ecp_sync(int);
126184588Sdfr
127184588Sdfrstatic int ppc_exec_microseq(int, struct ppb_microseq *, int *);
128184588Sdfrstatic int ppc_generic_setmode(int, int);
129184588Sdfr
130184588Sdfrstatic struct ppb_adapter ppc_adapter = {
131184588Sdfr
132184588Sdfr	0,	/* no intr handler, filled by chipset dependent code */
133184588Sdfr
134184588Sdfr	ppc_reset_epp_timeout, ppc_ecp_sync,
135184588Sdfr
136184588Sdfr	ppc_exec_microseq,
137184588Sdfr
138184588Sdfr	ppc_generic_setmode,
139184588Sdfr
140184588Sdfr	ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
141184588Sdfr	ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
142184588Sdfr
143184588Sdfr	ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
144184588Sdfr	ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
145184588Sdfr};
146184588Sdfr
147184588Sdfr/*
148184588Sdfr * ppc_ecp_sync()		XXX
149184588Sdfr */
150184588Sdfrstatic void
151184588Sdfrppc_ecp_sync(int unit) {
152184588Sdfr
153184588Sdfr	struct ppc_data *ppc = ppcdata[unit];
154184588Sdfr	int i, r;
155184588Sdfr
156184588Sdfr	r = r_ecr(ppc);
157184588Sdfr	if ((r & 0xe0) != 0x80)
158184588Sdfr		return;
159184588Sdfr
160184588Sdfr	for (i = 0; i < 100; i++) {
161184588Sdfr		r = r_ecr(ppc);
162184588Sdfr		if (r & 0x1)
163184588Sdfr			return;
164184588Sdfr		DELAY(100);
165184588Sdfr	}
166184588Sdfr
167184588Sdfr	printf("ppc%d: ECP sync failed as data still " \
168184588Sdfr		"present in FIFO.\n", unit);
169184588Sdfr
170184588Sdfr	return;
171184588Sdfr}
172184588Sdfr
173184588Sdfrvoid
174184588Sdfrppcintr(int unit)
175184588Sdfr{
176184588Sdfr	/* call directly upper code */
177184588Sdfr	ppb_intr(&ppcdata[unit]->ppc_link);
178184588Sdfr
179184588Sdfr	return;
180184588Sdfr}
181184588Sdfr
182184588Sdfrstatic void
183184588Sdfrppc_ecp_config(struct ppc_data *ppc, int chipset_mode)
184184588Sdfr{
185184588Sdfr	/* XXX disable DMA, enable interrupts */
186184588Sdfr	if (chipset_mode & PPB_EPP)
187184588Sdfr		/* select EPP mode */
188184588Sdfr		w_ecr(ppc, 0x80);
189184588Sdfr	else if (chipset_mode & PPB_PS2)
190184588Sdfr			/* select PS2 mode with ECP */
191184588Sdfr			w_ecr(ppc, 0x20);
192184588Sdfr		else
193184588Sdfr			/* keep ECP mode alone, default for NIBBLE */
194184588Sdfr			w_ecr(ppc, 0x70);
195184588Sdfr
196184588Sdfr	return;
197184588Sdfr}
198184588Sdfr
199184588Sdfrstatic int
200184588Sdfrppc_detect_port(struct ppc_data *ppc)
201184588Sdfr{
202184588Sdfr
203184588Sdfr	w_ctr(ppc, 0x0c);	/* To avoid missing PS2 ports */
204184588Sdfr	w_dtr(ppc, 0xaa);
205184588Sdfr	if (r_dtr(ppc) != (char) 0xaa)
206184588Sdfr		return (0);
207184588Sdfr
208184588Sdfr	return (1);
209184588Sdfr}
210184588Sdfr
211184588Sdfr/*
212184588Sdfr * ppc_pc873xx_detect
213184588Sdfr *
214184588Sdfr * Probe for a Natsemi PC873xx-family part.
215184588Sdfr *
216184588Sdfr * References in this function are to the National Semiconductor
217184588Sdfr * PC87332 datasheet TL/C/11930, May 1995 revision.
218184588Sdfr */
219184588Sdfrstatic int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
220184588Sdfrstatic int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
221184588Sdfr
222184588Sdfrstatic int
223184588Sdfrppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode)	/* XXX mode never forced */
224184588Sdfr{
225184588Sdfr    static int	index = 0;
226184588Sdfr    int		base, idport;
227184588Sdfr    int		val;
228184588Sdfr
229184588Sdfr    while ((idport = pc873xx_basetab[index++])) {
230184588Sdfr
231184588Sdfr	/* XXX should check first to see if this location is already claimed */
232184588Sdfr
233184588Sdfr	/*
234184588Sdfr	 * Pull the 873xx through the power-on ID cycle (2.2,1.).  We can't use this
235184588Sdfr	 * to locate the chip as it may already have been used by the BIOS.
236184588Sdfr	 */
237184588Sdfr	(void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport);
238184588Sdfr
239184588Sdfr	/*
240184588Sdfr	 * Read the SID byte.  Possible values are :
241184588Sdfr	 *
242184588Sdfr	 * 0001xxxx	PC87332
243184588Sdfr	 * 01110xxx	PC87306
244184588Sdfr	 */
245184588Sdfr	outb(idport, PC873_SID);
246184588Sdfr	val = inb(idport + 1);
247184588Sdfr	if ((val & 0xf0) == 0x10) {
248184588Sdfr	    ppc->ppc_type = NS_PC87332;
249184588Sdfr	} else if ((val & 0xf8) == 0x70) {
250184588Sdfr	    ppc->ppc_type = NS_PC87306;
251184588Sdfr	} else {
252184588Sdfr	    if (bootverbose && (val != 0xff))
253184588Sdfr		printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
254184588Sdfr	    continue ;		/* not recognised */
255184588Sdfr	}
256184588Sdfr
257184588Sdfr	/*
258184588Sdfr	 * We think we have one.  Is it enabled and where we want it to be?
259184588Sdfr	 */
260184588Sdfr	outb(idport, PC873_FER);
261184588Sdfr	val = inb(idport + 1);
262184588Sdfr	if (!(val & PC873_PPENABLE)) {
263184588Sdfr	    if (bootverbose)
264184588Sdfr		printf("PC873xx parallel port disabled\n");
265184588Sdfr	    continue;
266184588Sdfr	}
267184588Sdfr	outb(idport, PC873_FAR);
268184588Sdfr	val = inb(idport + 1) & 0x3;
269184588Sdfr	/* XXX we should create a driver instance for every port found */
270184588Sdfr	if (pc873xx_porttab[val] != ppc->ppc_base) {
271184588Sdfr	    if (bootverbose)
272184588Sdfr		printf("PC873xx at 0x%x not for driver at port 0x%x\n",
273184588Sdfr		       pc873xx_porttab[val], ppc->ppc_base);
274184588Sdfr	    continue;
275184588Sdfr	}
276184588Sdfr
277184588Sdfr	/*
278184588Sdfr	 * This is the port we want.  Can we dink with it to improve
279184588Sdfr	 * our chances?
280184588Sdfr	 */
281184588Sdfr	outb(idport, PC873_PTR);
282184588Sdfr	val = inb(idport + 1);
283184588Sdfr	if (val & PC873_CFGLOCK) {
284184588Sdfr	    if (bootverbose)
285184588Sdfr		printf("PC873xx locked\n");
286184588Sdfr
287184588Sdfr	    /* work out what mode we're in */
288184588Sdfr	    ppc->ppc_avm |= PPB_NIBBLE;		/* worst case */
289184588Sdfr
290184588Sdfr	    outb(idport, PC873_PCR);
291184588Sdfr	    val = inb(idport + 1);
292184588Sdfr	    if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
293184588Sdfr		outb(idport, PC873_PTR);
294184588Sdfr		val = inb(idport + 1);
295184588Sdfr		if (!(val & PC873_EPPRDIR)) {
296184588Sdfr		    ppc->ppc_avm |= PPB_EPP;	/* As we would have done it anwyay */
297184588Sdfr		}
298184588Sdfr	    } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
299184588Sdfr		ppc->ppc_avm |= PPB_PS2;	/* tolerable alternative */
300184588Sdfr	    }
301184588Sdfr	} else {
302184588Sdfr	    if (bootverbose)
303184588Sdfr		printf("PC873xx unlocked, ");
304184588Sdfr
305184588Sdfr#if 0	/* broken */
306184588Sdfr	    /*
307184588Sdfr	     * Frob the zero-wait-state option if possible; it causes
308184588Sdfr	     * unreliable operation.
309184588Sdfr	     */
310184588Sdfr	    outb(idport, PC873_FCR);
311184588Sdfr	    val = inb(idport + 1);
312184588Sdfr	    if ((ppc->ppc_type == NS_PC87306) ||	/* we are a '306 */
313184588Sdfr		!(val & PC873_ZWSPWDN)) {		/* or pin _is_ ZWS */
314184588Sdfr		val &= ~PC873_ZWS;
315184588Sdfr		outb(idport + 1, val);			/* must disable ZWS */
316184588Sdfr		outb(idport + 1, val);
317184588Sdfr
318184588Sdfr		if (bootverbose)
319184588Sdfr		    printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled");
320184588Sdfr	    }
321184588Sdfr
322184588Sdfr#endif
323184588Sdfr	    if (bootverbose)
324184588Sdfr		printf("reconfiguring for ");
325184588Sdfr
326184588Sdfr	    /*
327184588Sdfr	     * if the chip is at 0x3bc, we can't use EPP as there's no room
328184588Sdfr	     * for the extra registers.
329184588Sdfr	     *
330184588Sdfr	     * XXX should we use ECP mode always and use the EPP submode?
331184588Sdfr	     */
332184588Sdfr	    if (ppc->ppc_base != 0x3bc) {
333184588Sdfr		if (bootverbose)
334184588Sdfr		    printf("EPP 1.9\n");
335184588Sdfr
336184588Sdfr		/* configure for EPP 1.9 operation XXX should be configurable */
337184588Sdfr		outb(idport, PC873_PCR);
338184588Sdfr		val = inb(idport + 1);
339184588Sdfr		val &= ~(PC873_ECPEN | PC873_ECPCLK);	/* disable ECP */
340184588Sdfr		val |= (PC873_EPPEN | PC873_EPP19);	/* enable EPP */
341184588Sdfr		outb(idport + 1, val);
342184588Sdfr		outb(idport + 1, val);
343184588Sdfr
344184588Sdfr		/* enable automatic direction turnover */
345184588Sdfr		outb(idport, PC873_PTR);
346184588Sdfr		val = inb(idport + 1);
347184588Sdfr		val &= ~PC873_EPPRDIR;			/* disable "regular" direction change */
348184588Sdfr		outb(idport + 1, val);
349184588Sdfr		outb(idport + 1, val);
350184588Sdfr
351184588Sdfr		/* we are an EPP-32 port */
352184588Sdfr		ppc->ppc_avm |= PPB_EPP;
353184588Sdfr	    } else {
354184588Sdfr		if (bootverbose)
355184588Sdfr		    printf("ECP\n");
356184588Sdfr
357184588Sdfr		/* configure as an ECP port to get bidirectional operation for now */
358184588Sdfr		outb(idport, PC873_PCR);
359184588Sdfr		outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
360184588Sdfr
361184588Sdfr		/* we look like a PS/2 port */
362184588Sdfr		ppc->ppc_avm |= PPB_PS2;
363184588Sdfr	    }
364184588Sdfr	}
365184588Sdfr
366184588Sdfr	return(chipset_mode);
367184588Sdfr    }
368184588Sdfr    return(-1);
369184588Sdfr}
370184588Sdfr
371184588Sdfrstatic int
372184588Sdfrppc_check_epp_timeout(struct ppc_data *ppc)
373184588Sdfr{
374184588Sdfr	ppc_reset_epp_timeout(ppc->ppc_unit);
375184588Sdfr
376184588Sdfr	return (!(r_str(ppc) & TIMEOUT));
377184588Sdfr}
378184588Sdfr
379184588Sdfr/*
380184588Sdfr * ppc_smc37c66xgt_detect
381184588Sdfr *
382184588Sdfr * SMC FDC37C66xGT configuration.
383184588Sdfr */
384184588Sdfrstatic int
385184588Sdfrppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
386184588Sdfr{
387184588Sdfr	int s, i;
388184588Sdfr	char r;
389184588Sdfr	int type = -1;
390184588Sdfr	int csr = SMC66x_CSR;	/* initial value is 0x3F0 */
391184588Sdfr
392184588Sdfr	int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
393184588Sdfr
394184588Sdfr
395184588Sdfr#define cio csr+1	/* config IO port is either 0x3F1 or 0x371 */
396184588Sdfr
397184588Sdfr	/*
398184588Sdfr	 * Detection: enter configuration mode and read CRD register.
399184588Sdfr	 */
400184588Sdfr
401184588Sdfr	s = splhigh();
402184588Sdfr	outb(csr, SMC665_iCODE);
403184588Sdfr	outb(csr, SMC665_iCODE);
404184588Sdfr	splx(s);
405184588Sdfr
406184588Sdfr	outb(csr, 0xd);
407184588Sdfr	if (inb(cio) == 0x65) {
408184588Sdfr		type = SMC_37C665GT;
409184588Sdfr		goto config;
410184588Sdfr	}
411184588Sdfr
412184588Sdfr	for (i = 0; i < 2; i++) {
413184588Sdfr		s = splhigh();
414184588Sdfr		outb(csr, SMC666_iCODE);
415184588Sdfr		outb(csr, SMC666_iCODE);
416184588Sdfr		splx(s);
417184588Sdfr
418184588Sdfr		outb(csr, 0xd);
419184588Sdfr		if (inb(cio) == 0x66) {
420184588Sdfr			type = SMC_37C666GT;
421184588Sdfr			break;
422184588Sdfr		}
423184588Sdfr
424184588Sdfr		/* Another chance, CSR may be hard-configured to be at 0x370 */
425184588Sdfr		csr = SMC666_CSR;
426184588Sdfr	}
427184588Sdfr
428184588Sdfrconfig:
429184588Sdfr	/*
430184588Sdfr	 * If chipset not found, do not continue.
431184588Sdfr	 */
432184588Sdfr	if (type == -1)
433184588Sdfr		return (-1);
434184588Sdfr
435184588Sdfr	/* select CR1 */
436184588Sdfr	outb(csr, 0x1);
437184588Sdfr
438184588Sdfr	/* read the port's address: bits 0 and 1 of CR1 */
439184588Sdfr	r = inb(cio) & SMC_CR1_ADDR;
440184588Sdfr	if (port_address[r] != ppc->ppc_base)
441184588Sdfr		return (-1);
442184588Sdfr
443184588Sdfr	ppc->ppc_type = type;
444184588Sdfr
445184588Sdfr	/*
446184588Sdfr	 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
447184588Sdfr	 * If SPP mode is detected, try to set ECP+EPP mode
448184588Sdfr	 */
449184588Sdfr
450184588Sdfr	if (bootverbose) {
451184588Sdfr		outb(csr, 0x1);
452184588Sdfr		printf("SMC registers CR1=0x%x", inb(cio) & 0xff);
453184588Sdfr
454184588Sdfr		outb(csr, 0x4);
455184588Sdfr		printf(" CR4=0x%x", inb(cio) & 0xff);
456184588Sdfr	}
457184588Sdfr
458184588Sdfr	/* select CR1 */
459184588Sdfr	outb(csr, 0x1);
460184588Sdfr
461184588Sdfr	if (!chipset_mode) {
462184588Sdfr		/* autodetect mode */
463184588Sdfr
464184588Sdfr		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
465184588Sdfr		if (type == SMC_37C666GT) {
466184588Sdfr			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
467184588Sdfr
468184588Sdfr		} else
469184588Sdfr		   if ((inb(cio) & SMC_CR1_MODE) == 0) {
470184588Sdfr			/* already in extended parallel port mode, read CR4 */
471184588Sdfr			outb(csr, 0x4);
472184588Sdfr			r = (inb(cio) & SMC_CR4_EMODE);
473184588Sdfr
474184588Sdfr			switch (r) {
475184588Sdfr			case SMC_SPP:
476184588Sdfr				ppc->ppc_avm |= PPB_SPP;
477184588Sdfr				break;
478184588Sdfr
479184588Sdfr			case SMC_EPPSPP:
480184588Sdfr				ppc->ppc_avm |= PPB_EPP | PPB_SPP;
481184588Sdfr				break;
482184588Sdfr
483184588Sdfr			case SMC_ECP:
484184588Sdfr				ppc->ppc_avm |= PPB_ECP | PPB_SPP;
485184588Sdfr				break;
486184588Sdfr
487184588Sdfr			case SMC_ECPEPP:
488184588Sdfr				ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
489184588Sdfr				break;
490184588Sdfr			}
491184588Sdfr		   } else {
492184588Sdfr			/* not an extended port mode */
493184588Sdfr			ppc->ppc_avm |= PPB_SPP;
494184588Sdfr		   }
495184588Sdfr
496184588Sdfr	} else {
497184588Sdfr		/* mode forced */
498184588Sdfr
499184588Sdfr		/* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
500184588Sdfr		if (type == SMC_37C666GT)
501184588Sdfr			goto end_detect;
502184588Sdfr
503184588Sdfr		r = inb(cio);
504184588Sdfr		if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) {
505184588Sdfr			/* do not use ECP when the mode is not forced to */
506184588Sdfr			outb(cio, r | SMC_CR1_MODE);
507184588Sdfr		} else {
508184588Sdfr			/* an extended mode is selected */
509184588Sdfr			outb(cio, r & ~SMC_CR1_MODE);
510184588Sdfr
511184588Sdfr			/* read CR4 register and reset mode field */
512184588Sdfr			outb(csr, 0x4);
513184588Sdfr			r = inb(cio) & ~SMC_CR4_EMODE;
514184588Sdfr
515184588Sdfr			if (chipset_mode & PPB_ECP) {
516184588Sdfr				if (chipset_mode & PPB_EPP) {
517184588Sdfr					outb(cio, r | SMC_ECPEPP);
518184588Sdfr				} else {
519184588Sdfr					outb(cio, r | SMC_ECP);
520184588Sdfr				}
521184588Sdfr			} else {
522184588Sdfr				/* PPB_EPP is set */
523184588Sdfr				outb(cio, r | SMC_EPPSPP);
524184588Sdfr			}
525184588Sdfr		}
526184588Sdfr		ppc->ppc_avm = chipset_mode;
527184588Sdfr	}
528184588Sdfr
529184588Sdfrend_detect:
530184588Sdfr
531184588Sdfr	if (bootverbose)
532184588Sdfr		printf ("\n");
533184588Sdfr
534184588Sdfr	if (chipset_mode & PPB_EPP) {
535184588Sdfr		/* select CR4 */
536184588Sdfr		outb(csr, 0x4);
537184588Sdfr		r = inb(cio);
538184588Sdfr
539184588Sdfr		/*
540184588Sdfr		 * Set the EPP protocol...
541184588Sdfr		 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
542184588Sdfr		 */
543184588Sdfr		if (ppc->ppc_epp == EPP_1_9)
544184588Sdfr			outb(cio, (r & ~SMC_CR4_EPPTYPE));
545184588Sdfr		else
546184588Sdfr			outb(cio, (r | SMC_CR4_EPPTYPE));
547184588Sdfr	}
548184588Sdfr
549184588Sdfr	/* end config mode */
550184588Sdfr	outb(csr, 0xaa);
551184588Sdfr
552184588Sdfr	if (ppc->ppc_avm & PPB_ECP)
553184588Sdfr		ppc_ecp_config(ppc, chipset_mode);
554184588Sdfr
555184588Sdfr	return (chipset_mode);
556184588Sdfr}
557184588Sdfr
558184588Sdfr/*
559184588Sdfr * Winbond W83877F stuff
560184588Sdfr *
561184588Sdfr * EFER: extended function enable register
562184588Sdfr * EFIR: extended function index register
563184588Sdfr * EFDR: extended function data register
564184588Sdfr */
565184588Sdfr#define efir ((efer == 0x250) ? 0x251 : 0x3f0)
566184588Sdfr#define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
567184588Sdfr
568184588Sdfrstatic int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 };
569184588Sdfrstatic int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 };
570184588Sdfrstatic int w83877f_keyiter[] = { 1, 2, 2, 1 };
571184588Sdfrstatic int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 };
572184588Sdfr
573184588Sdfrstatic int
574184588Sdfrppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
575184588Sdfr{
576184588Sdfr	int i, j, efer, base;
577184588Sdfr	unsigned char r, hefere, hefras;
578184588Sdfr
579184588Sdfr	for (i = 0; i < 4; i ++) {
580184588Sdfr		/* first try to enable configuration registers */
581184588Sdfr		efer = w83877f_efers[i];
582184588Sdfr
583184588Sdfr		/* write the key to the EFER */
584184588Sdfr		for (j = 0; j < w83877f_keyiter[i]; j ++)
585184588Sdfr			outb (efer, w83877f_keys[i]);
586184588Sdfr
587184588Sdfr		/* then check HEFERE and HEFRAS bits */
588184588Sdfr		outb (efir, 0x0c);
589184588Sdfr		hefere = inb(efdr) & WINB_HEFERE;
590184588Sdfr
591184588Sdfr		outb (efir, 0x16);
592184588Sdfr		hefras = inb(efdr) & WINB_HEFRAS;
593184588Sdfr
594184588Sdfr		/*
595184588Sdfr		 * HEFRAS	HEFERE
596184588Sdfr		 *   0		   1	write 89h to 250h (power-on default)
597184588Sdfr		 *   1		   0	write 86h twice to 3f0h
598184588Sdfr		 *   1		   1	write 87h twice to 3f0h
599184588Sdfr		 *   0		   0	write 88h to 250h
600184588Sdfr		 */
601184588Sdfr		if ((hefere | hefras) == w83877f_hefs[i])
602184588Sdfr			goto found;
603184588Sdfr	}
604184588Sdfr
605184588Sdfr	return (-1);	/* failed */
606184588Sdfr
607184588Sdfrfound:
608184588Sdfr	/* check base port address - read from CR23 */
609184588Sdfr	outb(efir, 0x23);
610184588Sdfr	if (ppc->ppc_base != inb(efdr) * 4)		/* 4 bytes boundaries */
611184588Sdfr		return (-1);
612184588Sdfr
613184588Sdfr	/* read CHIP ID from CR9/bits0-3 */
614184588Sdfr	outb(efir, 0x9);
615184588Sdfr
616184588Sdfr	switch (inb(efdr) & WINB_CHIPID) {
617184588Sdfr		case WINB_W83877F_ID:
618184588Sdfr			ppc->ppc_type = WINB_W83877F;
619184588Sdfr			break;
620184588Sdfr
621		case WINB_W83877AF_ID:
622			ppc->ppc_type = WINB_W83877AF;
623			break;
624
625		default:
626			ppc->ppc_type = WINB_UNKNOWN;
627	}
628
629	if (bootverbose) {
630		/* dump of registers */
631		printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]);
632		for (i = 0; i <= 0xd; i ++) {
633			outb(efir, i);
634			printf("0x%x ", inb(efdr));
635		}
636		for (i = 0x10; i <= 0x17; i ++) {
637			outb(efir, i);
638			printf("0x%x ", inb(efdr));
639		}
640		outb(efir, 0x1e);
641		printf("0x%x ", inb(efdr));
642		for (i = 0x20; i <= 0x29; i ++) {
643			outb(efir, i);
644			printf("0x%x ", inb(efdr));
645		}
646		printf("\n");
647	}
648
649	if (!chipset_mode) {
650		/* autodetect mode */
651
652		/* select CR0 */
653		outb(efir, 0x0);
654		r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
655
656		/* select CR9 */
657		outb(efir, 0x9);
658		r |= (inb(efdr) & WINB_PRTMODS2);
659
660		switch (r) {
661		case WINB_W83757:
662			if (bootverbose)
663				printf("ppc%d: W83757 compatible mode\n",
664					ppc->ppc_unit);
665			return (-1);	/* generic or SMC-like */
666
667		case WINB_EXTFDC:
668		case WINB_EXTADP:
669		case WINB_EXT2FDD:
670		case WINB_JOYSTICK:
671			if (bootverbose)
672				printf("ppc%d: not in parallel port mode\n",
673					ppc->ppc_unit);
674			return (-1);
675
676		case (WINB_PARALLEL | WINB_EPP_SPP):
677			ppc->ppc_avm |= PPB_EPP | PPB_SPP;
678			break;
679
680		case (WINB_PARALLEL | WINB_ECP):
681			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
682			break;
683
684		case (WINB_PARALLEL | WINB_ECP_EPP):
685			ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
686			break;
687		default:
688			printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r);
689		}
690
691	} else {
692		/* mode forced */
693
694		/* select CR9 and set PRTMODS2 bit */
695		outb(efir, 0x9);
696		outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
697
698		/* select CR0 and reset PRTMODSx bits */
699		outb(efir, 0x0);
700		outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
701
702		if (chipset_mode & PPB_ECP) {
703			if (chipset_mode & PPB_EPP)
704				outb(efdr, inb(efdr) | WINB_ECP_EPP);
705			else
706				outb(efdr, inb(efdr) | WINB_ECP);
707		} else {
708			/* select EPP_SPP otherwise */
709			outb(efdr, inb(efdr) | WINB_EPP_SPP);
710		}
711		ppc->ppc_avm = chipset_mode;
712	}
713
714	/* exit configuration mode */
715	outb(efer, 0xaa);
716
717	if (ppc->ppc_avm & PPB_ECP)
718		ppc_ecp_config(ppc, chipset_mode);
719
720	return (chipset_mode);
721}
722
723/*
724 * ppc_generic_detect
725 */
726static int
727ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
728{
729	char save_control;
730
731	if (!chipset_mode) {
732		/* first, check for ECP */
733		w_ecr(ppc, 0x20);
734		if ((r_ecr(ppc) & 0xe0) == 0x20) {
735			ppc->ppc_avm |= PPB_ECP | PPB_SPP;
736
737			/* search for SMC style ECP+EPP mode */
738			w_ecr(ppc, 0x80);
739		}
740
741		/* try to reset EPP timeout bit */
742		if (ppc_check_epp_timeout(ppc)) {
743			ppc->ppc_avm |= PPB_EPP;
744
745			if (ppc->ppc_avm & PPB_ECP)
746				/* SMC like chipset found */
747				ppc->ppc_type = SMC_LIKE;
748		}
749
750		/* XXX try to detect NIBBLE mode */
751		ppc->ppc_avm |= PPB_NIBBLE;
752
753	} else
754		ppc->ppc_avm = chipset_mode;
755
756	if (ppc->ppc_avm & PPB_ECP)
757		ppc_ecp_config(ppc, chipset_mode);
758
759	return (chipset_mode);
760}
761
762/*
763 * ppc_detect()
764 *
765 * mode is the mode suggested at boot
766 */
767static int
768ppc_detect(struct ppc_data *ppc, int chipset_mode) {
769
770	int i, mode;
771
772	/* list of supported chipsets */
773	int (*chipset_detect[])(struct ppc_data *, int) = {
774		ppc_pc873xx_detect,
775		ppc_smc37c66xgt_detect,
776		ppc_w83877f_detect,
777		ppc_generic_detect,
778		NULL
779	};
780
781	/* if can't find the port and mode not forced return error */
782	if (!ppc_detect_port(ppc) && chipset_mode == 0)
783		return (EIO);			/* failed, port not present */
784
785	/* assume centronics compatible mode is supported */
786	ppc->ppc_avm = PPB_COMPATIBLE;
787
788	/* we have to differenciate available chipset modes,
789	 * chipset running modes and IEEE-1284 operating modes
790	 *
791	 * after detection, the port must support running in compatible mode
792	 */
793	for (i=0; chipset_detect[i] != NULL; i++) {
794		if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
795			ppc->ppc_mode = mode;
796			break;
797		}
798	}
799
800	return (0);
801}
802
803/*
804 * ppc_exec_microseq()
805 *
806 * Execute a microsequence.
807 * Microsequence mechanism is supposed to handle fast I/O operations.
808 */
809static int
810ppc_exec_microseq(int unit, struct ppb_microseq *msq, int *ppbpc)
811{
812	struct ppc_data	*ppc = ppcdata[unit];
813	struct ppb_microseq *pc;
814	char cc, *p;
815	int i, iter, reg;
816	int error;
817
818	/* static to be reused after few ppc_exec_microseq()/return calls
819	 * XXX should be in a context variable shared with ppb level */
820	static int accum;
821	static char *ptr;
822
823	struct ppb_microseq *microseq_stack = 0;
824	struct ppb_microseq *pc_stack = 0;
825
826/* microsequence registers are equivalent to PC-like port registers */
827#define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register))
828#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte)
829
830#define INCR_PC (pc ++)		/* increment program counter */
831#define mi pc			/* microinstruction currently executed */
832
833	/* get the state of pc from ppb level of execution */
834	pc = &msq[*ppbpc];
835
836	for (;;) {
837
838		switch (mi->opcode) {
839		case MS_OP_RSET:
840			cc = r_reg(mi->arg[0].i, ppc);
841			cc &= mi->arg[2].c;		/* clear mask */
842			cc |= mi->arg[1].c;		/* assert mask */
843                        w_reg(mi->arg[0].i, ppc, cc);
844			INCR_PC;
845                        break;
846
847		case MS_OP_RASSERT_P:
848			for (i=0; i<mi->arg[0].i; i++)
849				w_reg(mi->arg[1].i, ppc, *ptr++);
850			INCR_PC;
851			break;
852
853                case MS_OP_RFETCH_P:
854			for (i=0; i<mi->arg[0].i; i++)
855				*ptr++ = r_reg(mi->arg[1].i, ppc) &
856								mi->arg[2].c;
857			INCR_PC;
858                        break;
859
860                case MS_OP_RFETCH:
861			*((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
862							mi->arg[1].c;
863			INCR_PC;
864                        break;
865
866		case MS_OP_RASSERT:
867
868		/* let's suppose the next instr. is the same */
869		prefetch:
870			for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
871				w_reg(mi->arg[0].i, ppc, mi->arg[1].c);
872
873			if (mi->opcode == MS_OP_DELAY) {
874				DELAY(mi->arg[0].i);
875				INCR_PC;
876				goto prefetch;
877			}
878			break;
879
880                case MS_OP_DELAY:
881                        DELAY(mi->arg[0].i);
882			INCR_PC;
883                        break;
884
885		case MS_OP_TRIG:
886			reg = mi->arg[0].i;
887			iter = mi->arg[1].i;
888			p = (char *)mi->arg[2].p;
889
890			for (i=0; i<iter; i++) {
891				w_reg(reg, ppc, *p++);
892				DELAY((unsigned char)*p++);
893			}
894			INCR_PC;
895			break;
896
897                case MS_OP_SET:
898                        accum = mi->arg[0].i;
899			INCR_PC;
900                        break;
901
902                case MS_OP_DBRA:
903                        if (--accum > 0)
904                                pc += mi->arg[0].i;
905			else
906				INCR_PC;
907                        break;
908
909                case MS_OP_BRSET:
910                        cc = r_str(ppc);
911                        if ((cc & mi->arg[0].c) == mi->arg[0].c)
912                                pc += mi->arg[1].i;
913			else
914				INCR_PC;
915                        break;
916
917                case MS_OP_BRCLEAR:
918                        cc = r_str(ppc);
919                        if ((cc & mi->arg[0].c) == 0)
920                                pc += mi->arg[1].i;
921			else
922				INCR_PC;
923                        break;
924
925		case MS_OP_C_CALL:
926			/*
927			 * If the C call returns !0 then end the microseq.
928			 * The current state of ptr is passed to the C function
929			 */
930			if ((error = mi->arg[0].f(mi->arg[1].p, ptr)))
931				return (error);
932
933			INCR_PC;
934			break;
935
936		case MS_OP_PTR:
937			ptr = (char *)mi->arg[0].p;
938			INCR_PC;
939			break;
940
941		case MS_OP_CALL:
942			if (microseq_stack)
943				panic("%s: too much calls", __FUNCTION__);
944
945			if (mi->arg[0].p) {
946				/* store the state of the actual
947				 * microsequence
948				 */
949				microseq_stack = msq;
950				pc_stack = pc;
951
952				/* jump to the new microsequence */
953				msq = (struct ppb_microseq *)mi->arg[0].p;
954				pc = msq;
955			} else
956				INCR_PC;
957
958			break;
959
960		case MS_OP_SUBRET:
961			/* retrieve microseq and pc state before the call */
962			msq = microseq_stack;
963			pc = pc_stack;
964
965			/* reset the stack */
966			microseq_stack = 0;
967
968			/* XXX return code */
969
970			INCR_PC;
971			break;
972
973                case MS_OP_PUT:
974                case MS_OP_GET:
975                case MS_OP_RET:
976			/* can't return to ppb level during the execution
977			 * of a submicrosequence */
978			if (microseq_stack)
979				panic("%s: can't return to ppb level",
980								__FUNCTION__);
981
982			/* update pc for ppb level of execution */
983			*ppbpc = (int)(pc - msq);
984
985			/* return to ppb level of execution */
986			return (0);
987
988                default:
989                        panic("%s: unknown microsequence opcode 0x%x",
990                                __FUNCTION__, mi->opcode);
991                }
992	}
993
994	/* unreached */
995}
996
997/*
998 * Configure current operating mode
999 */
1000static int
1001ppc_generic_setmode(int unit, int mode)
1002{
1003	struct ppc_data *ppc = ppcdata[unit];
1004
1005	/* back to compatible mode, XXX don't know yet what to do here */
1006	if (mode == 0) {
1007		ppc->ppc_mode = PPB_COMPATIBLE;
1008		return (0);
1009	}
1010
1011	/* check if mode is available */
1012	if (!(ppc->ppc_avm & mode))
1013		return (EOPNOTSUPP);
1014
1015	/* if ECP mode, configure ecr register */
1016	if (ppc->ppc_avm & PPB_ECP)
1017		ppc_ecp_config(ppc, mode);
1018
1019	ppc->ppc_mode = mode;
1020
1021	return (0);
1022}
1023
1024/*
1025 * EPP timeout, according to the PC87332 manual
1026 * Semantics of clearing EPP timeout bit.
1027 * PC87332	- reading SPP_STR does it...
1028 * SMC		- write 1 to EPP timeout bit			XXX
1029 * Others	- (???) write 0 to EPP timeout bit
1030 */
1031static void
1032ppc_reset_epp_timeout(int unit)
1033{
1034	struct ppc_data *ppc = ppcdata[unit];
1035	register char r;
1036
1037	r = r_str(ppc);
1038	w_str(ppc, r | 0x1);
1039	w_str(ppc, r & 0xfe);
1040
1041	return;
1042}
1043
1044static int
1045ppcprobe(struct isa_device *dvp)
1046{
1047	static short next_bios_ppc = 0;
1048	struct ppc_data *ppc;
1049	int error;
1050
1051	/*
1052	 * If port not specified, use bios list.
1053	 */
1054	if(dvp->id_iobase < 0) {
1055		if((next_bios_ppc < BIOS_MAX_PPC) &&
1056				(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
1057			dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
1058		} else
1059			return (0);
1060	}
1061
1062	/*
1063	 * Port was explicitly specified.
1064	 * This allows probing of ports unknown to the BIOS.
1065	 */
1066
1067	/*
1068	 * Allocate the ppc_data structure.
1069	 */
1070	ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
1071	if (!ppc) {
1072		printf("ppc: cannot malloc!\n");
1073		goto error;
1074	}
1075	bzero(ppc, sizeof(struct ppc_data));
1076
1077	ppc->ppc_base = dvp->id_iobase;
1078	ppc->ppc_unit = dvp->id_unit;
1079	ppc->ppc_type = GENERIC;
1080
1081	ppc->ppc_mode = PPB_COMPATIBLE;
1082	ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
1083
1084	/*
1085	 * XXX
1086	 * Try and detect if interrupts are working.
1087	 */
1088	if (!(dvp->id_flags & 0x20))
1089		ppc->ppc_irq = (dvp->id_irq);
1090
1091	ppcdata[ppc->ppc_unit] = ppc;
1092	nppc ++;
1093
1094	/*
1095	 * Try to detect the chipset and its mode.
1096	 */
1097	if (ppc_detect(ppc, dvp->id_flags & 0xf))
1098		goto error;
1099
1100end_probe:
1101
1102	return (1);
1103
1104error:
1105	return (0);
1106}
1107
1108static int
1109ppcattach(struct isa_device *isdp)
1110{
1111	struct ppc_data *ppc = ppcdata[isdp->id_unit];
1112	struct ppb_data *ppbus;
1113	char * mode;
1114
1115	/*
1116	 * Link the Parallel Port Chipset (adapter) to
1117	 * the future ppbus.
1118	 */
1119	ppc->ppc_link.adapter_unit = ppc->ppc_unit;
1120	ppc->ppc_link.adapter = &ppc_adapter;
1121
1122	printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
1123		ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
1124		ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
1125			ppc_epp_protocol[ppc->ppc_epp] : "");
1126
1127	/*
1128	 * Prepare ppbus data area for upper level code.
1129	 */
1130	ppbus = ppb_alloc_bus();
1131
1132	if (!ppbus)
1133		return (0);
1134
1135	ppc->ppc_link.ppbus = ppbus;
1136	ppbus->ppb_link = &ppc->ppc_link;
1137
1138	/*
1139	 * Probe the ppbus and attach devices found.
1140	 */
1141	ppb_attachdevs(ppbus);
1142
1143	return (1);
1144}
1145#endif
1146