1 /* $NetBSD: uba.c,v 1.49 2000/01/24 02:40:30 matt 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/param.h> 41 #include <sys/types.h> 42 #include <sys/time.h> 43 #include <sys/systm.h> 44 #include <sys/map.h> 45 #include <sys/buf.h> 46 #include <sys/proc.h> 47 #include <sys/user.h> 48 #include <sys/conf.h> 49 #include <sys/dkstat.h> 50 #include <sys/kernel.h> 51 #include <sys/malloc.h> 52 #include <sys/device.h> 53 54 #include <vm/vm.h> 55 #include <vm/vm_kern.h> 56 57 #include <machine/bus.h> 58 #include <machine/scb.h> 59 #include <machine/cpu.h> 60 61 #include <dev/qbus/ubavar.h> 62 63 #include "ioconf.h" 64 65 static int ubasearch __P((struct device *, struct cfdata *, void *)); 66 static int ubaprint __P((void *, const char *)); 67 68 /* 69 * If we failed to allocate uba resources, put us on a queue to wait 70 * until there is available resources. Resources to compete about 71 * are map registers and BDPs. This is normally only a problem on 72 * Unibus systems, Qbus systems have more map registers than usable. 73 */ 74 void 75 uba_enqueue(uu) 76 struct uba_unit *uu; 77 { 78 struct uba_softc *uh; 79 int s; 80 81 uh = (void *)((struct device *)(uu->uu_softc))->dv_parent; 82 83 s = splimp(); 84 SIMPLEQ_INSERT_TAIL(&uh->uh_resq, uu, uu_resq); 85 splx(s); 86 } 87 88 /* 89 * When a routine that uses resources is finished, the next device 90 * in queue for map registers etc is called. If it succeeds to get 91 * resources, call next, and next, and next... 92 * This routine must be called at splimp. 93 */ 94 void 95 uba_done(uh) 96 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 * Generate a reset on uba number uban. Then 111 * call each device that asked to be called during attach, 112 * giving it a chance to clean up so as to be able to continue. 113 */ 114 void 115 ubareset(uban) 116 int uban; 117 { 118 register struct uba_softc *uh = uba_cd.cd_devs[uban]; 119 int s, i; 120 121 s = splimp(); 122 SIMPLEQ_INIT(&uh->uh_resq); 123 printf("%s: reset", uh->uh_dev.dv_xname); 124 (*uh->uh_ubainit)(uh); 125 126 for (i = 0; i < uh->uh_resno; i++) 127 (*uh->uh_reset[i])(uh->uh_resarg[i]); 128 printf("\n"); 129 splx(s); 130 } 131 132 /* 133 * The common attach routine: 134 * Calls the scan routine to search for uba devices. 135 */ 136 void 137 uba_attach(sc, iopagephys) 138 struct uba_softc *sc; 139 paddr_t iopagephys; 140 { 141 142 /* 143 * Set last free interrupt vector for devices with 144 * programmable interrupt vectors. Use is to decrement 145 * this number and use result as interrupt vector. 146 */ 147 sc->uh_lastiv = 0x200; 148 SIMPLEQ_INIT(&sc->uh_resq); 149 150 /* 151 * Allocate place for unibus I/O space in virtual space. 152 */ 153 if (bus_space_map(sc->uh_iot, iopagephys, UBAIOSIZE, 0, &sc->uh_ioh)) 154 return; 155 156 if (sc->uh_beforescan) 157 (*sc->uh_beforescan)(sc); 158 /* 159 * Now start searching for devices. 160 */ 161 config_search(ubasearch,(struct device *)sc, NULL); 162 163 if (sc->uh_afterscan) 164 (*sc->uh_afterscan)(sc); 165 } 166 167 int 168 ubasearch(parent, cf, aux) 169 struct device *parent; 170 struct cfdata *cf; 171 void *aux; 172 { 173 struct uba_softc *sc = (struct uba_softc *)parent; 174 struct uba_attach_args ua; 175 int i, vec, br; 176 177 ua.ua_ioh = ubdevreg(cf->cf_loc[0]) + sc->uh_ioh; 178 ua.ua_iot = sc->uh_iot; 179 ua.ua_dmat = sc->uh_dmat; 180 ua.ua_reset = NULL; 181 182 if (badaddr((caddr_t)ua.ua_ioh, 2) || 183 (sc->uh_errchk ? (*sc->uh_errchk)(sc):0)) 184 goto forgetit; 185 186 scb_vecref(0, 0); /* Clear vector ref */ 187 i = (*cf->cf_attach->ca_match) (parent, cf, &ua); 188 189 if (sc->uh_errchk) 190 if ((*sc->uh_errchk)(sc)) 191 goto forgetit; 192 if (i == 0) 193 goto forgetit; 194 195 i = scb_vecref(&vec, &br); 196 if (i == 0) 197 goto fail; 198 if (vec == 0) 199 goto fail; 200 201 if (ua.ua_reset) { /* device wants ubareset */ 202 if (sc->uh_resno == 0) { 203 #define RESETSIXE 128 204 sc->uh_reset = malloc(sizeof(void *) * RESETSIXE, 205 M_DEVBUF, M_NOWAIT); 206 sc->uh_resarg = malloc(sizeof(void *) * RESETSIXE, 207 M_DEVBUF, M_NOWAIT); 208 } 209 if (sc->uh_resno < RESETSIXE) { 210 sc->uh_resarg[sc->uh_resno] = cf->cf_unit; 211 sc->uh_reset[sc->uh_resno++] = ua.ua_reset; 212 } else { 213 printf("%s: Expand reset table, skipping reset %s%d\n", 214 sc->uh_dev.dv_xname, cf->cf_driver->cd_name, 215 cf->cf_unit); 216 } 217 } 218 219 ua.ua_br = br; 220 ua.ua_cvec = vec; 221 ua.ua_iaddr = cf->cf_loc[0]; 222 223 config_attach(parent, cf, &ua, ubaprint); 224 return 0; 225 226 fail: 227 printf("%s%d at %s csr %o %s\n", 228 cf->cf_driver->cd_name, cf->cf_unit, parent->dv_xname, 229 cf->cf_loc[0], (i ? "zero vector" : "didn't interrupt")); 230 231 forgetit: 232 return 0; 233 } 234 235 /* 236 * Print out some interesting info common to all unibus devices. 237 */ 238 int 239 ubaprint(aux, uba) 240 void *aux; 241 const char *uba; 242 { 243 struct uba_attach_args *ua = aux; 244 245 printf(" csr %o vec %o ipl %x", ua->ua_iaddr, 246 ua->ua_cvec & 511, ua->ua_br); 247 return UNCONF; 248 } 249 250 /* 251 * Move to machdep eventually 252 */ 253 void 254 uba_intr_establish(icookie, vec, ifunc, iarg) 255 void *icookie; 256 int vec; 257 void (*ifunc)(void *iarg); 258 void *iarg; 259 { 260 scb_vecalloc(vec, ifunc, iarg, SCB_ISTACK); 261 } 262