2 * Copyright (c) 1997, 1998 Nicolas Souchu
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $Id: ppc.c,v 1.9 1998/09/20 14:47:01 nsouch Exp $
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/kernel.h>
39 #include <machine/clock.h>
42 #include <vm/vm_param.h>
45 #include <i386/isa/isa_device.h>
47 #include <dev/ppbus/ppbconf.h>
48 #include <dev/ppbus/ppb_msq.h>
50 #include <i386/isa/ppcreg.h>
52 static int ppcprobe(struct isa_device *);
53 static int ppcattach(struct isa_device *);
55 struct isa_driver ppcdriver = {
56 ppcprobe, ppcattach, "ppc"
59 static struct ppc_data *ppcdata[NPPC];
62 static char *ppc_types[] = {
63 "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
64 "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0
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
75 /* list of current executing modes
76 * Note that few modes do not actually exist.
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
85 static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
88 * BIOS printer list - used by BIOS probe.
90 #define BIOS_PPC_PORTS 0x408
91 #define BIOS_PORTS (short *)(KERNBASE+BIOS_PPC_PORTS)
92 #define BIOS_MAX_PPC 4
95 * All these functions are default actions for IN/OUT operations.
96 * They may be redefined if needed.
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); }
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]); }
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); }
125 static void ppc_reset_epp_timeout(int);
126 static void ppc_ecp_sync(int);
127 static ointhand2_t ppcintr;
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);
133 static struct ppb_adapter ppc_smclike_adapter = {
135 0, /* no intr handler, filled by chipset dependent code */
137 ppc_reset_epp_timeout, ppc_ecp_sync,
143 ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
144 ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
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
150 static struct ppb_adapter ppc_generic_adapter = {
152 0, /* no intr handler, filled by chipset dependent code */
154 ppc_reset_epp_timeout, ppc_ecp_sync,
160 ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
161 ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
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
171 ppc_ecp_sync(int unit) {
173 struct ppc_data *ppc = ppcdata[unit];
177 if ((r & 0xe0) != 0x80)
180 for (i = 0; i < 100; i++) {
187 printf("ppc%d: ECP sync failed as data still " \
188 "present in FIFO.\n", unit);
196 /* call directly upper code */
197 ppb_intr(&ppcdata[unit]->ppc_link);
203 ppc_detect_port(struct ppc_data *ppc)
206 w_ctr(ppc, 0x0c); /* To avoid missing PS2 ports */
208 if (r_dtr(ppc) != (char) 0xaa)
217 * Probe for a Natsemi PC873xx-family part.
219 * References in this function are to the National Semiconductor
220 * PC87332 datasheet TL/C/11930, May 1995 revision.
222 static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
223 static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
226 ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */
228 static int index = 0;
232 while ((idport = pc873xx_basetab[index++])) {
234 /* XXX should check first to see if this location is already claimed */
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.
240 (void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport);
243 * Read the SID byte. Possible values are :
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;
255 if (bootverbose && (val != 0xff))
256 printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
257 continue ; /* not recognised */
261 * We think we have one. Is it enabled and where we want it to be?
263 outb(idport, PC873_FER);
264 val = inb(idport + 1);
265 if (!(val & PC873_PPENABLE)) {
267 printf("PC873xx parallel port disabled\n");
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) {
275 printf("PC873xx at 0x%x not for driver at port 0x%x\n",
276 pc873xx_porttab[val], ppc->ppc_base);
281 * This is the port we want. Can we dink with it to improve
284 outb(idport, PC873_PTR);
285 val = inb(idport + 1);
286 if (val & PC873_CFGLOCK) {
288 printf("PC873xx locked\n");
290 /* work out what mode we're in */
291 ppc->ppc_avm |= PPB_NIBBLE; /* worst case */
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 */
301 } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
302 ppc->ppc_avm |= PPB_PS2; /* tolerable alternative */
306 printf("PC873xx unlocked, ");
310 * Frob the zero-wait-state option if possible; it causes
311 * unreliable operation.
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 */
318 outb(idport + 1, val); /* must disable ZWS */
319 outb(idport + 1, val);
322 printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled");
327 printf("reconfiguring for ");
330 * if the chip is at 0x3bc, we can't use EPP as there's no room
331 * for the extra registers.
333 * XXX should we use ECP mode always and use the EPP submode?
335 if (ppc->ppc_base != 0x3bc) {
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);
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);
354 /* we are an EPP-32 port */
355 ppc->ppc_avm |= PPB_EPP;
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);
364 /* we look like a PS/2 port */
365 ppc->ppc_avm |= PPB_PS2;
369 return(chipset_mode);
375 ppc_check_epp_timeout(struct ppc_data *ppc)
377 ppc_reset_epp_timeout(ppc->ppc_unit);
379 return (!(r_str(ppc) & TIMEOUT));
383 * ppc_smc37c66xgt_detect
385 * SMC FDC37C66xGT configuration.
388 ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
393 int csr = SMC66x_CSR; /* initial value is 0x3F0 */
395 int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
398 #define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */
401 * Detection: enter configuration mode and read CRD register.
405 outb(csr, SMC665_iCODE);
406 outb(csr, SMC665_iCODE);
410 if (inb(cio) == 0x65) {
415 for (i = 0; i < 2; i++) {
417 outb(csr, SMC666_iCODE);
418 outb(csr, SMC666_iCODE);
422 if (inb(cio) == 0x66) {
427 /* Another chance, CSR may be hard-configured to be at 0x370 */
433 * If chipset not found, do not continue.
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)
446 ppc->ppc_type = type;
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
455 printf("ppc%d: SMC registers CR1=0x%x", ppc->ppc_unit,
459 printf(" CR4=0x%x", inb(cio) & 0xff);
466 /* autodetect mode */
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;
472 printf(" configuration hardwired, supposing " \
476 if ((inb(cio) & SMC_CR1_MODE) == 0) {
477 /* already in extended parallel port mode, read CR4 */
479 r = (inb(cio) & SMC_CR4_EMODE);
483 ppc->ppc_avm |= PPB_SPP;
489 ppc->ppc_avm |= PPB_EPP | PPB_SPP;
495 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
501 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
503 printf(" ECP+EPP SPP");
507 /* not an extended port mode */
508 ppc->ppc_avm |= PPB_SPP;
515 ppc->ppc_avm = chipset_mode;
517 /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
518 if (type == SMC_37C666GT)
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);
528 /* an extended mode is selected */
529 outb(cio, r & ~SMC_CR1_MODE);
531 /* read CR4 register and reset mode field */
533 r = inb(cio) & ~SMC_CR4_EMODE;
535 if (chipset_mode & PPB_ECP) {
536 if (chipset_mode & PPB_EPP) {
537 outb(cio, r | SMC_ECPEPP);
541 outb(cio, r | SMC_ECP);
547 outb(cio, r | SMC_EPPSPP);
552 ppc->ppc_avm = chipset_mode;
560 if (ppc->ppc_avm & PPB_EPP) {
566 * Set the EPP protocol...
567 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
569 if (ppc->ppc_epp == EPP_1_9)
570 outb(cio, (r & ~SMC_CR4_EPPTYPE));
572 outb(cio, (r | SMC_CR4_EPPTYPE));
575 /* end config mode */
578 ppc->ppc_link.adapter = &ppc_smclike_adapter;
579 ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
581 return (chipset_mode);
585 * Winbond W83877F stuff
587 * EFER: extended function enable register
588 * EFIR: extended function index register
589 * EFDR: extended function data register
591 #define efir ((efer == 0x250) ? 0x251 : 0x3f0)
592 #define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
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 };
600 ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
602 int i, j, efer, base;
603 unsigned char r, hefere, hefras;
605 for (i = 0; i < 4; i ++) {
606 /* first try to enable configuration registers */
607 efer = w83877f_efers[i];
609 /* write the key to the EFER */
610 for (j = 0; j < w83877f_keyiter[i]; j ++)
611 outb (efer, w83877f_keys[i]);
613 /* then check HEFERE and HEFRAS bits */
615 hefere = inb(efdr) & WINB_HEFERE;
618 hefras = inb(efdr) & WINB_HEFRAS;
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
627 if ((hefere | hefras) == w83877f_hefs[i])
631 return (-1); /* failed */
634 /* check base port address - read from CR23 */
636 if (ppc->ppc_base != inb(efdr) * 4) /* 4 bytes boundaries */
639 /* read CHIP ID from CR9/bits0-3 */
642 switch (inb(efdr) & WINB_CHIPID) {
643 case WINB_W83877F_ID:
644 ppc->ppc_type = WINB_W83877F;
647 case WINB_W83877AF_ID:
648 ppc->ppc_type = WINB_W83877AF;
652 ppc->ppc_type = WINB_UNKNOWN;
656 /* dump of registers */
657 printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]);
658 for (i = 0; i <= 0xd; i ++) {
660 printf("0x%x ", inb(efdr));
662 for (i = 0x10; i <= 0x17; i ++) {
664 printf("0x%x ", inb(efdr));
667 printf("0x%x ", inb(efdr));
668 for (i = 0x20; i <= 0x29; i ++) {
670 printf("0x%x ", inb(efdr));
673 printf("ppc%d:", ppc->ppc_unit);
676 ppc->ppc_link.adapter = &ppc_generic_adapter;
679 /* autodetect mode */
683 r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
687 r |= (inb(efdr) & WINB_PRTMODS2);
692 printf("ppc%d: W83757 compatible mode\n",
694 return (-1); /* generic or SMC-like */
701 printf(" not in parallel port mode\n");
704 case (WINB_PARALLEL | WINB_EPP_SPP):
705 ppc->ppc_avm |= PPB_EPP | PPB_SPP;
710 case (WINB_PARALLEL | WINB_ECP):
711 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
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;
721 printf(" ECP+EPP SPP");
724 printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r);
730 /* select CR9 and set PRTMODS2 bit */
732 outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
734 /* select CR0 and reset PRTMODSx bits */
736 outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
738 if (chipset_mode & PPB_ECP) {
739 if (chipset_mode & PPB_EPP) {
740 outb(efdr, inb(efdr) | WINB_ECP_EPP);
744 ppc->ppc_link.adapter = &ppc_smclike_adapter;
747 outb(efdr, inb(efdr) | WINB_ECP);
752 /* select EPP_SPP otherwise */
753 outb(efdr, inb(efdr) | WINB_EPP_SPP);
757 ppc->ppc_avm = chipset_mode;
763 /* exit configuration mode */
766 ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
768 return (chipset_mode);
775 ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
779 /* default to generic */
780 ppc->ppc_link.adapter = &ppc_generic_adapter;
783 printf("ppc%d:", ppc->ppc_unit);
786 /* first, check for ECP */
788 if ((r_ecr(ppc) & 0xe0) == 0x20) {
789 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
793 /* search for SMC style ECP+EPP mode */
797 /* try to reset EPP timeout bit */
798 if (ppc_check_epp_timeout(ppc)) {
799 ppc->ppc_avm |= PPB_EPP;
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;
813 /* restore to standard mode */
817 /* XXX try to detect NIBBLE and PS2 modes */
818 ppc->ppc_avm |= PPB_NIBBLE;
824 ppc->ppc_avm = chipset_mode;
830 ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
832 return (chipset_mode);
838 * mode is the mode suggested at boot
841 ppc_detect(struct ppc_data *ppc, int chipset_mode) {
845 /* list of supported chipsets */
846 int (*chipset_detect[])(struct ppc_data *, int) = {
848 ppc_smc37c66xgt_detect,
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 */
858 /* assume centronics compatible mode is supported */
859 ppc->ppc_avm = PPB_COMPATIBLE;
861 /* we have to differenciate available chipset modes,
862 * chipset running modes and IEEE-1284 operating modes
864 * after detection, the port must support running in compatible mode
866 for (i=0; chipset_detect[i] != NULL; i++) {
867 if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
868 ppc->ppc_mode = mode;
877 * ppc_exec_microseq()
879 * Execute a microsequence.
880 * Microsequence mechanism is supposed to handle fast I/O operations.
883 ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
885 struct ppc_data *ppc = ppcdata[unit];
886 struct ppb_microseq *mi;
893 register int accum = 0;
894 register char *ptr = 0;
896 struct ppb_microseq *stack = 0;
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)
902 #define INCR_PC (mi ++) /* increment program counter */
906 switch (mi->opcode) {
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);
915 case MS_OP_RASSERT_P:
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;
925 for (i=0; i<len; i++)
926 w_reg(reg, ppc, *ptr++);
934 mask = (char)mi->arg[2].i;
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;
943 for (i=0; i<len; i++)
944 *ptr++ = r_reg(reg, ppc) & mask;
951 *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
959 /* let's suppose the next instr. is the same */
961 for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
962 w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i);
964 if (mi->opcode == MS_OP_DELAY) {
973 tsleep(NULL, PPBPRI, "ppbdelay",
974 mi->arg[0].i * (hz/1000));
981 p = (char *)mi->arg[2].p;
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++);
992 ppc->ppc_accum = mi->arg[0].i;
997 if (--ppc->ppc_accum > 0)
1005 if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i)
1013 if ((cc & (char)mi->arg[0].i) == 0)
1021 if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) ==
1030 * If the C call returns !0 then end the microseq.
1031 * The current state of ptr is passed to the C function
1033 if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr)))
1040 ppc->ppc_ptr = (char *)mi->arg[0].p;
1046 panic("%s: too much calls", __FUNCTION__);
1049 /* store the state of the actual
1054 /* jump to the new microsequence */
1055 mi = (struct ppb_microseq *)mi->arg[0].p;
1062 /* retrieve microseq and pc state before the call */
1065 /* reset the stack */
1068 /* XXX return code */
1076 /* can't return to ppb level during the execution
1077 * of a submicrosequence */
1079 panic("%s: can't return to ppb level",
1082 /* update pc for ppb level of execution */
1085 /* return to ppb level of execution */
1089 panic("%s: unknown microsequence opcode 0x%x",
1090 __FUNCTION__, mi->opcode);
1098 * Configure current operating mode
1101 ppc_generic_setmode(int unit, int mode)
1103 struct ppc_data *ppc = ppcdata[unit];
1105 /* back to compatible mode, XXX don't know yet what to do here */
1107 ppc->ppc_mode = PPB_COMPATIBLE;
1111 /* check if mode is available */
1112 if (!(ppc->ppc_avm & mode))
1113 return (EOPNOTSUPP);
1115 /* if ECP mode, configure ecr register */
1116 if (ppc->ppc_avm & PPB_ECP) {
1118 /* XXX disable DMA, enable interrupts */
1120 return (EOPNOTSUPP);
1121 else if (mode & PPB_PS2)
1122 /* select PS2 mode with ECP */
1124 else if (mode & PPB_ECP)
1125 /* select ECP mode */
1128 /* select standard parallel port mode */
1132 ppc->ppc_mode = mode;
1138 ppc_smclike_setmode(int unit, int mode)
1140 struct ppc_data *ppc = ppcdata[unit];
1142 /* back to compatible mode, XXX don't know yet what to do here */
1144 ppc->ppc_mode = PPB_COMPATIBLE;
1148 /* check if mode is available */
1149 if (!(ppc->ppc_avm & mode))
1150 return (EOPNOTSUPP);
1152 /* if ECP mode, configure ecr register */
1153 if (ppc->ppc_avm & PPB_ECP) {
1155 /* XXX disable DMA, enable interrupts */
1157 /* select EPP mode */
1159 else if (mode & PPB_PS2)
1160 /* select PS2 mode with ECP */
1162 else if (mode & PPB_ECP)
1163 /* select ECP mode */
1166 /* select standard parallel port mode */
1170 ppc->ppc_mode = mode;
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
1184 ppc_reset_epp_timeout(int unit)
1186 struct ppc_data *ppc = ppcdata[unit];
1190 w_str(ppc, r | 0x1);
1191 w_str(ppc, r & 0xfe);
1197 ppcprobe(struct isa_device *dvp)
1199 static short next_bios_ppc = 0;
1200 struct ppc_data *ppc;
1204 * If port not specified, use bios list.
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",
1217 * Port was explicitly specified.
1218 * This allows probing of ports unknown to the BIOS.
1222 * Allocate the ppc_data structure.
1224 ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
1226 printf("ppc: cannot malloc!\n");
1229 bzero(ppc, sizeof(struct ppc_data));
1231 ppc->ppc_base = dvp->id_iobase;
1232 ppc->ppc_unit = dvp->id_unit;
1233 ppc->ppc_type = GENERIC;
1235 ppc->ppc_mode = PPB_COMPATIBLE;
1236 ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
1239 * XXX Try and detect if interrupts are working
1241 if (!(dvp->id_flags & 0x20))
1242 ppc->ppc_irq = (dvp->id_irq);
1244 ppcdata[ppc->ppc_unit] = ppc;
1248 * Link the Parallel Port Chipset (adapter) to
1249 * the future ppbus. Default to a generic chipset
1251 ppc->ppc_link.adapter_unit = ppc->ppc_unit;
1252 ppc->ppc_link.adapter = &ppc_generic_adapter;
1255 * Try to detect the chipset and its mode.
1257 if (ppc_detect(ppc, dvp->id_flags & 0xf))
1269 ppcattach(struct isa_device *isdp)
1271 struct ppc_data *ppc = ppcdata[isdp->id_unit];
1272 struct ppb_data *ppbus;
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] : "");
1280 isdp->id_ointr = ppcintr;
1283 * Prepare ppbus data area for upper level code.
1285 ppbus = ppb_alloc_bus();
1290 ppc->ppc_link.ppbus = ppbus;
1291 ppbus->ppb_link = &ppc->ppc_link;
1294 * Probe the ppbus and attach devices found.
1296 ppb_attachdevs(ppbus);