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