xref: /openbsd/sys/dev/sbus/xbox.c (revision 22e452df)
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