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/mvme/vme_two.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: vme_two.c,v 1.9 2021/12/05 07:21:59 msaitoh Exp $      */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Steve C. Woodford.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * VME support specific to the VMEchip2 found on all high-end MVME boards
   34  */
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: vme_two.c,v 1.9 2021/12/05 07:21:59 msaitoh Exp $");
   38 
   39 #include "vmetwo.h"
   40 
   41 #include <sys/param.h>
   42 #include <sys/kernel.h>
   43 #include <sys/systm.h>
   44 #include <sys/device.h>
   45 
   46 #include <sys/cpu.h>
   47 #include <sys/bus.h>
   48 
   49 #include <dev/vme/vmereg.h>
   50 #include <dev/vme/vmevar.h>
   51 
   52 #include <dev/mvme/mvmebus.h>
   53 #include <dev/mvme/vme_tworeg.h>
   54 #include <dev/mvme/vme_twovar.h>
   55 
   56 void vmetwo_master_range(struct vmetwo_softc *, int, struct mvmebus_range *);
   57 void vmetwo_slave_range(struct vmetwo_softc *, int, vme_am_t,
   58         struct mvmebus_range *);
   59 
   60 /* ARGSUSED */
   61 void
   62 vmetwo_init(struct vmetwo_softc *sc)
   63 {
   64         u_int32_t reg;
   65         int i;
   66 
   67         /* Initialise stuff for the common mvmebus front-end */
   68         sc->sc_mvmebus.sc_chip = sc;
   69         sc->sc_mvmebus.sc_nmasters = VME2_NMASTERS;
   70         sc->sc_mvmebus.sc_masters = &sc->sc_master[0];
   71         sc->sc_mvmebus.sc_nslaves = VME2_NSLAVES;
   72         sc->sc_mvmebus.sc_slaves = &sc->sc_slave[0];
   73         sc->sc_mvmebus.sc_intr_establish = vmetwo_intr_establish;
   74         sc->sc_mvmebus.sc_intr_disestablish = vmetwo_intr_disestablish;
   75 
   76         /* Initialise interrupts */
   77         vmetwo_intr_init(sc);
   78 
   79         reg = vme2_lcsr_read(sc, VME2LCSR_BOARD_CONTROL);
   80         printf(": Type 2 VMEchip, scon jumper %s\n",
   81             (reg & VME2_BOARD_CONTROL_SCON) ? "enabled" : "disabled");
   82 
   83         /*
   84          * Figure out what bits of the VMEbus we can access.
   85          * First record the `fixed' maps (if they're enabled)
   86          */
   87         reg = vme2_lcsr_read(sc, VME2LCSR_IO_CONTROL);
   88         if (reg & VME2_IO_CONTROL_I1EN) {
   89                 /* This range is fixed to A16, DATA */
   90                 sc->sc_master[0].vr_am = VME_AM_A16 | MVMEBUS_AM_CAP_DATA;
   91 
   92                 /* However, SUPER/USER is selectable... */
   93                 if (reg & VME2_IO_CONTROL_I1SU)
   94                         sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_SUPER;
   95                 else
   96                         sc->sc_master[0].vr_am |= MVMEBUS_AM_CAP_USER;
   97 
   98                 /* As is the datasize */
   99                 sc->sc_master[0].vr_datasize = VME_D32 | VME_D16;
  100                 if (reg & VME2_IO_CONTROL_I1D16)
  101                         sc->sc_master[0].vr_datasize &= ~VME_D32;
  102 
  103                 sc->sc_master[0].vr_locstart = VME2_IO0_LOCAL_START;
  104                 sc->sc_master[0].vr_mask = VME2_IO0_MASK;
  105                 sc->sc_master[0].vr_vmestart = VME2_IO0_VME_START;
  106                 sc->sc_master[0].vr_vmeend = VME2_IO0_VME_END;
  107         } else
  108                 sc->sc_master[0].vr_am = MVMEBUS_AM_DISABLED;
  109 
  110         if (reg & VME2_IO_CONTROL_I2EN) {
  111                 /* These two ranges are fixed to A24D16 and A32D16 */
  112                 sc->sc_master[1].vr_am = VME_AM_A24;
  113                 sc->sc_master[1].vr_datasize = VME_D16;
  114                 sc->sc_master[2].vr_am = VME_AM_A32;
  115                 sc->sc_master[2].vr_datasize = VME_D16;
  116 
  117                 /* However, SUPER/USER is selectable */
  118                 if (reg & VME2_IO_CONTROL_I2SU) {
  119                         sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_SUPER;
  120                         sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_SUPER;
  121                 } else {
  122                         sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_USER;
  123                         sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_USER;
  124                 }
  125 
  126                 /* As is PROGRAM/DATA */
  127                 if (reg & VME2_IO_CONTROL_I2PD) {
  128                         sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_PROG;
  129                         sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_PROG;
  130                 } else {
  131                         sc->sc_master[1].vr_am |= MVMEBUS_AM_CAP_DATA;
  132                         sc->sc_master[2].vr_am |= MVMEBUS_AM_CAP_DATA;
  133                 }
  134 
  135                 sc->sc_master[1].vr_locstart = VME2_IO1_LOCAL_START;
  136                 sc->sc_master[1].vr_mask = VME2_IO1_MASK;
  137                 sc->sc_master[1].vr_vmestart = VME2_IO1_VME_START;
  138                 sc->sc_master[1].vr_vmeend = VME2_IO1_VME_END;
  139 
  140                 sc->sc_master[2].vr_locstart = VME2_IO2_LOCAL_START;
  141                 sc->sc_master[2].vr_mask = VME2_IO2_MASK;
  142                 sc->sc_master[2].vr_vmestart = VME2_IO2_VME_START;
  143                 sc->sc_master[2].vr_vmeend = VME2_IO2_VME_END;
  144         } else {
  145                 sc->sc_master[1].vr_am = MVMEBUS_AM_DISABLED;
  146                 sc->sc_master[2].vr_am = MVMEBUS_AM_DISABLED;
  147         }
  148 
  149         /*
  150          * Now read the programmable maps
  151          */
  152         for (i = 0; i < VME2_MASTER_WINDOWS; i++)
  153                 vmetwo_master_range(sc, i,
  154                     &(sc->sc_master[i + VME2_MASTER_PROG_START]));
  155 
  156         /* XXX: No A16 slave yet :XXX */
  157         sc->sc_slave[VME2_SLAVE_A16].vr_am = MVMEBUS_AM_DISABLED;
  158 
  159         for (i = 0; i < VME2_SLAVE_WINDOWS; i++) {
  160                 vmetwo_slave_range(sc, i, VME_AM_A32,
  161                     &sc->sc_slave[i + VME2_SLAVE_PROG_START]);
  162                 vmetwo_slave_range(sc, i, VME_AM_A24,
  163                     &sc->sc_slave[i + VME2_SLAVE_PROG_START + 2]);
  164         }
  165 
  166         mvmebus_attach(&sc->sc_mvmebus);
  167 }
  168 
  169 void
  170 vmetwo_master_range(struct vmetwo_softc *sc, int range, struct mvmebus_range *vr)
  171 {
  172         u_int32_t start, end, attr;
  173         u_int32_t reg;
  174 
  175         /*
  176          * First, check if the range is actually enabled...
  177          */
  178         reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ENABLE);
  179         if ((reg & VME2_MASTER_ENABLE(range)) == 0) {
  180                 vr->vr_am = MVMEBUS_AM_DISABLED;
  181                 return;
  182         }
  183 
  184         /*
  185          * Fetch and record the range's attributes
  186          */
  187         attr = vme2_lcsr_read(sc, VME2LCSR_MASTER_ATTR);
  188         attr >>= VME2_MASTER_ATTR_AM_SHIFT(range);
  189 
  190         /*
  191          * Fix up the datasizes available through this range
  192          */
  193         vr->vr_datasize = VME_D32 | VME_D16;
  194         if (attr & VME2_MASTER_ATTR_D16)
  195                 vr->vr_datasize &= ~VME_D32;
  196         attr &= VME2_MASTER_ATTR_AM_MASK;
  197 
  198         vr->vr_am = (attr & VME_AM_ADRSIZEMASK) | MVMEBUS_AM2CAP(attr);
  199         switch (vr->vr_am & VME_AM_ADRSIZEMASK) {
  200         case VME_AM_A32:
  201         default:
  202                 vr->vr_mask = 0xffffffffu;
  203                 break;
  204 
  205         case VME_AM_A24:
  206                 vr->vr_mask = 0x00ffffffu;
  207                 break;
  208 
  209         case VME_AM_A16:
  210                 vr->vr_mask = 0x0000ffffu;
  211                 break;
  212         }
  213 
  214         /*
  215          * XXX
  216          * It would be nice if users of the MI VMEbus code could pass down
  217          * whether they can tolerate Write-Posting to their device(s).
  218          * XXX
  219          */
  220 
  221         /*
  222          * Fetch the local-bus start and end addresses for the range
  223          */
  224         reg = vme2_lcsr_read(sc, VME2LCSR_MASTER_ADDRESS(range));
  225         start = (reg & VME2_MAST_ADDRESS_START_MASK);
  226         start <<= VME2_MAST_ADDRESS_START_SHIFT;
  227         vr->vr_locstart = start & ~vr->vr_mask;
  228         end = (reg & VME2_MAST_ADDRESS_END_MASK);
  229         end <<= VME2_MAST_ADDRESS_END_SHIFT;
  230         end |= 0xffffu;
  231         end += 1;
  232 
  233         /*
  234          * Local->VMEbus map '4' has optional translation bits, so
  235          * the VMEbus start and end addresses may need to be adjusted.
  236          */
  237         if (range == 3 && (reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS))!=0) {
  238                 uint32_t addr, sel, len = end - start;
  239 
  240                 reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS);
  241                 reg &= VME2_MAST4_TRANS_SELECT_MASK;
  242                 sel = reg << VME2_MAST4_TRANS_SELECT_SHIFT;
  243 
  244                 reg = vme2_lcsr_read(sc, VME2LCSR_MAST4_TRANS);
  245                 reg &= VME2_MAST4_TRANS_ADDRESS_MASK;
  246                 addr = reg << VME2_MAST4_TRANS_ADDRESS_SHIFT;
  247 
  248                 start = (addr & sel) | (start & (~sel));
  249                 end = start + len;
  250                 vr->vr_mask &= len - 1;
  251         }
  252 
  253         /* XXX Deal with overlap of onboard RAM address space */
  254         /* XXX Then again, 167-Bug warns about this at setup time ... */
  255 
  256         /*
  257          * Fixup the addresses this range corresponds to
  258          */
  259         vr->vr_vmestart = start & vr->vr_mask;
  260         vr->vr_vmeend = (end - 1) & vr->vr_mask;
  261 }
  262 
  263 void
  264 vmetwo_slave_range(struct vmetwo_softc *sc, int range, vme_am_t am, struct mvmebus_range *vr)
  265 {
  266         u_int32_t reg;
  267 
  268         /*
  269          * First, check if the range is actually enabled.
  270          * Note that bit 1 of `range' is used to indicte if we're
  271          * looking for an A24 range (set) or an A32 range (clear).
  272          */
  273         reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL);
  274 
  275         if (am == VME_AM_A32 && (reg & VME2_SLAVE_AMSEL_A32(range))) {
  276                 vr->vr_am = VME_AM_A32;
  277                 vr->vr_mask = 0xffffffffu;
  278         } else
  279         if (am == VME_AM_A24 && (reg & VME2_SLAVE_AMSEL_A24(range))) {
  280                 vr->vr_am = VME_AM_A24;
  281                 vr->vr_mask = 0x00ffffffu;
  282         } else {
  283                 /* The range is not enabled */
  284                 vr->vr_am = MVMEBUS_AM_DISABLED;
  285                 return;
  286         }
  287 
  288         if ((reg & VME2_SLAVE_AMSEL_DAT(range)) != 0)
  289                 vr->vr_am |= MVMEBUS_AM_CAP_DATA;
  290 
  291         if ((reg & VME2_SLAVE_AMSEL_PGM(range)) != 0)
  292                 vr->vr_am |= MVMEBUS_AM_CAP_PROG;
  293 
  294         if ((reg & VME2_SLAVE_AMSEL_USR(range)) != 0)
  295                 vr->vr_am |= MVMEBUS_AM_CAP_USER;
  296 
  297         if ((reg & VME2_SLAVE_AMSEL_SUP(range)) != 0)
  298                 vr->vr_am |= MVMEBUS_AM_CAP_SUPER;
  299 
  300         if ((reg & VME2_SLAVE_AMSEL_BLK(range)) != 0)
  301                 vr->vr_am |= MVMEBUS_AM_CAP_BLK;
  302 
  303         if ((reg & VME2_SLAVE_AMSEL_BLKD64(range)) != 0)
  304                 vr->vr_am |= MVMEBUS_AM_CAP_BLKD64;
  305 
  306         vr->vr_datasize = VME_D32 | VME_D16 | VME_D8;
  307 
  308         /*
  309          * Record the VMEbus start and end addresses of the slave image
  310          */
  311         reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_ADDRESS(range));
  312         vr->vr_vmestart = reg & VME2_SLAVE_ADDRESS_START_MASK;
  313         vr->vr_vmestart <<= VME2_SLAVE_ADDRESS_START_SHIFT;
  314         vr->vr_vmestart &= vr->vr_mask;
  315         vr->vr_vmeend = reg & VME2_SLAVE_ADDRESS_END_MASK;
  316         vr->vr_vmeend <<= VME2_SLAVE_ADDRESS_END_SHIFT;
  317         vr->vr_vmeend &= vr->vr_mask;
  318         vr->vr_vmeend |= 0xffffu;
  319 
  320         /*
  321          * Now figure out the local-bus address
  322          */
  323         reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_CTRL);
  324         if ((reg & VME2_SLAVE_CTRL_ADDER(range)) != 0) {
  325                 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range));
  326                 reg &= VME2_SLAVE_TRANS_ADDRESS_MASK;
  327                 reg <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT;
  328                 vr->vr_locstart = vr->vr_vmestart + reg;
  329         } else {
  330                 u_int32_t sel, addr;
  331 
  332                 reg = vme2_lcsr_read(sc, VME2LCSR_SLAVE_TRANS(range));
  333                 sel = reg & VME2_SLAVE_TRANS_SELECT_MASK;
  334                 sel <<= VME2_SLAVE_TRANS_SELECT_SHIFT;
  335                 addr = reg & VME2_SLAVE_TRANS_ADDRESS_MASK;
  336                 addr <<= VME2_SLAVE_TRANS_ADDRESS_SHIFT;
  337 
  338                 vr->vr_locstart = addr & sel;
  339                 vr->vr_locstart |= vr->vr_vmestart & (~sel);
  340         }
  341 }

Cache object: 361b3adaefd0184e629d2c812a44e8c7


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