The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ppc/ppc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1997-2000 Nicolas Souchu
    5  * Copyright (c) 2001 Alcove - Nicolas Souchu
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_ppc.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/bus.h>
   38 #include <sys/kernel.h>
   39 #include <sys/lock.h>
   40 #include <sys/interrupt.h>
   41 #include <sys/module.h>
   42 #include <sys/malloc.h>
   43 #include <sys/mutex.h>
   44 #include <sys/proc.h>
   45 
   46 #include <machine/bus.h>
   47 #include <machine/resource.h>
   48 #include <sys/rman.h>
   49 
   50 #ifdef __i386__
   51 #include <vm/vm.h>
   52 #include <vm/pmap.h>
   53 #include <machine/vmparam.h>
   54 #include <machine/pc/bios.h>
   55 #endif
   56 
   57 #include <dev/ppbus/ppbconf.h>
   58 #include <dev/ppbus/ppb_msq.h>
   59 
   60 #include <dev/ppc/ppcvar.h>
   61 #include <dev/ppc/ppcreg.h>
   62 
   63 #include "ppbus_if.h"
   64 
   65 static void ppcintr(void *arg);
   66 
   67 #define IO_LPTSIZE_EXTENDED     8       /* "Extended" LPT controllers */
   68 #define IO_LPTSIZE_NORMAL       4       /* "Normal" LPT controllers */
   69 
   70 #define LOG_PPC(function, ppc, string) \
   71                 if (bootverbose) printf("%s: %s\n", function, string)
   72 
   73 #define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev))
   74 
   75 /*
   76  * We use critical enter/exit for the simple config locking needed to
   77  * detect the devices. We just want to make sure that both of our writes
   78  * happen without someone else also writing to those config registers. Since
   79  * we just do this at startup, Giant keeps multiple threads from executing,
   80  * and critical_enter() then is all that's needed to keep us from being preempted
   81  * during the critical sequences with the hardware.
   82  *
   83  * Note: this doesn't prevent multiple threads from putting the chips into
   84  * config mode, but since we only do that to detect the type at startup the
   85  * extra overhead isn't needed since Giant protects us from multiple entry
   86  * and no other code changes these registers.
   87  */
   88 #define PPC_CONFIG_LOCK(ppc)            critical_enter()
   89 #define PPC_CONFIG_UNLOCK(ppc)          critical_exit()
   90 
   91 const char ppc_driver_name[] = "ppc";
   92 
   93 static char *ppc_models[] = {
   94         "SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
   95         "82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334",
   96         "SMC FDC37C935", "PC87303", 0
   97 };
   98 
   99 /* list of available modes */
  100 static char *ppc_avms[] = {
  101         "COMPATIBLE", "NIBBLE-only", "PS2-only", "PS2/NIBBLE", "EPP-only",
  102         "EPP/NIBBLE", "EPP/PS2", "EPP/PS2/NIBBLE", "ECP-only",
  103         "ECP/NIBBLE", "ECP/PS2", "ECP/PS2/NIBBLE", "ECP/EPP",
  104         "ECP/EPP/NIBBLE", "ECP/EPP/PS2", "ECP/EPP/PS2/NIBBLE", 0
  105 };
  106 
  107 /* list of current executing modes
  108  * Note that few modes do not actually exist.
  109  */
  110 static char *ppc_modes[] = {
  111         "COMPATIBLE", "NIBBLE", "PS/2", "PS/2", "EPP",
  112         "EPP", "EPP", "EPP", "ECP",
  113         "ECP", "ECP+PS2", "ECP+PS2", "ECP+EPP",
  114         "ECP+EPP", "ECP+EPP", "ECP+EPP", 0
  115 };
  116 
  117 static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
  118 
  119 #ifdef __i386__
  120 /*
  121  * BIOS printer list - used by BIOS probe.
  122  */
  123 #define BIOS_PPC_PORTS  0x408
  124 #define BIOS_PORTS      ((short *)BIOS_PADDRTOVADDR(BIOS_PPC_PORTS))
  125 #define BIOS_MAX_PPC    4
  126 #endif
  127 
  128 /*
  129  * ppc_ecp_sync()               XXX
  130  */
  131 int
  132 ppc_ecp_sync(device_t dev)
  133 {
  134         int i, r;
  135         struct ppc_data *ppc = DEVTOSOFTC(dev);
  136 
  137         PPC_ASSERT_LOCKED(ppc);
  138         if (!(ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_dtm & PPB_ECP))
  139                 return 0;
  140 
  141         r = r_ecr(ppc);
  142         if ((r & 0xe0) != PPC_ECR_EPP)
  143                 return 0;
  144 
  145         for (i = 0; i < 100; i++) {
  146                 r = r_ecr(ppc);
  147                 if (r & 0x1)
  148                         return 0;
  149                 DELAY(100);
  150         }
  151 
  152         device_printf(dev, "ECP sync failed as data still present in FIFO.\n");
  153 
  154         return 0;
  155 }
  156 
  157 /*
  158  * ppc_detect_fifo()
  159  *
  160  * Detect parallel port FIFO
  161  */
  162 static int
  163 ppc_detect_fifo(struct ppc_data *ppc)
  164 {
  165         char ecr_sav;
  166         char ctr_sav, ctr;
  167         short i;
  168 
  169         /* save registers */
  170         ecr_sav = r_ecr(ppc);
  171         ctr_sav = r_ctr(ppc);
  172 
  173         /* enter ECP configuration mode, no interrupt, no DMA */
  174         w_ecr(ppc, 0xf4);
  175 
  176         /* read PWord size - transfers in FIFO mode must be PWord aligned */
  177         ppc->ppc_pword = (r_cnfgA(ppc) & PPC_PWORD_MASK);
  178 
  179         /* XXX 16 and 32 bits implementations not supported */
  180         if (ppc->ppc_pword != PPC_PWORD_8) {
  181                 LOG_PPC(__func__, ppc, "PWord not supported");
  182                 goto error;
  183         }
  184 
  185         w_ecr(ppc, 0x34);               /* byte mode, no interrupt, no DMA */
  186         ctr = r_ctr(ppc);
  187         w_ctr(ppc, ctr | PCD);          /* set direction to 1 */
  188 
  189         /* enter ECP test mode, no interrupt, no DMA */
  190         w_ecr(ppc, 0xd4);
  191 
  192         /* flush the FIFO */
  193         for (i=0; i<1024; i++) {
  194                 if (r_ecr(ppc) & PPC_FIFO_EMPTY)
  195                         break;
  196                 r_fifo(ppc);
  197         }
  198 
  199         if (i >= 1024) {
  200                 LOG_PPC(__func__, ppc, "can't flush FIFO");
  201                 goto error;
  202         }
  203 
  204         /* enable interrupts, no DMA */
  205         w_ecr(ppc, 0xd0);
  206 
  207         /* determine readIntrThreshold
  208          * fill the FIFO until serviceIntr is set
  209          */
  210         for (i=0; i<1024; i++) {
  211                 w_fifo(ppc, (char)i);
  212                 if (!ppc->ppc_rthr && (r_ecr(ppc) & PPC_SERVICE_INTR)) {
  213                         /* readThreshold reached */
  214                         ppc->ppc_rthr = i+1;
  215                 }
  216                 if (r_ecr(ppc) & PPC_FIFO_FULL) {
  217                         ppc->ppc_fifo = i+1;
  218                         break;
  219                 }
  220         }
  221 
  222         if (i >= 1024) {
  223                 LOG_PPC(__func__, ppc, "can't fill FIFO");
  224                 goto error;
  225         }
  226 
  227         w_ecr(ppc, 0xd4);               /* test mode, no interrupt, no DMA */
  228         w_ctr(ppc, ctr & ~PCD);         /* set direction to 0 */
  229         w_ecr(ppc, 0xd0);               /* enable interrupts */
  230 
  231         /* determine writeIntrThreshold
  232          * empty the FIFO until serviceIntr is set
  233          */
  234         for (i=ppc->ppc_fifo; i>0; i--) {
  235                 if (r_fifo(ppc) != (char)(ppc->ppc_fifo-i)) {
  236                         LOG_PPC(__func__, ppc, "invalid data in FIFO");
  237                         goto error;
  238                 }
  239                 if (r_ecr(ppc) & PPC_SERVICE_INTR) {
  240                         /* writeIntrThreshold reached */
  241                         ppc->ppc_wthr = ppc->ppc_fifo - i+1;
  242                 }
  243                 /* if FIFO empty before the last byte, error */
  244                 if (i>1 && (r_ecr(ppc) & PPC_FIFO_EMPTY)) {
  245                         LOG_PPC(__func__, ppc, "data lost in FIFO");
  246                         goto error;
  247                 }
  248         }
  249 
  250         /* FIFO must be empty after the last byte */
  251         if (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) {
  252                 LOG_PPC(__func__, ppc, "can't empty the FIFO");
  253                 goto error;
  254         }
  255 
  256         w_ctr(ppc, ctr_sav);
  257         w_ecr(ppc, ecr_sav);
  258 
  259         return (0);
  260 
  261 error:
  262         w_ctr(ppc, ctr_sav);
  263         w_ecr(ppc, ecr_sav);
  264 
  265         return (EINVAL);
  266 }
  267 
  268 static int
  269 ppc_detect_port(struct ppc_data *ppc)
  270 {
  271 
  272         w_ctr(ppc, 0x0c);       /* To avoid missing PS2 ports */
  273         w_dtr(ppc, 0xaa);
  274         if (r_dtr(ppc) != 0xaa)
  275                 return (0);
  276 
  277         return (1);
  278 }
  279 
  280 /*
  281  * EPP timeout, according to the PC87332 manual
  282  * Semantics of clearing EPP timeout bit.
  283  * PC87332      - reading SPP_STR does it...
  284  * SMC          - write 1 to EPP timeout bit                    XXX
  285  * Others       - (?) write 0 to EPP timeout bit
  286  */
  287 static void
  288 ppc_reset_epp_timeout(struct ppc_data *ppc)
  289 {
  290         char r;
  291 
  292         r = r_str(ppc);
  293         w_str(ppc, r | 0x1);
  294         w_str(ppc, r & 0xfe);
  295 
  296         return;
  297 }
  298 
  299 static int
  300 ppc_check_epp_timeout(struct ppc_data *ppc)
  301 {
  302         ppc_reset_epp_timeout(ppc);
  303 
  304         return (!(r_str(ppc) & TIMEOUT));
  305 }
  306 
  307 /*
  308  * Configure current operating mode
  309  */
  310 static int
  311 ppc_generic_setmode(struct ppc_data *ppc, int mode)
  312 {
  313         u_char ecr = 0;
  314 
  315         /* check if mode is available */
  316         if (mode && !(ppc->ppc_avm & mode))
  317                 return (EINVAL);
  318 
  319         /* if ECP mode, configure ecr register */
  320         if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
  321                 /* return to byte mode (keeping direction bit),
  322                  * no interrupt, no DMA to be able to change to
  323                  * ECP
  324                  */
  325                 w_ecr(ppc, PPC_ECR_RESET);
  326                 ecr = PPC_DISABLE_INTR;
  327 
  328                 if (mode & PPB_EPP)
  329                         return (EINVAL);
  330                 else if (mode & PPB_ECP)
  331                         /* select ECP mode */
  332                         ecr |= PPC_ECR_ECP;
  333                 else if (mode & PPB_PS2)
  334                         /* select PS2 mode with ECP */
  335                         ecr |= PPC_ECR_PS2;
  336                 else
  337                         /* select COMPATIBLE/NIBBLE mode */
  338                         ecr |= PPC_ECR_STD;
  339 
  340                 w_ecr(ppc, ecr);
  341         }
  342 
  343         ppc->ppc_mode = mode;
  344 
  345         return (0);
  346 }
  347 
  348 /*
  349  * The ppc driver is free to choose options like FIFO or DMA
  350  * if ECP mode is available.
  351  *
  352  * The 'RAW' option allows the upper drivers to force the ppc mode
  353  * even with FIFO, DMA available.
  354  */
  355 static int
  356 ppc_smclike_setmode(struct ppc_data *ppc, int mode)
  357 {
  358         u_char ecr = 0;
  359 
  360         /* check if mode is available */
  361         if (mode && !(ppc->ppc_avm & mode))
  362                 return (EINVAL);
  363 
  364         /* if ECP mode, configure ecr register */
  365         if ((ppc->ppc_avm & PPB_ECP) || (ppc->ppc_dtm & PPB_ECP)) {
  366                 /* return to byte mode (keeping direction bit),
  367                  * no interrupt, no DMA to be able to change to
  368                  * ECP or EPP mode
  369                  */
  370                 w_ecr(ppc, PPC_ECR_RESET);
  371                 ecr = PPC_DISABLE_INTR;
  372 
  373                 if (mode & PPB_EPP)
  374                         /* select EPP mode */
  375                         ecr |= PPC_ECR_EPP;
  376                 else if (mode & PPB_ECP)
  377                         /* select ECP mode */
  378                         ecr |= PPC_ECR_ECP;
  379                 else if (mode & PPB_PS2)
  380                         /* select PS2 mode with ECP */
  381                         ecr |= PPC_ECR_PS2;
  382                 else
  383                         /* select COMPATIBLE/NIBBLE mode */
  384                         ecr |= PPC_ECR_STD;
  385 
  386                 w_ecr(ppc, ecr);
  387         }
  388 
  389         ppc->ppc_mode = mode;
  390 
  391         return (0);
  392 }
  393 
  394 #ifdef PPC_PROBE_CHIPSET
  395 /*
  396  * ppc_pc873xx_detect
  397  *
  398  * Probe for a Natsemi PC873xx-family part.
  399  *
  400  * References in this function are to the National Semiconductor
  401  * PC87332 datasheet TL/C/11930, May 1995 revision.
  402  */
  403 static int pc873xx_basetab[] = {0x0398, 0x026e, 0x015c, 0x002e, 0};
  404 static int pc873xx_porttab[] = {0x0378, 0x03bc, 0x0278, 0};
  405 static int pc873xx_irqtab[] = {5, 7, 5, 0};
  406 
  407 static int pc873xx_regstab[] = {
  408         PC873_FER, PC873_FAR, PC873_PTR,
  409         PC873_FCR, PC873_PCR, PC873_PMC,
  410         PC873_TUP, PC873_SID, PC873_PNP0,
  411         PC873_PNP1, PC873_LPTBA, -1
  412 };
  413 
  414 static char *pc873xx_rnametab[] = {
  415         "FER", "FAR", "PTR", "FCR", "PCR",
  416         "PMC", "TUP", "SID", "PNP0", "PNP1",
  417         "LPTBA", NULL
  418 };
  419 
  420 static int
  421 ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode)      /* XXX mode never forced */
  422 {
  423     static int  index = 0;
  424     int         idport, irq;
  425     int         ptr, pcr, val, i;
  426 
  427     while ((idport = pc873xx_basetab[index++])) {
  428         /* XXX should check first to see if this location is already claimed */
  429 
  430         /*
  431          * Pull the 873xx through the power-on ID cycle (2.2,1.).
  432          * We can't use this to locate the chip as it may already have
  433          * been used by the BIOS.
  434          */
  435         (void)inb(idport); (void)inb(idport);
  436         (void)inb(idport); (void)inb(idport);
  437 
  438         /*
  439          * Read the SID byte.  Possible values are :
  440          *
  441          * 01010xxx     PC87334
  442          * 0001xxxx     PC87332
  443          * 01110xxx     PC87306
  444          * 00110xxx     PC87303
  445          */
  446         outb(idport, PC873_SID);
  447         val = inb(idport + 1);
  448         if ((val & 0xf0) == 0x10) {
  449             ppc->ppc_model = NS_PC87332;
  450         } else if ((val & 0xf8) == 0x70) {
  451             ppc->ppc_model = NS_PC87306;
  452         } else if ((val & 0xf8) == 0x50) {
  453             ppc->ppc_model = NS_PC87334;
  454         } else if ((val & 0xf8) == 0x40) { /* Should be 0x30 by the
  455                                               documentation, but probing
  456                                               yielded 0x40... */
  457             ppc->ppc_model = NS_PC87303;
  458         } else {
  459             if (bootverbose && (val != 0xff))
  460                 printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
  461             continue ;          /* not recognised */
  462         }
  463 
  464         /* print registers */
  465         if (bootverbose) {
  466                 printf("PC873xx");
  467                 for (i=0; pc873xx_regstab[i] != -1; i++) {
  468                         outb(idport, pc873xx_regstab[i]);
  469                         printf(" %s=0x%x", pc873xx_rnametab[i],
  470                                                 inb(idport + 1) & 0xff);
  471                 }
  472                 printf("\n");
  473         }
  474 
  475         /*
  476          * We think we have one.  Is it enabled and where we want it to be?
  477          */
  478         outb(idport, PC873_FER);
  479         val = inb(idport + 1);
  480         if (!(val & PC873_PPENABLE)) {
  481             if (bootverbose)
  482                 printf("PC873xx parallel port disabled\n");
  483             continue;
  484         }
  485         outb(idport, PC873_FAR);
  486         val = inb(idport + 1);
  487         /* XXX we should create a driver instance for every port found */
  488         if (pc873xx_porttab[val & 0x3] != ppc->ppc_base) {
  489             /* First try to change the port address to that requested... */
  490 
  491             switch (ppc->ppc_base) {
  492                 case 0x378:
  493                 val &= 0xfc;
  494                 break;
  495 
  496                 case 0x3bc:
  497                 val &= 0xfd;
  498                 break;
  499 
  500                 case 0x278:
  501                 val &= 0xfe;
  502                 break;
  503 
  504                 default:
  505                 val &= 0xfd;
  506                 break;
  507             }
  508 
  509             outb(idport, PC873_FAR);
  510             outb(idport + 1, val);
  511             outb(idport + 1, val);
  512 
  513             /* Check for success by reading back the value we supposedly
  514                wrote and comparing...*/
  515 
  516             outb(idport, PC873_FAR);
  517             val = inb(idport + 1) & 0x3;
  518 
  519             /* If we fail, report the failure... */
  520 
  521             if (pc873xx_porttab[val] != ppc->ppc_base) {
  522                 if (bootverbose)
  523                     printf("PC873xx at 0x%x not for driver at port 0x%x\n",
  524                            pc873xx_porttab[val], ppc->ppc_base);
  525             }
  526             continue;
  527         }
  528 
  529         outb(idport, PC873_PTR);
  530         ptr = inb(idport + 1);
  531 
  532         /* get irq settings */
  533         if (ppc->ppc_base == 0x378)
  534                 irq = (ptr & PC873_LPTBIRQ7) ? 7 : 5;
  535         else
  536                 irq = pc873xx_irqtab[val];
  537 
  538         if (bootverbose)
  539                 printf("PC873xx irq %d at 0x%x\n", irq, ppc->ppc_base);
  540 
  541         /*
  542          * Check if irq settings are correct
  543          */
  544         if (irq != ppc->ppc_irq) {
  545                 /*
  546                  * If the chipset is not locked and base address is 0x378,
  547                  * we have another chance
  548                  */
  549                 if (ppc->ppc_base == 0x378 && !(ptr & PC873_CFGLOCK)) {
  550                         if (ppc->ppc_irq == 7) {
  551                                 outb(idport + 1, (ptr | PC873_LPTBIRQ7));
  552                                 outb(idport + 1, (ptr | PC873_LPTBIRQ7));
  553                         } else {
  554                                 outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
  555                                 outb(idport + 1, (ptr & ~PC873_LPTBIRQ7));
  556                         }
  557                         if (bootverbose)
  558                            printf("PC873xx irq set to %d\n", ppc->ppc_irq);
  559                 } else {
  560                         if (bootverbose)
  561                            printf("PC873xx sorry, can't change irq setting\n");
  562                 }
  563         } else {
  564                 if (bootverbose)
  565                         printf("PC873xx irq settings are correct\n");
  566         }
  567 
  568         outb(idport, PC873_PCR);
  569         pcr = inb(idport + 1);
  570 
  571         if ((ptr & PC873_CFGLOCK) || !chipset_mode) {
  572             if (bootverbose)
  573                 printf("PC873xx %s", (ptr & PC873_CFGLOCK)?"locked":"unlocked");
  574 
  575             ppc->ppc_avm |= PPB_NIBBLE;
  576             if (bootverbose)
  577                 printf(", NIBBLE");
  578 
  579             if (pcr & PC873_EPPEN) {
  580                 ppc->ppc_avm |= PPB_EPP;
  581 
  582                 if (bootverbose)
  583                         printf(", EPP");
  584 
  585                 if (pcr & PC873_EPP19)
  586                         ppc->ppc_epp = EPP_1_9;
  587                 else
  588                         ppc->ppc_epp = EPP_1_7;
  589 
  590                 if ((ppc->ppc_model == NS_PC87332) && bootverbose) {
  591                         outb(idport, PC873_PTR);
  592                         ptr = inb(idport + 1);
  593                         if (ptr & PC873_EPPRDIR)
  594                                 printf(", Regular mode");
  595                         else
  596                                 printf(", Automatic mode");
  597                 }
  598             } else if (pcr & PC873_ECPEN) {
  599                 ppc->ppc_avm |= PPB_ECP;
  600                 if (bootverbose)
  601                         printf(", ECP");
  602 
  603                 if (pcr & PC873_ECPCLK) {               /* XXX */
  604                         ppc->ppc_avm |= PPB_PS2;
  605                         if (bootverbose)
  606                                 printf(", PS/2");
  607                 }
  608             } else {
  609                 outb(idport, PC873_PTR);
  610                 ptr = inb(idport + 1);
  611                 if (ptr & PC873_EXTENDED) {
  612                         ppc->ppc_avm |= PPB_SPP;
  613                         if (bootverbose)
  614                                 printf(", SPP");
  615                 }
  616             }
  617         } else {
  618                 if (bootverbose)
  619                         printf("PC873xx unlocked");
  620 
  621                 if (chipset_mode & PPB_ECP) {
  622                         if ((chipset_mode & PPB_EPP) && bootverbose)
  623                                 printf(", ECP+EPP not supported");
  624 
  625                         pcr &= ~PC873_EPPEN;
  626                         pcr |= (PC873_ECPEN | PC873_ECPCLK);    /* XXX */
  627                         outb(idport + 1, pcr);
  628                         outb(idport + 1, pcr);
  629 
  630                         if (bootverbose)
  631                                 printf(", ECP");
  632 
  633                 } else if (chipset_mode & PPB_EPP) {
  634                         pcr &= ~(PC873_ECPEN | PC873_ECPCLK);
  635                         pcr |= (PC873_EPPEN | PC873_EPP19);
  636                         outb(idport + 1, pcr);
  637                         outb(idport + 1, pcr);
  638 
  639                         ppc->ppc_epp = EPP_1_9;                 /* XXX */
  640 
  641                         if (bootverbose)
  642                                 printf(", EPP1.9");
  643 
  644                         /* enable automatic direction turnover */
  645                         if (ppc->ppc_model == NS_PC87332) {
  646                                 outb(idport, PC873_PTR);
  647                                 ptr = inb(idport + 1);
  648                                 ptr &= ~PC873_EPPRDIR;
  649                                 outb(idport + 1, ptr);
  650                                 outb(idport + 1, ptr);
  651 
  652                                 if (bootverbose)
  653                                         printf(", Automatic mode");
  654                         }
  655                 } else {
  656                         pcr &= ~(PC873_ECPEN | PC873_ECPCLK | PC873_EPPEN);
  657                         outb(idport + 1, pcr);
  658                         outb(idport + 1, pcr);
  659 
  660                         /* configure extended bit in PTR */
  661                         outb(idport, PC873_PTR);
  662                         ptr = inb(idport + 1);
  663 
  664                         if (chipset_mode & PPB_PS2) {
  665                                 ptr |= PC873_EXTENDED;
  666 
  667                                 if (bootverbose)
  668                                         printf(", PS/2");
  669 
  670                         } else {
  671                                 /* default to NIBBLE mode */
  672                                 ptr &= ~PC873_EXTENDED;
  673 
  674                                 if (bootverbose)
  675                                         printf(", NIBBLE");
  676                         }
  677                         outb(idport + 1, ptr);
  678                         outb(idport + 1, ptr);
  679                 }
  680 
  681                 ppc->ppc_avm = chipset_mode;
  682         }
  683 
  684         if (bootverbose)
  685                 printf("\n");
  686 
  687         ppc->ppc_type = PPC_TYPE_GENERIC;
  688         ppc_generic_setmode(ppc, chipset_mode);
  689 
  690         return(chipset_mode);
  691     }
  692     return(-1);
  693 }
  694 
  695 /*
  696  * ppc_smc37c66xgt_detect
  697  *
  698  * SMC FDC37C66xGT configuration.
  699  */
  700 static int
  701 ppc_smc37c66xgt_detect(struct ppc_data *ppc, int chipset_mode)
  702 {
  703         int i;
  704         u_char r;
  705         int type = -1;
  706         int csr = SMC66x_CSR;   /* initial value is 0x3F0 */
  707 
  708         int port_address[] = { -1 /* disabled */ , 0x3bc, 0x378, 0x278 };
  709 
  710 #define cio csr+1       /* config IO port is either 0x3F1 or 0x371 */
  711 
  712         /*
  713          * Detection: enter configuration mode and read CRD register.
  714          */
  715         PPC_CONFIG_LOCK(ppc);
  716         outb(csr, SMC665_iCODE);
  717         outb(csr, SMC665_iCODE);
  718         PPC_CONFIG_UNLOCK(ppc);
  719 
  720         outb(csr, 0xd);
  721         if (inb(cio) == 0x65) {
  722                 type = SMC_37C665GT;
  723                 goto config;
  724         }
  725 
  726         for (i = 0; i < 2; i++) {
  727                 PPC_CONFIG_LOCK(ppc);
  728                 outb(csr, SMC666_iCODE);
  729                 outb(csr, SMC666_iCODE);
  730                 PPC_CONFIG_UNLOCK(ppc);
  731 
  732                 outb(csr, 0xd);
  733                 if (inb(cio) == 0x66) {
  734                         type = SMC_37C666GT;
  735                         break;
  736                 }
  737 
  738                 /* Another chance, CSR may be hard-configured to be at 0x370 */
  739                 csr = SMC666_CSR;
  740         }
  741 
  742 config:
  743         /*
  744          * If chipset not found, do not continue.
  745          */
  746         if (type == -1) {
  747                 outb(csr, 0xaa);        /* end config mode */
  748                 return (-1);
  749         }
  750 
  751         /* select CR1 */
  752         outb(csr, 0x1);
  753 
  754         /* read the port's address: bits 0 and 1 of CR1 */
  755         r = inb(cio) & SMC_CR1_ADDR;
  756         if (port_address[(int)r] != ppc->ppc_base) {
  757                 outb(csr, 0xaa);        /* end config mode */
  758                 return (-1);
  759         }
  760 
  761         ppc->ppc_model = type;
  762 
  763         /*
  764          * CR1 and CR4 registers bits 3 and 0/1 for mode configuration
  765          * If SPP mode is detected, try to set ECP+EPP mode
  766          */
  767 
  768         if (bootverbose) {
  769                 outb(csr, 0x1);
  770                 device_printf(ppc->ppc_dev, "SMC registers CR1=0x%x",
  771                     inb(cio) & 0xff);
  772 
  773                 outb(csr, 0x4);
  774                 printf(" CR4=0x%x", inb(cio) & 0xff);
  775         }
  776 
  777         /* select CR1 */
  778         outb(csr, 0x1);
  779 
  780         if (!chipset_mode) {
  781                 /* autodetect mode */
  782 
  783                 /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
  784                 if (type == SMC_37C666GT) {
  785                         ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
  786                         if (bootverbose)
  787                                 printf(" configuration hardwired, supposing " \
  788                                         "ECP+EPP SPP");
  789 
  790                 } else
  791                    if ((inb(cio) & SMC_CR1_MODE) == 0) {
  792                         /* already in extended parallel port mode, read CR4 */
  793                         outb(csr, 0x4);
  794                         r = (inb(cio) & SMC_CR4_EMODE);
  795 
  796                         switch (r) {
  797                         case SMC_SPP:
  798                                 ppc->ppc_avm |= PPB_SPP;
  799                                 if (bootverbose)
  800                                         printf(" SPP");
  801                                 break;
  802 
  803                         case SMC_EPPSPP:
  804                                 ppc->ppc_avm |= PPB_EPP | PPB_SPP;
  805                                 if (bootverbose)
  806                                         printf(" EPP SPP");
  807                                 break;
  808 
  809                         case SMC_ECP:
  810                                 ppc->ppc_avm |= PPB_ECP | PPB_SPP;
  811                                 if (bootverbose)
  812                                         printf(" ECP SPP");
  813                                 break;
  814 
  815                         case SMC_ECPEPP:
  816                                 ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
  817                                 if (bootverbose)
  818                                         printf(" ECP+EPP SPP");
  819                                 break;
  820                         }
  821                    } else {
  822                         /* not an extended port mode */
  823                         ppc->ppc_avm |= PPB_SPP;
  824                         if (bootverbose)
  825                                 printf(" SPP");
  826                    }
  827 
  828         } else {
  829                 /* mode forced */
  830                 ppc->ppc_avm = chipset_mode;
  831 
  832                 /* 666GT is ~certainly~ hardwired to an extended ECP+EPP mode */
  833                 if (type == SMC_37C666GT)
  834                         goto end_detect;
  835 
  836                 r = inb(cio);
  837                 if ((chipset_mode & (PPB_ECP | PPB_EPP)) == 0) {
  838                         /* do not use ECP when the mode is not forced to */
  839                         outb(cio, r | SMC_CR1_MODE);
  840                         if (bootverbose)
  841                                 printf(" SPP");
  842                 } else {
  843                         /* an extended mode is selected */
  844                         outb(cio, r & ~SMC_CR1_MODE);
  845 
  846                         /* read CR4 register and reset mode field */
  847                         outb(csr, 0x4);
  848                         r = inb(cio) & ~SMC_CR4_EMODE;
  849 
  850                         if (chipset_mode & PPB_ECP) {
  851                                 if (chipset_mode & PPB_EPP) {
  852                                         outb(cio, r | SMC_ECPEPP);
  853                                         if (bootverbose)
  854                                                 printf(" ECP+EPP");
  855                                 } else {
  856                                         outb(cio, r | SMC_ECP);
  857                                         if (bootverbose)
  858                                                 printf(" ECP");
  859                                 }
  860                         } else {
  861                                 /* PPB_EPP is set */
  862                                 outb(cio, r | SMC_EPPSPP);
  863                                 if (bootverbose)
  864                                         printf(" EPP SPP");
  865                         }
  866                 }
  867                 ppc->ppc_avm = chipset_mode;
  868         }
  869 
  870         /* set FIFO threshold to 16 */
  871         if (ppc->ppc_avm & PPB_ECP) {
  872                 /* select CRA */
  873                 outb(csr, 0xa);
  874                 outb(cio, 16);
  875         }
  876 
  877 end_detect:
  878 
  879         if (bootverbose)
  880                 printf ("\n");
  881 
  882         if (ppc->ppc_avm & PPB_EPP) {
  883                 /* select CR4 */
  884                 outb(csr, 0x4);
  885                 r = inb(cio);
  886 
  887                 /*
  888                  * Set the EPP protocol...
  889                  * Low=EPP 1.9 (1284 standard) and High=EPP 1.7
  890                  */
  891                 if (ppc->ppc_epp == EPP_1_9)
  892                         outb(cio, (r & ~SMC_CR4_EPPTYPE));
  893                 else
  894                         outb(cio, (r | SMC_CR4_EPPTYPE));
  895         }
  896 
  897         outb(csr, 0xaa);        /* end config mode */
  898 
  899         ppc->ppc_type = PPC_TYPE_SMCLIKE;
  900         ppc_smclike_setmode(ppc, chipset_mode);
  901 
  902         return (chipset_mode);
  903 }
  904 
  905 /*
  906  * SMC FDC37C935 configuration
  907  * Found on many Alpha machines
  908  */
  909 static int
  910 ppc_smc37c935_detect(struct ppc_data *ppc, int chipset_mode)
  911 {
  912         int type = -1;
  913 
  914         PPC_CONFIG_LOCK(ppc);
  915         outb(SMC935_CFG, 0x55); /* enter config mode */
  916         outb(SMC935_CFG, 0x55);
  917         PPC_CONFIG_UNLOCK(ppc);
  918 
  919         outb(SMC935_IND, SMC935_ID); /* check device id */
  920         if (inb(SMC935_DAT) == 0x2)
  921                 type = SMC_37C935;
  922 
  923         if (type == -1) {
  924                 outb(SMC935_CFG, 0xaa); /* exit config mode */
  925                 return (-1);
  926         }
  927 
  928         ppc->ppc_model = type;
  929 
  930         outb(SMC935_IND, SMC935_LOGDEV); /* select parallel port, */
  931         outb(SMC935_DAT, 3);         /* which is logical device 3 */
  932 
  933         /* set io port base */
  934         outb(SMC935_IND, SMC935_PORTHI);
  935         outb(SMC935_DAT, (u_char)((ppc->ppc_base & 0xff00) >> 8));
  936         outb(SMC935_IND, SMC935_PORTLO);
  937         outb(SMC935_DAT, (u_char)(ppc->ppc_base & 0xff));
  938 
  939         if (!chipset_mode)
  940                 ppc->ppc_avm = PPB_COMPATIBLE; /* default mode */
  941         else {
  942                 ppc->ppc_avm = chipset_mode;
  943                 outb(SMC935_IND, SMC935_PPMODE);
  944                 outb(SMC935_DAT, SMC935_CENT); /* start in compatible mode */
  945 
  946                 /* SPP + EPP or just plain SPP */
  947                 if (chipset_mode & (PPB_SPP)) {
  948                         if (chipset_mode & PPB_EPP) {
  949                                 if (ppc->ppc_epp == EPP_1_9) {
  950                                         outb(SMC935_IND, SMC935_PPMODE);
  951                                         outb(SMC935_DAT, SMC935_EPP19SPP);
  952                                 }
  953                                 if (ppc->ppc_epp == EPP_1_7) {
  954                                         outb(SMC935_IND, SMC935_PPMODE);
  955                                         outb(SMC935_DAT, SMC935_EPP17SPP);
  956                                 }
  957                         } else {
  958                                 outb(SMC935_IND, SMC935_PPMODE);
  959                                 outb(SMC935_DAT, SMC935_SPP);
  960                         }
  961                 }
  962 
  963                 /* ECP + EPP or just plain ECP */
  964                 if (chipset_mode & PPB_ECP) {
  965                         if (chipset_mode & PPB_EPP) {
  966                                 if (ppc->ppc_epp == EPP_1_9) {
  967                                         outb(SMC935_IND, SMC935_PPMODE);
  968                                         outb(SMC935_DAT, SMC935_ECPEPP19);
  969                                 }
  970                                 if (ppc->ppc_epp == EPP_1_7) {
  971                                         outb(SMC935_IND, SMC935_PPMODE);
  972                                         outb(SMC935_DAT, SMC935_ECPEPP17);
  973                                 }
  974                         } else {
  975                                 outb(SMC935_IND, SMC935_PPMODE);
  976                                 outb(SMC935_DAT, SMC935_ECP);
  977                         }
  978                 }
  979         }
  980 
  981         outb(SMC935_CFG, 0xaa); /* exit config mode */
  982 
  983         ppc->ppc_type = PPC_TYPE_SMCLIKE;
  984         ppc_smclike_setmode(ppc, chipset_mode);
  985 
  986         return (chipset_mode);
  987 }
  988 
  989 /*
  990  * Winbond W83877F stuff
  991  *
  992  * EFER: extended function enable register
  993  * EFIR: extended function index register
  994  * EFDR: extended function data register
  995  */
  996 #define efir ((efer == 0x250) ? 0x251 : 0x3f0)
  997 #define efdr ((efer == 0x250) ? 0x252 : 0x3f1)
  998 
  999 static int w83877f_efers[] = { 0x250, 0x3f0, 0x3f0, 0x250 };
 1000 static int w83877f_keys[] = { 0x89, 0x86, 0x87, 0x88 };
 1001 static int w83877f_keyiter[] = { 1, 2, 2, 1 };
 1002 static int w83877f_hefs[] = { WINB_HEFERE, WINB_HEFRAS, WINB_HEFERE | WINB_HEFRAS, 0 };
 1003 
 1004 static int
 1005 ppc_w83877f_detect(struct ppc_data *ppc, int chipset_mode)
 1006 {
 1007         int i, j, efer;
 1008         unsigned char r, hefere, hefras;
 1009 
 1010         for (i = 0; i < 4; i ++) {
 1011                 /* first try to enable configuration registers */
 1012                 efer = w83877f_efers[i];
 1013 
 1014                 /* write the key to the EFER */
 1015                 for (j = 0; j < w83877f_keyiter[i]; j ++)
 1016                         outb (efer, w83877f_keys[i]);
 1017 
 1018                 /* then check HEFERE and HEFRAS bits */
 1019                 outb (efir, 0x0c);
 1020                 hefere = inb(efdr) & WINB_HEFERE;
 1021 
 1022                 outb (efir, 0x16);
 1023                 hefras = inb(efdr) & WINB_HEFRAS;
 1024 
 1025                 /*
 1026                  * HEFRAS       HEFERE
 1027                  *   0             1    write 89h to 250h (power-on default)
 1028                  *   1             0    write 86h twice to 3f0h
 1029                  *   1             1    write 87h twice to 3f0h
 1030                  *   0             0    write 88h to 250h
 1031                  */
 1032                 if ((hefere | hefras) == w83877f_hefs[i])
 1033                         goto found;
 1034         }
 1035 
 1036         return (-1);    /* failed */
 1037 
 1038 found:
 1039         /* check base port address - read from CR23 */
 1040         outb(efir, 0x23);
 1041         if (ppc->ppc_base != inb(efdr) * 4)             /* 4 bytes boundaries */
 1042                 return (-1);
 1043 
 1044         /* read CHIP ID from CR9/bits0-3 */
 1045         outb(efir, 0x9);
 1046 
 1047         switch (inb(efdr) & WINB_CHIPID) {
 1048                 case WINB_W83877F_ID:
 1049                         ppc->ppc_model = WINB_W83877F;
 1050                         break;
 1051 
 1052                 case WINB_W83877AF_ID:
 1053                         ppc->ppc_model = WINB_W83877AF;
 1054                         break;
 1055 
 1056                 default:
 1057                         ppc->ppc_model = WINB_UNKNOWN;
 1058         }
 1059 
 1060         if (bootverbose) {
 1061                 /* dump of registers */
 1062                 device_printf(ppc->ppc_dev, "0x%x - ", w83877f_keys[i]);
 1063                 for (i = 0; i <= 0xd; i ++) {
 1064                         outb(efir, i);
 1065                         printf("0x%x ", inb(efdr));
 1066                 }
 1067                 for (i = 0x10; i <= 0x17; i ++) {
 1068                         outb(efir, i);
 1069                         printf("0x%x ", inb(efdr));
 1070                 }
 1071                 outb(efir, 0x1e);
 1072                 printf("0x%x ", inb(efdr));
 1073                 for (i = 0x20; i <= 0x29; i ++) {
 1074                         outb(efir, i);
 1075                         printf("0x%x ", inb(efdr));
 1076                 }
 1077                 printf("\n");
 1078         }
 1079 
 1080         ppc->ppc_type = PPC_TYPE_GENERIC;
 1081 
 1082         if (!chipset_mode) {
 1083                 /* autodetect mode */
 1084 
 1085                 /* select CR0 */
 1086                 outb(efir, 0x0);
 1087                 r = inb(efdr) & (WINB_PRTMODS0 | WINB_PRTMODS1);
 1088 
 1089                 /* select CR9 */
 1090                 outb(efir, 0x9);
 1091                 r |= (inb(efdr) & WINB_PRTMODS2);
 1092 
 1093                 switch (r) {
 1094                 case WINB_W83757:
 1095                         if (bootverbose)
 1096                                 device_printf(ppc->ppc_dev,
 1097                                     "W83757 compatible mode\n");
 1098                         return (-1);    /* generic or SMC-like */
 1099 
 1100                 case WINB_EXTFDC:
 1101                 case WINB_EXTADP:
 1102                 case WINB_EXT2FDD:
 1103                 case WINB_JOYSTICK:
 1104                         if (bootverbose)
 1105                                 device_printf(ppc->ppc_dev,
 1106                                     "not in parallel port mode\n");
 1107                         return (-1);
 1108 
 1109                 case (WINB_PARALLEL | WINB_EPP_SPP):
 1110                         ppc->ppc_avm |= PPB_EPP | PPB_SPP;
 1111                         if (bootverbose)
 1112                                 device_printf(ppc->ppc_dev, "EPP SPP\n");
 1113                         break;
 1114 
 1115                 case (WINB_PARALLEL | WINB_ECP):
 1116                         ppc->ppc_avm |= PPB_ECP | PPB_SPP;
 1117                         if (bootverbose)
 1118                                 device_printf(ppc->ppc_dev, "ECP SPP\n");
 1119                         break;
 1120 
 1121                 case (WINB_PARALLEL | WINB_ECP_EPP):
 1122                         ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
 1123                         ppc->ppc_type = PPC_TYPE_SMCLIKE;
 1124 
 1125                         if (bootverbose)
 1126                                 device_printf(ppc->ppc_dev, "ECP+EPP SPP\n");
 1127                         break;
 1128                 default:
 1129                         printf("%s: unknown case (0x%x)!\n", __func__, r);
 1130                 }
 1131 
 1132         } else {
 1133                 /* mode forced */
 1134 
 1135                 /* select CR9 and set PRTMODS2 bit */
 1136                 outb(efir, 0x9);
 1137                 outb(efdr, inb(efdr) & ~WINB_PRTMODS2);
 1138 
 1139                 /* select CR0 and reset PRTMODSx bits */
 1140                 outb(efir, 0x0);
 1141                 outb(efdr, inb(efdr) & ~(WINB_PRTMODS0 | WINB_PRTMODS1));
 1142 
 1143                 if (chipset_mode & PPB_ECP) {
 1144                         if (chipset_mode & PPB_EPP) {
 1145                                 outb(efdr, inb(efdr) | WINB_ECP_EPP);
 1146                                 if (bootverbose)
 1147                                         device_printf(ppc->ppc_dev,
 1148                                             "ECP+EPP\n");
 1149 
 1150                                 ppc->ppc_type = PPC_TYPE_SMCLIKE;
 1151 
 1152                         } else {
 1153                                 outb(efdr, inb(efdr) | WINB_ECP);
 1154                                 if (bootverbose)
 1155                                         device_printf(ppc->ppc_dev, "ECP\n");
 1156                         }
 1157                 } else {
 1158                         /* select EPP_SPP otherwise */
 1159                         outb(efdr, inb(efdr) | WINB_EPP_SPP);
 1160                         if (bootverbose)
 1161                                 device_printf(ppc->ppc_dev, "EPP SPP\n");
 1162                 }
 1163                 ppc->ppc_avm = chipset_mode;
 1164         }
 1165 
 1166         /* exit configuration mode */
 1167         outb(efer, 0xaa);
 1168 
 1169         switch (ppc->ppc_type) {
 1170         case PPC_TYPE_SMCLIKE:
 1171                 ppc_smclike_setmode(ppc, chipset_mode);
 1172                 break;
 1173         default:
 1174                 ppc_generic_setmode(ppc, chipset_mode);
 1175                 break;
 1176         }
 1177 
 1178         return (chipset_mode);
 1179 }
 1180 #endif
 1181 
 1182 /*
 1183  * ppc_generic_detect
 1184  */
 1185 static int
 1186 ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
 1187 {
 1188         /* default to generic */
 1189         ppc->ppc_type = PPC_TYPE_GENERIC;
 1190 
 1191         if (bootverbose)
 1192                 device_printf(ppc->ppc_dev, "SPP");
 1193 
 1194         /* first, check for ECP */
 1195         w_ecr(ppc, PPC_ECR_PS2);
 1196         if ((r_ecr(ppc) & 0xe0) == PPC_ECR_PS2) {
 1197                 ppc->ppc_dtm |= PPB_ECP | PPB_SPP;
 1198                 if (bootverbose)
 1199                         printf(" ECP ");
 1200 
 1201                 /* search for SMC style ECP+EPP mode */
 1202                 w_ecr(ppc, PPC_ECR_EPP);
 1203         }
 1204 
 1205         /* try to reset EPP timeout bit */
 1206         if (ppc_check_epp_timeout(ppc)) {
 1207                 ppc->ppc_dtm |= PPB_EPP;
 1208 
 1209                 if (ppc->ppc_dtm & PPB_ECP) {
 1210                         /* SMC like chipset found */
 1211                         ppc->ppc_model = SMC_LIKE;
 1212                         ppc->ppc_type = PPC_TYPE_SMCLIKE;
 1213 
 1214                         if (bootverbose)
 1215                                 printf(" ECP+EPP");
 1216                 } else {
 1217                         if (bootverbose)
 1218                                 printf(" EPP");
 1219                 }
 1220         } else {
 1221                 /* restore to standard mode */
 1222                 w_ecr(ppc, PPC_ECR_STD);
 1223         }
 1224 
 1225         /* XXX try to detect NIBBLE and PS2 modes */
 1226         ppc->ppc_dtm |= PPB_NIBBLE;
 1227 
 1228         if (chipset_mode)
 1229                 ppc->ppc_avm = chipset_mode;
 1230         else
 1231                 ppc->ppc_avm = ppc->ppc_dtm;
 1232 
 1233         if (bootverbose)
 1234                 printf("\n");
 1235 
 1236         switch (ppc->ppc_type) {
 1237         case PPC_TYPE_SMCLIKE:
 1238                 ppc_smclike_setmode(ppc, chipset_mode);
 1239                 break;
 1240         default:
 1241                 ppc_generic_setmode(ppc, chipset_mode);
 1242                 break;
 1243         }
 1244 
 1245         return (chipset_mode);
 1246 }
 1247 
 1248 /*
 1249  * ppc_detect()
 1250  *
 1251  * mode is the mode suggested at boot
 1252  */
 1253 static int
 1254 ppc_detect(struct ppc_data *ppc, int chipset_mode) {
 1255 #ifdef PPC_PROBE_CHIPSET
 1256         int i, mode;
 1257 
 1258         /* list of supported chipsets */
 1259         int (*chipset_detect[])(struct ppc_data *, int) = {
 1260                 ppc_pc873xx_detect,
 1261                 ppc_smc37c66xgt_detect,
 1262                 ppc_w83877f_detect,
 1263                 ppc_smc37c935_detect,
 1264                 ppc_generic_detect,
 1265                 NULL
 1266         };
 1267 #endif
 1268 
 1269         /* if can't find the port and mode not forced return error */
 1270         if (!ppc_detect_port(ppc) && chipset_mode == 0)
 1271                 return (EIO);                   /* failed, port not present */
 1272 
 1273         /* assume centronics compatible mode is supported */
 1274         ppc->ppc_avm = PPB_COMPATIBLE;
 1275 
 1276 #ifdef PPC_PROBE_CHIPSET
 1277         /* we have to differenciate available chipset modes,
 1278          * chipset running modes and IEEE-1284 operating modes
 1279          *
 1280          * after detection, the port must support running in compatible mode
 1281          */
 1282         if (ppc->ppc_flags & 0x40) {
 1283                 if (bootverbose)
 1284                         printf("ppc: chipset forced to generic\n");
 1285 #endif
 1286 
 1287                 ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
 1288 
 1289 #ifdef PPC_PROBE_CHIPSET
 1290         } else {
 1291                 for (i=0; chipset_detect[i] != NULL; i++) {
 1292                         if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
 1293                                 ppc->ppc_mode = mode;
 1294                                 break;
 1295                         }
 1296                 }
 1297         }
 1298 #endif
 1299 
 1300         /* configure/detect ECP FIFO */
 1301         if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80))
 1302                 ppc_detect_fifo(ppc);
 1303 
 1304         return (0);
 1305 }
 1306 
 1307 /*
 1308  * ppc_exec_microseq()
 1309  *
 1310  * Execute a microsequence.
 1311  * Microsequence mechanism is supposed to handle fast I/O operations.
 1312  */
 1313 int
 1314 ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
 1315 {
 1316         struct ppc_data *ppc = DEVTOSOFTC(dev);
 1317         struct ppb_microseq *mi;
 1318         char cc, *p;
 1319         int i, iter, len;
 1320         int error;
 1321 
 1322         int reg;
 1323         char mask;
 1324         int accum = 0;
 1325         char *ptr = NULL;
 1326 
 1327         struct ppb_microseq *stack = NULL;
 1328 
 1329 /* microsequence registers are equivalent to PC-like port registers */
 1330 
 1331 #define r_reg(reg,ppc) (bus_read_1((ppc)->res_ioport, reg))
 1332 #define w_reg(reg, ppc, byte) (bus_write_1((ppc)->res_ioport, reg, byte))
 1333 
 1334 #define INCR_PC (mi ++)         /* increment program counter */
 1335 
 1336         PPC_ASSERT_LOCKED(ppc);
 1337         mi = *p_msq;
 1338         for (;;) {
 1339                 switch (mi->opcode) {
 1340                 case MS_OP_RSET:
 1341                         cc = r_reg(mi->arg[0].i, ppc);
 1342                         cc &= (char)mi->arg[2].i;       /* clear mask */
 1343                         cc |= (char)mi->arg[1].i;       /* assert mask */
 1344                         w_reg(mi->arg[0].i, ppc, cc);
 1345                         INCR_PC;
 1346                         break;
 1347 
 1348                 case MS_OP_RASSERT_P:
 1349                         reg = mi->arg[1].i;
 1350                         ptr = ppc->ppc_ptr;
 1351 
 1352                         if ((len = mi->arg[0].i) == MS_ACCUM) {
 1353                                 accum = ppc->ppc_accum;
 1354                                 for (; accum; accum--)
 1355                                         w_reg(reg, ppc, *ptr++);
 1356                                 ppc->ppc_accum = accum;
 1357                         } else
 1358                                 for (i=0; i<len; i++)
 1359                                         w_reg(reg, ppc, *ptr++);
 1360                         ppc->ppc_ptr = ptr;
 1361 
 1362                         INCR_PC;
 1363                         break;
 1364 
 1365                 case MS_OP_RFETCH_P:
 1366                         reg = mi->arg[1].i;
 1367                         mask = (char)mi->arg[2].i;
 1368                         ptr = ppc->ppc_ptr;
 1369 
 1370                         if ((len = mi->arg[0].i) == MS_ACCUM) {
 1371                                 accum = ppc->ppc_accum;
 1372                                 for (; accum; accum--)
 1373                                         *ptr++ = r_reg(reg, ppc) & mask;
 1374                                 ppc->ppc_accum = accum;
 1375                         } else
 1376                                 for (i=0; i<len; i++)
 1377                                         *ptr++ = r_reg(reg, ppc) & mask;
 1378                         ppc->ppc_ptr = ptr;
 1379 
 1380                         INCR_PC;
 1381                         break;
 1382 
 1383                 case MS_OP_RFETCH:
 1384                         *((char *) mi->arg[2].p) = r_reg(mi->arg[0].i, ppc) &
 1385                                                         (char)mi->arg[1].i;
 1386                         INCR_PC;
 1387                         break;
 1388 
 1389                 case MS_OP_RASSERT:
 1390                 case MS_OP_DELAY:
 1391 
 1392                 /* let's suppose the next instr. is the same */
 1393                 prefetch:
 1394                         for (;mi->opcode == MS_OP_RASSERT; INCR_PC)
 1395                                 w_reg(mi->arg[0].i, ppc, (char)mi->arg[1].i);
 1396 
 1397                         if (mi->opcode == MS_OP_DELAY) {
 1398                                 DELAY(mi->arg[0].i);
 1399                                 INCR_PC;
 1400                                 goto prefetch;
 1401                         }
 1402                         break;
 1403 
 1404                 case MS_OP_ADELAY:
 1405                         if (mi->arg[0].i) {
 1406                                 PPC_UNLOCK(ppc);
 1407                                 pause("ppbdelay", mi->arg[0].i * (hz/1000));
 1408                                 PPC_LOCK(ppc);
 1409                         }
 1410                         INCR_PC;
 1411                         break;
 1412 
 1413                 case MS_OP_TRIG:
 1414                         reg = mi->arg[0].i;
 1415                         iter = mi->arg[1].i;
 1416                         p = (char *)mi->arg[2].p;
 1417 
 1418                         /* XXX delay limited to 255 us */
 1419                         for (i=0; i<iter; i++) {
 1420                                 w_reg(reg, ppc, *p++);
 1421                                 DELAY((unsigned char)*p++);
 1422                         }
 1423                         INCR_PC;
 1424                         break;
 1425 
 1426                 case MS_OP_SET:
 1427                         ppc->ppc_accum = mi->arg[0].i;
 1428                         INCR_PC;
 1429                         break;
 1430 
 1431                 case MS_OP_DBRA:
 1432                         if (--ppc->ppc_accum > 0)
 1433                                 mi += mi->arg[0].i;
 1434                         INCR_PC;
 1435                         break;
 1436 
 1437                 case MS_OP_BRSET:
 1438                         cc = r_str(ppc);
 1439                         if ((cc & (char)mi->arg[0].i) == (char)mi->arg[0].i)
 1440                                 mi += mi->arg[1].i;
 1441                         INCR_PC;
 1442                         break;
 1443 
 1444                 case MS_OP_BRCLEAR:
 1445                         cc = r_str(ppc);
 1446                         if ((cc & (char)mi->arg[0].i) == 0)
 1447                                 mi += mi->arg[1].i;
 1448                         INCR_PC;
 1449                         break;
 1450 
 1451                 case MS_OP_BRSTAT:
 1452                         cc = r_str(ppc);
 1453                         if ((cc & ((char)mi->arg[0].i | (char)mi->arg[1].i)) ==
 1454                                                         (char)mi->arg[0].i)
 1455                                 mi += mi->arg[2].i;
 1456                         INCR_PC;
 1457                         break;
 1458 
 1459                 case MS_OP_C_CALL:
 1460                         /*
 1461                          * If the C call returns !0 then end the microseq.
 1462                          * The current state of ptr is passed to the C function
 1463                          */
 1464                         if ((error = mi->arg[0].f(mi->arg[1].p, ppc->ppc_ptr)))
 1465                                 return (error);
 1466 
 1467                         INCR_PC;
 1468                         break;
 1469 
 1470                 case MS_OP_PTR:
 1471                         ppc->ppc_ptr = (char *)mi->arg[0].p;
 1472                         INCR_PC;
 1473                         break;
 1474 
 1475                 case MS_OP_CALL:
 1476                         if (stack)
 1477                                 panic("%s: too much calls", __func__);
 1478 
 1479                         if (mi->arg[0].p) {
 1480                                 /* store the state of the actual
 1481                                  * microsequence
 1482                                  */
 1483                                 stack = mi;
 1484 
 1485                                 /* jump to the new microsequence */
 1486                                 mi = (struct ppb_microseq *)mi->arg[0].p;
 1487                         } else
 1488                                 INCR_PC;
 1489 
 1490                         break;
 1491 
 1492                 case MS_OP_SUBRET:
 1493                         /* retrieve microseq and pc state before the call */
 1494                         mi = stack;
 1495 
 1496                         /* reset the stack */
 1497                         stack = NULL;
 1498 
 1499                         /* XXX return code */
 1500 
 1501                         INCR_PC;
 1502                         break;
 1503 
 1504                 case MS_OP_PUT:
 1505                 case MS_OP_GET:
 1506                 case MS_OP_RET:
 1507                         /* can't return to ppb level during the execution
 1508                          * of a submicrosequence */
 1509                         if (stack)
 1510                                 panic("%s: can't return to ppb level",
 1511                                                                 __func__);
 1512 
 1513                         /* update pc for ppb level of execution */
 1514                         *p_msq = mi;
 1515 
 1516                         /* return to ppb level of execution */
 1517                         return (0);
 1518 
 1519                 default:
 1520                         panic("%s: unknown microsequence opcode 0x%x",
 1521                             __func__, mi->opcode);
 1522                 }
 1523         }
 1524 
 1525         /* unreached */
 1526 }
 1527 
 1528 static void
 1529 ppcintr(void *arg)
 1530 {
 1531         struct ppc_data *ppc = arg;
 1532         u_char ctr, ecr, str;
 1533 
 1534         /*
 1535          * If we have any child interrupt handlers registered, let
 1536          * them handle this interrupt.
 1537          *
 1538          * XXX: If DMA is in progress should we just complete that w/o
 1539          * doing this?
 1540          */
 1541         PPC_LOCK(ppc);
 1542         if (ppc->ppc_intr_hook != NULL &&
 1543             ppc->ppc_intr_hook(ppc->ppc_intr_arg) == 0) {
 1544                 PPC_UNLOCK(ppc);
 1545                 return;
 1546         }
 1547 
 1548         str = r_str(ppc);
 1549         ctr = r_ctr(ppc);
 1550         ecr = r_ecr(ppc);
 1551 
 1552 #if defined(PPC_DEBUG) && PPC_DEBUG > 1
 1553                 printf("![%x/%x/%x]", ctr, ecr, str);
 1554 #endif
 1555 
 1556         /* don't use ecp mode with IRQENABLE set */
 1557         if (ctr & IRQENABLE) {
 1558                 PPC_UNLOCK(ppc);
 1559                 return;
 1560         }
 1561 
 1562         /* interrupts are generated by nFault signal
 1563          * only in ECP mode */
 1564         if ((str & nFAULT) && (ppc->ppc_mode & PPB_ECP)) {
 1565                 /* check if ppc driver has programmed the
 1566                  * nFault interrupt */
 1567                 if  (ppc->ppc_irqstat & PPC_IRQ_nFAULT) {
 1568                         w_ecr(ppc, ecr | PPC_nFAULT_INTR);
 1569                         ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT;
 1570                 } else {
 1571                         /* shall be handled by underlying layers XXX */
 1572                         PPC_UNLOCK(ppc);
 1573                         return;
 1574                 }
 1575         }
 1576 
 1577         if (ppc->ppc_irqstat & PPC_IRQ_DMA) {
 1578                 /* disable interrupts (should be done by hardware though) */
 1579                 w_ecr(ppc, ecr | PPC_SERVICE_INTR);
 1580                 ppc->ppc_irqstat &= ~PPC_IRQ_DMA;
 1581                 ecr = r_ecr(ppc);
 1582 
 1583                 /* check if DMA completed */
 1584                 if ((ppc->ppc_avm & PPB_ECP) && (ecr & PPC_ENABLE_DMA)) {
 1585 #ifdef PPC_DEBUG
 1586                         printf("a");
 1587 #endif
 1588                         /* stop DMA */
 1589                         w_ecr(ppc, ecr & ~PPC_ENABLE_DMA);
 1590                         ecr = r_ecr(ppc);
 1591 
 1592                         if (ppc->ppc_dmastat == PPC_DMA_STARTED) {
 1593 #ifdef PPC_DEBUG
 1594                                 printf("d");
 1595 #endif
 1596                                 ppc->ppc_dmadone(ppc);
 1597                                 ppc->ppc_dmastat = PPC_DMA_COMPLETE;
 1598 
 1599                                 /* wakeup the waiting process */
 1600                                 wakeup(ppc);
 1601                         }
 1602                 }
 1603         } else if (ppc->ppc_irqstat & PPC_IRQ_FIFO) {
 1604                 /* classic interrupt I/O */
 1605                 ppc->ppc_irqstat &= ~PPC_IRQ_FIFO;
 1606         }
 1607         PPC_UNLOCK(ppc);
 1608 
 1609         return;
 1610 }
 1611 
 1612 int
 1613 ppc_read(device_t dev, char *buf, int len, int mode)
 1614 {
 1615         return (EINVAL);
 1616 }
 1617 
 1618 int
 1619 ppc_write(device_t dev, char *buf, int len, int how)
 1620 {
 1621         return (EINVAL);
 1622 }
 1623 
 1624 int
 1625 ppc_reset_epp(device_t dev)
 1626 {
 1627         struct ppc_data *ppc = DEVTOSOFTC(dev);
 1628 
 1629         PPC_ASSERT_LOCKED(ppc);
 1630         ppc_reset_epp_timeout(ppc);
 1631 
 1632         return 0;
 1633 }
 1634 
 1635 int
 1636 ppc_setmode(device_t dev, int mode)
 1637 {
 1638         struct ppc_data *ppc = DEVTOSOFTC(dev);
 1639 
 1640         PPC_ASSERT_LOCKED(ppc);
 1641         switch (ppc->ppc_type) {
 1642         case PPC_TYPE_SMCLIKE:
 1643                 return (ppc_smclike_setmode(ppc, mode));
 1644                 break;
 1645 
 1646         case PPC_TYPE_GENERIC:
 1647         default:
 1648                 return (ppc_generic_setmode(ppc, mode));
 1649                 break;
 1650         }
 1651 
 1652         /* not reached */
 1653         return (ENXIO);
 1654 }
 1655 
 1656 int
 1657 ppc_probe(device_t dev, int rid)
 1658 {
 1659         struct ppc_data *ppc;
 1660 #ifdef __i386__
 1661         static short next_bios_ppc = 0;
 1662         int error;
 1663         rman_res_t port;
 1664 #endif
 1665 
 1666         /*
 1667          * Allocate the ppc_data structure.
 1668          */
 1669         ppc = DEVTOSOFTC(dev);
 1670         bzero(ppc, sizeof(struct ppc_data));
 1671 
 1672         ppc->rid_ioport = rid;
 1673 
 1674 #ifdef __i386__
 1675         /* retrieve ISA parameters */
 1676         error = bus_get_resource(dev, SYS_RES_IOPORT, rid, &port, NULL);
 1677 
 1678         /*
 1679          * If port not specified, use bios list.
 1680          */
 1681         if (error) {
 1682                 if ((next_bios_ppc < BIOS_MAX_PPC) &&
 1683                     (*(BIOS_PORTS + next_bios_ppc) != 0)) {
 1684                         port = *(BIOS_PORTS + next_bios_ppc++);
 1685                         if (bootverbose)
 1686                                 device_printf(dev,
 1687                                     "parallel port found at 0x%jx\n", port);
 1688                 } else {
 1689                         device_printf(dev, "parallel port not found.\n");
 1690                         return (ENXIO);
 1691                 }
 1692                 bus_set_resource(dev, SYS_RES_IOPORT, rid, port,
 1693                                  IO_LPTSIZE_EXTENDED);
 1694         }
 1695 #endif
 1696 
 1697         /* IO port is mandatory */
 1698 
 1699         /* Try "extended" IO port range...*/
 1700         ppc->res_ioport = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
 1701                                                       &ppc->rid_ioport,
 1702                                                       IO_LPTSIZE_EXTENDED,
 1703                                                       RF_ACTIVE);
 1704 
 1705         if (ppc->res_ioport != 0) {
 1706                 if (bootverbose)
 1707                         device_printf(dev, "using extended I/O port range\n");
 1708         } else {
 1709                 /* Failed? If so, then try the "normal" IO port range... */
 1710                  ppc->res_ioport = bus_alloc_resource_anywhere(dev,
 1711                                                                SYS_RES_IOPORT,
 1712                                                                &ppc->rid_ioport,
 1713                                                                IO_LPTSIZE_NORMAL,
 1714                                                                RF_ACTIVE);
 1715                 if (ppc->res_ioport != 0) {
 1716                         if (bootverbose)
 1717                                 device_printf(dev, "using normal I/O port range\n");
 1718                 } else {
 1719                         if (bootverbose)
 1720                                 device_printf(dev, "cannot reserve I/O port range\n");
 1721                         goto error;
 1722                 }
 1723         }
 1724 
 1725         ppc->ppc_base = rman_get_start(ppc->res_ioport);
 1726 
 1727         ppc->ppc_flags = device_get_flags(dev);
 1728 
 1729         if (!(ppc->ppc_flags & 0x20)) {
 1730                 ppc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
 1731                                                       &ppc->rid_irq,
 1732                                                       RF_SHAREABLE);
 1733                 ppc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
 1734                                                       &ppc->rid_drq,
 1735                                                       RF_ACTIVE);
 1736         }
 1737 
 1738         if (ppc->res_irq)
 1739                 ppc->ppc_irq = rman_get_start(ppc->res_irq);
 1740         if (ppc->res_drq)
 1741                 ppc->ppc_dmachan = rman_get_start(ppc->res_drq);
 1742 
 1743         ppc->ppc_dev = dev;
 1744         ppc->ppc_model = GENERIC;
 1745 
 1746         ppc->ppc_mode = PPB_COMPATIBLE;
 1747         ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;
 1748 
 1749         ppc->ppc_type = PPC_TYPE_GENERIC;
 1750 
 1751         /*
 1752          * Try to detect the chipset and its mode.
 1753          */
 1754         if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
 1755                 goto error;
 1756 
 1757         return (0);
 1758 
 1759 error:
 1760         if (ppc->res_irq != 0) {
 1761                 bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
 1762                                      ppc->res_irq);
 1763         }
 1764         if (ppc->res_ioport != 0) {
 1765                 bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
 1766                                      ppc->res_ioport);
 1767         }
 1768         if (ppc->res_drq != 0) {
 1769                 bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
 1770                                      ppc->res_drq);
 1771         }
 1772         return (ENXIO);
 1773 }
 1774 
 1775 int
 1776 ppc_attach(device_t dev)
 1777 {
 1778         struct ppc_data *ppc = DEVTOSOFTC(dev);
 1779         int error;
 1780 
 1781         mtx_init(&ppc->ppc_lock, device_get_nameunit(dev), "ppc", MTX_DEF);
 1782 
 1783         device_printf(dev, "%s chipset (%s) in %s mode%s\n",
 1784                       ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm],
 1785                       ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
 1786                       ppc_epp_protocol[ppc->ppc_epp] : "");
 1787 
 1788         if (ppc->ppc_fifo)
 1789                 device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
 1790                               ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);
 1791 
 1792         if (ppc->res_irq) {
 1793                 /* default to the tty mask for registration */  /* XXX */
 1794                 error = bus_setup_intr(dev, ppc->res_irq, INTR_TYPE_TTY |
 1795                     INTR_MPSAFE, NULL, ppcintr, ppc, &ppc->intr_cookie);
 1796                 if (error) {
 1797                         device_printf(dev,
 1798                             "failed to register interrupt handler: %d\n",
 1799                             error);
 1800                         mtx_destroy(&ppc->ppc_lock);
 1801                         return (error);
 1802                 }
 1803         }
 1804 
 1805         /* add ppbus as a child of this isa to parallel bridge */
 1806         ppc->ppbus = device_add_child(dev, "ppbus", -1);
 1807 
 1808         /*
 1809          * Probe the ppbus and attach devices found.
 1810          */
 1811         device_probe_and_attach(ppc->ppbus);
 1812 
 1813         return (0);
 1814 }
 1815 
 1816 int
 1817 ppc_detach(device_t dev)
 1818 {
 1819         struct ppc_data *ppc = DEVTOSOFTC(dev);
 1820 
 1821         if (ppc->res_irq == 0) {
 1822                 return (ENXIO);
 1823         }
 1824 
 1825         /* detach & delete all children */
 1826         device_delete_children(dev);
 1827 
 1828         if (ppc->res_irq != 0) {
 1829                 bus_teardown_intr(dev, ppc->res_irq, ppc->intr_cookie);
 1830                 bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
 1831                                      ppc->res_irq);
 1832         }
 1833         if (ppc->res_ioport != 0) {
 1834                 bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
 1835                                      ppc->res_ioport);
 1836         }
 1837         if (ppc->res_drq != 0) {
 1838                 bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
 1839                                      ppc->res_drq);
 1840         }
 1841 
 1842         mtx_destroy(&ppc->ppc_lock);
 1843 
 1844         return (0);
 1845 }
 1846 
 1847 u_char
 1848 ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
 1849 {
 1850         struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
 1851 
 1852         PPC_ASSERT_LOCKED(ppc);
 1853         switch (iop) {
 1854         case PPB_OUTSB_EPP:
 1855             bus_write_multi_1(ppc->res_ioport, PPC_EPP_DATA, addr, cnt);
 1856                 break;
 1857         case PPB_OUTSW_EPP:
 1858             bus_write_multi_2(ppc->res_ioport, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
 1859                 break;
 1860         case PPB_OUTSL_EPP:
 1861             bus_write_multi_4(ppc->res_ioport, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
 1862                 break;
 1863         case PPB_INSB_EPP:
 1864             bus_read_multi_1(ppc->res_ioport, PPC_EPP_DATA, addr, cnt);
 1865                 break;
 1866         case PPB_INSW_EPP:
 1867             bus_read_multi_2(ppc->res_ioport, PPC_EPP_DATA, (u_int16_t *)addr, cnt);
 1868                 break;
 1869         case PPB_INSL_EPP:
 1870             bus_read_multi_4(ppc->res_ioport, PPC_EPP_DATA, (u_int32_t *)addr, cnt);
 1871                 break;
 1872         case PPB_RDTR:
 1873                 return (r_dtr(ppc));
 1874         case PPB_RSTR:
 1875                 return (r_str(ppc));
 1876         case PPB_RCTR:
 1877                 return (r_ctr(ppc));
 1878         case PPB_REPP_A:
 1879                 return (r_epp_A(ppc));
 1880         case PPB_REPP_D:
 1881                 return (r_epp_D(ppc));
 1882         case PPB_RECR:
 1883                 return (r_ecr(ppc));
 1884         case PPB_RFIFO:
 1885                 return (r_fifo(ppc));
 1886         case PPB_WDTR:
 1887                 w_dtr(ppc, byte);
 1888                 break;
 1889         case PPB_WSTR:
 1890                 w_str(ppc, byte);
 1891                 break;
 1892         case PPB_WCTR:
 1893                 w_ctr(ppc, byte);
 1894                 break;
 1895         case PPB_WEPP_A:
 1896                 w_epp_A(ppc, byte);
 1897                 break;
 1898         case PPB_WEPP_D:
 1899                 w_epp_D(ppc, byte);
 1900                 break;
 1901         case PPB_WECR:
 1902                 w_ecr(ppc, byte);
 1903                 break;
 1904         case PPB_WFIFO:
 1905                 w_fifo(ppc, byte);
 1906                 break;
 1907         default:
 1908                 panic("%s: unknown I/O operation", __func__);
 1909                 break;
 1910         }
 1911 
 1912         return (0);     /* not significative */
 1913 }
 1914 
 1915 int
 1916 ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
 1917 {
 1918         struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus);
 1919 
 1920         switch (index) {
 1921         case PPC_IVAR_EPP_PROTO:
 1922                 PPC_ASSERT_LOCKED(ppc);
 1923                 *val = (u_long)ppc->ppc_epp;
 1924                 break;
 1925         case PPC_IVAR_LOCK:
 1926                 *val = (uintptr_t)&ppc->ppc_lock;
 1927                 break;
 1928         default:
 1929                 return (ENOENT);
 1930         }
 1931 
 1932         return (0);
 1933 }
 1934 
 1935 int
 1936 ppc_write_ivar(device_t bus, device_t dev, int index, uintptr_t val)
 1937 {
 1938         struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus);
 1939 
 1940         switch (index) {
 1941         case PPC_IVAR_INTR_HANDLER:
 1942                 PPC_ASSERT_LOCKED(ppc);
 1943                 if (dev != ppc->ppbus)
 1944                         return (EINVAL);
 1945                 if (val == 0) {
 1946                         ppc->ppc_intr_hook = NULL;
 1947                         break;
 1948                 }
 1949                 if (ppc->ppc_intr_hook != NULL)
 1950                         return (EBUSY);
 1951                 ppc->ppc_intr_hook = (void *)val;
 1952                 ppc->ppc_intr_arg = device_get_softc(dev);
 1953                 break;
 1954         default:
 1955                 return (ENOENT);
 1956         }
 1957 
 1958         return (0);
 1959 }
 1960 
 1961 /*
 1962  * We allow child devices to allocate an IRQ resource at rid 0 for their
 1963  * interrupt handlers.
 1964  */
 1965 struct resource *
 1966 ppc_alloc_resource(device_t bus, device_t child, int type, int *rid,
 1967     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
 1968 {
 1969         struct ppc_data *ppc = DEVTOSOFTC(bus);
 1970 
 1971         switch (type) {
 1972         case SYS_RES_IRQ:
 1973                 if (*rid == 0)
 1974                         return (ppc->res_irq);
 1975                 break;
 1976         }
 1977         return (NULL);
 1978 }
 1979 
 1980 int
 1981 ppc_release_resource(device_t bus, device_t child, int type, int rid,
 1982     struct resource *r)
 1983 {
 1984 #ifdef INVARIANTS
 1985         struct ppc_data *ppc = DEVTOSOFTC(bus);
 1986 #endif
 1987 
 1988         switch (type) {
 1989         case SYS_RES_IRQ:
 1990                 if (rid == 0) {
 1991                         KASSERT(r == ppc->res_irq,
 1992                             ("ppc child IRQ resource mismatch"));
 1993                         return (0);
 1994                 }
 1995                 break;
 1996         }
 1997         return (EINVAL);
 1998 }
 1999 
 2000 MODULE_DEPEND(ppc, ppbus, 1, 1, 1);

Cache object: b67f0cd5e17d94e41fe887ce1b0a454f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.