1 /* $OpenBSD: xbox.c,v 1.3 2006/06/02 20:00:56 miod Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Driver for the Sun SBus Expansion Subsystem 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/kernel.h> 36 #include <sys/errno.h> 37 #include <sys/ioctl.h> 38 #include <sys/syslog.h> 39 #include <sys/device.h> 40 #include <sys/malloc.h> 41 42 #include <machine/autoconf.h> 43 #include <machine/bus.h> 44 #include <machine/cpu.h> 45 #include <dev/sbus/sbusvar.h> 46 47 #include <dev/sbus/xboxreg.h> 48 #include <dev/sbus/xboxvar.h> 49 50 int xboxmatch(struct device *, void *, void *); 51 void xboxattach(struct device *, struct device *, void *); 52 int xboxprint(void *, const char *); 53 int xbox_fix_range(struct xbox_softc *sc, struct sbus_softc *sbp); 54 55 struct cfattach xbox_ca = { 56 sizeof (struct xbox_softc), xboxmatch, xboxattach 57 }; 58 59 struct cfdriver xbox_cd = { 60 NULL, "xbox", DV_DULL 61 }; 62 63 int 64 xboxmatch(struct device *parent, void *cf, void *aux) 65 { 66 struct sbus_attach_args *sa = aux; 67 68 if (strcmp("SUNW,xbox", sa->sa_name)) 69 return (0); 70 71 return (1); 72 } 73 74 void 75 xboxattach(struct device *parent, struct device *self, void *aux) 76 { 77 struct xbox_softc *sc = (struct xbox_softc *)self; 78 struct sbus_attach_args *sa = aux; 79 int node = sa->sa_node; 80 struct xbox_attach_args xa; 81 bus_space_handle_t write0; 82 char *s; 83 84 s = getpropstring(node, "model"); 85 printf(": model %s", s); 86 87 s = getpropstring(node, "child-present"); 88 if (strcmp(s, "false") == 0) { 89 printf(": no devices\n"); 90 return; 91 } 92 93 sc->sc_key = getpropint(node, "write0-key", -1); 94 sc->sc_node = node; 95 96 /* 97 * Setup transparent access 98 */ 99 100 if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot, 101 sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size, 0, 0, 102 &write0) != 0) { 103 printf(": couldn't map write 0 register\n"); 104 return; 105 } 106 107 bus_space_write_4(sa->sa_bustag, write0, 0, 108 (sc->sc_key << 24) | XAC_CTL1_OFFSET | 109 XBOX_CTL1_CSIE | XBOX_CTL1_TRANSPARENT); 110 bus_space_write_4(sa->sa_bustag, write0, 0, 111 (sc->sc_key << 24) | XBC_CTL1_OFFSET | 112 XBOX_CTL1_XSIE | XBOX_CTL1_XSBRE | XBOX_CTL1_XSSE); 113 DELAY(100); 114 115 bus_space_unmap(sa->sa_bustag, write0, sa->sa_reg[0].sbr_size); 116 117 printf("\n"); 118 119 if (xbox_fix_range(sc, (struct sbus_softc *)parent) != 0) 120 return; 121 122 bzero(&xa, sizeof xa); 123 xa.xa_name = "sbus"; 124 xa.xa_node = node; 125 xa.xa_bustag = sa->sa_bustag; 126 xa.xa_dmatag = sa->sa_dmatag; 127 128 (void)config_found(&sc->sc_dev, (void *)&xa, xboxprint); 129 } 130 131 /* 132 * Fix up our address ranges based on parent address spaces. 133 */ 134 int 135 xbox_fix_range(struct xbox_softc *sc, struct sbus_softc *sbp) 136 { 137 int error, i, j; 138 139 error = getprop(sc->sc_node, "ranges", sizeof(struct sbus_range), 140 &sc->sc_nrange, (void **)&sc->sc_range); 141 if (error != 0) { 142 printf("%s: PROM ranges too large\n", sc->sc_dev.dv_xname); 143 return (error); 144 } 145 146 for (i = 0; i < sc->sc_nrange; i++) { 147 for (j = 0; j < sbp->sc_nrange; j++) { 148 if (sc->sc_range[i].pspace == sbp->sc_range[j].cspace) { 149 sc->sc_range[i].poffset += 150 sbp->sc_range[j].poffset; 151 sc->sc_range[i].pspace = 152 sbp->sc_range[j].pspace; 153 break; 154 } 155 } 156 } 157 158 return (0); 159 } 160 161 int 162 xboxprint(void *args, const char *bus) 163 { 164 struct xbox_attach_args *xa = args; 165 166 if (bus != NULL) 167 printf("%s at %s", xa->xa_name, bus); 168 return (UNCONF); 169 } 170