xel.c revision 1.13.40.1 1 /* $NetBSD: xel.c,v 1.13.40.1 2008/05/18 12:33:00 yamt Exp $ */
2
3 /*
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Minoura Makoto.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * TSR Xellent30 driver.
34 * Detect Xellent30, and reserve its I/O area.
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: xel.c,v 1.13.40.1 2008/05/18 12:33:00 yamt Exp $");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44
45 #include <machine/cpu.h>
46 #include <machine/bus.h>
47
48 #include <arch/x68k/dev/intiovar.h>
49
50 static paddr_t xel_addr(struct device *, struct cfdata *,
51 struct intio_attach_args *);
52 static int xel_probe(paddr_t);
53 static int xel_match(struct device *, struct cfdata *, void *);
54 static void xel_attach(struct device *, struct device *, void *);
55
56 struct xel_softc {
57 struct device dev;
58
59 bus_space_tag_t sc_bst;
60 bus_space_handle_t sc_bh;
61 };
62
63 CFATTACH_DECL(xel, sizeof(struct xel_softc),
64 xel_match, xel_attach, NULL, NULL);
65
66 static paddr_t xel_addrs[] = { 0xec0000, 0xec4000, 0xec8000, 0xecc000 };
67
68 #define XEL_MODE_RAM_LOWER 0x00
69 #define XEL_MODE_RAM_HIGHER 0x01
70 #define XEL_MODE_UNMAP_RAM 0x00
71 #define XEL_MODE_MAP_RAM 0x02
72 #define XEL_MODE_MPU_000 0x00
73 #define XEL_MODE_MPU_030 0x04
74
75 #define XEL_RAM_ADDR_LOWER 0xbc0000
76 #define XEL_RAM_ADDR_HIGHER 0xfc0000
77
78
79 static paddr_t
80 xel_addr(struct device *parent, struct cfdata *match,
81 struct intio_attach_args *ia)
82 {
83 paddr_t addr = 0;
84
85 if (match->cf_addr == INTIOCF_ADDR_DEFAULT) {
86 int i;
87
88 for (i = 0; i < sizeof(xel_addrs)/sizeof(xel_addrs[0]); i++) {
89 if (xel_probe(xel_addrs[i])) {
90 addr = xel_addrs[i];
91 break;
92 }
93 }
94 } else {
95 if (xel_probe((paddr_t) match->cf_addr))
96 addr = (paddr_t) match->cf_addr;
97 }
98
99 if (addr) {
100 /* found! */
101 ia->ia_addr = (int) addr;
102 ia->ia_size = 0x4000;
103 if (intio_map_allocate_region(parent, ia, INTIO_MAP_TESTONLY)
104 < 0)
105 return 0;
106 else
107 return addr;
108 }
109
110 return 0;
111 }
112
113 extern int *nofault;
114
115 static int
116 xel_probe(paddr_t addr)
117 {
118 u_int32_t b1, b2;
119 volatile u_int16_t *start = (volatile void *)INTIO_ADDR(addr);
120 label_t faultbuf;
121 volatile u_int32_t *sram = (volatile void *)INTIO_ADDR(XEL_RAM_ADDR_HIGHER);
122
123 if (badaddr(start))
124 return 0;
125
126 nofault = (int *) &faultbuf;
127 if (setjmp(&faultbuf)) {
128 nofault = NULL;
129 return 0;
130 }
131
132 b1 = sram[0];
133 b2 = sram[1];
134 /* Try to map the Xellent local memory. */
135 start[0] = XEL_MODE_RAM_HIGHER | XEL_MODE_MAP_RAM | XEL_MODE_MPU_030;
136
137 #if 0
138 /* the contents should be deferent. */
139 if (b1 == sram[0] && b2 == sram[1]) {
140 nofault = (int *) 0;
141 return 0;
142 }
143 #else
144 /* Try to write to the local memory. */
145 sram[0] = 0x55555555;
146 sram[1] = 0xaaaaaaaa;
147 if (sram[0] != 0x55555555 || sram[1] != 0xaaaaaaaa) {
148 sram[0] = b1;
149 sram[1] = b2;
150 nofault = (int *) 0;
151 return 0;
152 }
153 sram[0] = 0xaaaaaaaa;
154 sram[1] = 0x55555555;
155 if (sram[0] != 0xaaaaaaaa || sram[1] != 0x55555555) {
156 sram[0] = b1;
157 sram[1] = b2;
158 nofault = (int *) 0;
159 return 0;
160 }
161 sram[0] = b1;
162 sram[1] = b2;
163 #endif
164
165 /* Unmap. */
166 start[0] = XEL_MODE_UNMAP_RAM | XEL_MODE_MPU_030;
167
168 nofault = NULL;
169 return 1;
170 }
171
172 static int
173 xel_match(struct device *parent, struct cfdata *match, void *aux)
174 {
175 struct intio_attach_args *ia = aux;
176
177 if (strcmp(ia->ia_name, "xel") != 0)
178 return 0;
179
180 if (xel_addr(parent, match, ia)) {
181 #ifdef DIAGNOSTIC
182 if (cputype != CPU_68030)
183 panic("Non-030 Xellent???");
184 #endif
185 return 1;
186 }
187 return 0;
188 }
189
190 static void
191 xel_attach(struct device *parent, struct device *self, void *aux)
192 {
193 struct xel_softc *sc = (void *)self;
194 struct intio_attach_args *ia = aux;
195 struct cfdata *cf = device_cfdata(self);
196 paddr_t addr;
197 int r;
198
199 addr = xel_addr(parent, cf, aux);
200 sc->sc_bst = ia->ia_bst;
201 ia->ia_addr = (int) addr;
202 ia->ia_size = 0x4000;
203 r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE);
204 #ifdef DIAGNOSTIC
205 if (r)
206 panic("IO map for Xellent30 corruption??");
207 #endif
208 printf(": Xellent30 MPU Accelerator.\n");
209
210 return;
211 }
212