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