vsbus.c revision 1.10 1 /* $NetBSD: vsbus.c,v 1.10 1998/05/21 13:10:59 ragge Exp $ */
2 /*
3 * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Ludd by Bertram Barth.
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 at Ludd, University of
19 * Lule}, Sweden and its contributors.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/buf.h>
38 #include <sys/conf.h>
39 #include <sys/file.h>
40 #include <sys/ioctl.h>
41 #include <sys/proc.h>
42 #include <sys/user.h>
43 #include <sys/map.h>
44 #include <sys/device.h>
45 #include <sys/dkstat.h>
46 #include <sys/disklabel.h>
47 #include <sys/syslog.h>
48 #include <sys/stat.h>
49
50 #include <machine/pte.h>
51 #include <machine/sid.h>
52 #include <machine/scb.h>
53 #include <machine/cpu.h>
54 #include <machine/trap.h>
55 #include <machine/nexus.h>
56
57 #include <machine/uvax.h>
58 #include <machine/ka410.h>
59 #include <machine/ka43.h>
60
61 #include <machine/vsbus.h>
62
63 #include "ioconf.h"
64
65 int vsbus_match __P((struct device *, struct cfdata *, void *));
66 void vsbus_attach __P((struct device *, struct device *, void *));
67 int vsbus_print __P((void *, const char *));
68
69 void ka410_attach __P((struct device *, struct device *, void *));
70 void ka43_attach __P((struct device *, struct device *, void *));
71
72 #define VSBUS_MAXINTR 8
73
74 struct vsbus_softc {
75 struct device sc_dev;
76 struct ivec_dsp sc_dsp[VSBUS_MAXINTR];
77 };
78
79 struct cfattach vsbus_ca = {
80 sizeof(struct vsbus_softc), vsbus_match, vsbus_attach
81 };
82
83 void vsbus_intr_setup __P((struct vsbus_softc *));
84
85 #define VSBUS_MAXDEVS 8
86
87 int
88 vsbus_print(aux, name)
89 void *aux;
90 const char *name;
91 {
92 struct vsbus_attach_args *va = aux;
93
94 if (name) {
95 printf ("device %d at %s", va->va_type, name);
96 return (UNSUPP);
97 }
98 return (UNCONF);
99 }
100
101 int
102 vsbus_match(parent, cf, aux)
103 struct device *parent;
104 struct cfdata *cf;
105 void *aux;
106 {
107 struct bp_conf *bp = aux;
108
109 if (strcmp(bp->type, "vsbus"))
110 return 0;
111 /*
112 * on machines which can have it, the vsbus is always there
113 */
114 if ((vax_bustype & VAX_VSBUS) == 0)
115 return (0);
116
117 return (1);
118 }
119
120 void
121 vsbus_attach(parent, self, aux)
122 struct device *parent, *self;
123 void *aux;
124 {
125 struct vsbus_softc *sc = (void *)self;
126 struct vsbus_attach_args va;
127
128 printf("\n");
129 /*
130 * first setup interrupt-table, so that devices can register
131 * their interrupt-routines...
132 */
133 vsbus_intr_setup(sc);
134
135 /*
136 * now check for all possible devices on this "bus"
137 */
138 /* Always have network */
139 va.va_type = INR_NP;
140 config_found(self, &va, vsbus_print);
141
142 /* Always have serial line */
143 va.va_type = INR_SR;
144 config_found(self, &va, vsbus_print);
145 }
146
147 static void stray __P((int));
148
149 static void
150 stray(arg)
151 int arg;
152 {
153 printf("stray interrupt nr %d.\n", arg);
154 }
155
156 static int inrs[] = {IVEC_DC, IVEC_SC, IVEC_VS, IVEC_VF,
157 IVEC_NS, IVEC_NP, IVEC_ST, IVEC_SR};
158
159 void
160 vsbus_intr_setup(sc)
161 struct vsbus_softc *sc;
162 {
163 extern struct ivec_dsp idsptch; /* subr.s */
164 void **scbP = (void*)scb;
165 int i;
166
167 vs_cpu->vc_intmsk = 0; /* disable all interrupts */
168 vs_cpu->vc_intclr = 0xFF; /* clear all old interrupts */
169
170 for (i = 0; i < VSBUS_MAXINTR; i++) {
171 bcopy(&idsptch, &sc->sc_dsp[i], sizeof(struct ivec_dsp));
172 sc->sc_dsp[i].hoppaddr = stray;
173 sc->sc_dsp[i].pushlarg = i;
174 scbP[inrs[i]/4] = &sc->sc_dsp[i];
175 }
176 }
177
178 void
179 vsbus_intr_attach(nr, func, arg)
180 int nr;
181 void (*func)(int);
182 int arg;
183 {
184 struct vsbus_softc *sc = vsbus_cd.cd_devs[0];
185
186 sc->sc_dsp[nr].hoppaddr = func;
187 sc->sc_dsp[nr].pushlarg = arg;
188 }
189
190 void
191 vsbus_intr_enable(nr)
192 int nr;
193 {
194 vs_cpu->vc_intclr = (1<<nr);
195 vs_cpu->vc_intmsk |= (1<<nr);
196 }
197
198 void
199 vsbus_intr_disable(nr)
200 int nr;
201 {
202 vs_cpu->vc_intmsk = vs_cpu->vc_intmsk & ~(1<<nr);
203 }
204
205 /*
206 *
207 *
208 */
209
210 static volatile struct dma_lock {
211 int dl_locked;
212 int dl_wanted;
213 void *dl_owner;
214 int dl_count;
215 } dmalock = { 0, 0, NULL, 0 };
216
217 int
218 vsbus_lockDMA(ca)
219 struct confargs *ca;
220 {
221 while (dmalock.dl_locked) {
222 dmalock.dl_wanted++;
223 sleep((caddr_t)&dmalock, PRIBIO); /* PLOCK or PRIBIO ? */
224 dmalock.dl_wanted--;
225 }
226 dmalock.dl_locked++;
227 dmalock.dl_owner = ca;
228
229 /*
230 * no checks yet, no timeouts, nothing...
231 */
232
233 #ifdef DEBUG
234 if ((++dmalock.dl_count % 1000) == 0)
235 printf("%d locks, owner: %s\n", dmalock.dl_count, ca->ca_name);
236 #endif
237 return (0);
238 }
239
240 int
241 vsbus_unlockDMA(ca)
242 struct confargs *ca;
243 {
244 if (dmalock.dl_locked != 1 || dmalock.dl_owner != ca) {
245 printf("locking-problem: %d, %s\n", dmalock.dl_locked,
246 (char *)(dmalock.dl_owner ? dmalock.dl_owner : "null"));
247 dmalock.dl_locked = 0;
248 return (-1);
249 }
250 dmalock.dl_owner = NULL;
251 dmalock.dl_locked = 0;
252 if (dmalock.dl_wanted) {
253 wakeup((caddr_t)&dmalock);
254 }
255 return (0);
256 }
257