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

Cache object: 4888c37a20ce041c4e6babb0cf40a281


[ 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.