ppc.c revision 39142
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.7 1998/09/13 18:26:44 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 *, int *); 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 *msq, int *ppbpc) 883{ 884 struct ppc_data *ppc = ppcdata[unit]; 885 struct ppb_microseq *pc; 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 *microseq_stack = 0; 896 struct ppb_microseq *pc_stack = 0; 897 898/* microsequence registers are equivalent to PC-like port registers */ 899#define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register)) 900#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte) 901 902#define INCR_PC (pc ++) /* increment program counter */ 903#define mi pc /* microinstruction currently executed */ 904 905 /* get the state of pc from ppb level of execution */ 906 pc = &msq[*ppbpc]; 907 908 for (;;) { 909 910 switch (mi->opcode) { 911 case MS_OP_RSET: 912 cc = r_reg(mi->arg[0].i, ppc); 913 cc &= (char)mi->arg[2].i; /* clear mask */ 914 cc |= (char)mi->arg[1].i; /* assert mask */ 915 w_reg(mi->arg[0].i, ppc, cc); 916 INCR_PC; 917 break; 918 919 case MS_OP_RASSERT_P: 920 reg = mi->arg[1].i; 921 ptr = ppc->ppc_ptr; 922 923 if ((len = mi->arg[0].i) == MS_ACCUM) { 924 accum = ppc->ppc_accum; 925 for (; accum; accum--) 926 w_reg(reg, ppc, *ptr++); 927 ppc->ppc_accum = accum; 928 } else 929 for (i=0; i<len; i++) 930 w_reg(reg, ppc, *ptr++); 931 ppc->ppc_ptr = ptr; 932 933 INCR_PC; 934 break; 935 936 case MS_OP_RFETCH_P: 937 reg = mi->arg[1].i; 938 mask = (char)mi->arg[2].i; 939 ptr = ppc->ppc_ptr; 940 941 if ((len = mi->arg[0].i) == MS_ACCUM) { 942 accum = ppc->ppc_accum; 943 for (; accum; accum--) 944 *ptr++ = r_reg(reg, ppc) & mask; 945 ppc->ppc_accum = accum; 946 } else 947 for (i=0; i<len; i++) 948 *ptr++ = r_reg(reg, ppc) & mask; 949 ppc->ppc_ptr = ptr; 950 951 INCR_PC; 952 break; 953 954 case MS_OP_RFETCH: 955 *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) & 956 (char)mi->arg[1].i; 957 INCR_PC; 958 break; 959 960 case MS_OP_RASSERT: 961 case MS_OP_DELAY: 962 963 /* let's suppose the next instr. is the same */ 964 prefetch: 965 for (;mi->opcode == MS_OP_RASSERT; INCR_PC) 966 w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i); 967 968 if (mi->opcode == MS_OP_DELAY) { 969 DELAY(mi->arg[0].i); 970 INCR_PC; 971 goto prefetch; 972 } 973 break; 974 975 case MS_OP_ADELAY: 976 if (mi->arg[0].i) 977 tsleep(NULL, PPBPRI, "ppbdelay", 978 mi->arg[0].i * (hz/1000)); 979 INCR_PC; 980 break; 981 982 case MS_OP_TRIG: 983 reg = mi->arg[0].i; 984 iter = mi->arg[1].i; 985 p = (char *)mi->arg[2].p; 986 987 /* XXX delay limited to 255 us */ 988 for (i=0; i<iter; i++) { 989 w_reg(reg, ppc, *p++); 990 DELAY((unsigned char)*p++); 991 } 992 INCR_PC; 993 break; 994 995 case MS_OP_SET: 996 ppc->ppc_accum = mi->arg[0].i; 997 INCR_PC; 998 break; 999 1000 case MS_OP_DBRA: 1001 if (--ppc->ppc_accum > 0) 1002 pc += mi->arg[0].i; 1003 else 1004 INCR_PC; 1005 break; 1006 1007 case MS_OP_BRSET: 1008 cc = r_str(ppc); 1009 if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i) 1010 pc += mi->arg[1].i; 1011 else 1012 INCR_PC; 1013 break; 1014 1015 case MS_OP_BRCLEAR: 1016 cc = r_str(ppc); 1017 if ((cc & (char)mi->arg[0].i) == 0) 1018 pc += mi->arg[1].i; 1019 else 1020 INCR_PC; 1021 break; 1022 1023 case MS_OP_BRSTAT: 1024 cc = r_str(ppc); 1025 if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) == 1026 (char)mi->arg[0].i) 1027 pc += mi->arg[2].i; 1028 else 1029 INCR_PC; 1030 break; 1031 1032 case MS_OP_C_CALL: 1033 /* 1034 * If the C call returns !0 then end the microseq. 1035 * The current state of ptr is passed to the C function 1036 */ 1037 if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr))) 1038 return (error); 1039 1040 INCR_PC; 1041 break; 1042 1043 case MS_OP_PTR: 1044 ppc->ppc_ptr = (char *)mi->arg[0].p; 1045 INCR_PC; 1046 break; 1047 1048 case MS_OP_CALL: 1049 if (microseq_stack) 1050 panic("%s: too much calls", __FUNCTION__); 1051 1052 if (mi->arg[0].p) { 1053 /* store the state of the actual 1054 * microsequence 1055 */ 1056 microseq_stack = msq; 1057 pc_stack = pc; 1058 1059 /* jump to the new microsequence */ 1060 msq = (struct ppb_microseq *)mi->arg[0].p; 1061 pc = msq; 1062 } else 1063 INCR_PC; 1064 1065 break; 1066 1067 case MS_OP_SUBRET: 1068 /* retrieve microseq and pc state before the call */ 1069 msq = microseq_stack; 1070 pc = pc_stack; 1071 1072 /* reset the stack */ 1073 microseq_stack = 0; 1074 1075 /* XXX return code */ 1076 1077 INCR_PC; 1078 break; 1079 1080 case MS_OP_PUT: 1081 case MS_OP_GET: 1082 case MS_OP_RET: 1083 /* can't return to ppb level during the execution 1084 * of a submicrosequence */ 1085 if (microseq_stack) 1086 panic("%s: can't return to ppb level", 1087 __FUNCTION__); 1088 1089 /* update pc for ppb level of execution */ 1090 *ppbpc = (int)(pc - msq); 1091 1092 /* return to ppb level of execution */ 1093 return (0); 1094 1095 default: 1096 panic("%s: unknown microsequence opcode 0x%x", 1097 __FUNCTION__, mi->opcode); 1098 } 1099 } 1100 1101 /* unreached */ 1102} 1103 1104/* 1105 * Configure current operating mode 1106 */ 1107static int 1108ppc_generic_setmode(int unit, int mode) 1109{ 1110 struct ppc_data *ppc = ppcdata[unit]; 1111 1112 /* back to compatible mode, XXX don't know yet what to do here */ 1113 if (mode == 0) { 1114 ppc->ppc_mode = PPB_COMPATIBLE; 1115 return (0); 1116 } 1117 1118 /* check if mode is available */ 1119 if (!(ppc->ppc_avm & mode)) 1120 return (EOPNOTSUPP); 1121 1122 /* if ECP mode, configure ecr register */ 1123 if (ppc->ppc_avm & PPB_ECP) { 1124 1125 /* XXX disable DMA, enable interrupts */ 1126 if (mode & PPB_EPP) 1127 return (EOPNOTSUPP); 1128 else if (mode & PPB_PS2) 1129 /* select PS2 mode with ECP */ 1130 w_ecr(ppc, 0x20); 1131 else if (mode & PPB_ECP) 1132 /* select ECP mode */ 1133 w_ecr(ppc, 0x60); 1134 else 1135 /* select standard parallel port mode */ 1136 w_ecr(ppc, 0x00); 1137 } 1138 1139 ppc->ppc_mode = mode; 1140 1141 return (0); 1142} 1143 1144int 1145ppc_smclike_setmode(int unit, int mode) 1146{ 1147 struct ppc_data *ppc = ppcdata[unit]; 1148 1149 /* back to compatible mode, XXX don't know yet what to do here */ 1150 if (mode == 0) { 1151 ppc->ppc_mode = PPB_COMPATIBLE; 1152 return (0); 1153 } 1154 1155 /* check if mode is available */ 1156 if (!(ppc->ppc_avm & mode)) 1157 return (EOPNOTSUPP); 1158 1159 /* if ECP mode, configure ecr register */ 1160 if (ppc->ppc_avm & PPB_ECP) { 1161 1162 /* XXX disable DMA, enable interrupts */ 1163 if (mode & PPB_EPP) 1164 /* select EPP mode */ 1165 w_ecr(ppc, 0x80); 1166 else if (mode & PPB_PS2) 1167 /* select PS2 mode with ECP */ 1168 w_ecr(ppc, 0x20); 1169 else if (mode & PPB_ECP) 1170 /* select ECP mode */ 1171 w_ecr(ppc, 0x60); 1172 else 1173 /* select standard parallel port mode */ 1174 w_ecr(ppc, 0x00); 1175 } 1176 1177 ppc->ppc_mode = mode; 1178 1179 1180 return (0); 1181} 1182 1183/* 1184 * EPP timeout, according to the PC87332 manual 1185 * Semantics of clearing EPP timeout bit. 1186 * PC87332 - reading SPP_STR does it... 1187 * SMC - write 1 to EPP timeout bit XXX 1188 * Others - (???) write 0 to EPP timeout bit 1189 */ 1190static void 1191ppc_reset_epp_timeout(int unit) 1192{ 1193 struct ppc_data *ppc = ppcdata[unit]; 1194 register char r; 1195 1196 r = r_str(ppc); 1197 w_str(ppc, r | 0x1); 1198 w_str(ppc, r & 0xfe); 1199 1200 return; 1201} 1202 1203static int 1204ppcprobe(struct isa_device *dvp) 1205{ 1206 static short next_bios_ppc = 0; 1207 struct ppc_data *ppc; 1208 int error; 1209 1210 /* 1211 * If port not specified, use bios list. 1212 */ 1213 if(dvp->id_iobase < 0) { 1214 if((next_bios_ppc < BIOS_MAX_PPC) && 1215 (*(BIOS_PORTS+next_bios_ppc) != 0) ) { 1216 dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++); 1217 printf("ppc: parallel port found at 0x%x\n", 1218 dvp->id_iobase); 1219 } else 1220 return (0); 1221 } 1222 1223 /* 1224 * Port was explicitly specified. 1225 * This allows probing of ports unknown to the BIOS. 1226 */ 1227 1228 /* 1229 * Allocate the ppc_data structure. 1230 */ 1231 ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT); 1232 if (!ppc) { 1233 printf("ppc: cannot malloc!\n"); 1234 goto error; 1235 } 1236 bzero(ppc, sizeof(struct ppc_data)); 1237 1238 ppc->ppc_base = dvp->id_iobase; 1239 ppc->ppc_unit = dvp->id_unit; 1240 ppc->ppc_type = GENERIC; 1241 1242 ppc->ppc_mode = PPB_COMPATIBLE; 1243 ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4; 1244 1245 /* 1246 * XXX Try and detect if interrupts are working 1247 */ 1248 if (!(dvp->id_flags & 0x20)) 1249 ppc->ppc_irq = (dvp->id_irq); 1250 1251 ppcdata[ppc->ppc_unit] = ppc; 1252 nppc ++; 1253 1254 /* 1255 * Link the Parallel Port Chipset (adapter) to 1256 * the future ppbus. Default to a generic chipset 1257 */ 1258 ppc->ppc_link.adapter_unit = ppc->ppc_unit; 1259 ppc->ppc_link.adapter = &ppc_generic_adapter; 1260 1261 /* 1262 * Try to detect the chipset and its mode. 1263 */ 1264 if (ppc_detect(ppc, dvp->id_flags & 0xf)) 1265 goto error; 1266 1267end_probe: 1268 1269 return (1); 1270 1271error: 1272 return (0); 1273} 1274 1275static int 1276ppcattach(struct isa_device *isdp) 1277{ 1278 struct ppc_data *ppc = ppcdata[isdp->id_unit]; 1279 struct ppb_data *ppbus; 1280 char * mode; 1281 1282 printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit, 1283 ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm], 1284 ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ? 1285 ppc_epp_protocol[ppc->ppc_epp] : ""); 1286 1287 /* 1288 * Prepare ppbus data area for upper level code. 1289 */ 1290 ppbus = ppb_alloc_bus(); 1291 1292 if (!ppbus) 1293 return (0); 1294 1295 ppc->ppc_link.ppbus = ppbus; 1296 ppbus->ppb_link = &ppc->ppc_link; 1297 1298 /* 1299 * Probe the ppbus and attach devices found. 1300 */ 1301 ppb_attachdevs(ppbus); 1302 1303 return (1); 1304} 1305#endif 1306