Deleted Added
sdiff udiff text old ( 35256 ) new ( 38061 )
full compact
1/*-
2 * Copyright (c) 1997 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

--- 7 unchanged lines hidden (view full) ---

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.2 1997/09/01 02:08:41 bde Exp $
27 *
28 */
29#include "ppc.h"
30
31#if NPPC > 0
32
33#include <sys/param.h>
34#include <sys/systm.h>

--- 4 unchanged lines hidden (view full) ---

39
40#include <vm/vm.h>
41#include <vm/vm_param.h>
42#include <vm/pmap.h>
43
44#include <i386/isa/isa_device.h>
45
46#include <dev/ppbus/ppbconf.h>
47#include <i386/isa/ppcreg.h>
48
49static int ppcprobe(struct isa_device *);
50static int ppcattach(struct isa_device *);
51
52struct isa_driver ppcdriver = {
53 ppcprobe, ppcattach, "ppc"
54};
55
56static struct ppc_data *ppcdata[NPPC];
57static int nppc = 0;
58
59static char *ppc_types[] = {
60 "SMC", "SMC FDC37C665GT", "SMC FDC37C666GT",
61 "NatSemi", "PC87332", "PC87306",
62 "Intel 82091AA", "Generic", 0
63};
64
65static char *ppc_modes[] = {
66 "AUTODETECT", "NIBBLE", "PS/2", "EPP", "ECP+EPP", "ECP+PS/2", "ECP",
67 "UNKNOWN", 0
68};
69
70static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
71
72/*
73 * BIOS printer list - used by BIOS probe.
74 */
75#define BIOS_PPC_PORTS 0x408

--- 29 unchanged lines hidden (view full) ---

