Home | History | Annotate | Line # | Download | only in qbus
      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 }
    353