apbus.c revision 1.2 1 /* $NetBSD: apbus.c,v 1.2 1999/12/23 06:52:30 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1999 SHIMIZU Ryo. 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. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32
33 #include <machine/adrsmap.h>
34 #include <machine/autoconf.h>
35 #include <newsmips/apbus/apbusvar.h>
36
37 static int apbusmatch __P((struct device *, struct cfdata *, void *));
38 static void apbusattach __P((struct device *, struct device *, void *));
39 static int apbusprint __P((void *, const char *));
40 /* static void *aptokseg0 __P((void *)); */
41
42 #define MAXAPDEVNUM 32
43
44 struct apbus_softc {
45 struct device apbs_dev;
46 };
47
48 struct cfattach ap_ca = {
49 sizeof(struct apbus_softc), apbusmatch, apbusattach
50 };
51
52 #define APBUS_DEVNAMELEN 16
53
54 struct ap_intrhand {
55 int ai_mask;
56 int ai_priority;
57 void (*ai_func) __P((void*)); /* function */
58 void *ai_aux; /* softc */
59 char ai_name[APBUS_DEVNAMELEN];
60 int ai_ctlno;
61 };
62
63 #define NLEVEL 2
64 #define NBIT 16
65 #define LEVELxBIT(l,b) (((l)*NBIT)+(b))
66
67 static struct ap_intrhand apintr[NLEVEL*NBIT];
68
69 static int
70 apbusmatch(parent, cfdata, aux)
71 struct device *parent;
72 struct cfdata *cfdata;
73 void *aux;
74 {
75 struct confargs *ca = aux;
76
77 if (strcmp(ca->ca_name, "ap") != 0)
78 return 0;
79
80 return 1;
81 }
82
83
84 static void
85 apbusattach(parent, self, aux)
86 struct device *parent;
87 struct device *self;
88 void *aux;
89 {
90 struct apbus_attach_args child;
91 struct apbus_dev *apdev;
92 struct apbus_ctl *apctl;
93
94 *(volatile u_int *)(NEWS5000_APBUS_INTST) = 0xffffffff;
95 *(volatile u_int *)(NEWS5000_APBUS_INTMSK) = 0xffffffff;
96 *(volatile u_int *)(NEWS5000_APBUS_CTRL) = 0x00000004;
97 *(volatile u_int *)(NEWS5000_APBUS_DMA) = 0xffffffff;
98
99 printf("\n");
100
101 /*
102 * get first ap-device
103 */
104 apdev = apbus_lookupdev(NULL);
105
106 /*
107 * trace device chain
108 */
109 while (apdev) {
110 apctl = apdev->apbd_ctl;
111
112 /*
113 * probe physical device only
114 * (no pseudo device)
115 */
116 if (apctl && apctl->apbc_hwbase) {
117 /*
118 * ... and, all units
119 */
120 while (apctl) {
121 /* make apbus_attach_args for devices */
122 child.apa_name = apdev->apbd_name;
123 child.apa_ctlnum = apctl->apbc_ctlno;
124 child.apa_slotno = apctl->apbc_sl;
125 child.apa_hwbase = apctl->apbc_hwbase;
126
127 config_found(self, &child, apbusprint);
128
129 apctl = apctl->apbc_link;
130 }
131 }
132
133 apdev = apdev->apbd_link;
134 }
135 }
136
137 int
138 apbusprint(aux, pnp)
139 void *aux;
140 const char *pnp;
141 {
142 struct apbus_attach_args *a = aux;
143
144 if (pnp)
145 printf("%s at %s slot%d addr 0x%lx",
146 a->apa_name, pnp, a->apa_slotno, a->apa_hwbase);
147
148 return UNCONF;
149 }
150
151 #if 0
152 void *
153 aptokseg0(va)
154 void *va;
155 {
156 vaddr_t addr = (vaddr_t)va;
157
158 if (addr >= 0xfff00000) {
159 addr -= 0xfff00000;
160 addr += physmem << PGSHIFT;
161 addr += 0x80000000;
162 va = (void *)addr;
163 }
164 return va;
165 }
166 #endif
167
168 void
169 apbus_wbflush()
170 {
171 volatile int *wbflush = (int *)NEWS5000_WBFLUSH;
172
173 (void)*wbflush;
174 }
175
176 /*
177 * called by hardware interrupt routine
178 */
179 int
180 apbus_intr_call(level, stat)
181 int level;
182 int stat;
183 {
184 int i;
185 int nintr = 0;
186 struct ap_intrhand *aip = &apintr[LEVELxBIT(level,0)];
187
188 for(i = 0; i < NBIT; i++) {
189 if (aip->ai_mask & stat) {
190 (*aip->ai_func)(aip->ai_aux);
191 nintr++;
192 }
193 aip++;
194 }
195 return nintr;
196 }
197
198 /*
199 * register device interrupt routine
200 */
201 void *
202 apbus_intr_establish(level, mask, priority, func, aux, name, ctlno)
203 int level;
204 int mask;
205 int priority;
206 void (*func) __P((void *));
207 void *aux;
208 char *name;
209 int ctlno;
210 {
211 int i;
212 int nbit = -1;
213 struct ap_intrhand *aip;
214
215 for (i = 0; i < NBIT; i++) {
216 if (mask & (1 << i)) {
217 nbit = i;
218 break;
219 }
220 }
221
222 if (nbit == -1)
223 panic("apbus_intr_establish");
224
225 aip = &apintr[LEVELxBIT(level,nbit)];
226 aip->ai_mask = 1 << nbit;
227 aip->ai_priority = priority;
228 aip->ai_func = func;
229 aip->ai_aux = aux;
230 strncpy(aip->ai_name, name, APBUS_DEVNAMELEN-1);
231 aip->ai_ctlno = ctlno;
232
233 return (void *)aip;
234 }
235