105static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
106static void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); }
107static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
108static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
109
110static void ppc_reset_epp_timeout(int);
111static void ppc_ecp_sync(int);
112
113static struct ppb_adapter ppc_adapter = {
114
115 0, /* no intr handler, filled by chipset dependent code */
116
117 ppc_reset_epp_timeout, ppc_ecp_sync,
118
119 ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
120 ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
121
122 ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo,
123 ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo
124};
125
126/*

--- 11 unchanged lines hidden (view full) ---

138
139 for (i = 0; i < 100; i++) {
140 r = r_ecr(ppc);
141 if (r & 0x1)
142 return;
143 DELAY(100);
144 }
145
146 printf("ppc: ECP sync failed as data still " \
147 "present in FIFO.\n");
148
149 return;
150}
151
152void
153ppcintr(int unit)
154{
155 /* call directly upper code */
156 ppb_intr(&ppcdata[unit]->ppc_link);
157
158 return;
159}
160
161/*
162 * ppc_pc873xx_detect
163 *
164 * Probe for a Natsemi PC873xx-family part.
165 *
166 * References in this function are to the National Semiconductor
167 * PC87332 datasheet TL/C/11930, May 1995 revision.
168 */
169static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
170static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
171
172static int
173ppc_pc873xx_detect(struct ppc_data *ppc)
174{
175 static int index = 0;
176 int base, idport;
177 int val, mode;
178
179 while ((idport = pc873xx_basetab[index++])) {
180
181 /* XXX should check first to see if this location is already claimed */
182
183 /*
184 * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this
185 * to locate the chip as it may already have been used by the BIOS.

--- 44 unchanged lines hidden (view full) ---

230 */
231 outb(idport, PC873_PTR);
232 val = inb(idport + 1);
233 if (val & PC873_CFGLOCK) {
234 if (bootverbose)
235 printf("PC873xx locked\n");
236
237 /* work out what mode we're in */
238 mode = PPB_NIBBLE; /* worst case */
239
240 outb(idport, PC873_PCR);
241 val = inb(idport + 1);
242 if ((val & PC873_EPPEN) && (val & PC873_EPP19)) {
243 outb(idport, PC873_PTR);
244 val = inb(idport + 1);
245 if (!(val & PC873_EPPRDIR)) {
246 mode = PPB_EPP; /* As we would have done it anwyay */
247 }
248 } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) {
249 mode = PPB_PS2; /* tolerable alternative */
250 }
251 } else {
252 if (bootverbose)
253 printf("PC873xx unlocked, ");
254
255#if 0 /* broken */
256 /*
257 * Frob the zero-wait-state option if possible; it causes

--- 36 unchanged lines hidden (view full) ---

294 /* enable automatic direction turnover */
295 outb(idport, PC873_PTR);
296 val = inb(idport + 1);
297 val &= ~PC873_EPPRDIR; /* disable "regular" direction change */
298 outb(idport + 1, val);
299 outb(idport + 1, val);
300
301 /* we are an EPP-32 port */
302 mode = PPB_EPP;
303 } else {
304 if (bootverbose)
305 printf("ECP\n");
306
307 /* configure as an ECP port to get bidirectional operation for now */
308 outb(idport, PC873_PCR);
309 outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK);
310
311 /* we look like a PS/2 port */
312 mode = PPB_PS2;
313 }
314 }
315 return(mode);
316 }
317 return(0);
318}
319
320static int
321ppc_detect_ps2(struct ppc_data *ppc)
322{
323 char save_control, r;
324
325 save_control = r_ctr(ppc);
326
327 /* Try PS/2 mode */
328 w_ctr(ppc, 0xec);
329 w_dtr(ppc, 0x55);
330
331 /* needed if in ECP mode */
332 if (ppc->ppc_mode == PPB_ECP)
333 w_ctr(ppc, PCD | 0xec);
334 r = r_dtr(ppc);
335
336 if (r != (char) 0xff) {
337 if (r != (char) 0x55)
338 return 0;
339
340 w_dtr(ppc, 0xaa);
341 r = r_dtr(ppc);
342 if (r != (char) 0xaa)
343 return 0;
344
345 return (PPB_NIBBLE);
346 } else
347 w_ctr(ppc, save_control);
348
349 return (PPB_PS2);
350}
351
352/*
353 * ppc_smc37c66xgt_detect
354 *
355 * SMC FDC37C66xGT configuration.
356 */
357static int
358ppc_smc37c66xgt_detect(struct ppc_data *ppc, int mode)
359{
360 int s, i;
361 char r;
362 int retry = 0; /* boolean */
363 int type = -1;
364 int csr = SMC66x_CSR; /* initial value is 0x3F0 */
365
366 int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
367
368
369#define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */
370

--- 28 unchanged lines hidden (view full) ---

399 csr = SMC666_CSR;
400 }
401
402config:
403 /*
404 * If chipset not found, do not continue.
405 */
406 if (type == -1)
407 return (0);
408
409 /* select CR1 */
410 outb(csr, 0x1);
411
412 /* read the port's address: bits 0 and 1 of CR1 */
413 r = inb(cio) & SMC_CR1_ADDR;
414 if (port_address[r] != ppc->ppc_base)
415 return (0);
416
417 ppc->ppc_type = type;
418
419 /*
420 * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
421 * If SPP mode is detected, try to set ECP+EPP mode end retry
422 * detection to verify.
423 */
424
425retry:
426 /* select CR1 register */
427 outb(csr, 0x1);
428
429 if (!mode) {
430 /* autodetect mode */
431
432 /* 666GT chipset is hardwired to an extended mode */
433 if (type == SMC_37C666GT)
434 mode = PPB_ECP_EPP;
435
436 else if ((inb(cio) & SMC_CR1_MODE) == 0) {
437 /* already in extended parallel port mode, read CR4 */
438 outb(csr, 0x4);
439 r = (inb(cio) & SMC_CR4_EMODE);
440
441 switch (r) {
442 case SMC_SPP:
443 /* let's detect NIBBLE or PS/2 later */
444 break;
445
446 case SMC_EPPSPP:
447 mode = PPB_EPP;
448 break;
449
450 case SMC_ECP:
451 /*
452 * Yet, don't know what to do with it! XXX
453 * So, consider ECP mode as PS/2.
454 * (see configuration later).
455 */
456 mode = PPB_ECP;
457 break;
458
459 case SMC_ECPEPP:
460 mode = PPB_ECP_EPP;
461 break;
462 }
463 }
464 } else {
465 /* mode forced */
466
467 /* 666GT chipset is hardwired to an extended mode */
468 if (type == SMC_37C666GT)
469 goto end_detect;
470
471 r = inb(cio);
472 if (mode == PPB_NIBBLE || mode == PPB_PS2) {
473 /* do not use ECP when the mode is forced to SPP */
474 outb(cio, r | SMC_CR1_MODE);
475 } else {
476 /* an extended mode is selected */
477 outb(cio, r & ~SMC_CR1_MODE);
478
479 /* read CR4 register and reset mode field */
480 outb(csr, 0x4);
481 r = inb(cio) & ~SMC_CR4_EMODE;
482
483 switch (mode) {
484 case PPB_EPP:
485 outb(cio, r | SMC_EPPSPP);
486 break;
487
488 case PPB_ECP:
489 case PPB_ECP_PS2:
490 outb(cio, r | SMC_ECP);
491 break;
492
493 case PPB_ECP_EPP:
494 outb(cio, r | SMC_ECPEPP);
495 break;
496
497 default:
498 printf("ppc: unknown mode (%d)\n",
499 mode);
500 return (0);
501 }
502 }
503 }
504
505end_detect:
506 if (PPB_IS_EPP(mode)) {
507 /* select CR4 */
508 outb(csr, 0x4);
509 r = inb(cio);
510
511 /*
512 * Set the EPP protocol...
513 * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
514 * ...then check the result.
515 */
516 if (ppc->ppc_epp == EPP_1_9)
517 outb(cio, (r & ~SMC_CR4_EPPTYPE));
518
519 else
520 outb(cio, (r | SMC_CR4_EPPTYPE));
521 }
522
523 /* end config mode */
524 outb(csr, 0xaa);
525
526 /*
527 * Write 100 to the mode bits and disable DMA, enable intr.
528 */
529 if (mode == PPB_ECP_EPP)
530 w_ecr(ppc, 0x80);
531
532 /*
533 * Write 001 to the mode bits and disable DMA, enable intr.
534 */
535 if (mode == PPB_ECP)
536 w_ecr(ppc, 0x20);
537
538 if (PPB_IS_EPP(mode)) {
539 /*
540 * Try to reset EPP timeout bit.
541 * If it fails, try PS/2 and NIBBLE modes.
542 */
543 ppc_reset_epp_timeout(ppc->ppc_unit);
544
545 r = r_str(ppc);
546 if (!(r & TIMEOUT))
547 return (mode);
548 } else {
549 if (mode)
550 return (mode);
551 }
552
553 /* detect PS/2 or NIBBLE mode */
554 return (ppc_detect_ps2(ppc));
555}
556
557static int
558ppc_check_ecpepp_timeout(struct ppc_data *ppc)
559{
560 char r;
561
562 ppc_reset_epp_timeout(ppc->ppc_unit);
563
564 r = r_str(ppc);
565 if (!(r & TIMEOUT)) {
566 return (PPB_ECP_EPP);
567 }
568
569 /* If EPP timeout bit is not reset, DON'T use EPP */
570 w_ecr(ppc, 0x20);
571
572 return (PPB_ECP_PS2);
573}
574
575/*
576 * ppc_generic_detect
577 */
578static int
579ppc_generic_detect(struct ppc_data *ppc, int mode)
580{
581 char save_control, r;
582
583 /* don't know what to do here */
584 if (mode)
585 return (mode);
586
587 /* try to reset EPP timeout bit */
588 ppc_reset_epp_timeout(ppc->ppc_unit);
589
590 r = r_str(ppc);
591 if (!(r & TIMEOUT)) {
592 return (PPB_EPP);
593 }
594
595 /* Now check for ECP */
596 w_ecr(ppc, 0x20);
597 r = r_ecr(ppc);
598 if ((r & 0xe0) == 0x20) {
599 /* Search for SMC style EPP+ECP mode */
600 w_ecr(ppc, 0x80);
601
602 return (ppc_check_ecpepp_timeout(ppc));
603 }
604
605 return (ppc_detect_ps2(ppc));
606}
607
608/*
609 * ppc_detect()
610 *
611 * mode is the mode suggested at boot
612 */
613static int
614ppc_detect(struct ppc_data *ppc, int mode) {
615
616 if (!ppc->ppc_mode && (ppc->ppc_mode = ppc_pc873xx_detect(ppc)))
617 goto end_detect;
618
619 if (!ppc->ppc_mode && (ppc->ppc_mode =
620 ppc_smc37c66xgt_detect(ppc, mode)))
621 goto end_detect;
622
623 if (!ppc->ppc_mode && (ppc->ppc_mode = ppc_generic_detect(ppc, mode)))
624 goto end_detect;
625
626 printf("ppc: port not present at 0x%x.\n", ppc->ppc_base);
627 return (PPC_ENOPORT);
628
629end_detect:
630
631 return (0);
632}
633
634/*
635 * EPP timeout, according to the PC87332 manual
636 * Semantics of clearing EPP timeout bit.
637 * PC87332 - reading SPP_STR does it...
638 * SMC - write 1 to EPP timeout bit XXX
639 * Others - (???) write 0 to EPP timeout bit
640 */
641static void
642ppc_reset_epp_timeout(int unit)

