ppc.c revision 38505
1184588Sdfr/*- 2184588Sdfr * Copyright (c) 1997, 1998 Nicolas Souchu 3184588Sdfr * All rights reserved. 4184588Sdfr * 5184588Sdfr * Redistribution and use in source and binary forms, with or without 6184588Sdfr * modification, are permitted provided that the following conditions 7184588Sdfr * are met: 8184588Sdfr * 1. Redistributions of source code must retain the above copyright 9184588Sdfr * notice, this list of conditions and the following disclaimer. 10184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright 11184588Sdfr * notice, this list of conditions and the following disclaimer in the 12184588Sdfr * documentation and/or other materials provided with the distribution. 13184588Sdfr * 14184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184588Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184588Sdfr * SUCH DAMAGE. 25184588Sdfr * 26184588Sdfr * $Id: ppc.c,v 1.4 1998/08/03 19:14:32 msmith Exp $ 27184588Sdfr * 28184588Sdfr */ 29184588Sdfr#include "ppc.h" 30184588Sdfr 31184588Sdfr#if NPPC > 0 32184588Sdfr 33184588Sdfr#include <sys/param.h> 34184588Sdfr#include <sys/systm.h> 35184588Sdfr#include <sys/conf.h> 36184588Sdfr#include <sys/malloc.h> 37184588Sdfr 38184588Sdfr#include <machine/clock.h> 39184588Sdfr 40184588Sdfr#include <vm/vm.h> 41184588Sdfr#include <vm/vm_param.h> 42184588Sdfr#include <vm/pmap.h> 43184588Sdfr 44184588Sdfr#include <i386/isa/isa_device.h> 45184588Sdfr 46184588Sdfr#include <dev/ppbus/ppbconf.h> 47184588Sdfr#include <dev/ppbus/ppb_msq.h> 48184588Sdfr 49184588Sdfr#include <i386/isa/ppcreg.h> 50184588Sdfr 51184588Sdfrstatic int ppcprobe(struct isa_device *); 52184588Sdfrstatic int ppcattach(struct isa_device *); 53184588Sdfr 54184588Sdfrstruct isa_driver ppcdriver = { 55184588Sdfr ppcprobe, ppcattach, "ppc" 56184588Sdfr}; 57184588Sdfr 58184588Sdfrstatic struct ppc_data *ppcdata[NPPC]; 59184588Sdfrstatic int nppc = 0; 60184588Sdfr 61184588Sdfrstatic char *ppc_types[] = { 62184588Sdfr "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306", 63184588Sdfr "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", 0 64184588Sdfr}; 65184588Sdfr 66184588Sdfr/* list of available modes */ 67184588Sdfrstatic char *ppc_avms[] = { 68184588Sdfr "COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only", 69184588Sdfr "EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only", 70184588Sdfr "ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP", 71184588Sdfr "ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0 72184588Sdfr}; 73184588Sdfr 74184588Sdfr/* list of current executing modes 75184588Sdfr * Note that few modes do not actually exist. 76184588Sdfr */ 77184588Sdfrstatic char *ppc_modes[] = { 78184588Sdfr "COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP", 79184588Sdfr "EPP", "EPP", "EPP", "ECP", 80184588Sdfr "ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP", 81184588Sdfr "ECP+EPP", "ECP+EPP", "ECP+EPP", 0 82184588Sdfr}; 83184588Sdfr 84184588Sdfrstatic char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 }; 85184588Sdfr 86184588Sdfr/* 87184588Sdfr * BIOS printer list - used by BIOS probe. 88184588Sdfr */ 89184588Sdfr#define BIOS_PPC_PORTS 0x408 90184588Sdfr#define BIOS_PORTS (short *)(KERNBASE+BIOS_PPC_PORTS) 91184588Sdfr#define BIOS_MAX_PPC 4 92184588Sdfr 93184588Sdfr/* 94184588Sdfr * All these functions are default actions for IN/OUT operations. 95184588Sdfr * They may be redefined if needed. 96184588Sdfr */ 97184588Sdfrstatic void ppc_outsb_epp(int unit, char *addr, int cnt) { 98184588Sdfr outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 99184588Sdfrstatic void ppc_outsw_epp(int unit, char *addr, int cnt) { 100184588Sdfr outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 101184588Sdfrstatic void ppc_outsl_epp(int unit, char *addr, int cnt) { 102184588Sdfr outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 103184588Sdfrstatic void ppc_insb_epp(int unit, char *addr, int cnt) { 104184588Sdfr insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 105184588Sdfrstatic void ppc_insw_epp(int unit, char *addr, int cnt) { 106184588Sdfr insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 107184588Sdfrstatic void ppc_insl_epp(int unit, char *addr, int cnt) { 108184588Sdfr insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); } 109184588Sdfr 110184588Sdfrstatic char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); } 111184588Sdfrstatic char ppc_rstr(int unit) { return r_str(ppcdata[unit]); } 112184588Sdfrstatic char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); } 113184588Sdfrstatic char ppc_repp(int unit) { return r_epp(ppcdata[unit]); } 114184588Sdfrstatic char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); } 115184588Sdfrstatic char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); } 116184588Sdfr 117184588Sdfrstatic void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); } 118184588Sdfrstatic void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); } 119184588Sdfrstatic void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); } 120184588Sdfrstatic void ppc_wepp(int unit, char byte) { w_epp(ppcdata[unit], byte); } 121184588Sdfrstatic void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); } 122184588Sdfrstatic void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); } 123184588Sdfr 124184588Sdfrstatic void ppc_reset_epp_timeout(int); 125184588Sdfrstatic void ppc_ecp_sync(int); 126184588Sdfr 127184588Sdfrstatic int ppc_exec_microseq(int, struct ppb_microseq *, int *); 128184588Sdfrstatic int ppc_generic_setmode(int, int); 129184588Sdfr 130184588Sdfrstatic struct ppb_adapter ppc_adapter = { 131184588Sdfr 132184588Sdfr 0, /* no intr handler, filled by chipset dependent code */ 133184588Sdfr 134184588Sdfr ppc_reset_epp_timeout, ppc_ecp_sync, 135184588Sdfr 136184588Sdfr ppc_exec_microseq, 137184588Sdfr 138184588Sdfr ppc_generic_setmode, 139184588Sdfr 140184588Sdfr ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp, 141184588Sdfr ppc_insb_epp, ppc_insw_epp, ppc_insl_epp, 142184588Sdfr 143184588Sdfr ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp, ppc_recr, ppc_rfifo, 144184588Sdfr ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp, ppc_wecr, ppc_wfifo 145184588Sdfr}; 146184588Sdfr 147184588Sdfr/* 148184588Sdfr * ppc_ecp_sync() XXX 149184588Sdfr */ 150184588Sdfrstatic void 151184588Sdfrppc_ecp_sync(int unit) { 152184588Sdfr 153184588Sdfr struct ppc_data *ppc = ppcdata[unit]; 154184588Sdfr int i, r; 155184588Sdfr 156184588Sdfr r = r_ecr(ppc); 157184588Sdfr if ((r & 0xe0) != 0x80) 158184588Sdfr return; 159184588Sdfr 160184588Sdfr for (i = 0; i < 100; i++) { 161184588Sdfr r = r_ecr(ppc); 162184588Sdfr if (r & 0x1) 163184588Sdfr return; 164184588Sdfr DELAY(100); 165184588Sdfr } 166184588Sdfr 167184588Sdfr printf("ppc%d: ECP sync failed as data still " \ 168184588Sdfr "present in FIFO.\n", unit); 169184588Sdfr 170184588Sdfr return; 171184588Sdfr} 172184588Sdfr 173184588Sdfrvoid 174184588Sdfrppcintr(int unit) 175184588Sdfr{ 176184588Sdfr /* call directly upper code */ 177184588Sdfr ppb_intr(&ppcdata[unit]->ppc_link); 178184588Sdfr 179184588Sdfr return; 180184588Sdfr} 181184588Sdfr 182184588Sdfrstatic void 183184588Sdfrppc_ecp_config(struct ppc_data *ppc, int chipset_mode) 184184588Sdfr{ 185184588Sdfr /* XXX disable DMA, enable interrupts */ 186184588Sdfr if (chipset_mode & PPB_EPP) 187184588Sdfr /* select EPP mode */ 188184588Sdfr w_ecr(ppc, 0x80); 189184588Sdfr else if (chipset_mode & PPB_PS2) 190184588Sdfr /* select PS2 mode with ECP */ 191184588Sdfr w_ecr(ppc, 0x20); 192184588Sdfr else 193184588Sdfr /* keep ECP mode alone, default for NIBBLE */ 194184588Sdfr w_ecr(ppc, 0x70); 195184588Sdfr 196184588Sdfr return; 197184588Sdfr} 198184588Sdfr 199184588Sdfrstatic int 200184588Sdfrppc_detect_port(struct ppc_data *ppc) 201184588Sdfr{ 202184588Sdfr 203184588Sdfr w_ctr(ppc, 0x0c); /* To avoid missing PS2 ports */ 204184588Sdfr w_dtr(ppc, 0xaa); 205184588Sdfr if (r_dtr(ppc) != (char) 0xaa) 206184588Sdfr return (0); 207184588Sdfr 208184588Sdfr return (1); 209184588Sdfr} 210184588Sdfr 211184588Sdfr/* 212184588Sdfr * ppc_pc873xx_detect 213184588Sdfr * 214184588Sdfr * Probe for a Natsemi PC873xx-family part. 215184588Sdfr * 216184588Sdfr * References in this function are to the National Semiconductor 217184588Sdfr * PC87332 datasheet TL/C/11930, May 1995 revision. 218184588Sdfr */ 219184588Sdfrstatic int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0}; 220184588Sdfrstatic int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0}; 221184588Sdfr 222184588Sdfrstatic int 223184588Sdfrppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never forced */ 224184588Sdfr{ 225184588Sdfr static int index = 0; 226184588Sdfr int base, idport; 227184588Sdfr int val; 228184588Sdfr 229184588Sdfr while ((idport = pc873xx_basetab[index++])) { 230184588Sdfr 231184588Sdfr /* XXX should check first to see if this location is already claimed */ 232184588Sdfr 233184588Sdfr /* 234184588Sdfr * Pull the 873xx through the power-on ID cycle (2.2,1.). We can't use this 235184588Sdfr * to locate the chip as it may already have been used by the BIOS. 236184588Sdfr */ 237184588Sdfr (void)inb(idport); (void)inb(idport); (void)inb(idport); (void)inb(idport); 238184588Sdfr 239184588Sdfr /* 240184588Sdfr * Read the SID byte. Possible values are : 241184588Sdfr * 242184588Sdfr * 0001xxxx PC87332 243184588Sdfr * 01110xxx PC87306 244184588Sdfr */ 245184588Sdfr outb(idport, PC873_SID); 246184588Sdfr val = inb(idport + 1); 247184588Sdfr if ((val & 0xf0) == 0x10) { 248184588Sdfr ppc->ppc_type = NS_PC87332; 249184588Sdfr } else if ((val & 0xf8) == 0x70) { 250184588Sdfr ppc->ppc_type = NS_PC87306; 251184588Sdfr } else { 252184588Sdfr if (bootverbose && (val != 0xff)) 253184588Sdfr printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val); 254184588Sdfr continue ; /* not recognised */ 255184588Sdfr } 256184588Sdfr 257184588Sdfr /* 258184588Sdfr * We think we have one. Is it enabled and where we want it to be? 259184588Sdfr */ 260184588Sdfr outb(idport, PC873_FER); 261184588Sdfr val = inb(idport + 1); 262184588Sdfr if (!(val & PC873_PPENABLE)) { 263184588Sdfr if (bootverbose) 264184588Sdfr printf("PC873xx parallel port disabled\n"); 265184588Sdfr continue; 266184588Sdfr } 267184588Sdfr outb(idport, PC873_FAR); 268184588Sdfr val = inb(idport + 1) & 0x3; 269184588Sdfr /* XXX we should create a driver instance for every port found */ 270184588Sdfr if (pc873xx_porttab[val] != ppc->ppc_base) { 271184588Sdfr if (bootverbose) 272184588Sdfr printf("PC873xx at 0x%x not for driver at port 0x%x\n", 273184588Sdfr pc873xx_porttab[val], ppc->ppc_base); 274184588Sdfr continue; 275184588Sdfr } 276184588Sdfr 277184588Sdfr /* 278184588Sdfr * This is the port we want. Can we dink with it to improve 279184588Sdfr * our chances? 280184588Sdfr */ 281184588Sdfr outb(idport, PC873_PTR); 282184588Sdfr val = inb(idport + 1); 283184588Sdfr if (val & PC873_CFGLOCK) { 284184588Sdfr if (bootverbose) 285184588Sdfr printf("PC873xx locked\n"); 286184588Sdfr 287184588Sdfr /* work out what mode we're in */ 288184588Sdfr ppc->ppc_avm |= PPB_NIBBLE; /* worst case */ 289184588Sdfr 290184588Sdfr outb(idport, PC873_PCR); 291184588Sdfr val = inb(idport + 1); 292184588Sdfr if ((val & PC873_EPPEN) && (val & PC873_EPP19)) { 293184588Sdfr outb(idport, PC873_PTR); 294184588Sdfr val = inb(idport + 1); 295184588Sdfr if (!(val & PC873_EPPRDIR)) { 296184588Sdfr ppc->ppc_avm |= PPB_EPP; /* As we would have done it anwyay */ 297184588Sdfr } 298184588Sdfr } else if ((val & PC873_ECPEN) && (val & PC873_ECPCLK)) { 299184588Sdfr ppc->ppc_avm |= PPB_PS2; /* tolerable alternative */ 300184588Sdfr } 301184588Sdfr } else { 302184588Sdfr if (bootverbose) 303184588Sdfr printf("PC873xx unlocked, "); 304184588Sdfr 305184588Sdfr#if 0 /* broken */ 306184588Sdfr /* 307184588Sdfr * Frob the zero-wait-state option if possible; it causes 308184588Sdfr * unreliable operation. 309184588Sdfr */ 310184588Sdfr outb(idport, PC873_FCR); 311184588Sdfr val = inb(idport + 1); 312184588Sdfr if ((ppc->ppc_type == NS_PC87306) || /* we are a '306 */ 313184588Sdfr !(val & PC873_ZWSPWDN)) { /* or pin _is_ ZWS */ 314184588Sdfr val &= ~PC873_ZWS; 315184588Sdfr outb(idport + 1, val); /* must disable ZWS */ 316184588Sdfr outb(idport + 1, val); 317184588Sdfr 318184588Sdfr if (bootverbose) 319184588Sdfr printf("ZWS %s, ", (val & PC873_ZWS) ? "enabled" : "disabled"); 320184588Sdfr } 321184588Sdfr 322184588Sdfr#endif 323184588Sdfr if (bootverbose) 324184588Sdfr printf("reconfiguring for "); 325184588Sdfr 326184588Sdfr /* 327184588Sdfr * if the chip is at 0x3bc, we can't use EPP as there's no room 328184588Sdfr * for the extra registers. 329184588Sdfr * 330184588Sdfr * XXX should we use ECP mode always and use the EPP submode? 331184588Sdfr */ 332184588Sdfr if (ppc->ppc_base != 0x3bc) { 333184588Sdfr if (bootverbose) 334184588Sdfr printf("EPP 1.9\n"); 335184588Sdfr 336184588Sdfr /* configure for EPP 1.9 operation XXX should be configurable */ 337184588Sdfr outb(idport, PC873_PCR); 338184588Sdfr val = inb(idport + 1); 339184588Sdfr val &= ~(PC873_ECPEN | PC873_ECPCLK); /* disable ECP */ 340184588Sdfr val |= (PC873_EPPEN | PC873_EPP19); /* enable EPP */ 341184588Sdfr outb(idport + 1, val); 342184588Sdfr outb(idport + 1, val); 343184588Sdfr 344184588Sdfr /* enable automatic direction turnover */ 345184588Sdfr outb(idport, PC873_PTR); 346184588Sdfr val = inb(idport + 1); 347184588Sdfr val &= ~PC873_EPPRDIR; /* disable "regular" direction change */ 348184588Sdfr outb(idport + 1, val); 349184588Sdfr outb(idport + 1, val); 350184588Sdfr 351184588Sdfr /* we are an EPP-32 port */ 352184588Sdfr ppc->ppc_avm |= PPB_EPP; 353184588Sdfr } else { 354184588Sdfr if (bootverbose) 355184588Sdfr printf("ECP\n"); 356184588Sdfr 357184588Sdfr /* configure as an ECP port to get bidirectional operation for now */ 358184588Sdfr outb(idport, PC873_PCR); 359184588Sdfr outb(idport + 1, inb(idport + 1) | PC873_ECPEN | PC873_ECPCLK); 360184588Sdfr 361184588Sdfr /* we look like a PS/2 port */ 362184588Sdfr ppc->ppc_avm |= PPB_PS2; 363184588Sdfr } 364184588Sdfr } 365184588Sdfr 366184588Sdfr return(chipset_mode); 367184588Sdfr } 368184588Sdfr return(-1); 369184588Sdfr} 370184588Sdfr 371184588Sdfrstatic int 372184588Sdfrppc_check_epp_timeout(struct ppc_data *ppc) 373184588Sdfr{ 374184588Sdfr ppc_reset_epp_timeout(ppc->ppc_unit); 375184588Sdfr 376184588Sdfr return (!(r_str(ppc) & TIMEOUT)); 377184588Sdfr} 378184588Sdfr 379184588Sdfr/* 380184588Sdfr * ppc_smc37c66xgt_detect 381184588Sdfr * 382184588Sdfr * SMC FDC37C66xGT configuration. 383184588Sdfr */ 384184588Sdfrstatic int 385184588Sdfrppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode) 386184588Sdfr{ 387184588Sdfr int s, i; 388184588Sdfr char r; 389184588Sdfr int type = -1; 390184588Sdfr int csr = SMC66x_CSR; /* initial value is 0x3F0 */ 391184588Sdfr 392184588Sdfr int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 }; 393184588Sdfr 394184588Sdfr 395184588Sdfr#define cio csr+1 /* config IO port is either 0x3F1 or 0x371 */ 396184588Sdfr 397184588Sdfr /* 398184588Sdfr * Detection: enter configuration mode and read CRD register. 399184588Sdfr */ 400184588Sdfr 401184588Sdfr s = splhigh(); 402184588Sdfr outb(csr, SMC665_iCODE); 403184588Sdfr outb(csr, SMC665_iCODE); 404184588Sdfr splx(s); 405184588Sdfr 406184588Sdfr outb(csr, 0xd); 407184588Sdfr if (inb(cio) == 0x65) { 408184588Sdfr type = SMC_37C665GT; 409184588Sdfr goto config; 410184588Sdfr } 411184588Sdfr 412184588Sdfr for (i = 0; i < 2; i++) { 413184588Sdfr s = splhigh(); 414184588Sdfr outb(csr, SMC666_iCODE); 415184588Sdfr outb(csr, SMC666_iCODE); 416184588Sdfr splx(s); 417184588Sdfr 418184588Sdfr outb(csr, 0xd); 419184588Sdfr if (inb(cio) == 0x66) { 420184588Sdfr type = SMC_37C666GT; 421184588Sdfr break; 422184588Sdfr } 423184588Sdfr 424184588Sdfr /* Another chance, CSR may be hard-configured to be at 0x370 */ 425184588Sdfr csr = SMC666_CSR; 426184588Sdfr } 427184588Sdfr 428184588Sdfrconfig: 429184588Sdfr /* 430184588Sdfr * If chipset not found, do not continue. 431184588Sdfr */ 432184588Sdfr if (type == -1) 433184588Sdfr return (-1); 434184588Sdfr 435184588Sdfr /* select CR1 */ 436184588Sdfr outb(csr, 0x1); 437184588Sdfr 438184588Sdfr /* read the port's address: bits 0 and 1 of CR1 */ 439184588Sdfr r = inb(cio) & SMC_CR1_ADDR; 440184588Sdfr if (port_address[r] != ppc->ppc_base) 441184588Sdfr return (-1); 442184588Sdfr 443184588Sdfr ppc->ppc_type = type; 444184588Sdfr 445184588Sdfr /* 446184588Sdfr * CR1 and CR4 registers bits 3 and 0/1 for mode configuration 447184588Sdfr * If SPP mode is detected, try to set ECP+EPP mode 448184588Sdfr */ 449184588Sdfr 450184588Sdfr if (bootverbose) { 451184588Sdfr outb(csr, 0x1); 452184588Sdfr printf("SMC registers CR1=0x%x", inb(cio) & 0xff); 453184588Sdfr 454184588Sdfr outb(csr, 0x4); 455184588Sdfr printf(" CR4=0x%x", inb(cio) & 0xff); 456184588Sdfr } 457184588Sdfr 458184588Sdfr /* select CR1 */ 459184588Sdfr outb(csr, 0x1); 460184588Sdfr 461184588Sdfr if (!chipset_mode) { 462184588Sdfr /* autodetect mode */ 463184588Sdfr 464184588Sdfr /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */ 465184588Sdfr if (type == SMC_37C666GT) { 466184588Sdfr ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; 467184588Sdfr 468184588Sdfr } else 469184588Sdfr if ((inb(cio) & SMC_CR1_MODE) == 0) { 470184588Sdfr /* already in extended parallel port mode, read CR4 */ 471184588Sdfr outb(csr, 0x4); 472184588Sdfr r = (inb(cio) & SMC_CR4_EMODE); 473184588Sdfr 474184588Sdfr switch (r) { 475184588Sdfr case SMC_SPP: 476184588Sdfr ppc->ppc_avm |= PPB_SPP; 477184588Sdfr break; 478184588Sdfr 479184588Sdfr case SMC_EPPSPP: 480184588Sdfr ppc->ppc_avm |= PPB_EPP | PPB_SPP; 481184588Sdfr break; 482184588Sdfr 483184588Sdfr case SMC_ECP: 484184588Sdfr ppc->ppc_avm |= PPB_ECP | PPB_SPP; 485184588Sdfr break; 486184588Sdfr 487184588Sdfr case SMC_ECPEPP: 488184588Sdfr ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; 489184588Sdfr break; 490184588Sdfr } 491184588Sdfr } else { 492184588Sdfr /* not an extended port mode */ 493184588Sdfr ppc->ppc_avm |= PPB_SPP; 494184588Sdfr } 495184588Sdfr 496184588Sdfr } else { 497184588Sdfr /* mode forced */ 498184588Sdfr 499184588Sdfr /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */ 500184588Sdfr if (type == SMC_37C666GT) 501184588Sdfr goto end_detect; 502184588Sdfr 503184588Sdfr r = inb(cio); 504184588Sdfr if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) { 505184588Sdfr /* do not use ECP when the mode is not forced to */ 506184588Sdfr outb(cio, r | SMC_CR1_MODE); 507184588Sdfr } else { 508184588Sdfr /* an extended mode is selected */ 509184588Sdfr outb(cio, r & ~SMC_CR1_MODE); 510184588Sdfr 511184588Sdfr /* read CR4 register and reset mode field */ 512184588Sdfr outb(csr, 0x4); 513184588Sdfr r = inb(cio) & ~SMC_CR4_EMODE; 514184588Sdfr 515184588Sdfr if (chipset_mode & PPB_ECP) { 516184588Sdfr if (chipset_mode & PPB_EPP) { 517184588Sdfr outb(cio, r | SMC_ECPEPP); 518184588Sdfr } else { 519184588Sdfr outb(cio, r | SMC_ECP); 520184588Sdfr } 521184588Sdfr } else { 522184588Sdfr /* PPB_EPP is set */ 523184588Sdfr outb(cio, r | SMC_EPPSPP); 524184588Sdfr } 525184588Sdfr } 526184588Sdfr ppc->ppc_avm = chipset_mode; 527184588Sdfr } 528184588Sdfr 529184588Sdfrend_detect: 530184588Sdfr 531184588Sdfr if (bootverbose) 532184588Sdfr printf ("\n"); 533184588Sdfr 534184588Sdfr if (chipset_mode & PPB_EPP) { 535184588Sdfr /* select CR4 */ 536184588Sdfr outb(csr, 0x4); 537184588Sdfr r = inb(cio); 538184588Sdfr 539184588Sdfr /* 540184588Sdfr * Set the EPP protocol... 541184588Sdfr * Low=EPP 1.9 (1284 standard) and High=EPP 1.7 542184588Sdfr */ 543184588Sdfr if (ppc->ppc_epp == EPP_1_9) 544184588Sdfr outb(cio, (r & ~SMC_CR4_EPPTYPE)); 545184588Sdfr else 546184588Sdfr outb(cio, (r | SMC_CR4_EPPTYPE)); 547184588Sdfr } 548184588Sdfr 549184588Sdfr /* end config mode */ 550184588Sdfr outb(csr, 0xaa); 551184588Sdfr 552184588Sdfr if (ppc->ppc_avm & PPB_ECP) 553184588Sdfr ppc_ecp_config(ppc, chipset_mode); 554184588Sdfr 555184588Sdfr return (chipset_mode); 556184588Sdfr} 557184588Sdfr 558184588Sdfr/* 559184588Sdfr * Winbond W83877F stuff 560184588Sdfr * 561184588Sdfr * EFER: extended function enable register 562184588Sdfr * EFIR: extended function index register 563184588Sdfr * EFDR: extended function data register 564184588Sdfr */ 565184588Sdfr#define efir ((efer == 0x250) ? 0x251 : 0x3f0) 566184588Sdfr#define efdr ((efer == 0x250) ? 0x252 : 0x3f1) 567184588Sdfr 568184588Sdfrstatic int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 }; 569184588Sdfrstatic int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 }; 570184588Sdfrstatic int w83877f_keyiter[] = { 1, 2, 2, 1 }; 571184588Sdfrstatic int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 }; 572184588Sdfr 573184588Sdfrstatic int 574184588Sdfrppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode) 575184588Sdfr{ 576184588Sdfr int i, j, efer, base; 577184588Sdfr unsigned char r, hefere, hefras; 578184588Sdfr 579184588Sdfr for (i = 0; i < 4; i ++) { 580184588Sdfr /* first try to enable configuration registers */ 581184588Sdfr efer = w83877f_efers[i]; 582184588Sdfr 583184588Sdfr /* write the key to the EFER */ 584184588Sdfr for (j = 0; j < w83877f_keyiter[i]; j ++) 585184588Sdfr outb (efer, w83877f_keys[i]); 586184588Sdfr 587184588Sdfr /* then check HEFERE and HEFRAS bits */ 588184588Sdfr outb (efir, 0x0c); 589184588Sdfr hefere = inb(efdr) & WINB_HEFERE; 590184588Sdfr 591184588Sdfr outb (efir, 0x16); 592184588Sdfr hefras = inb(efdr) & WINB_HEFRAS; 593184588Sdfr 594184588Sdfr /* 595184588Sdfr * HEFRAS HEFERE 596184588Sdfr * 0 1 write 89h to 250h (power-on default) 597184588Sdfr * 1 0 write 86h twice to 3f0h 598184588Sdfr * 1 1 write 87h twice to 3f0h 599184588Sdfr * 0 0 write 88h to 250h 600184588Sdfr */ 601184588Sdfr if ((hefere | hefras) == w83877f_hefs[i]) 602184588Sdfr goto found; 603184588Sdfr } 604184588Sdfr 605184588Sdfr return (-1); /* failed */ 606184588Sdfr 607184588Sdfrfound: 608184588Sdfr /* check base port address - read from CR23 */ 609184588Sdfr outb(efir, 0x23); 610184588Sdfr if (ppc->ppc_base != inb(efdr) * 4) /* 4 bytes boundaries */ 611184588Sdfr return (-1); 612184588Sdfr 613184588Sdfr /* read CHIP ID from CR9/bits0-3 */ 614184588Sdfr outb(efir, 0x9); 615184588Sdfr 616184588Sdfr switch (inb(efdr) & WINB_CHIPID) { 617184588Sdfr case WINB_W83877F_ID: 618184588Sdfr ppc->ppc_type = WINB_W83877F; 619184588Sdfr break; 620184588Sdfr 621 case WINB_W83877AF_ID: 622 ppc->ppc_type = WINB_W83877AF; 623 break; 624 625 default: 626 ppc->ppc_type = WINB_UNKNOWN; 627 } 628 629 if (bootverbose) { 630 /* dump of registers */ 631 printf("ppc%d: 0x%x - ", ppc->ppc_unit, w83877f_keys[i]); 632 for (i = 0; i <= 0xd; i ++) { 633 outb(efir, i); 634 printf("0x%x ", inb(efdr)); 635 } 636 for (i = 0x10; i <= 0x17; i ++) { 637 outb(efir, i); 638 printf("0x%x ", inb(efdr)); 639 } 640 outb(efir, 0x1e); 641 printf("0x%x ", inb(efdr)); 642 for (i = 0x20; i <= 0x29; i ++) { 643 outb(efir, i); 644 printf("0x%x ", inb(efdr)); 645 } 646 printf("\n"); 647 } 648 649 if (!chipset_mode) { 650 /* autodetect mode */ 651 652 /* select CR0 */ 653 outb(efir, 0x0); 654 r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1); 655 656 /* select CR9 */ 657 outb(efir, 0x9); 658 r |= (inb(efdr) & WINB_PRTMODS2); 659 660 switch (r) { 661 case WINB_W83757: 662 if (bootverbose) 663 printf("ppc%d: W83757 compatible mode\n", 664 ppc->ppc_unit); 665 return (-1); /* generic or SMC-like */ 666 667 case WINB_EXTFDC: 668 case WINB_EXTADP: 669 case WINB_EXT2FDD: 670 case WINB_JOYSTICK: 671 if (bootverbose) 672 printf("ppc%d: not in parallel port mode\n", 673 ppc->ppc_unit); 674 return (-1); 675 676 case (WINB_PARALLEL | WINB_EPP_SPP): 677 ppc->ppc_avm |= PPB_EPP | PPB_SPP; 678 break; 679 680 case (WINB_PARALLEL | WINB_ECP): 681 ppc->ppc_avm |= PPB_ECP | PPB_SPP; 682 break; 683 684 case (WINB_PARALLEL | WINB_ECP_EPP): 685 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP; 686 break; 687 default: 688 printf("%s: unknown case (0x%x)!\n", __FUNCTION__, r); 689 } 690 691 } else { 692 /* mode forced */ 693 694 /* select CR9 and set PRTMODS2 bit */ 695 outb(efir, 0x9); 696 outb(efdr, inb(efdr) & ~WINB_PRTMODS2); 697 698 /* select CR0 and reset PRTMODSx bits */ 699 outb(efir, 0x0); 700 outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1)); 701 702 if (chipset_mode & PPB_ECP) { 703 if (chipset_mode & PPB_EPP) 704 outb(efdr, inb(efdr) | WINB_ECP_EPP); 705 else 706 outb(efdr, inb(efdr) | WINB_ECP); 707 } else { 708 /* select EPP_SPP otherwise */ 709 outb(efdr, inb(efdr) | WINB_EPP_SPP); 710 } 711 ppc->ppc_avm = chipset_mode; 712 } 713 714 /* exit configuration mode */ 715 outb(efer, 0xaa); 716 717 if (ppc->ppc_avm & PPB_ECP) 718 ppc_ecp_config(ppc, chipset_mode); 719 720 return (chipset_mode); 721} 722 723/* 724 * ppc_generic_detect 725 */ 726static int 727ppc_generic_detect(struct ppc_data *ppc, int chipset_mode) 728{ 729 char save_control; 730 731 if (!chipset_mode) { 732 /* first, check for ECP */ 733 w_ecr(ppc, 0x20); 734 if ((r_ecr(ppc) & 0xe0) == 0x20) { 735 ppc->ppc_avm |= PPB_ECP | PPB_SPP; 736 737 /* search for SMC style ECP+EPP mode */ 738 w_ecr(ppc, 0x80); 739 } 740 741 /* try to reset EPP timeout bit */ 742 if (ppc_check_epp_timeout(ppc)) { 743 ppc->ppc_avm |= PPB_EPP; 744 745 if (ppc->ppc_avm & PPB_ECP) 746 /* SMC like chipset found */ 747 ppc->ppc_type = SMC_LIKE; 748 } 749 750 /* XXX try to detect NIBBLE mode */ 751 ppc->ppc_avm |= PPB_NIBBLE; 752 753 } else 754 ppc->ppc_avm = chipset_mode; 755 756 if (ppc->ppc_avm & PPB_ECP) 757 ppc_ecp_config(ppc, chipset_mode); 758 759 return (chipset_mode); 760} 761 762/* 763 * ppc_detect() 764 * 765 * mode is the mode suggested at boot 766 */ 767static int 768ppc_detect(struct ppc_data *ppc, int chipset_mode) { 769 770 int i, mode; 771 772 /* list of supported chipsets */ 773 int (*chipset_detect[])(struct ppc_data *, int) = { 774 ppc_pc873xx_detect, 775 ppc_smc37c66xgt_detect, 776 ppc_w83877f_detect, 777 ppc_generic_detect, 778 NULL 779 }; 780 781 /* if can't find the port and mode not forced return error */ 782 if (!ppc_detect_port(ppc) && chipset_mode == 0) 783 return (EIO); /* failed, port not present */ 784 785 /* assume centronics compatible mode is supported */ 786 ppc->ppc_avm = PPB_COMPATIBLE; 787 788 /* we have to differenciate available chipset modes, 789 * chipset running modes and IEEE-1284 operating modes 790 * 791 * after detection, the port must support running in compatible mode 792 */ 793 for (i=0; chipset_detect[i] != NULL; i++) { 794 if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) { 795 ppc->ppc_mode = mode; 796 break; 797 } 798 } 799 800 return (0); 801} 802 803/* 804 * ppc_exec_microseq() 805 * 806 * Execute a microsequence. 807 * Microsequence mechanism is supposed to handle fast I/O operations. 808 */ 809static int 810ppc_exec_microseq(int unit, struct ppb_microseq *msq, int *ppbpc) 811{ 812 struct ppc_data *ppc = ppcdata[unit]; 813 struct ppb_microseq *pc; 814 char cc, *p; 815 int i, iter, reg; 816 int error; 817 818 /* static to be reused after few ppc_exec_microseq()/return calls 819 * XXX should be in a context variable shared with ppb level */ 820 static int accum; 821 static char *ptr; 822 823 struct ppb_microseq *microseq_stack = 0; 824 struct ppb_microseq *pc_stack = 0; 825 826/* microsequence registers are equivalent to PC-like port registers */ 827#define r_reg(register,ppc) ((char)inb((ppc)->ppc_base + register)) 828#define w_reg(register,ppc,byte) outb((ppc)->ppc_base + register, byte) 829 830#define INCR_PC (pc ++) /* increment program counter */ 831#define mi pc /* microinstruction currently executed */ 832 833 /* get the state of pc from ppb level of execution */ 834 pc = &msq[*ppbpc]; 835 836 for (;;) { 837 838 switch (mi->opcode) { 839 case MS_OP_RSET: 840 cc = r_reg(mi->arg[0].i, ppc); 841 cc &= mi->arg[2].c; /* clear mask */ 842 cc |= mi->arg[1].c; /* assert mask */ 843 w_reg(mi->arg[0].i, ppc, cc); 844 INCR_PC; 845 break; 846 847 case MS_OP_RASSERT_P: 848 for (i=0; i<mi->arg[0].i; i++) 849 w_reg(mi->arg[1].i, ppc, *ptr++); 850 INCR_PC; 851 break; 852 853 case MS_OP_RFETCH_P: 854 for (i=0; i<mi->arg[0].i; i++) 855 *ptr++ = r_reg(mi->arg[1].i, ppc) & 856 mi->arg[2].c; 857 INCR_PC; 858 break; 859 860 case MS_OP_RFETCH: 861 *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) & 862 mi->arg[1].c; 863 INCR_PC; 864 break; 865 866 case MS_OP_RASSERT: 867 868 /* let's suppose the next instr. is the same */ 869 prefetch: 870 for (;mi->opcode == MS_OP_RASSERT; INCR_PC) 871 w_reg(mi->arg[0].i, ppc, mi->arg[1].c); 872 873 if (mi->opcode == MS_OP_DELAY) { 874 DELAY(mi->arg[0].i); 875 INCR_PC; 876 goto prefetch; 877 } 878 break; 879 880 case MS_OP_DELAY: 881 DELAY(mi->arg[0].i); 882 INCR_PC; 883 break; 884 885 case MS_OP_TRIG: 886 reg = mi->arg[0].i; 887 iter = mi->arg[1].i; 888 p = (char *)mi->arg[2].p; 889 890 for (i=0; i<iter; i++) { 891 w_reg(reg, ppc, *p++); 892 DELAY((unsigned char)*p++); 893 } 894 INCR_PC; 895 break; 896 897 case MS_OP_SET: 898 accum = mi->arg[0].i; 899 INCR_PC; 900 break; 901 902 case MS_OP_DBRA: 903 if (--accum > 0) 904 pc += mi->arg[0].i; 905 else 906 INCR_PC; 907 break; 908 909 case MS_OP_BRSET: 910 cc = r_str(ppc); 911 if ((cc & mi->arg[0].c) == mi->arg[0].c) 912 pc += mi->arg[1].i; 913 else 914 INCR_PC; 915 break; 916 917 case MS_OP_BRCLEAR: 918 cc = r_str(ppc); 919 if ((cc & mi->arg[0].c) == 0) 920 pc += mi->arg[1].i; 921 else 922 INCR_PC; 923 break; 924 925 case MS_OP_C_CALL: 926 /* 927 * If the C call returns !0 then end the microseq. 928 * The current state of ptr is passed to the C function 929 */ 930 if ((error = mi->arg[0].f(mi->arg[1].p, ptr))) 931 return (error); 932 933 INCR_PC; 934 break; 935 936 case MS_OP_PTR: 937 ptr = (char *)mi->arg[0].p; 938 INCR_PC; 939 break; 940 941 case MS_OP_CALL: 942 if (microseq_stack) 943 panic("%s: too much calls", __FUNCTION__); 944 945 if (mi->arg[0].p) { 946 /* store the state of the actual 947 * microsequence 948 */ 949 microseq_stack = msq; 950 pc_stack = pc; 951 952 /* jump to the new microsequence */ 953 msq = (struct ppb_microseq *)mi->arg[0].p; 954 pc = msq; 955 } else 956 INCR_PC; 957 958 break; 959 960 case MS_OP_SUBRET: 961 /* retrieve microseq and pc state before the call */ 962 msq = microseq_stack; 963 pc = pc_stack; 964 965 /* reset the stack */ 966 microseq_stack = 0; 967 968 /* XXX return code */ 969 970 INCR_PC; 971 break; 972 973 case MS_OP_PUT: 974 case MS_OP_GET: 975 case MS_OP_RET: 976 /* can't return to ppb level during the execution 977 * of a submicrosequence */ 978 if (microseq_stack) 979 panic("%s: can't return to ppb level", 980 __FUNCTION__); 981 982 /* update pc for ppb level of execution */ 983 *ppbpc = (int)(pc - msq); 984 985 /* return to ppb level of execution */ 986 return (0); 987 988 default: 989 panic("%s: unknown microsequence opcode 0x%x", 990 __FUNCTION__, mi->opcode); 991 } 992 } 993 994 /* unreached */ 995} 996 997/* 998 * Configure current operating mode 999 */ 1000static int 1001ppc_generic_setmode(int unit, int mode) 1002{ 1003 struct ppc_data *ppc = ppcdata[unit]; 1004 1005 /* back to compatible mode, XXX don't know yet what to do here */ 1006 if (mode == 0) { 1007 ppc->ppc_mode = PPB_COMPATIBLE; 1008 return (0); 1009 } 1010 1011 /* check if mode is available */ 1012 if (!(ppc->ppc_avm & mode)) 1013 return (EOPNOTSUPP); 1014 1015 /* if ECP mode, configure ecr register */ 1016 if (ppc->ppc_avm & PPB_ECP) 1017 ppc_ecp_config(ppc, mode); 1018 1019 ppc->ppc_mode = mode; 1020 1021 return (0); 1022} 1023 1024/* 1025 * EPP timeout, according to the PC87332 manual 1026 * Semantics of clearing EPP timeout bit. 1027 * PC87332 - reading SPP_STR does it... 1028 * SMC - write 1 to EPP timeout bit XXX 1029 * Others - (???) write 0 to EPP timeout bit 1030 */ 1031static void 1032ppc_reset_epp_timeout(int unit) 1033{ 1034 struct ppc_data *ppc = ppcdata[unit]; 1035 register char r; 1036 1037 r = r_str(ppc); 1038 w_str(ppc, r | 0x1); 1039 w_str(ppc, r & 0xfe); 1040 1041 return; 1042} 1043 1044static int 1045ppcprobe(struct isa_device *dvp) 1046{ 1047 static short next_bios_ppc = 0; 1048 struct ppc_data *ppc; 1049 int error; 1050 1051 /* 1052 * If port not specified, use bios list. 1053 */ 1054 if(dvp->id_iobase < 0) { 1055 if((next_bios_ppc < BIOS_MAX_PPC) && 1056 (*(BIOS_PORTS+next_bios_ppc) != 0) ) { 1057 dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++); 1058 } else 1059 return (0); 1060 } 1061 1062 /* 1063 * Port was explicitly specified. 1064 * This allows probing of ports unknown to the BIOS. 1065 */ 1066 1067 /* 1068 * Allocate the ppc_data structure. 1069 */ 1070 ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT); 1071 if (!ppc) { 1072 printf("ppc: cannot malloc!\n"); 1073 goto error; 1074 } 1075 bzero(ppc, sizeof(struct ppc_data)); 1076 1077 ppc->ppc_base = dvp->id_iobase; 1078 ppc->ppc_unit = dvp->id_unit; 1079 ppc->ppc_type = GENERIC; 1080 1081 ppc->ppc_mode = PPB_COMPATIBLE; 1082 ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4; 1083 1084 /* 1085 * XXX 1086 * Try and detect if interrupts are working. 1087 */ 1088 if (!(dvp->id_flags & 0x20)) 1089 ppc->ppc_irq = (dvp->id_irq); 1090 1091 ppcdata[ppc->ppc_unit] = ppc; 1092 nppc ++; 1093 1094 /* 1095 * Try to detect the chipset and its mode. 1096 */ 1097 if (ppc_detect(ppc, dvp->id_flags & 0xf)) 1098 goto error; 1099 1100end_probe: 1101 1102 return (1); 1103 1104error: 1105 return (0); 1106} 1107 1108static int 1109ppcattach(struct isa_device *isdp) 1110{ 1111 struct ppc_data *ppc = ppcdata[isdp->id_unit]; 1112 struct ppb_data *ppbus; 1113 char * mode; 1114 1115 /* 1116 * Link the Parallel Port Chipset (adapter) to 1117 * the future ppbus. 1118 */ 1119 ppc->ppc_link.adapter_unit = ppc->ppc_unit; 1120 ppc->ppc_link.adapter = &ppc_adapter; 1121 1122 printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit, 1123 ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm], 1124 ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ? 1125 ppc_epp_protocol[ppc->ppc_epp] : ""); 1126 1127 /* 1128 * Prepare ppbus data area for upper level code. 1129 */ 1130 ppbus = ppb_alloc_bus(); 1131 1132 if (!ppbus) 1133 return (0); 1134 1135 ppc->ppc_link.ppbus = ppbus; 1136 ppbus->ppb_link = &ppc->ppc_link; 1137 1138 /* 1139 * Probe the ppbus and attach devices found. 1140 */ 1141 ppb_attachdevs(ppbus); 1142 1143 return (1); 1144} 1145#endif 1146