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/pci/universe_pci.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 /* $NetBSD: universe_pci.c,v 1.5 2003/01/31 00:07:43 thorpej Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1999
    5  *      Matthias Drochner.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 /*
   30  * Common functions for PCI-VME-interfaces using the
   31  * Newbridge/Tundra Universe II chip (CA91C142).
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: universe_pci.c,v 1.5 2003/01/31 00:07:43 thorpej Exp $");
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/device.h>
   40 
   41 #include <dev/pci/pcireg.h>
   42 #include <dev/pci/pcivar.h>
   43 /*#include <dev/pci/pcidevs.h>*/
   44 
   45 #include <machine/bus.h>
   46 
   47 #include <dev/vme/vmereg.h>
   48 #include <dev/vme/vmevar.h>
   49 
   50 #include <dev/ic/universereg.h>
   51 #include <dev/pci/universe_pci_var.h>
   52 
   53 int univ_pci_intr __P((void *));
   54 
   55 #define read_csr_4(d, reg) \
   56   bus_space_read_4(d->csrt, d->csrh, offsetof(struct universereg, reg))
   57 #define write_csr_4(d, reg, val) \
   58   bus_space_write_4(d->csrt, d->csrh, offsetof(struct universereg, reg), val)
   59 
   60 #define _pso(i) offsetof(struct universereg, __CONCAT(pcislv, i))
   61 static int pcislvoffsets[8] = {
   62         _pso(0), _pso(1), _pso(2), _pso(3),
   63         _pso(4), _pso(5), _pso(6), _pso(7)
   64 };
   65 #undef _pso
   66 
   67 #define read_pcislv(d, idx, reg) \
   68   bus_space_read_4(d->csrt, d->csrh, \
   69    pcislvoffsets[idx] + offsetof(struct universe_pcislvimg, reg))
   70 #define write_pcislv(d, idx, reg, val) \
   71   bus_space_write_4(d->csrt, d->csrh, \
   72    pcislvoffsets[idx] + offsetof(struct universe_pcislvimg, reg), val)
   73 
   74 
   75 #define _vso(i) offsetof(struct universereg, __CONCAT(vmeslv, i))
   76 static int vmeslvoffsets[8] = {
   77         _vso(0), _vso(1), _vso(2), _vso(3),
   78         _vso(4), _vso(5), _vso(6), _vso(7)
   79 };
   80 #undef _vso
   81 
   82 #define read_vmeslv(d, idx, reg) \
   83   bus_space_read_4(d->csrt, d->csrh, \
   84    vmeslvoffsets[idx] + offsetof(struct universe_vmeslvimg, reg))
   85 #define write_vmeslv(d, idx, reg, val) \
   86   bus_space_write_4(d->csrt, d->csrh, \
   87    vmeslvoffsets[idx] + offsetof(struct universe_vmeslvimg, reg), val)
   88 
   89 int
   90 univ_pci_attach(d, pa, name, inthdl, intcookie)
   91         struct univ_pci_data *d;
   92         struct pci_attach_args *pa;
   93         const char *name;
   94         void (*inthdl) __P((void *, int, int));
   95         void *intcookie;
   96 {
   97         pci_chipset_tag_t pc = pa->pa_pc;
   98         pci_intr_handle_t ih;
   99         const char *intrstr = NULL;
  100         u_int32_t reg;
  101         int i;
  102 
  103         d->pc = pc;
  104         strncpy(d->devname, name, sizeof(d->devname));
  105         d->devname[sizeof(d->devname) - 1] = '\0';
  106 
  107         if (pci_mapreg_map(pa, 0x10,
  108                            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
  109                            0, &d->csrt, &d->csrh, NULL, NULL) &&
  110             pci_mapreg_map(pa, 0x14,
  111                            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
  112                            0, &d->csrt, &d->csrh, NULL, NULL) &&
  113             pci_mapreg_map(pa, 0x10,
  114                            PCI_MAPREG_TYPE_IO,
  115                            0, &d->csrt, &d->csrh, NULL, NULL) &&
  116             pci_mapreg_map(pa, 0x14,
  117                            PCI_MAPREG_TYPE_IO,
  118                            0, &d->csrt, &d->csrh, NULL, NULL))
  119                 return (-1);
  120 
  121         /* name sure the chip is in a sane state */
  122         write_csr_4(d, lint_en, 0); /* mask all PCI interrupts */
  123         write_csr_4(d, vint_en, 0); /* mask all VME interrupts */
  124         write_csr_4(d, dgcs, 0x40000000); /* stop DMA activity */
  125         for (i = 0; i < 8; i++) {
  126                 univ_pci_unmapvme(d, i);
  127                 univ_pci_unmappci(d, i);
  128         }
  129         write_csr_4(d, slsi, 0); /* disable "special PCI slave image" */
  130 
  131         /* enable DMA */
  132         pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
  133             pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
  134             PCI_COMMAND_MASTER_ENABLE);
  135 
  136         reg = read_csr_4(d, misc_ctl);
  137         aprint_normal("%s: ", name);
  138         if (reg & 0x00020000) /* SYSCON */
  139                 aprint_normal("VME bus controller, ");
  140         reg = read_csr_4(d, mast_ctl);
  141         aprint_normal("requesting at VME bus level %d\n", (reg >> 22) & 3);
  142 
  143         /* Map and establish the PCI interrupt. */
  144         if (pci_intr_map(pa, &ih)) {
  145                 aprint_error("%s: couldn't map interrupt\n", name);
  146                 return (-1);
  147         }
  148         intrstr = pci_intr_string(pc, ih);
  149         /*
  150          * Use a low interrupt level (the lowest?).
  151          * We will raise before calling a subdevice's handler.
  152          */
  153         d->ih = pci_intr_establish(pc, ih, IPL_BIO, univ_pci_intr, d);
  154         if (d->ih == NULL) {
  155                 aprint_error("%s: couldn't establish interrupt", name);
  156                 if (intrstr != NULL)
  157                         aprint_normal(" at %s", intrstr);
  158                 aprint_normal("\n");
  159                 return (-1);
  160         }
  161         aprint_normal("%s: interrupting at %s\n", name, intrstr);
  162 
  163         /* handle all VME interrupts (XXX should be configurable) */
  164         d->vmeinthandler = inthdl;
  165         d->vmeintcookie = intcookie;
  166         write_csr_4(d, lint_stat, 0x00ff37ff); /* ack all pending IRQs */
  167         write_csr_4(d, lint_en, 0x000000fe); /* enable VME IRQ 1..7 */
  168 
  169         return (0);
  170 }
  171 
  172 int
  173 univ_pci_mapvme(d, wnd, vmebase, len, am, datawidth, pcibase)
  174         struct univ_pci_data *d;
  175         int wnd;
  176         vme_addr_t vmebase;
  177         u_int32_t len;
  178         vme_am_t am;
  179         vme_datasize_t datawidth;
  180         u_int32_t pcibase;
  181 {
  182         u_int32_t ctl = 0x80000000;
  183 
  184         switch (am & VME_AM_ADRSIZEMASK) {
  185         case VME_AM_A32:
  186                 ctl |= 0x00020000;
  187                 break;
  188         case VME_AM_A24:
  189                 ctl |= 0x00010000;
  190                 break;
  191         case VME_AM_A16:
  192                 break;
  193         default:
  194                 return (EINVAL);
  195         }
  196         if (am & VME_AM_SUPER)
  197                 ctl |= 0x00001000;
  198         if ((am & VME_AM_MODEMASK) == VME_AM_PRG)
  199                 ctl |= 0x00004000;
  200         if (datawidth & VME_D32)
  201                 ctl |= 0x00800000;
  202         else if (datawidth & VME_D16)
  203                 ctl |= 0x00400000;
  204         else if (!(datawidth & VME_D8))
  205                 return (EINVAL);
  206 
  207 #ifdef UNIV_DEBUG
  208         printf("%s: wnd %d, map VME %x-%x to %x, ctl=%x\n",
  209                d->devname, wnd, vmebase, vmebase + len, pcibase, ctl);
  210 #endif
  211 
  212         write_pcislv(d, wnd, lsi_bs, pcibase);
  213         write_pcislv(d, wnd, lsi_bd, pcibase + len);
  214         write_pcislv(d, wnd, lsi_to, vmebase - pcibase);
  215         write_pcislv(d, wnd, lsi_ctl, ctl);
  216         return (0);
  217 }
  218 
  219 void
  220 univ_pci_unmapvme(d, wnd)
  221         struct univ_pci_data *d;
  222         int wnd;
  223 {
  224 #ifdef UNIV_DEBUG
  225         printf("%s: unmap VME wnd %d\n", d->devname, wnd);
  226 #endif
  227         write_pcislv(d, wnd, lsi_ctl, 0);
  228 }
  229 
  230 
  231 int
  232 univ_pci_mappci(d, wnd, pcibase, len, vmebase, am)
  233         struct univ_pci_data *d;
  234         int wnd;
  235         u_int32_t pcibase;
  236         u_int32_t len;
  237         vme_addr_t vmebase;
  238         vme_am_t am;
  239 {
  240         u_int32_t ctl = 0x80000000;
  241 
  242         switch (am & VME_AM_ADRSIZEMASK) {
  243         case VME_AM_A32:
  244                 ctl |= 0x00020000;
  245                 break;
  246         case VME_AM_A24:
  247                 ctl |= 0x00010000;
  248                 break;
  249         case VME_AM_A16:
  250                 break;
  251         default:
  252                 return (EINVAL);
  253         }
  254         if (am & VME_AM_SUPER)
  255                 ctl |= 0x00200000;
  256         else
  257                 ctl |= 0x00300000; /* both */
  258         if ((am & VME_AM_MODEMASK) == VME_AM_PRG)
  259                 ctl |= 0x00800000;
  260         else
  261                 ctl |= 0x00c00000; /* both */
  262 
  263 #ifdef UNIV_DEBUG
  264         printf("%s: wnd %d, map PCI %x-%x to %x, ctl=%x\n",
  265                d->devname, wnd, pcibase, pcibase + len, vmebase, ctl);
  266 #endif
  267 
  268         write_vmeslv(d, wnd, vsi_bs, vmebase);
  269         write_vmeslv(d, wnd, vsi_bd, vmebase + len);
  270         write_vmeslv(d, wnd, vsi_to, pcibase - vmebase);
  271         write_vmeslv(d, wnd, vsi_ctl, ctl);
  272         return (0);
  273 }
  274 
  275 void
  276 univ_pci_unmappci(d, wnd)
  277         struct univ_pci_data *d;
  278         int wnd;
  279 {
  280 #ifdef UNIV_DEBUG
  281         printf("%s: unmap PCI wnd %d\n", d->devname, wnd);
  282 #endif
  283         write_vmeslv(d, wnd, vsi_ctl, 0);
  284 }
  285 
  286 int
  287 univ_pci_vmebuserr(d, clear)
  288         struct univ_pci_data *d;
  289         int clear;
  290 {
  291         u_int32_t pcicsr;
  292 
  293         pcicsr = read_csr_4(d, pci_csr);
  294         if ((pcicsr & 0xf8000000) && clear)
  295                 write_csr_4(d, pci_csr, pcicsr | 0xf8000000);
  296         return (pcicsr & 0x08000000); /* target abort */
  297 }
  298 
  299 int
  300 univ_pci_intr(v)
  301         void *v;
  302 {
  303         struct univ_pci_data *d = v;
  304         u_int32_t intcsr;
  305         int i, vec;
  306 
  307         intcsr = read_csr_4(d, lint_stat) & 0xffffff;
  308         if (!intcsr)
  309                 return (0);
  310 
  311         /* ack everything */
  312         write_csr_4(d, lint_stat, intcsr);
  313 #ifdef UNIV_DEBUG
  314         printf("%s: intr, lint_stat=%x\n", d->devname, intcsr);
  315 #endif
  316         if (intcsr & 0x000000fe) { /* VME interrupt */
  317                 for (i = 7; i >= 1; i--) {
  318                         if (!(intcsr & (1 << i)))
  319                                 continue;
  320                         vec = read_csr_4(d, v_statid[i - 1]);
  321                         if (vec & 0x100) {
  322                                 printf("%s: err irq %d\n", d->devname, i);
  323                                 continue;
  324                         }
  325                         if (d->vmeinthandler)
  326                                 (*d->vmeinthandler)(d->vmeintcookie, i, vec);
  327                 }
  328         }
  329 
  330         return (1);
  331 }

Cache object: 7ae34e9cec99a32b6cfb1c2662a9bd5c


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