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