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/i386/isa/isa.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) 1991 The Regents of the University of California.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * William Jolitz.
    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  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      from: @(#)isa.c 7.2 (Berkeley) 5/13/91
   37  * $FreeBSD: src/sys/i386/isa/isa.c,v 1.74.2.8 1999/09/05 08:13:02 peter Exp $
   38  */
   39 
   40 /*
   41  * code to manage AT bus
   42  *
   43  * 92/08/18  Frank P. MacLachlan (fpm@crash.cts.com):
   44  * Fixed uninitialized variable problem and added code to deal
   45  * with DMA page boundaries in isa_dmarangecheck().  Fixed word
   46  * mode DMA count compution and reorganized DMA setup code in
   47  * isa_dmastart()
   48  */
   49 
   50 #include "opt_auto_eoi.h"
   51 
   52 #include <sys/param.h>
   53 #include <sys/systm.h>
   54 #include <sys/buf.h>
   55 #include <sys/syslog.h>
   56 #include <sys/malloc.h>
   57 #include <machine/md_var.h>
   58 #include <machine/segments.h>
   59 #include <vm/vm.h>
   60 #include <vm/vm_param.h>
   61 #include <vm/pmap.h>
   62 #include <i386/isa/isa_device.h>
   63 #include <i386/isa/isa.h>
   64 #include <i386/isa/icu.h>
   65 #include <i386/isa/ic/i8237.h>
   66 #include "vector.h"
   67 
   68 /*
   69 **  Register definitions for DMA controller 1 (channels 0..3):
   70 */
   71 #define DMA1_CHN(c)     (IO_DMA1 + 1*(2*(c)))   /* addr reg for channel c */
   72 #define DMA1_SMSK       (IO_DMA1 + 1*10)        /* single mask register */
   73 #define DMA1_MODE       (IO_DMA1 + 1*11)        /* mode register */
   74 #define DMA1_FFC        (IO_DMA1 + 1*12)        /* clear first/last FF */
   75 
   76 /*
   77 **  Register definitions for DMA controller 2 (channels 4..7):
   78 */
   79 #define DMA2_CHN(c)     (IO_DMA2 + 2*(2*(c)))   /* addr reg for channel c */
   80 #define DMA2_SMSK       (IO_DMA2 + 2*10)        /* single mask register */
   81 #define DMA2_MODE       (IO_DMA2 + 2*11)        /* mode register */
   82 #define DMA2_FFC        (IO_DMA2 + 2*12)        /* clear first/last FF */
   83 
   84 u_long  *intr_countp[ICU_LEN];
   85 inthand2_t *intr_handler[ICU_LEN];
   86 u_int   intr_mask[ICU_LEN];
   87 u_int*  intr_mptr[ICU_LEN];
   88 int     intr_unit[ICU_LEN];
   89 
   90 static inthand_t *fastintr[ICU_LEN] = {
   91         &IDTVEC(fastintr0), &IDTVEC(fastintr1),
   92         &IDTVEC(fastintr2), &IDTVEC(fastintr3),
   93         &IDTVEC(fastintr4), &IDTVEC(fastintr5),
   94         &IDTVEC(fastintr6), &IDTVEC(fastintr7),
   95         &IDTVEC(fastintr8), &IDTVEC(fastintr9),
   96         &IDTVEC(fastintr10), &IDTVEC(fastintr11),
   97         &IDTVEC(fastintr12), &IDTVEC(fastintr13),
   98         &IDTVEC(fastintr14), &IDTVEC(fastintr15)
   99 };
  100 
  101 static inthand_t *slowintr[ICU_LEN] = {
  102         &IDTVEC(intr0), &IDTVEC(intr1), &IDTVEC(intr2), &IDTVEC(intr3),
  103         &IDTVEC(intr4), &IDTVEC(intr5), &IDTVEC(intr6), &IDTVEC(intr7),
  104         &IDTVEC(intr8), &IDTVEC(intr9), &IDTVEC(intr10), &IDTVEC(intr11),
  105         &IDTVEC(intr12), &IDTVEC(intr13), &IDTVEC(intr14), &IDTVEC(intr15)
  106 };
  107 
  108 static void config_isadev __P((struct isa_device *isdp, u_int *mp));
  109 static void config_isadev_c __P((struct isa_device *isdp, u_int *mp,
  110                                  int reconfig));
  111 static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp,
  112                           int item, char const *whatnot, char const *reason,
  113                           char const *format));
  114 static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp,
  115                          u_int checkbits));
  116 static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan));
  117 static inthand2_t isa_strayintr;
  118 static void register_imask __P((struct isa_device *dvp, u_int mask));
  119 
  120 /*
  121  * print a conflict message
  122  */
  123 static void
  124 conflict(dvp, tmpdvp, item, whatnot, reason, format)
  125         struct isa_device       *dvp;
  126         struct isa_device       *tmpdvp;
  127         int                     item;
  128         char const              *whatnot;
  129         char const              *reason;
  130         char const              *format;
  131 {
  132         printf("%s%d not %sed due to %s conflict with %s%d at ",
  133                 dvp->id_driver->name, dvp->id_unit, whatnot, reason,
  134                 tmpdvp->id_driver->name, tmpdvp->id_unit);
  135         printf(format, item);
  136         printf("\n");
  137 }
  138 
  139 /*
  140  * Check to see if things are already in use, like IRQ's, I/O addresses
  141  * and Memory addresses.
  142  */
  143 static int
  144 haveseen(dvp, tmpdvp, checkbits)
  145         struct isa_device *dvp;
  146         struct isa_device *tmpdvp;
  147         u_int   checkbits;
  148 {
  149         /*
  150          * Only check against devices that have already been found and are not
  151          * unilaterally allowed to conflict anyway.
  152          */
  153         if (tmpdvp->id_alive && !dvp->id_conflicts) {
  154                 char const *whatnot;
  155 
  156                 whatnot = checkbits & CC_ATTACH ? "attach" : "prob";
  157                 /*
  158                  * Check for I/O address conflict.  We can only check the
  159                  * starting address of the device against the range of the
  160                  * device that has already been probed since we do not
  161                  * know how many I/O addresses this device uses.
  162                  */
  163                 if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) {
  164                         if ((dvp->id_iobase >= tmpdvp->id_iobase) &&
  165                             (dvp->id_iobase <=
  166                                   (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) {
  167                                 conflict(dvp, tmpdvp, dvp->id_iobase, whatnot,
  168                                          "I/O address", "0x%x");
  169                                 return 1;
  170                         }
  171                 }
  172                 /*
  173                  * Check for Memory address conflict.  We can check for
  174                  * range overlap, but it will not catch all cases since the
  175                  * driver may adjust the msize paramater during probe, for
  176                  * now we just check that the starting address does not
  177                  * fall within any allocated region.
  178                  * XXX could add a second check after the probe for overlap,
  179                  * since at that time we would know the full range.
  180                  * XXX KERNBASE is a hack, we should have vaddr in the table!
  181                  */
  182                 if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) {
  183                         if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) &&
  184                             (KERNBASE + dvp->id_maddr <=
  185                              (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) {
  186                                 conflict(dvp, tmpdvp, (int)dvp->id_maddr,
  187                                          whatnot, "maddr", "0x%x");
  188                                 return 1;
  189                         }
  190                 }
  191                 /*
  192                  * Check for IRQ conflicts.
  193                  */
  194                 if (checkbits & CC_IRQ && tmpdvp->id_irq) {
  195                         if (tmpdvp->id_irq == dvp->id_irq) {
  196                                 conflict(dvp, tmpdvp, ffs(dvp->id_irq) - 1,
  197                                          whatnot, "irq", "%d");
  198                                 return 1;
  199                         }
  200                 }
  201                 /*
  202                  * Check for DRQ conflicts.
  203                  */
  204                 if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) {
  205                         if (tmpdvp->id_drq == dvp->id_drq) {
  206                                 conflict(dvp, tmpdvp, dvp->id_drq, whatnot,
  207                                          "drq", "%d");
  208                                 return 1;
  209                         }
  210                 }
  211         }
  212         return 0;
  213 }
  214 
  215 /*
  216  * Search through all the isa_devtab_* tables looking for anything that
  217  * conflicts with the current device.
  218  */
  219 int
  220 haveseen_isadev(dvp, checkbits)
  221         struct isa_device *dvp;
  222         u_int   checkbits;
  223 {
  224         struct isa_device *tmpdvp;
  225         int     status = 0;
  226 
  227         for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) {
  228                 status |= haveseen(dvp, tmpdvp, checkbits);
  229                 if (status)
  230                         return status;
  231         }
  232         for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) {
  233                 status |= haveseen(dvp, tmpdvp, checkbits);
  234                 if (status)
  235                         return status;
  236         }
  237         for (tmpdvp = isa_devtab_cam; tmpdvp->id_driver; tmpdvp++) {
  238                 status |= haveseen(dvp, tmpdvp, checkbits);
  239                 if (status)
  240                         return status;
  241         }
  242         for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) {
  243                 status |= haveseen(dvp, tmpdvp, checkbits);
  244                 if (status)
  245                         return status;
  246         }
  247         for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) {
  248                 status |= haveseen(dvp, tmpdvp, checkbits);
  249                 if (status)
  250                         return status;
  251         }
  252         return(status);
  253 }
  254 
  255 /*
  256  * Configure all ISA devices
  257  */
  258 void
  259 isa_configure() {
  260         struct isa_device *dvp;
  261 
  262         splhigh();
  263         printf("Probing for devices on the ISA bus:\n");
  264         /* First probe all the sensitive probes */
  265         for (dvp = isa_devtab_tty; dvp->id_driver; dvp++)
  266                 if (dvp->id_driver->sensitive_hw)
  267                         config_isadev(dvp, &tty_imask);
  268         for (dvp = isa_devtab_bio; dvp->id_driver; dvp++)
  269                 if (dvp->id_driver->sensitive_hw)
  270                         config_isadev(dvp, &bio_imask);
  271         for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
  272                 if (dvp->id_driver->sensitive_hw)
  273                         config_isadev(dvp, &cam_imask);
  274         for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
  275                 if (dvp->id_driver->sensitive_hw)
  276                         config_isadev(dvp, &net_imask);
  277         for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
  278                 if (dvp->id_driver->sensitive_hw)
  279                         config_isadev(dvp, (u_int *)NULL);
  280 
  281         /* Then all the bad ones */
  282         for (dvp = isa_devtab_tty; dvp->id_driver; dvp++)
  283                 if (!dvp->id_driver->sensitive_hw)
  284                         config_isadev(dvp, &tty_imask);
  285         for (dvp = isa_devtab_bio; dvp->id_driver; dvp++)
  286                 if (!dvp->id_driver->sensitive_hw)
  287                         config_isadev(dvp, &bio_imask);
  288         for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
  289                 if (!dvp->id_driver->sensitive_hw)
  290                         config_isadev(dvp, &cam_imask);
  291         for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
  292                 if (!dvp->id_driver->sensitive_hw)
  293                         config_isadev(dvp, &net_imask);
  294         for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
  295                 if (!dvp->id_driver->sensitive_hw)
  296                         config_isadev(dvp, (u_int *)NULL);
  297 
  298         bio_imask |= SWI_CLOCK_MASK;
  299         net_imask |= SWI_NET_MASK;
  300         tty_imask |= SWI_TTY_MASK;
  301 
  302 /*
  303  * XXX we should really add the tty device to net_imask when the line is
  304  * switched to SLIPDISC, and then remove it when it is switched away from
  305  * SLIPDISC.  No need to block out ALL ttys during a splimp when only one
  306  * of them is running slip.
  307  *
  308  * XXX actually, blocking all ttys during a splimp doesn't matter so much
  309  * with sio because the serial interrupt layer doesn't use tty_imask.  Only
  310  * non-serial ttys suffer.  It's more stupid that ALL 'net's are blocked
  311  * during spltty.
  312  */
  313 #include "sl.h"
  314 #if NSL > 0
  315         net_imask |= tty_imask;
  316         tty_imask = net_imask;
  317 #endif
  318 
  319         /* bio_imask |= tty_imask ;  can some tty devices use buffers? */
  320 
  321         if (bootverbose)
  322                 printf("imasks: bio %x, tty %x, net %x\n",
  323                        bio_imask, tty_imask, net_imask);
  324 
  325         /*
  326          * Finish initializing intr_mask[].  Note that the partly
  327          * constructed masks aren't actually used since we're at splhigh.
  328          * For fully dynamic initialization, register_intr() and
  329          * unregister_intr() will have to adjust the masks for _all_
  330          * interrupts and for tty_imask, etc.
  331          */
  332         for (dvp = isa_devtab_tty; dvp->id_driver; dvp++)
  333                 register_imask(dvp, tty_imask);
  334         for (dvp = isa_devtab_bio; dvp->id_driver; dvp++)
  335                 register_imask(dvp, bio_imask);
  336         for (dvp = isa_devtab_cam; dvp->id_driver; dvp++)
  337                 register_imask(dvp, cam_imask);
  338         for (dvp = isa_devtab_net; dvp->id_driver; dvp++)
  339                 register_imask(dvp, net_imask);
  340         for (dvp = isa_devtab_null; dvp->id_driver; dvp++)
  341                 register_imask(dvp, SWI_CLOCK_MASK);
  342         spl0();
  343 }
  344 
  345 /*
  346  * Configure an ISA device.
  347  */
  348 
  349 
  350 static void
  351 config_isadev(isdp, mp)
  352      struct isa_device *isdp;
  353      u_int *mp;
  354 {
  355         config_isadev_c(isdp, mp, 0);
  356 }
  357 
  358 void
  359 reconfig_isadev(isdp, mp)
  360         struct isa_device *isdp;
  361         u_int *mp;
  362 {
  363         config_isadev_c(isdp, mp, 1);
  364 }
  365 
  366 static void
  367 config_isadev_c(isdp, mp, reconfig)
  368         struct isa_device *isdp;
  369         u_int *mp;
  370         int reconfig;
  371 {
  372         u_int checkbits;
  373         int id_alive;
  374         int last_alive;
  375         struct isa_driver *dp = isdp->id_driver;
  376 
  377         if (!isdp->id_enabled) {
  378                 if (bootverbose)
  379                         printf("%s%d: disabled, not probed.\n",
  380                                 dp->name, isdp->id_unit);
  381                 return;
  382         }
  383         checkbits = CC_DRQ | CC_IOADDR | CC_MEMADDR;
  384         if (!reconfig && haveseen_isadev(isdp, checkbits))
  385                 return;
  386         if (!reconfig && isdp->id_maddr) {
  387                 isdp->id_maddr -= ISA_HOLE_START;
  388                 isdp->id_maddr += atdevbase;
  389         }
  390         if (reconfig) {
  391                 last_alive = isdp->id_alive;
  392                 isdp->id_reconfig = 1;
  393         }
  394         else {
  395                 last_alive = 0;
  396                 isdp->id_reconfig = 0;
  397         }
  398         id_alive = (*dp->probe)(isdp);
  399         if (id_alive) {
  400                 /*
  401                  * Only print the I/O address range if id_alive != -1
  402                  * Right now this is a temporary fix just for the new
  403                  * NPX code so that if it finds a 486 that can use trap
  404                  * 16 it will not report I/O addresses.
  405                  * Rod Grimes 04/26/94
  406                  */
  407                 if (!isdp->id_reconfig) {
  408                         printf("%s%d", dp->name, isdp->id_unit);
  409                         if (id_alive != -1) {
  410                                 printf(" at 0x%x", isdp->id_iobase);
  411                                 if (isdp->id_iobase + id_alive - 1 !=
  412                                     isdp->id_iobase) {
  413                                         printf("-0x%x",
  414                                                isdp->id_iobase + id_alive - 1);
  415                                 }
  416                         }
  417                         if (isdp->id_irq)
  418                                 printf(" irq %d", ffs(isdp->id_irq) - 1);
  419                         if (isdp->id_drq != -1)
  420                                 printf(" drq %d", isdp->id_drq);
  421                         if (isdp->id_maddr)
  422                                 printf(" maddr 0x%lx", kvtop(isdp->id_maddr));
  423                         if (isdp->id_msize)
  424                                 printf(" msize %d", isdp->id_msize);
  425                         if (isdp->id_flags)
  426                                 printf(" flags 0x%x", isdp->id_flags);
  427                         if (isdp->id_iobase && !(isdp->id_iobase & 0xf300)) {
  428                                 printf(" on motherboard");
  429                         } else if (isdp->id_iobase >= 0x1000 &&
  430                                     !(isdp->id_iobase & 0x300)) {
  431                                 printf (" on eisa slot %d",
  432                                         isdp->id_iobase >> 12);
  433                         } else {
  434                                 printf (" on isa");
  435                         }
  436                         printf("\n");
  437                         /*
  438                          * Check for conflicts again.  The driver may have
  439                          * changed *dvp.  We should weaken the early check
  440                          * since the driver may have been able to change
  441                          * *dvp to avoid conflicts if given a chance.  We
  442                          * already skip the early check for IRQs and force
  443                          * a check for IRQs in the next group of checks.
  444                          */
  445                         checkbits |= CC_IRQ;
  446                         if (haveseen_isadev(isdp, checkbits))
  447                                 return;
  448                         isdp->id_alive = id_alive;
  449                 }
  450                 (*dp->attach)(isdp);
  451                 if (isdp->id_irq) {
  452                         if (mp)
  453                                 INTRMASK(*mp, isdp->id_irq);
  454                         register_intr(ffs(isdp->id_irq) - 1, isdp->id_id,
  455                                       isdp->id_ri_flags, isdp->id_intr,
  456                                       mp, isdp->id_unit);
  457                         INTREN(isdp->id_irq);
  458                 }
  459         } else {
  460                 if (isdp->id_reconfig) {
  461                         (*dp->attach)(isdp); /* reconfiguration attach */
  462                 }
  463                 if (!last_alive) {
  464                         if (!isdp->id_reconfig) {
  465                                 printf("%s%d not found",
  466                                        dp->name, isdp->id_unit);
  467                                 if (isdp->id_iobase) {
  468                                         printf(" at 0x%x", isdp->id_iobase);
  469                                 }
  470                                 printf("\n");
  471                         }
  472                 }
  473                 else {
  474                         /* This code has not been tested.... */
  475                         if (isdp->id_irq) {
  476                                 INTRDIS(isdp->id_irq);
  477                                 unregister_intr(ffs(isdp->id_irq) - 1,
  478                                                 isdp->id_intr);
  479                                 if (mp)
  480                                         INTRUNMASK(*mp, isdp->id_irq);
  481                         }
  482                 }
  483         }
  484 }
  485 
  486 /*
  487  * Fill in default interrupt table (in case of spuruious interrupt
  488  * during configuration of kernel, setup interrupt control unit
  489  */
  490 void
  491 isa_defaultirq()
  492 {
  493         int i;
  494 
  495         /* icu vectors */
  496         for (i = 0; i < ICU_LEN; i++)
  497                 unregister_intr(i, (inthand2_t *)NULL);
  498 
  499         /* initialize 8259's */
  500         outb(IO_ICU1, 0x11);            /* reset; program device, four bytes */
  501         outb(IO_ICU1+1, NRSVIDT);       /* starting at this vector index */
  502         outb(IO_ICU1+1, 1<<2);          /* slave on line 2 */
  503 #ifdef AUTO_EOI_1
  504         outb(IO_ICU1+1, 2 | 1);         /* auto EOI, 8086 mode */
  505 #else
  506         outb(IO_ICU1+1, 1);             /* 8086 mode */
  507 #endif
  508         outb(IO_ICU1+1, 0xff);          /* leave interrupts masked */
  509         outb(IO_ICU1, 0x0a);            /* default to IRR on read */
  510         outb(IO_ICU1, 0xc0 | (3 - 1));  /* pri order 3-7, 0-2 (com2 first) */
  511 
  512         outb(IO_ICU2, 0x11);            /* reset; program device, four bytes */
  513         outb(IO_ICU2+1, NRSVIDT+8);     /* staring at this vector index */
  514         outb(IO_ICU2+1,2);              /* my slave id is 2 */
  515 #ifdef AUTO_EOI_2
  516         outb(IO_ICU2+1, 2 | 1);         /* auto EOI, 8086 mode */
  517 #else
  518         outb(IO_ICU2+1,1);              /* 8086 mode */
  519 #endif
  520         outb(IO_ICU2+1, 0xff);          /* leave interrupts masked */
  521         outb(IO_ICU2, 0x0a);            /* default to IRR on read */
  522 }
  523 
  524 static caddr_t  dma_bouncebuf[8];
  525 static u_int    dma_bouncebufsize[8];
  526 static u_int8_t dma_bounced = 0;
  527 static u_int8_t dma_busy = 0;           /* Used in isa_dmastart() */
  528 static u_int8_t dma_inuse = 0;          /* User for acquire/release */
  529 static u_int8_t        dma_auto_mode = 0;
  530 
  531 #define VALID_DMA_MASK (7)
  532 
  533 /* high byte of address is stored in this port for i-th dma channel */
  534 static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
  535 
  536 /*
  537  * Setup a DMA channel's bounce buffer.
  538  */
  539 void
  540 isa_dmainit(chan, bouncebufsize)
  541         int chan;
  542         u_int bouncebufsize;
  543 {
  544         void *buf;
  545 
  546 #ifdef DIAGNOSTIC
  547         if (chan & ~VALID_DMA_MASK)
  548                 panic("isa_dmainit: channel out of range");
  549 
  550         if (dma_bouncebuf[chan] != NULL)
  551                 panic("isa_dmainit: impossible request"); 
  552 #endif
  553 
  554         dma_bouncebufsize[chan] = bouncebufsize;
  555 
  556         /* Try malloc() first.  It works better if it works. */
  557         buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT);
  558         if (buf != NULL) {
  559                 if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) {
  560                         dma_bouncebuf[chan] = buf;
  561                         return;
  562                 }
  563                 free(buf, M_DEVBUF);
  564         }
  565         buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful,
  566                            1ul, chan & 4 ? 0x20000ul : 0x10000ul);
  567         if (buf == NULL)
  568                 printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize);
  569         else
  570                 dma_bouncebuf[chan] = buf;
  571 }
  572 
  573 /*
  574  * Register a DMA channel's usage.  Usually called from a device driver
  575  * in open() or during it's initialization.
  576  */
  577 int
  578 isa_dma_acquire(chan)
  579         int chan;
  580 {
  581 #ifdef DIAGNOSTIC
  582         if (chan & ~VALID_DMA_MASK)
  583                 panic("isa_dma_acquire: channel out of range");
  584 #endif
  585 
  586         if (dma_inuse & (1 << chan)) {
  587                 printf("isa_dma_acquire: channel %d already in use\n", chan);
  588                 return (EBUSY);
  589         }
  590         dma_inuse |= (1 << chan);
  591         dma_auto_mode &= ~(1 << chan);
  592 
  593         return (0);
  594 }
  595 
  596 /*
  597  * Unregister a DMA channel's usage.  Usually called from a device driver
  598  * during close() or during it's shutdown.
  599  */
  600 void
  601 isa_dma_release(chan)
  602         int chan;
  603 {
  604 #ifdef DIAGNOSTIC
  605         if (chan & ~VALID_DMA_MASK)
  606                 panic("isa_dma_release: channel out of range");
  607 
  608         if ((dma_inuse & (1 << chan)) == 0)
  609                 printf("isa_dma_release: channel %d not in use\n", chan);
  610 #endif
  611 
  612         if (dma_busy & (1 << chan)) {
  613                 dma_busy &= ~(1 << chan);
  614                 /* 
  615                  * XXX We should also do "dma_bounced &= (1 << chan);"
  616                  * because we are acting on behalf of isa_dmadone() which
  617                  * was not called to end the last DMA operation.  This does
  618                  * not matter now, but it may in the future.
  619                  */
  620         }
  621 
  622         dma_inuse &= ~(1 << chan);
  623         dma_auto_mode &= ~(1 << chan);
  624 }
  625 
  626 /*
  627  * isa_dmacascade(): program 8237 DMA controller channel to accept
  628  * external dma control by a board.
  629  */
  630 void isa_dmacascade(chan)
  631         int chan;
  632 {
  633 #ifdef DIAGNOSTIC
  634         if (chan & ~VALID_DMA_MASK)
  635                 panic("isa_dmacascade: channel out of range");
  636 #endif
  637 
  638         /* set dma channel mode, and set dma channel mode */
  639         if ((chan & 4) == 0) {
  640                 outb(DMA1_MODE, DMA37MD_CASCADE | chan);
  641                 outb(DMA1_SMSK, chan);
  642         } else {
  643                 outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3));
  644                 outb(DMA2_SMSK, chan & 3);
  645         }
  646 }
  647 
  648 /*
  649  * Query the progress of a transfer on a DMA channel.
  650  *
  651  * To avoid having to interrupt a transfer in progress, we sample
  652  * each of the high and low databytes twice, and apply the following
  653  * logic to determine the correct count.
  654  *
  655  * Reads are performed with interrupts disabled, thus it is to be
  656  * expected that the time between reads is very small.  At most
  657  * one rollover in the low count byte can be expected within the
  658  * four reads that are performed.
  659  *
  660  * There are three gaps in which a rollover can occur :
  661  *
  662  * - read low1 
  663  *              gap1
  664  * - read high1
  665  *              gap2
  666  * - read low2
  667  *              gap3
  668  * - read high2
  669  *
  670  * If a rollover occurs in gap1 or gap2, the low2 value will be
  671  * greater than the low1 value.  In this case, low2 and high2 are a
  672  * corresponding pair.
  673  *     
  674  * In any other case, low1 and high1 can be considered to be correct.
  675  *             
  676  * The function returns the number of bytes remaining in the transfer,
  677  * or -1 if the channel requested is not active.
  678  *
  679  */    
  680 int
  681 isa_dmastatus(int chan) 
  682 {      
  683          u_long  cnt = 0;
  684         int     ffport, waport, s;
  685          u_long  low, high, low2, high2;
  686  
  687          /* channel active? */
  688          if ((dma_inuse & (1 << chan)) == 0) {
  689                  printf("isa_dmastatus: channel %d not in use\n", chan);
  690                  return(-1);
  691          }
  692   
  693          /* 
  694          * do not print an error message if the chan is not busy,
  695          * it might just be a race condition.
  696          */
  697          if ( !(dma_busy & (1 << chan)) && !(dma_auto_mode & (1<<chan)) )
  698                  return(0); 
  699   
  700          if (chan < 4) {                 /* low DMA controller */
  701                  ffport = DMA1_FFC; 
  702                  waport = DMA1_CHN(chan) + 1;
  703          } else {                        /* high DMA controller */
  704                  ffport = DMA2_FFC;
  705                  waport = DMA2_CHN(chan - 4) + 2;
  706          }       
  707   
  708          disable_intr();                  /* no interrupts Mr Jones! */
  709          outb(ffport, 0);                /* clear register LSB flipflop */
  710          low = inb(waport);
  711          high = inb(waport);
  712          outb(ffport, 0);                /* clear again (paranoia? */
  713          low2 = inb(waport);
  714          high2 = inb(waport);
  715          enable_intr();
  716                 
  717          /* now decide if a wrap has tried to skew our results */
  718          if (low >= low2)
  719                  cnt = low + (high << 8) ;
  720          else
  721                  cnt = low2 + (high2 << 8) ;
  722  
  723         cnt = (cnt + 1) & 0xffff ;
  724   
  725         if (chan >=4)   /* 16-bit chans transfer words */
  726                 cnt *= 2 ;
  727          return(cnt);
  728 }
  729 
  730 
  731 /*
  732  * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
  733  * problems by using a bounce buffer.
  734  */
  735 void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)
  736 {
  737         vm_offset_t phys;
  738         int waport;
  739         caddr_t newaddr;
  740 
  741 #ifdef DIAGNOSTIC
  742         if (chan & ~VALID_DMA_MASK)
  743                 panic("isa_dmastart: channel out of range");
  744 
  745         if ((chan < 4 && nbytes > (1<<16))
  746             || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1)))
  747                 panic("isa_dmastart: impossible request");
  748 #endif
  749         if ((dma_inuse & (1 << chan)) == 0)
  750                 printf("isa_dmastart: channel %d not acquired\n", chan);
  751 
  752     if (!(flags & B_RAW))
  753         if (dma_busy & (1 << chan))
  754                 printf("isa_dmastart: channel %d busy\n", chan);
  755 
  756         dma_busy |= (1 << chan);
  757 
  758         if (isa_dmarangecheck(addr, nbytes, chan)) {
  759                 if (dma_bouncebuf[chan] == NULL
  760                     || dma_bouncebufsize[chan] < nbytes)
  761                         panic("isa_dmastart: bad bounce buffer"); 
  762                 dma_bounced |= (1 << chan);
  763                 newaddr = dma_bouncebuf[chan];
  764 
  765                 /* copy bounce buffer on write */
  766                 if (!(flags & B_READ))
  767                         bcopy(addr, newaddr, nbytes);
  768                 addr = newaddr;
  769         }
  770 
  771         /* translate to physical */
  772         phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
  773 
  774         if (flags & B_RAW) 
  775                 dma_auto_mode |= (1 << chan);
  776         else
  777                 dma_auto_mode &= ~(1 << chan);
  778 
  779 
  780         if ((chan & 4) == 0) {
  781                 /*
  782                  * Program one of DMA channels 0..3.  These are
  783                  * byte mode channels.
  784                  */
  785                 /* set dma channel mode, and reset address ff */
  786 
  787                 /* If B_RAW flag is set, then use autoinitialise mode */
  788                 if (flags & B_RAW) {
  789                   if (flags & B_READ)
  790                         outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan);
  791                   else
  792                         outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan);
  793                 }
  794                 else
  795                 if (flags & B_READ)
  796                         outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan);
  797                 else
  798                         outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan);
  799                 outb(DMA1_FFC, 0);
  800 
  801                 /* send start address */
  802                 waport =  DMA1_CHN(chan);
  803                 outb(waport, phys);
  804                 outb(waport, phys>>8);
  805                 outb(dmapageport[chan], phys>>16);
  806 
  807                 /* send count */
  808                 outb(waport + 1, --nbytes);
  809                 outb(waport + 1, nbytes>>8);
  810 
  811                 /* unmask channel */
  812                 outb(DMA1_SMSK, chan);
  813         } else {
  814                 /*
  815                  * Program one of DMA channels 4..7.  These are
  816                  * word mode channels.
  817                  */
  818                 /* set dma channel mode, and reset address ff */
  819 
  820                 /* If B_RAW flag is set, then use autoinitialise mode */
  821                 if (flags & B_RAW) {
  822                   if (flags & B_READ)
  823                         outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3));
  824                   else
  825                         outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3));
  826                 }
  827                 else
  828                 if (flags & B_READ)
  829                         outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
  830                 else
  831                         outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
  832                 outb(DMA2_FFC, 0);
  833 
  834                 /* send start address */
  835                 waport = DMA2_CHN(chan - 4);
  836                 outb(waport, phys>>1);
  837                 outb(waport, phys>>9);
  838                 outb(dmapageport[chan], phys>>16);
  839 
  840                 /* send count */
  841                 nbytes >>= 1;
  842                 outb(waport + 2, --nbytes);
  843                 outb(waport + 2, nbytes>>8);
  844 
  845                 /* unmask channel */
  846                 outb(DMA2_SMSK, chan & 3);
  847         }
  848 }
  849 
  850 /*
  851  * this stops the dma channel and returns the residual count
  852  * derived calling isa_dmastatus
  853  */    
  854 int isa_dmastop(int chan)
  855 {
  856      if ( !(dma_inuse & (1 << chan)) )
  857         printf("isa_dmastop: channel %d not acquired\n", chan);
  858      if ( ! (dma_busy & (1 << chan))  &&
  859          ! (dma_auto_mode & (1 << chan)) )
  860         printf("isa_dmastop: channel %d not active\n", chan);
  861      if ( chan & 4 )
  862         outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */);
  863      else   
  864         outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */);
  865      return isa_dmastatus(chan);
  866 }      
  867 
  868 void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)
  869 {  
  870 #ifdef DIAGNOSTIC
  871         if (chan & ~VALID_DMA_MASK)
  872                 panic("isa_dmadone: channel out of range");
  873 
  874         if ((dma_inuse & (1 << chan)) == 0)
  875                 printf("isa_dmadone: channel %d not acquired\n", chan);
  876 #endif
  877 
  878         if ( ! (dma_busy & (1 << chan))  &&
  879              ! (dma_auto_mode & (1 << chan)) )
  880                 printf("isa_dmadone: channel %d not active\n", chan);
  881 
  882         if (dma_bounced & (1 << chan)) {
  883                 /* copy bounce buffer on read */
  884                 if (flags & B_READ)
  885                         bcopy(dma_bouncebuf[chan], addr, nbytes);
  886 
  887                 dma_bounced &= ~(1 << chan);
  888         }
  889         dma_busy &= ~(1 << chan);
  890 }
  891 
  892 /*
  893  * Check for problems with the address range of a DMA transfer
  894  * (non-contiguous physical pages, outside of bus address space,
  895  * crossing DMA page boundaries).
  896  * Return true if special handling needed.
  897  */
  898 
  899 static int
  900 isa_dmarangecheck(caddr_t va, u_int length, int chan) {
  901         vm_offset_t phys, priorpage = 0, endva;
  902         u_int dma_pgmsk = (chan & 4) ?  ~(128*1024-1) : ~(64*1024-1);
  903 
  904         endva = (vm_offset_t)round_page(va + length);
  905         for (; va < (caddr_t) endva ; va += PAGE_SIZE) {
  906                 phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
  907 #define ISARAM_END      RAM_END
  908                 if (phys == 0)
  909                         panic("isa_dmacheck: no physical page present");
  910                 if (phys >= ISARAM_END)
  911                         return (1);
  912                 if (priorpage) {
  913                         if (priorpage + PAGE_SIZE != phys)
  914                                 return (1);
  915                         /* check if crossing a DMA page boundary */
  916                         if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk)
  917                                 return (1);
  918                 }
  919                 priorpage = phys;
  920         }
  921         return (0);
  922 }
  923 
  924 #define NMI_PARITY (1 << 7)
  925 #define NMI_IOCHAN (1 << 6)
  926 #define ENMI_WATCHDOG (1 << 7)
  927 #define ENMI_BUSTIMER (1 << 6)
  928 #define ENMI_IOSTATUS (1 << 5)
  929 
  930 /*
  931  * Handle a NMI, possibly a machine check.
  932  * return true to panic system, false to ignore.
  933  */
  934 int
  935 isa_nmi(cd)
  936         int cd;
  937 {
  938         int isa_port = inb(0x61);
  939         int eisa_port = inb(0x461);
  940 
  941         if (isa_port & NMI_PARITY)
  942                 panic("RAM parity error, likely hardware failure.");
  943 
  944         if (isa_port & NMI_IOCHAN)
  945                 panic("I/O channel check, likely hardware failure.");
  946 
  947         /*
  948          * On a real EISA machine, this will never happen.  However it can
  949          * happen on ISA machines which implement XT style floating point
  950          * error handling (very rare).  Save them from a meaningless panic.
  951          */
  952         if (eisa_port == 0xff)
  953                 return(0);
  954 
  955         if (eisa_port & ENMI_WATCHDOG)
  956                 panic("EISA watchdog timer expired, likely hardware failure.");
  957 
  958         if (eisa_port & ENMI_BUSTIMER)
  959                 panic("EISA bus timeout, likely hardware failure.");
  960 
  961         if (eisa_port & ENMI_IOSTATUS)
  962                 panic("EISA I/O port status error.");
  963 
  964         printf("\nNMI ISA %x, EISA %x\n", isa_port, eisa_port);
  965         return(0);
  966 }
  967 
  968 /*
  969  * Caught a stray interrupt, notify
  970  */
  971 static void
  972 isa_strayintr(d)
  973         int d;
  974 {
  975 
  976         /* DON'T BOTHER FOR NOW! */
  977         /* for some reason, we get bursts of intr #7, even if not enabled! */
  978         /*
  979          * Well the reason you got bursts of intr #7 is because someone
  980          * raised an interrupt line and dropped it before the 8259 could
  981          * prioritize it.  This is documented in the intel data book.  This
  982          * means you have BAD hardware!  I have changed this so that only
  983          * the first 5 get logged, then it quits logging them, and puts
  984          * out a special message. rgrimes 3/25/1993
  985          */
  986         /*
  987          * XXX TODO print a different message for #7 if it is for a
  988          * glitch.  Glitches can be distinguished from real #7's by
  989          * testing that the in-service bit is _not_ set.  The test
  990          * must be done before sending an EOI so it can't be done if
  991          * we are using AUTO_EOI_1.
  992          */
  993         if (intrcnt[NR_DEVICES + d] <= 5)
  994                 log(LOG_ERR, "stray irq %d\n", d);
  995         if (intrcnt[NR_DEVICES + d] == 5)
  996                 log(LOG_CRIT,
  997                     "too many stray irq %d's; not logging any more\n", d);
  998 }
  999 
 1000 /*
 1001  * Find the highest priority enabled display device.  Since we can't
 1002  * distinguish display devices from ttys, depend on display devices
 1003  * being sensitive and before sensitive non-display devices (if any)
 1004  * in isa_devtab_tty.
 1005  *
 1006  * XXX we should add capability flags IAMDISPLAY and ISUPPORTCONSOLES.
 1007  */
 1008 struct isa_device *
 1009 find_display()
 1010 {
 1011         struct isa_device *dvp;
 1012 
 1013         for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++)
 1014                 if (dvp->id_driver->sensitive_hw && dvp->id_enabled)
 1015                         return (dvp);
 1016         return (NULL);
 1017 }
 1018 
 1019 /*
 1020  * find an ISA device in a given isa_devtab_* table, given
 1021  * the table to search, the expected id_driver entry, and the unit number.
 1022  *
 1023  * this function is defined in isa_device.h, and this location is debatable;
 1024  * i put it there because it's useless w/o, and directly operates on
 1025  * the other stuff in that file.
 1026  *
 1027  */
 1028 
 1029 struct isa_device *find_isadev(table, driverp, unit)
 1030      struct isa_device *table;
 1031      struct isa_driver *driverp;
 1032      int unit;
 1033 {
 1034   if (driverp == NULL) /* sanity check */
 1035     return NULL;
 1036 
 1037   while ((table->id_driver != driverp) || (table->id_unit != unit)) {
 1038     if (table->id_driver == 0)
 1039       return NULL;
 1040 
 1041     table++;
 1042   }
 1043 
 1044   return table;
 1045 }
 1046 
 1047 /*
 1048  * Return a bitmap of the current interrupt requests.  This is 8259-specific
 1049  * and is only suitable for use at probe time.
 1050  */
 1051 u_int
 1052 isa_irq_pending()
 1053 {
 1054         u_char irr1;
 1055         u_char irr2;
 1056 
 1057         irr1 = inb(IO_ICU1);
 1058         irr2 = inb(IO_ICU2);
 1059         return ((irr2 << 8) | irr1);
 1060 }
 1061 
 1062 int
 1063 update_intr_masks(void)
 1064 {
 1065         int intr, n=0;
 1066         u_int mask,*maskptr;
 1067 
 1068         for (intr=0; intr < ICU_LEN; intr ++) {
 1069                 if (intr==2) continue;
 1070                 maskptr = intr_mptr[intr];
 1071                 if (!maskptr) continue;
 1072                 *maskptr |= 1 << intr;
 1073                 mask = *maskptr;
 1074                 if (mask != intr_mask[intr]) {
 1075 #if 0
 1076                         printf ("intr_mask[%2d] old=%08x new=%08x ptr=%p.\n",
 1077                                 intr, intr_mask[intr], mask, maskptr);
 1078 #endif
 1079                         intr_mask[intr]=mask;
 1080                         n++;
 1081                 }
 1082 
 1083         }
 1084         return (n);
 1085 }
 1086 
 1087 int
 1088 register_intr(intr, device_id, flags, handler, maskptr, unit)
 1089         int     intr;
 1090         int     device_id;
 1091         u_int   flags;
 1092         inthand2_t *handler;
 1093         u_int   *maskptr;
 1094         int     unit;
 1095 {
 1096         char    *cp;
 1097         u_long  ef;
 1098         int     id;
 1099         u_int   mask = (maskptr ? *maskptr : 0);
 1100 
 1101         if ((u_int)intr >= ICU_LEN || intr == 2
 1102             || (u_int)device_id >= NR_DEVICES)
 1103                 return (EINVAL);
 1104         if (intr_handler[intr] != isa_strayintr)
 1105                 return (EBUSY);
 1106         ef = read_eflags();
 1107         disable_intr();
 1108         intr_countp[intr] = &intrcnt[device_id];
 1109         intr_handler[intr] = handler;
 1110         intr_mptr[intr] = maskptr;
 1111         intr_mask[intr] = mask | (1 << intr);
 1112         intr_unit[intr] = unit;
 1113         setidt(ICU_OFFSET + intr,
 1114                flags & RI_FAST ? fastintr[intr] : slowintr[intr],
 1115                SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL));
 1116         write_eflags(ef);
 1117         for (cp = intrnames, id = 0; id <= device_id; id++)
 1118                 while (*cp++ != '\0')
 1119                         ;
 1120         if (cp > eintrnames)
 1121                 return (0);
 1122         if (intr < 10) {
 1123                 cp[-3] = intr + '';
 1124                 cp[-2] = ' ';
 1125         } else {
 1126                 cp[-3] = '1';
 1127                 cp[-2] = intr - 10 + '';
 1128         }
 1129         return (0);
 1130 }
 1131 
 1132 static void
 1133 register_imask(dvp, mask)
 1134         struct isa_device *dvp;
 1135         u_int   mask;
 1136 {
 1137         if (dvp->id_alive && dvp->id_irq) {
 1138                 int     intr;
 1139 
 1140                 intr = ffs(dvp->id_irq) - 1;
 1141                 intr_mask[intr] = mask | (1 <<intr);
 1142         }
 1143         (void) update_intr_masks();
 1144 }
 1145 
 1146 int
 1147 unregister_intr(intr, handler)
 1148         int     intr;
 1149         inthand2_t *handler;
 1150 {
 1151         u_long  ef;
 1152 
 1153         if ((u_int)intr >= ICU_LEN || handler != intr_handler[intr])
 1154                 return (EINVAL);
 1155         ef = read_eflags();
 1156         disable_intr();
 1157         intr_countp[intr] = &intrcnt[NR_DEVICES + intr];
 1158         intr_handler[intr] = isa_strayintr;
 1159         intr_mptr[intr] = NULL;
 1160         intr_mask[intr] = HWI_MASK | SWI_MASK;
 1161         intr_unit[intr] = intr;
 1162         setidt(ICU_OFFSET + intr, slowintr[intr], SDT_SYS386IGT, SEL_KPL,
 1163             GSEL(GCODE_SEL, SEL_KPL));
 1164         write_eflags(ef);
 1165         return (0);
 1166 }

Cache object: b477898cc95dc2418ac2bd05776fccf4


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