--- 40 unchanged lines hidden (view full) ---

683 goto error;
684 }
685 bzero(ppc, sizeof(struct ppc_data));
686
687 ppc->ppc_base = dvp->id_iobase;
688 ppc->ppc_unit = dvp->id_unit;
689 ppc->ppc_type = GENERIC;
690
691 /* PPB_AUTODETECT is default to allow chipset detection even if
692 * mode is forced by dvp->id_flags (see later, ppc_detect() call) */
693 ppc->ppc_mode = PPB_AUTODETECT;
694 ppc->ppc_epp = (dvp->id_flags & 0x8) >> 3;
695
696 /*
697 * XXX
698 * Try and detect if interrupts are working.
699 */
700 if (!(dvp->id_flags & 0x10))
701 ppc->ppc_irq = (dvp->id_irq);
702
703 ppcdata[ppc->ppc_unit] = ppc;
704 nppc ++;
705
706 /*
707 * Try to detect the chipset and its mode.
708 */
709 if (ppc_detect(ppc, dvp->id_flags & 0x7))
710 goto error;
711
712end_probe:
713
714 return (1);
715
716error:
717 return (0);
718}
719
720static int
721ppcattach(struct isa_device *isdp)
722{
723 struct ppc_data *ppc = ppcdata[isdp->id_unit];
724 struct ppb_data *ppbus;
725
726 /*
727 * Link the Parallel Port Chipset (adapter) to
728 * the future ppbus.
729 */
730 ppc->ppc_link.adapter_unit = ppc->ppc_unit;
731 ppc->ppc_link.adapter = &ppc_adapter;
732
733 printf("ppc%d: %s chipset in %s mode%s\n", ppc->ppc_unit,
734 ppc_types[ppc->ppc_type], ppc_modes[ppc->ppc_mode],
735 (PPB_IS_EPP(ppc->ppc_mode)) ?
736 ppc_epp_protocol[ppc->ppc_epp] : "");
737
738 /*
739 * Prepare ppbus data area for upper level code.
740 */
741 ppbus = ppb_alloc_bus();
742
743 if (!ppbus)

--- 13 unchanged lines hidden ---