root/arch/i386/pci/piix.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. piix_init
  2. piix_getclink
  3. piix_get_intr
  4. piix_set_intr
  5. piix_get_trigger
  6. piix_set_trigger
  7. piix_pir_dump

    1 /*      $OpenBSD: piix.c,v 1.8 2006/09/19 11:06:34 jsg Exp $    */
    2 /*      $NetBSD: piix.c,v 1.1 1999/11/17 01:21:20 thorpej Exp $ */
    3 
    4 /*-
    5  * Copyright (c) 1999 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Copyright (c) 1999, by UCHIYAMA Yasushi
   43  * All rights reserved.
   44  *
   45  * Redistribution and use in source and binary forms, with or without
   46  * modification, are permitted provided that the following conditions
   47  * are met:
   48  * 1. Redistributions of source code must retain the above copyright
   49  *    notice, this list of conditions and the following disclaimer.
   50  * 2. The name of the developer may NOT be used to endorse or promote products
   51  *    derived from this software without specific prior written permission.
   52  * 
   53  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 
   54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 
   57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
   58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
   59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
   60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
   61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
   62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
   63  * SUCH DAMAGE. 
   64  */
   65 
   66 /*
   67  * Support for the Intel PIIX PCI-ISA bridge interrupt controller.
   68  */
   69 
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/device.h>
   73 #include <sys/malloc.h>
   74 
   75 #include <machine/intr.h>
   76 #include <machine/bus.h>
   77 
   78 #include <dev/pci/pcivar.h>
   79 #include <dev/pci/pcireg.h>
   80 #include <dev/pci/pcidevs.h>
   81 
   82 #include <i386/pci/pcibiosvar.h>
   83 #include <i386/pci/piixreg.h>
   84 #include <i386/pci/piixvar.h>
   85 
   86 #ifdef PIIX_DEBUG
   87 #define DPRINTF(arg) printf arg
   88 #else
   89 #define DPRINTF(arg)
   90 #endif
   91 
   92 int     piix_getclink(pciintr_icu_handle_t, int, int *);
   93 int     piix_get_intr(pciintr_icu_handle_t, int, int *);
   94 int     piix_set_intr(pciintr_icu_handle_t, int, int);
   95 #ifdef PIIX_DEBUG
   96 void    piix_pir_dump(struct piix_handle *);
   97 #endif
   98 
   99 const struct pciintr_icu piix_pci_icu = {
  100         piix_getclink,
  101         piix_get_intr,
  102         piix_set_intr,
  103         piix_get_trigger,
  104         piix_set_trigger,
  105 };
  106 
  107 int
  108 piix_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
  109     pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
  110 {
  111         struct piix_handle *ph;
  112 
  113         ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
  114         if (ph == NULL)
  115                 return (1);
  116 
  117         ph->ph_iot = iot;
  118         ph->ph_pc = pc;
  119         ph->ph_tag = tag;
  120 
  121         if (bus_space_map(iot, PIIX_REG_ELCR, PIIX_REG_ELCR_SIZE, 0,
  122             &ph->ph_elcr_ioh) != 0) {
  123                 free(ph, M_DEVBUF);
  124                 return (1);
  125         }
  126 
  127 #ifdef PIIX_DEBUG
  128         piix_pir_dump(ph);
  129 #endif
  130         *ptagp = &piix_pci_icu;
  131         *phandp = ph;
  132         return (0);
  133 }
  134 
  135 int
  136 piix_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
  137 {
  138         DPRINTF(("PIIX link value 0x%x: ", link));
  139 
  140         /* Pattern 1: simple. */
  141         if (PIIX_LEGAL_LINK(link - 1)) {
  142                 *clinkp = link - 1;
  143                 DPRINTF(("PIRQ %d (simple)\n", *clinkp));
  144                 return (0);
  145         }
  146 
  147         /* Pattern 2: configuration register offset */
  148         if (link >= 0x60 && link <= 0x63) {
  149                 *clinkp = link - 0x60;
  150                 DPRINTF(("PIRQ %d (register offset)\n", *clinkp));
  151                 return (0);
  152         }
  153 
  154         /* Pattern 3: configuration register offset, PIRQE# - PIRQH# */
  155         if (link >= 0x68 && link <= 0x6b) {
  156                 *clinkp = link - 0x64;
  157                 DPRINTF(("PIRQ %d (high register offset)\n", *clinkp));
  158                 return (0);
  159         }
  160 
  161         DPRINTF(("bogus IRQ selection source\n"));
  162         return (1);
  163 }
  164 
  165 int
  166 piix_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
  167 {
  168         struct piix_handle *ph = v;
  169         int shift, off;
  170         pcireg_t reg;
  171 
  172         if (PIIX_LEGAL_LINK(clink) == 0)
  173                 return (1);
  174 
  175         off = PIIX_CFG_PIRQ;
  176         if (clink > 3) {
  177                 off += 8;
  178                 clink -= 4;
  179         }
  180 
  181         reg = pci_conf_read(ph->ph_pc, ph->ph_tag, off);
  182         shift = clink << 3;
  183         if ((reg >> shift) & PIIX_CFG_PIRQ_NONE)
  184                 *irqp = I386_PCI_INTERRUPT_LINE_NO_CONNECTION;
  185         else
  186                 *irqp = PIIX_PIRQ(reg, clink);
  187 
  188         return (0);
  189 }
  190 
  191 int
  192 piix_set_intr(pciintr_icu_handle_t v, int clink, int irq)
  193 {
  194         struct piix_handle *ph = v;
  195         int shift, off;
  196         pcireg_t reg;
  197 
  198         if (PIIX_LEGAL_LINK(clink) == 0 || PIIX_LEGAL_IRQ(irq) == 0)
  199                 return (1);
  200 
  201         off = PIIX_CFG_PIRQ;
  202         if (clink > 3) {
  203                 off += 8;
  204                 clink -= 4;
  205         }
  206 
  207         reg = pci_conf_read(ph->ph_pc, ph->ph_tag, off);
  208         shift = clink << 3;
  209         reg &= ~((PIIX_CFG_PIRQ_NONE | PIIX_CFG_PIRQ_MASK) << shift);
  210         reg |= irq << shift;
  211         pci_conf_write(ph->ph_pc, ph->ph_tag, off, reg);
  212 
  213         return (0);
  214 }
  215 
  216 int
  217 piix_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
  218 {
  219         struct piix_handle *ph = v;
  220         int off, bit;
  221         u_int8_t elcr;
  222 
  223         if (PIIX_LEGAL_IRQ(irq) == 0)
  224                 return (1);
  225 
  226         off = (irq > 7) ? 1 : 0;
  227         bit = irq & 7;
  228 
  229         elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
  230         if (elcr & (1 << bit))
  231                 *triggerp = IST_LEVEL;
  232         else
  233                 *triggerp = IST_EDGE;
  234 
  235         return (0);
  236 }
  237 
  238 int
  239 piix_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
  240 {
  241         struct piix_handle *ph = v;
  242         int off, bit;
  243         u_int8_t elcr;
  244 
  245         if (PIIX_LEGAL_IRQ(irq) == 0)
  246                 return (1);
  247 
  248         off = (irq > 7) ? 1 : 0;
  249         bit = irq & 7;
  250 
  251         elcr = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, off);
  252         if (trigger == IST_LEVEL)
  253                 elcr |= (1 << bit);
  254         else
  255                 elcr &= ~(1 << bit);
  256         bus_space_write_1(ph->ph_iot, ph->ph_elcr_ioh, off, elcr);
  257 
  258         return (0);
  259 }
  260 
  261 #ifdef PIIX_DEBUG
  262 void
  263 piix_pir_dump(struct piix_handle *ph)
  264 {
  265         int i, irq;
  266         pcireg_t irqs = pci_conf_read(ph->ph_pc, ph->ph_tag, PIIX_CFG_PIRQ);
  267         u_int8_t elcr[2];
  268 
  269         elcr[0] = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, 0);
  270         elcr[1] = bus_space_read_1(ph->ph_iot, ph->ph_elcr_ioh, 1);
  271 
  272         for (i = 0; i < 8; i++) {
  273                 if (i == 4)
  274                         irqs = pci_conf_read(ph->ph_pc, ph->ph_tag,
  275                             PIIX_CFG_PIRQH);
  276 
  277                 irq = PIIX_PIRQ(irqs, i);
  278                 if (irq & PIIX_CFG_PIRQ_NONE)
  279                         printf("PIIX PIRQ %d: irq none (0x%x)\n", i, irq);
  280                 else
  281                         printf("PIIX PIRQ %d: irq %d\n", i, irq);
  282         }
  283 
  284         printf("PIIX irq:");
  285         for (i = 0; i < 16; i++)
  286                 printf(" %2d", i);
  287         printf("\n");
  288         printf(" trigger:");
  289         for (i = 0; i < 16; i++)
  290                 printf("  %c", (elcr[(i & 8) ? 1 : 0] & (1 << (i & 7))) ?
  291                        'L' : 'E');
  292         printf("\n");
  293 }
  294 #endif /* PIIX_DEBUG */

/* [<][>][^][v][top][bottom][index][help] */