vsbus.c revision 1.11 1 /* $NetBSD: vsbus.c,v 1.11 1998/06/04 15:51:12 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 /* If sm_addr is set, a monochrome graphics adapter is found */
147 if (sm_addr) {
148 va.va_type = INR_VF;
149 config_found(self, &va, vsbus_print);
150 }
151 }
152
153 static void stray __P((int));
154
155 static void
156 stray(arg)
157 int arg;
158 {
159 printf("stray interrupt nr %d.\n", arg);
160 }
161
162 static int inrs[] = {IVEC_DC, IVEC_SC, IVEC_VS, IVEC_VF,
163 IVEC_NS, IVEC_NP, IVEC_ST, IVEC_SR};
164
165 void
166 vsbus_intr_setup(sc)
167 struct vsbus_softc *sc;
168 {
169 extern struct ivec_dsp idsptch; /* subr.s */
170 void **scbP = (void*)scb;
171 int i;
172
173 vs_cpu->vc_intmsk = 0; /* disable all interrupts */
174 vs_cpu->vc_intclr = 0xFF; /* clear all old interrupts */
175
176 for (i = 0; i < VSBUS_MAXINTR; i++) {
177 bcopy(&idsptch, &sc->sc_dsp[i], sizeof(struct ivec_dsp));
178 sc->sc_dsp[i].hoppaddr = stray;
179 sc->sc_dsp[i].pushlarg = i;
180 scbP[inrs[i]/4] = &sc->sc_dsp[i];
181 }
182 }
183
184 void
185 vsbus_intr_attach(nr, func, arg)
186 int nr;
187 void (*func)(int);
188 int arg;
189 {
190 struct vsbus_softc *sc = vsbus_cd.cd_devs[0];
191
192 sc->sc_dsp[nr].hoppaddr = func;
193 sc->sc_dsp[nr].pushlarg = arg;
194 }
195
196 void
197 vsbus_intr_enable(nr)
198 int nr;
199 {
200 vs_cpu->vc_intclr = (1<<nr);
201 vs_cpu->vc_intmsk |= (1<<nr);
202 }
203
204 void
205 vsbus_intr_disable(nr)
206 int nr;
207 {
208 vs_cpu->vc_intmsk = vs_cpu->vc_intmsk & ~(1<<nr);
209 }
210
211 /*
212 *
213 *
214 */
215
216 static volatile struct dma_lock {
217 int dl_locked;
218 int dl_wanted;
219 void *dl_owner;
220 int dl_count;
221 } dmalock = { 0, 0, NULL, 0 };
222
223 int
224 vsbus_lockDMA(ca)
225 struct confargs *ca;
226 {
227 while (dmalock.dl_locked) {
228 dmalock.dl_wanted++;
229 sleep((caddr_t)&dmalock, PRIBIO); /* PLOCK or PRIBIO ? */
230 dmalock.dl_wanted--;
231 }
232 dmalock.dl_locked++;
233 dmalock.dl_owner = ca;
234
235 /*
236 * no checks yet, no timeouts, nothing...
237 */
238
239 #ifdef DEBUG
240 if ((++dmalock.dl_count % 1000) == 0)
241 printf("%d locks, owner: %s\n", dmalock.dl_count, ca->ca_name);
242 #endif
243 return (0);
244 }
245
246 int
247 vsbus_unlockDMA(ca)
248 struct confargs *ca;
249 {
250 if (dmalock.dl_locked != 1 || dmalock.dl_owner != ca) {
251 printf("locking-problem: %d, %s\n", dmalock.dl_locked,
252 (char *)(dmalock.dl_owner ? dmalock.dl_owner : "null"));
253 dmalock.dl_locked = 0;
254 return (-1);
255 }
256 dmalock.dl_owner = NULL;
257 dmalock.dl_locked = 0;
258 if (dmalock.dl_wanted) {
259 wakeup((caddr_t)&dmalock);
260 }
261 return (0);
262 }
263