1 /* $NetBSD: xel.c,v 1.14 2008/04/28 20:23:39 martin 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.14 2008/04/28 20:23:39 martin 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