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/qbus/uba.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: uba.c,v 1.83 2021/08/07 16:19:15 thorpej Exp $    */
    2 /*
    3  * Copyright (c) 1982, 1986 The Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. Neither the name of the University nor the names of its contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  *      @(#)uba.c       7.10 (Berkeley) 12/16/90
   31  *      @(#)autoconf.c  7.20 (Berkeley) 5/9/91
   32  */
   33 
   34 /*
   35  * Copyright (c) 1996 Jonathan Stone.
   36  * Copyright (c) 1994, 1996 Ludd, University of Lule}, Sweden.
   37  * All rights reserved.
   38  *
   39  * Redistribution and use in source and binary forms, with or without
   40  * modification, are permitted provided that the following conditions
   41  * are met:
   42  * 1. Redistributions of source code must retain the above copyright
   43  *    notice, this list of conditions and the following disclaimer.
   44  * 2. Redistributions in binary form must reproduce the above copyright
   45  *    notice, this list of conditions and the following disclaimer in the
   46  *    documentation and/or other materials provided with the distribution.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)uba.c       7.10 (Berkeley) 12/16/90
   61  *      @(#)autoconf.c  7.20 (Berkeley) 5/9/91
   62  */
   63 
   64 #include <sys/cdefs.h>
   65 __KERNEL_RCSID(0, "$NetBSD: uba.c,v 1.83 2021/08/07 16:19:15 thorpej Exp $");
   66 
   67 #include <sys/param.h>
   68 #include <sys/time.h>
   69 #include <sys/systm.h>
   70 #include <sys/buf.h>
   71 #include <sys/proc.h>
   72 #include <sys/conf.h>
   73 #include <sys/kernel.h>
   74 #include <sys/malloc.h>
   75 #include <sys/device.h>
   76 
   77 #include <sys/bus.h>
   78 #include <machine/scb.h>
   79 #include <sys/cpu.h>
   80 
   81 #include <dev/qbus/ubareg.h>
   82 #include <dev/qbus/ubavar.h>
   83 
   84 #include "ioconf.h"
   85 #include "locators.h"
   86 
   87 static int ubasearch (device_t, cfdata_t,
   88                       const int *, void *);
   89 static int ubaprint (void *, const char *);
   90 
   91 /*
   92  * If we failed to allocate uba resources, put us on a queue to wait
   93  * until there is available resources. Resources to compete about
   94  * are map registers and BDPs. This is normally only a problem on
   95  * Unibus systems, Qbus systems have more map registers than usable.
   96  */
   97 void
   98 uba_enqueue(struct uba_unit *uu)
   99 {
  100         struct uba_softc *uh;
  101         int s;
  102 
  103         uh = device_private(device_parent(uu->uu_dev));
  104 
  105         s = spluba();
  106         SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq);
  107         splx(s);
  108 }
  109 
  110 /*
  111  * When a routine that uses resources is finished, the next device
  112  * in queue for map registers etc is called. If it succeeds to get
  113  * resources, call next, and next, and next...
  114  * This routine must be called at spluba.
  115  */
  116 void
  117 uba_done(struct uba_softc *uh)
  118 {
  119         struct uba_unit *uu;
  120 
  121         while ((uu = SIMPLEQ_FIRST(&uh->uh_resq))) {
  122                 SIMPLEQ_REMOVE_HEAD(&uh->uh_resq, uu_resq);
  123                 if ((*uu->uu_ready)(uu) == 0) {
  124                         SIMPLEQ_INSERT_HEAD(&uh->uh_resq, uu, uu_resq);
  125                         break;
  126                 }
  127         }
  128 }
  129 
  130 /*
  131  * Each device that needs some handling if an ubareset occurs must
  132  * register for reset first through this routine.
  133  */
  134 void
  135 uba_reset_establish(void (*reset)(device_t), device_t dev)
  136 {
  137         struct uba_softc *uh = device_private(device_parent(dev));
  138         struct uba_reset *ur;
  139 
  140         ur = malloc(sizeof(struct uba_reset), M_DEVBUF, M_WAITOK|M_ZERO);
  141         ur->ur_dev = dev;
  142         ur->ur_reset = reset;
  143 
  144         SIMPLEQ_INSERT_TAIL(&uh->uh_resetq, ur, ur_resetq);
  145 }
  146 
  147 /*
  148  * Allocate a bunch of map registers and map them to the given address.
  149  */
  150 int
  151 uballoc(struct uba_softc *uh, struct ubinfo *ui, int flags)
  152 {
  153         int waitok = (flags & UBA_CANTWAIT) == 0;
  154         int error;
  155 
  156         if ((error = bus_dmamap_create(uh->uh_dmat, ui->ui_size, 1,
  157             ui->ui_size, 0, (waitok ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT),
  158             &ui->ui_dmam)))
  159                 return error;
  160 
  161         if ((error = bus_dmamap_load(uh->uh_dmat, ui->ui_dmam, ui->ui_vaddr,
  162             ui->ui_size, NULL, (waitok ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT)))) {
  163                 bus_dmamap_destroy(uh->uh_dmat, ui->ui_dmam);
  164                 return error;
  165         }
  166         ui->ui_baddr = ui->ui_dmam->dm_segs[0].ds_addr;
  167         return 0;
  168 }
  169 
  170 /*
  171  * Allocate DMA-able memory and map it on the unibus.
  172  */
  173 int
  174 ubmemalloc(struct uba_softc *uh, struct ubinfo *ui, int flags)
  175 {
  176         int waitok = (flags & UBA_CANTWAIT ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
  177         int error;
  178 
  179         if ((error = bus_dmamem_alloc(uh->uh_dmat, ui->ui_size, PAGE_SIZE, 0,
  180             &ui->ui_seg, 1, &ui->ui_rseg, waitok)))
  181                 return error;
  182         if ((error = bus_dmamem_map(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg,
  183             ui->ui_size, &ui->ui_vaddr, waitok|BUS_DMA_COHERENT))) {
  184                 bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg);
  185                 return error;
  186         }
  187         if ((error = uballoc(uh, ui, flags))) {
  188                 bus_dmamem_unmap(uh->uh_dmat, ui->ui_vaddr, ui->ui_size);
  189                 bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg);
  190         }
  191         return error;
  192 }
  193 
  194 void
  195 ubfree(struct uba_softc *uh, struct ubinfo *ui)
  196 {
  197         bus_dmamap_unload(uh->uh_dmat, ui->ui_dmam);
  198         bus_dmamap_destroy(uh->uh_dmat, ui->ui_dmam);
  199 }
  200 
  201 void
  202 ubmemfree(struct uba_softc *uh, struct ubinfo *ui)
  203 {
  204         bus_dmamem_unmap(uh->uh_dmat, ui->ui_vaddr, ui->ui_size);
  205         bus_dmamem_free(uh->uh_dmat, &ui->ui_seg, ui->ui_rseg);
  206         ubfree(uh, ui);
  207 }
  208 
  209 /*
  210  * Generate a reset on uba number uban.  Then
  211  * call each device that asked to be called during attach,
  212  * giving it a chance to clean up so as to be able to continue.
  213  */
  214 void
  215 ubareset(struct uba_softc *uh)
  216 {
  217         struct uba_reset *ur;
  218         int s;
  219 
  220         s = spluba();
  221         SIMPLEQ_INIT(&uh->uh_resq);
  222         printf("%s: reset", device_xname(uh->uh_dev));
  223         (*uh->uh_ubainit)(uh);
  224 
  225         ur = SIMPLEQ_FIRST(&uh->uh_resetq);
  226         if (ur) do {
  227                 printf(" %s", device_xname(ur->ur_dev));
  228                 (*ur->ur_reset)(ur->ur_dev);
  229         } while ((ur = SIMPLEQ_NEXT(ur, ur_resetq)));
  230 
  231         printf("\n");
  232         splx(s);
  233 }
  234 
  235 /*
  236  * The common attach routine:
  237  *   Calls the scan routine to search for uba devices.
  238  */
  239 void
  240 uba_attach(struct uba_softc *sc, paddr_t iopagephys)
  241 {
  242 
  243         /*
  244          * Set last free interrupt vector for devices with
  245          * programmable interrupt vectors.  Use is to decrement
  246          * this number and use result as interrupt vector.
  247          */
  248         sc->uh_lastiv = 0x200;
  249         SIMPLEQ_INIT(&sc->uh_resq);
  250         SIMPLEQ_INIT(&sc->uh_resetq);
  251 
  252         /*
  253          * Allocate place for unibus I/O space in virtual space.
  254          */
  255         if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh))
  256                 return;
  257 
  258         /*
  259          * Keep track of which addressed devices are found.
  260          */
  261         sc->uh_used = malloc(UBAIOSIZE, M_TEMP, M_WAITOK);
  262         memset(sc->uh_used, 0, UBAIOSIZE);
  263 
  264         if (sc->uh_beforescan)
  265                 (*sc->uh_beforescan)(sc);
  266         /*
  267          * Now start searching for devices.
  268          */
  269         config_search(sc->uh_dev, NULL,
  270             CFARGS(.search = ubasearch));
  271 
  272         if (sc->uh_afterscan)
  273                 (*sc->uh_afterscan)(sc);
  274 
  275         free(sc->uh_used, M_TEMP);
  276 }
  277 
  278 int
  279 ubasearch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
  280 {
  281         struct  uba_softc *sc = device_private(parent);
  282         struct  uba_attach_args ua;
  283         int     i, csr, vec, br;
  284 
  285         csr = cf->cf_loc[UBACF_CSR];
  286         if (sc->uh_used[ubdevreg(csr)])
  287                 return 0; /* something are already at this address */
  288 
  289         ua.ua_ioh = ubdevreg(csr) + sc->uh_ioh;
  290         ua.ua_iot = sc->uh_iot;
  291         ua.ua_dmat = sc->uh_dmat;
  292 
  293         if (badaddr((void *)ua.ua_ioh, 2) ||
  294             (sc->uh_errchk ? (*sc->uh_errchk)(sc):0))
  295                 goto forgetit;
  296 
  297         scb_vecref(0, 0); /* Clear vector ref */
  298         i = config_probe(parent, cf, &ua);
  299 
  300         if (sc->uh_errchk)
  301                 if ((*sc->uh_errchk)(sc))
  302                         goto forgetit;
  303         if (i == 0)
  304                 goto forgetit;
  305 
  306         i = scb_vecref(&vec, &br);
  307         if (i == 0)
  308                 goto fail;
  309         if (vec == 0)
  310                 goto fail;
  311 
  312         ua.ua_br = br;
  313         ua.ua_cvec = vec;
  314         ua.ua_iaddr = csr;
  315         ua.ua_evcnt = NULL;
  316 
  317         sc->uh_used[ubdevreg(csr)] = 1;
  318 
  319         config_attach(parent, cf, &ua, ubaprint, CFARGS_NONE);
  320         return 0;
  321 
  322 fail:
  323         printf("%s%d at %s csr %o %s\n",
  324             cf->cf_name, cf->cf_unit, device_xname(parent),
  325             csr, (i ? "zero vector" : "didn't interrupt"));
  326 
  327 forgetit:
  328         return 0;
  329 }
  330 
  331 /*
  332  * Print out some interesting info common to all unibus devices.
  333  */
  334 int
  335 ubaprint(void *aux, const char *uba)
  336 {
  337         struct uba_attach_args *ua = aux;
  338 
  339         aprint_normal(" csr %o vec %o ipl %x", ua->ua_iaddr,
  340             ua->ua_cvec & 511, ua->ua_br);
  341         return UNCONF;
  342 }
  343 
  344 /*
  345  * Move to machdep eventually
  346  */
  347 void
  348 uba_intr_establish(void *icookie, int vec, void (*ifunc)(void *iarg),
  349         void *iarg, struct evcnt *ev)
  350 {
  351         scb_vecalloc(vec, ifunc, iarg, SCB_ISTACK, ev);
  352 }

Cache object: 57d361c580d7669839273df2ea30c4e6


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