1 /* $OpenBSD: xbox.c,v 1.4 2022/03/13 13:34:54 mpi 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 const 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
xboxmatch(struct device * parent,void * cf,void * aux)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
xboxattach(struct device * parent,struct device * self,void * aux)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
xbox_fix_range(struct xbox_softc * sc,struct sbus_softc * sbp)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
xboxprint(void * args,const char * bus)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