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