root/arch/i386/pci/opti82c700.c

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

DEFINITIONS

This source file includes following definitions.
  1. opti82c700_init
  2. opti82c700_addr
  3. opti82c700_getclink
  4. opti82c700_get_intr
  5. opti82c700_set_intr
  6. opti82c700_get_trigger
  7. opti82c700_set_trigger

    1 /*      $OpenBSD: opti82c700.c,v 1.7 2006/09/19 11:06:34 jsg Exp $      */
    2 /*      $NetBSD: opti82c700.c,v 1.2 2000/07/18 11:07:20 soda 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 Opti 82c700 FireStar 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/opti82c700reg.h>
   84 
   85 #ifdef FIRESTARDEBUG
   86 #define DPRINTF(arg)    printf arg
   87 #else
   88 #define DPRINTF(arg)
   89 #endif
   90 
   91 int     opti82c700_getclink(pciintr_icu_handle_t, int, int *);
   92 int     opti82c700_get_intr(pciintr_icu_handle_t, int, int *);
   93 int     opti82c700_set_intr(pciintr_icu_handle_t, int, int);
   94 int     opti82c700_get_trigger(pciintr_icu_handle_t, int, int *);
   95 int     opti82c700_set_trigger(pciintr_icu_handle_t, int, int);
   96 
   97 const struct pciintr_icu opti82c700_pci_icu = {
   98         opti82c700_getclink,
   99         opti82c700_get_intr,
  100         opti82c700_set_intr,
  101         opti82c700_get_trigger,
  102         opti82c700_set_trigger,
  103 };
  104 
  105 struct opti82c700_handle {
  106         pci_chipset_tag_t ph_pc;
  107         pcitag_t ph_tag;
  108 };
  109 
  110 int     opti82c700_addr(int, int *, int *);
  111 #ifdef FIRESTARDEBUG
  112 void    opti82c700_pir_dump(struct opti82c700_handle *);
  113 #endif
  114 
  115 int
  116 opti82c700_init(pci_chipset_tag_t pc, bus_space_tag_t iot, pcitag_t tag,
  117     pciintr_icu_tag_t *ptagp, pciintr_icu_handle_t *phandp)
  118 {
  119         struct opti82c700_handle *ph;
  120 
  121         ph = malloc(sizeof(*ph), M_DEVBUF, M_NOWAIT);
  122         if (ph == NULL)
  123                 return (1);
  124 
  125         ph->ph_pc = pc;
  126         ph->ph_tag = tag;
  127 #ifdef FIRESTARDEBUG
  128         opti82c700_pir_dump(ph);
  129 #endif
  130         *ptagp = &opti82c700_pci_icu;
  131         *phandp = ph;
  132         return (0);
  133 }
  134 
  135 int
  136 opti82c700_addr(int link, int *addrofs, int *ofs)
  137 {
  138         int regofs, src;
  139 
  140         regofs = FIRESTAR_PIR_REGOFS(link);
  141         src = FIRESTAR_PIR_SELECTSRC(link);
  142 
  143         switch (src) {
  144         case FIRESTAR_PIR_SELECT_NONE:
  145                 return (1);
  146 
  147         case FIRESTAR_PIR_SELECT_IRQ:
  148                 if (regofs < 0 || regofs > 7)
  149                         return (1);
  150                 *addrofs = FIRESTAR_CFG_INTR_IRQ + (regofs >> 2);
  151                 *ofs = (regofs & 3) << 3;
  152                 break;
  153 
  154         case FIRESTAR_PIR_SELECT_PIRQ:
  155                 /* FALLTHROUGH */
  156         case FIRESTAR_PIR_SELECT_BRIDGE:
  157                 if (regofs < 0 || regofs > 3)
  158                         return (1);
  159                 *addrofs = FIRESTAR_CFG_INTR_PIRQ;
  160                 *ofs = regofs << 2;
  161                 break;
  162 
  163         default:
  164                 return (1);
  165         }
  166 
  167         return (0);
  168 }
  169 
  170 int
  171 opti82c700_getclink(pciintr_icu_handle_t v, int link, int *clinkp)
  172 {
  173         DPRINTF(("FireStar link value 0x%x: ", link));
  174 
  175         switch (FIRESTAR_PIR_SELECTSRC(link)) {
  176         default:
  177                 DPRINTF(("bogus IRQ selection source\n"));
  178                 return (1);
  179         case FIRESTAR_PIR_SELECT_NONE:
  180                 DPRINTF(("No interrupt connection\n"));
  181                 return (1);
  182         case FIRESTAR_PIR_SELECT_IRQ:
  183                 DPRINTF(("FireStar IRQ pin"));
  184                 break;
  185         case FIRESTAR_PIR_SELECT_PIRQ:
  186                 DPRINTF(("FireStar PIO pin or Serial IRQ PIRQ#"));
  187                 break;
  188         case FIRESTAR_PIR_SELECT_BRIDGE:
  189                 DPRINTF(("FireBridge 1 INTx# pin"));
  190                 break;
  191         }
  192 
  193         DPRINTF((" REGOFST:%#x\n", FIRESTAR_PIR_REGOFS(link)));
  194         *clinkp = link;
  195 
  196         return (0);
  197 }
  198 
  199 int
  200 opti82c700_get_intr(pciintr_icu_handle_t v, int clink, int *irqp)
  201 {
  202         struct opti82c700_handle *ph = v;
  203         pcireg_t reg;
  204         int val, addrofs, ofs;
  205 
  206         if (opti82c700_addr(clink, &addrofs, &ofs))
  207                 return (1);
  208 
  209         reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  210         val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
  211 
  212         *irqp = (val == FIRESTAR_PIRQ_NONE) ?
  213             I386_PCI_INTERRUPT_LINE_NO_CONNECTION : val;
  214 
  215         return (0);
  216 }
  217 
  218 int
  219 opti82c700_set_intr(pciintr_icu_handle_t v, int clink, int irq)
  220 {
  221         struct opti82c700_handle *ph = v;
  222         int addrofs, ofs;
  223         pcireg_t reg;
  224 
  225         if (FIRESTAR_LEGAL_IRQ(irq) == 0)
  226                 return (1);
  227 
  228         if (opti82c700_addr(clink, &addrofs, &ofs))
  229                 return (1);
  230 
  231         reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  232         reg &= ~(FIRESTAR_CFG_PIRQ_MASK << ofs);
  233         reg |= (irq << ofs);
  234         pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
  235 
  236         return (0);
  237 }
  238 
  239 int
  240 opti82c700_get_trigger(pciintr_icu_handle_t v, int irq, int *triggerp)
  241 {
  242         struct opti82c700_handle *ph = v;
  243         int i, val, addrofs, ofs;
  244         pcireg_t reg;
  245 
  246         if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
  247                 /* ISA IRQ? */
  248                 *triggerp = IST_EDGE;
  249                 return (0);
  250         }
  251 
  252         /*
  253          * Search PCIDV1 registers.
  254          */
  255         for (i = 0; i < 8; i++) {
  256                 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
  257                     i), &addrofs, &ofs);
  258                 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  259                 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
  260                 if (val != irq)
  261                         continue;
  262                 val = ((reg >> ofs) >> FIRESTAR_TRIGGER_SHIFT) &
  263                     FIRESTAR_TRIGGER_MASK;
  264                 *triggerp = val ? IST_LEVEL : IST_EDGE;
  265                 return (0);
  266         }
  267 
  268         /*
  269          * Search PIO PCIIRQ.
  270          */
  271         for (i = 0; i < 4; i++) {
  272                 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
  273                     i), &addrofs, &ofs);
  274                 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  275                 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
  276                 if (val != irq)
  277                         continue;
  278                 *triggerp = IST_LEVEL;
  279                 return (0);
  280         }
  281 
  282         return (1);
  283 }
  284 
  285 int
  286 opti82c700_set_trigger(pciintr_icu_handle_t v, int irq, int trigger)
  287 {
  288         struct opti82c700_handle *ph = v;
  289         int i, val, addrofs, ofs;
  290         pcireg_t reg;
  291 
  292         if (FIRESTAR_LEGAL_IRQ(irq) == 0) {
  293                 /* ISA IRQ? */
  294                 return ((trigger != IST_LEVEL) ? 0 : 1);
  295         }
  296 
  297         /*
  298          * Search PCIDV1 registers.
  299          */
  300         for (i = 0; i < 8; i++) {
  301                 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_IRQ,
  302                     i), &addrofs, &ofs);
  303                 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  304                 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
  305                 if (val != irq)
  306                         continue;
  307                 if (trigger == IST_LEVEL)
  308                         reg |= (FIRESTAR_TRIGGER_MASK <<
  309                             (FIRESTAR_TRIGGER_SHIFT + ofs));
  310                 else
  311                         reg &= ~(FIRESTAR_TRIGGER_MASK <<
  312                             (FIRESTAR_TRIGGER_SHIFT + ofs));
  313                 pci_conf_write(ph->ph_pc, ph->ph_tag, addrofs, reg);
  314                 return (0);
  315         }
  316 
  317         /*
  318          * Search PIO PCIIRQ.
  319          */
  320         for (i = 0; i < 4; i++) {
  321                 opti82c700_addr(FIRESTAR_PIR_MAKELINK(FIRESTAR_PIR_SELECT_PIRQ,
  322                     i), &addrofs, &ofs);
  323                 reg = pci_conf_read(ph->ph_pc, ph->ph_tag, addrofs);
  324                 val = (reg >> ofs) & FIRESTAR_CFG_PIRQ_MASK;
  325                 if (val != irq)
  326                         continue;
  327                 return (trigger == IST_LEVEL ? 0 : 1);
  328         }
  329 
  330         return (1);
  331 }

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