ioasic.c revision 1.1.2.4 1 /* $NetBSD: ioasic.c,v 1.1.2.4 1999/03/29 16:50:35 drochner Exp $ */
2
3 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
4
5 __KERNEL_RCSID(0, "$NetBSD: ioasic.c,v 1.1.2.4 1999/03/29 16:50:35 drochner Exp $");
6
7 #include <sys/param.h>
8 #include <sys/systm.h>
9 #include <sys/device.h>
10
11 #include <machine/autoconf.h>
12 #include <machine/bus.h>
13 #include <machine/intr.h>
14
15 #include <dev/tc/tcvar.h>
16 #include <dev/tc/ioasicvar.h>
17 #include <pmax/tc/ioasicreg.h>
18 #include <pmax/pmax/pmaxtype.h>
19
20 int ioasicmatch __P((struct device *, struct cfdata *, void *));
21 void ioasicattach __P((struct device *, struct device *, void *));
22 int ioasicprint __P((void *, const char *));
23 int ioasic_submatch __P((struct cfdata *, struct ioasicdev_attach_args *));
24
25 tc_addr_t ioasic_base;
26
27 struct cfattach ioasic_ca = {
28 sizeof(struct ioasic_softc), ioasicmatch, ioasicattach,
29 };
30
31 /* XXX XXX XXX */
32 #define IOASIC_INTR_SCSI 0x000e0200
33 #define IOASIC_INTR_DTOP 0x00000001
34 #define IOASIC_INTR_FDC 0x00000090
35 #define XINE_INTR_TC_0 0x00001000
36 #define XINE_INTR_TC_1 0x00000020
37 #define KN03_INTR_TC_0 0x00000800
38 #define KN03_INTR_TC_1 0x00001000
39 #define KN03_INTR_TC_2 0x00002000
40 #define KMIN_INTR_CLOCK 0x00000020
41
42 extern u_int32_t iplmask[], oldiplmask[];
43 /* XXX XXX XXX */
44
45 #define C(x) (void *)(x)
46
47 struct ioasic_dev xine_ioasic_devs[] = {
48 { "lance", 0x0c0000, C(SYS_DEV_LANCE), IOASIC_INTR_LANCE, },
49 { "z8530 ", 0x100000, C(SYS_DEV_SCC0), IOASIC_INTR_SCC_0, },
50 { "mc146818", 0x200000, C(SYS_DEV_BOGUS), 0, },
51 { "isdn", 0x240000, C(SYS_DEV_ISDN), IOASIC_INTR_ISDN, },
52 { "dtop", 0x280000, C(SYS_DEV_DTOP), IOASIC_INTR_DTOP, },
53 { "fdc", 0x2C0000, C(SYS_DEV_FDC), IOASIC_INTR_FDC, },
54 { "asc", 0x300000, C(SYS_DEV_SCSI), IOASIC_INTR_SCSI },
55 { "(TC0)", 0x0, C(SYS_DEV_OPT0), XINE_INTR_TC_0 },
56 { "(TC1)", 0x0, C(SYS_DEV_OPT1), XINE_INTR_TC_1 },
57 };
58 int xine_builtin_ndevs = 7;
59 int xine_ioasic_ndevs = sizeof(xine_ioasic_devs)/sizeof(xine_ioasic_devs[0]);
60
61 struct ioasic_dev kn03_ioasic_devs[] = {
62 { "lance", 0x0c0000, C(SYS_DEV_LANCE), IOASIC_INTR_LANCE, },
63 { "z8530 ", 0x100000, C(SYS_DEV_SCC0), IOASIC_INTR_SCC_0, },
64 { "z8530 ", 0x180000, C(SYS_DEV_SCC1), IOASIC_INTR_SCC_1, },
65 { "mc146818", 0x200000, C(SYS_DEV_BOGUS), KMIN_INTR_CLOCK, },
66 { "asc", 0x300000, C(SYS_DEV_SCSI), IOASIC_INTR_SCSI },
67 { "(TC0)", 0x0, C(SYS_DEV_OPT0), KN03_INTR_TC_0 },
68 { "(TC1)", 0x0, C(SYS_DEV_OPT1), KN03_INTR_TC_1 },
69 { "(TC2)", 0x0, C(SYS_DEV_OPT2), KN03_INTR_TC_2 },
70 };
71 int kn03_builtin_ndevs = 5;
72 int kn03_ioasic_ndevs = sizeof(kn03_ioasic_devs)/sizeof(kn03_ioasic_devs[0]);
73
74 struct ioasic_dev *ioasic_devs;
75 int ioasic_ndevs, builtin_ndevs;
76
77 /* There can be only one. */
78 int ioasicfound;
79
80 extern int systype;
81
82 int
83 ioasicmatch(parent, cfdata, aux)
84 struct device *parent;
85 struct cfdata *cfdata;
86 void *aux;
87 {
88 struct tc_attach_args *ta = aux;
89
90 /* Make sure that we're looking for this type of device. */
91 if (strncmp("IOCTL ", ta->ta_modname, TC_ROM_LLEN))
92 return (0);
93
94 if (systype == DS_MAXINE) {
95 ioasic_devs = xine_ioasic_devs;
96 ioasic_ndevs = xine_ioasic_ndevs;
97 builtin_ndevs = xine_builtin_ndevs;
98 }
99 else if (systype == DS_3MIN || systype == DS_3MAXPLUS) {
100 ioasic_devs = kn03_ioasic_devs;
101 ioasic_ndevs = kn03_ioasic_ndevs;
102 builtin_ndevs = kn03_builtin_ndevs;
103 }
104 else
105 panic("ioasicmatch: how did we get here?");
106
107 if (ioasicfound)
108 return (0);
109
110 return (1);
111 }
112
113 void
114 ioasicattach(parent, self, aux)
115 struct device *parent, *self;
116 void *aux;
117 {
118 struct ioasic_softc *sc = (struct ioasic_softc *)self;
119 struct tc_attach_args *ta = aux;
120 int i;
121
122 ioasicfound = 1;
123
124 sc->sc_bst = ta->ta_memt;
125 sc->sc_dmat = ta->ta_dmat;
126 if (bus_space_map(ta->ta_memt, ta->ta_addr,
127 0x400000, 0, &sc->sc_bsh)) {
128 printf("%s: unable to map device\n", sc->sc_dv.dv_xname);
129 return;
130 }
131 sc->sc_cookie = ta->ta_cookie;
132
133 /* XXX XXX XXX */
134 sc->sc_base = ta->ta_addr;
135
136 printf("\n");
137
138 #if 1 /* !!! necessary? already all-0 upon booting as documented !!! */
139 /*
140 * Turn off all device interrupt bits.
141 * (This _does_ include TC option slot bits.
142 */
143 for (i = 0; i < ioasic_ndevs; i++)
144 *(volatile u_int32_t *)(sc->sc_base + IOASIC_IMSK)
145 &= ~ioasic_devs[i].iad_intrbits;
146 tc_mb();
147 #endif
148
149 #if 0
150 /*
151 * Set up the LANCE DMA area.
152 */
153 ioasic_lance_dma_setup(sc);
154 #endif
155
156 ioasic_attach_devs(sc, ioasic_devs, builtin_ndevs);
157 }
158
159 void
160 ioasic_intr_establish(ioa, cookie, level, func, arg)
161 struct device *ioa;
162 void *cookie, *arg;
163 tc_intrlevel_t level;
164 int (*func) __P((void *));
165 {
166 struct ioasic_softc *sc = (void *)ioasic_cd.cd_devs[0];
167 u_int dev, i, intrbits;
168
169 dev = (u_long)cookie;
170
171 intrtab[dev].ih_func = func;
172 intrtab[dev].ih_arg = arg;
173
174 for (i = 0; i < ioasic_ndevs; i++) {
175 if (ioasic_devs[i].iad_cookie == cookie)
176 break;
177 }
178 if (i == ioasic_ndevs) {
179 printf("\ndevice %s with cookie %d ", ioa->dv_xname, dev);
180 panic("ioasic_intr_establish: invalid cookie.");
181 }
182
183 intrbits = ioasic_devs[i].iad_intrbits;
184 iplmask[level] |= intrbits;
185 *(volatile u_int32_t *)(sc->sc_base + IOASIC_IMSK) |= intrbits;
186 tc_mb();
187 }
188
189 void
190 ioasic_intr_disestablish(ioa, cookie)
191 struct device *ioa;
192 void *cookie;
193 {
194 printf("device %s with cookie %d: ", ioa->dv_xname, (int)cookie);
195 panic("ioasic_intr_disestablish called");
196 }
197
198 char *
199 ioasic_lance_ether_address()
200 {
201
202 return (char *)(ioasic_base + IOASIC_SLOT_2_START);
203 }
204
205 #if 0 /* Jason's new LANCE DMA region */
206 /*
207 * DMA area for IOASIC LANCE.
208 * XXX Should be done differently, but this is better than it used to be.
209 */
210 #define LE_IOASIC_MEMSIZE (128*1024)
211 #define LE_IOASIC_MEMALIGN (128*1024)
212 caddr_t le_iomem;
213
214 void ioasic_lance_dma_setup __P((struct ioasic_softc *));
215
216 void
217 ioasic_lance_dma_setup(sc)
218 struct ioasic_softc *sc;
219 {
220 bus_dma_tag_t dmat = sc->sc_dmat;
221 bus_dma_segment_t seg;
222 u_int32_t csr;
223 tc_addr_t tca;
224 int rseg;
225
226 /*
227 * Allocate a DMA area for the chip.
228 */
229 if (bus_dmamem_alloc(dmat, LE_IOASIC_MEMSIZE, LE_IOASIC_MEMALIGN,
230 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
231 printf("%s: can't allocate DMA area for LANCE\n",
232 sc->sc_dv.dv_xname);
233 return;
234 }
235 if (bus_dmamem_map(dmat, &seg, rseg, LE_IOASIC_MEMSIZE,
236 &le_iomem, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
237 printf("%s: can't map DMA area for LANCE\n",
238 sc->sc_dv.dv_xname);
239 bus_dmamem_free(dmat, &seg, rseg);
240 return;
241 }
242
243 /*
244 * Create and load the DMA map for the DMA area.
245 */
246 if (bus_dmamap_create(dmat, LE_IOASIC_MEMSIZE, 1,
247 LE_IOASIC_MEMSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_lance_dmam)) {
248 printf("%s: can't create DMA map\n", sc->sc_dv.dv_xname);
249 goto bad;
250 }
251 if (bus_dmamap_load(dmat, sc->sc_lance_dmam,
252 le_iomem, LE_IOASIC_MEMSIZE, NULL, BUS_DMA_NOWAIT)) {
253 printf("%s: can't load DMA map\n", sc->sc_dv.dv_xname);
254 goto bad;
255 }
256
257 tca = (tc_addr_t)sc->sc_lance_dmam->dm_segs[0].ds_addr;
258 if (tca != sc->sc_lance_dmam->dm_segs[0].ds_addr) {
259 printf("%s: bad LANCE DMA address\n", sc->sc_dv.dv_xname);
260 bus_dmamap_unload(dmat, sc->sc_lance_dmam);
261 goto bad;
262 }
263 bus_space_write_4(sc->sc_bst, sc->sc_bsh,
264 IOASIC_LANCE_DMAPTR,
265 ((tca << 3) & ~(tc_addr_t)0x1f) | ((tca >> 29) & 0x1f));
266 csr = bus_space_read_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR);
267 csr |= IOASIC_CSR_DMAEN_LANCE;
268 bus_space_write_4(sc->sc_bst, sc->sc_bsh, IOASIC_CSR, csr);
269 return;
270
271 bad:
272 bus_dmamem_unmap(dmat, le_iomem, LE_IOASIC_MEMSIZE);
273 bus_dmamem_free(dmat, &seg, rseg);
274 le_iomem = 0;
275 }
276 #else /* old NetBSD/pmax code */
277 void ioasic_lance_dma_setup __P((void *));
278
279 void
280 ioasic_lance_dma_setup(v)
281 void *v;
282 {
283 volatile u_int32_t *ldp;
284 tc_addr_t tca;
285
286 tca = (tc_addr_t)v;
287
288 ldp = (volatile u_int *)IOASIC_REG_LANCE_DMAPTR(ioasic_base);
289 *ldp = ((tca << 3) & ~(tc_addr_t)0x1f) | ((tca >> 29) & 0x1f);
290 tc_wmb();
291
292 *(volatile u_int32_t *)IOASIC_REG_CSR(ioasic_base) |=
293 IOASIC_CSR_DMAEN_LANCE;
294 tc_mb();
295 }
296 #endif
297
298 /*
299 * spl(9) for IOASIC DECstations
300 */
301
302 int _splraise_ioasic __P((int));
303 int _spllower_ioasic __P((int));
304 int _splx_ioasic __P((int));
305
306 int
307 _splraise_ioasic(lvl)
308 int lvl;
309 {
310 u_int32_t new;
311
312 new = oldiplmask[lvl] = *(u_int32_t *)(ioasic_base + IOASIC_IMSK);
313 new &= ~iplmask[lvl];
314 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = new;
315 tc_wmb();
316 return lvl | _splraise(MIPS_SOFT_INT_MASK_0|MIPS_SOFT_INT_MASK_1);
317 }
318
319 int
320 _spllower_ioasic(mask)
321 {
322 int s;
323
324 s = IPL_NONE | _spllower(mask);
325 oldiplmask[IPL_NONE] = *(u_int32_t *)(ioasic_base + IOASIC_IMSK);
326 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) = iplmask[IPL_HIGH];
327 tc_wmb();
328 return s;
329 }
330
331 int
332 _splx_ioasic(lvl)
333 int lvl;
334 {
335 (void)_splset(lvl & MIPS_INT_MASK);
336 if (lvl & 0xff) {
337 *(u_int32_t *)(ioasic_base + IOASIC_IMSK) =
338 oldiplmask[lvl & 0xff];
339 tc_wmb();
340 }
341 return 0;
342 }
343