xref: /titanic_52/usr/src/lib/efcode/gp2/gp2.c (revision 0eb822a1c0c2bea495647510b75f77f0e57633eb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 
33 #include <fcode/private.h>
34 #include <fcode/log.h>
35 
36 #include <fcdriver/fcdriver.h>
37 
38 fstack_t
39 mem_map_in(fcode_env_t *env, fstack_t hi, fstack_t lo, fstack_t len)
40 {
41 	private_data_t *pdp = DEVICE_PRIVATE(env);
42 	fc_cell_t virt;
43 	fstack_t mcookie = NULL;
44 	char *service = "map-in";
45 	int error;
46 	int offset = 0;
47 
48 	/*
49 	 * The calculation of the offset, lo and len are left here
50 	 * due to historical precedence.
51 	 */
52 
53 	offset = lo & PAGEOFFSET;
54 	lo &= PAGEMASK;
55 	len = (len + offset + PAGEOFFSET) & PAGEMASK;
56 
57 	error = fc_run_priv(pdp->common, service, 3, 1, fc_size2cell(len),
58 	    fc_uint32_t2cell(hi), fc_uint32_t2cell(lo), &virt);
59 
60 	if (error)
61 		throw_from_fclib(env, 1, "gp2:%s: failed\n", service);
62 
63 	mcookie = mapping_to_mcookie(virt, len, NULL, NULL);
64 
65 	if (mcookie == NULL)
66 		throw_from_fclib(env, 1, "gp2:%s: mapping_to_mcookie failed\n",
67 		    service);
68 
69 	mcookie += offset;
70 
71 	debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %llx -> %x\n", service,
72 	    (uint64_t)virt, (uint32_t)mcookie);
73 
74 	return (mcookie);
75 }
76 
77 static void
78 mem_map_out(fcode_env_t *env, fstack_t mcookie, fstack_t len)
79 {
80 	private_data_t *pdp = DEVICE_PRIVATE(env);
81 	fc_cell_t virt;
82 	char *service = "map-out";
83 	int error;
84 	int offset;
85 
86 	/*
87 	 * The calculation of the offset, lo and len are left here
88 	 * due to historical precedence.
89 	 */
90 
91 	offset = mcookie & PAGEOFFSET;
92 	mcookie &= PAGEMASK;
93 	len = (len + offset + PAGEOFFSET) & PAGEMASK;
94 
95 	if (!is_mcookie(mcookie)) {
96 		log_message(MSG_ERROR, "gp2:%s: %x not an mcookie!\n",
97 		    service, (int)mcookie);
98 		virt = mcookie;
99 	} else {
100 		virt = mcookie_to_addr(mcookie);
101 		debug_msg(DEBUG_REG_ACCESS, "gp2:%s: %x -> %llx\n", service,
102 		    (int)mcookie, (uint64_t)virt);
103 		delete_mapping(mcookie);
104 	}
105 
106 	error = fc_run_priv(pdp->common, service, 2, 0, fc_size2cell(len),
107 	    virt);
108 	if (error)
109 		log_message(MSG_ERROR, "gp2:%s: failed\n", service);
110 }
111 
112 static void
113 do_get_portid(fcode_env_t *env)
114 {
115 	fstack_t	phi, plo, portid;
116 	private_data_t *pdp = DEVICE_PRIVATE(env);
117 
118 	CHECK_DEPTH(env, 2, "gp2:get-portid");
119 	phi = POP(DS);
120 	plo = POP(DS);
121 
122 	portid = ((plo & 0xff800000) >> 23) | ((phi & 1) << 9);
123 	debug_msg(DEBUG_REG_ACCESS, "gp2:get-portid ( %x %x ) -> %x\n",
124 	    (int)phi, (int)plo, (int)portid);
125 	PUSH(DS, portid);
126 }
127 
128 static void
129 do_map_in(fcode_env_t *env)
130 {
131 	fstack_t phi, pmid, plo, len, addr;
132 
133 	CHECK_DEPTH(env, 3, "gp2:map-in");
134 	len = POP(DS);
135 	phi = POP(DS);
136 	plo = POP(DS);
137 	addr = mem_map_in(env, phi, plo, len);
138 	PUSH(DS, addr);
139 }
140 
141 static void
142 do_map_out(fcode_env_t *env)
143 {
144 	fstack_t addr, len;
145 
146 	CHECK_DEPTH(env, 2, "gp2:map-out");
147 	len = POP(DS);
148 	addr = POP(DS);
149 	mem_map_out(env, addr, len);
150 }
151 
152 static void
153 do_encode_unit(fcode_env_t *env)
154 {
155 	char enc_buf[64];
156 	fstack_t hi, mid, lo;
157 	int id, off;
158 
159 	CHECK_DEPTH(env, 2, "gp2:encode-unit");
160 	hi = POP(DS);
161 	lo = POP(DS);
162 
163 	hi  = (hi & 0x00000001);	/* get high order agent id bit */
164 	id = (hi << 9) | (lo >> 23);	/* build extended agent id */
165 	off = lo & 0x7fffff;		/* build config offset */
166 
167 	if (off) {
168 		sprintf(enc_buf, "%x,%x", id, off);
169 	} else {
170 		sprintf(enc_buf, "%x", id);
171 	}
172 	debug_msg(DEBUG_REG_ACCESS, "gp2:encode_unit ( %x %x ) -> '%s'\n",
173 	    (int)hi, (int)lo, enc_buf);
174 	push_a_string(env, STRDUP(enc_buf));
175 }
176 
177 static void
178 do_decode_unit(fcode_env_t *env)
179 {
180 	uint32_t lo, hi;
181 	int agent, offset;
182 	char *buf;
183 
184 	CHECK_DEPTH(env, 2, "gp2:decode-unit");
185 	buf = pop_a_string(env, NULL);
186 	if (sscanf(buf, "%x,%x", &agent, &offset) != 2) {
187 		if (sscanf(buf, "%x", &agent) != 1) {
188 			throw_from_fclib(env, 1, "gp2:decode_unit:%s", buf);
189 		}
190 		offset = 0;
191 	}
192 	lo = offset | (agent << 23);
193 	hi = (agent >> 9) | 0x400;
194 	debug_msg(DEBUG_REG_ACCESS, "gp2:decode_unit ( '%s' ) -> %x %x\n", buf,
195 	    hi, lo);
196 	PUSH(DS, lo);
197 	PUSH(DS, hi);
198 }
199 
200 static void
201 do_claim_addr(fcode_env_t *env)
202 {
203 	fstack_t portid, bar, align, type, size_hi, size_lo;
204 	fc_cell_t lo, hi;
205 	private_data_t *pdp = DEVICE_PRIVATE(env);
206 	char *service = "claim-address";
207 	int error;
208 
209 	CHECK_DEPTH(env, 6, "gp2:claim-address");
210 	portid = POP(DS);
211 	bar = POP(DS);
212 	align = POP(DS);
213 	type = POP(DS);
214 	size_hi = POP(DS);
215 	size_lo = POP(DS);
216 
217 	error = fc_run_priv(pdp->common, service, 6, 2,
218 	    fc_int2cell(portid), fc_int2cell(bar), fc_int2cell(align),
219 	    fc_int2cell(type), fc_int2cell(size_hi), fc_int2cell(size_lo),
220 	    &lo, &hi);
221 
222 	if (error)
223 		throw_from_fclib(env, 1, "gp2:%s: failed\n", service);
224 
225 	debug_msg(DEBUG_REG_ACCESS,
226 	    "gp2:%s ( %x %x %x %x %x %x ) -> %x %x\n", service, (int)portid,
227 	    (int)bar, (int)align, (int)type, (int)size_hi, (int)size_lo,
228 	    (uint32_t)hi, (uint32_t)lo);
229 
230 	PUSH(DS, (uint32_t)lo);
231 	PUSH(DS, (uint32_t)hi);
232 }
233 
234 static void
235 do_master_interrupt(fcode_env_t *env)
236 {
237 	int portid;
238 	token_t xt;
239 
240 	CHECK_DEPTH(env, 2, "gp2:master-interrput");
241 	portid = POP(DS);
242 	xt = POP(DS);
243 	PUSH(DS, FALSE);
244 	debug_msg(DEBUG_REG_ACCESS, "gp2:master-interrupt ( %x %x ) -> %x\n",
245 	    portid, xt, (int)FALSE);
246 }
247 
248 static void
249 do_register_vectory_entry(fcode_env_t *env)
250 {
251 	int ign, ino, level;
252 
253 	CHECK_DEPTH(env, 3, "gp2:register-vector-entry");
254 	ign = POP(DS);
255 	ino = POP(DS);
256 	level = POP(DS);
257 	PUSH(DS, FALSE);
258 	debug_msg(DEBUG_REG_ACCESS, "gp2:register-vector-entry ( %x %x %x ) ->"
259 	    " %x\n", ign, ino, level, (int)FALSE);
260 }
261 
262 static void
263 do_get_interrupt_target(fcode_env_t *env)
264 {
265 	int mid = 0;
266 
267 	PUSH(DS, mid);
268 	debug_msg(DEBUG_REG_ACCESS, "gp2:get-interrupt-target ( ) -> %x\n",
269 	    mid);
270 }
271 
272 static void
273 do_device_id(fcode_env_t *env)
274 {
275 	fstack_t	phi, plo, addr;
276 	fc_cell_t	virtaddr;
277 	private_data_t *pdp = DEVICE_PRIVATE(env);
278 	uint64_t	wci_id_reg;
279 	int		rc, parid;
280 
281 	CHECK_DEPTH(env, 2, "gp2:device-id");
282 	phi = POP(DS);
283 	plo = POP(DS);
284 
285 	PUSH(DS, plo);
286 	PUSH(DS, phi);
287 	PUSH(DS, 0x100);
288 
289 	do_map_in(env);
290 
291 	addr = POP(DS);
292 
293 	virtaddr = mcookie_to_addr(addr);
294 
295 	/* Try to read the wci_id register */
296 	rc = fc_run_priv(pdp->common, "rx@", 1, 1, virtaddr + 0xe0,
297 		    &wci_id_reg);
298 
299 	mem_map_out(env, addr, 0x100);
300 
301 	/*
302 	 * Get the part id from the jtag ID register
303 	 */
304 	parid = ((wci_id_reg >> 12) & 0xffff);
305 
306 	if (!rc && parid == 0x4478) {
307 		debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-wci\n");
308 		push_a_string(env, "SUNW,wci");
309 	} else {
310 		debug_msg(DEBUG_FIND_FCODE, "gp2: do_device_id: gp2-pci\n");
311 		push_a_string(env, "gp2-pci");
312 	}
313 }
314 
315 #pragma init(_init)
316 
317 static void
318 _init(void)
319 {
320 	fcode_env_t *env = initial_env;
321 
322 	ASSERT(env);
323 	ASSERT(env->current_device);
324 	NOTICE;
325 
326 	create_int_prop(env, "#address-cells", 2);
327 
328 	FORTH(0,	"map-in",		do_map_in);
329 	FORTH(0,	"get-portid",		do_get_portid);
330 	FORTH(0,	"map-out",		do_map_out);
331 	FORTH(0,	"decode-unit",		do_decode_unit);
332 	FORTH(0,	"encode-unit",		do_encode_unit);
333 	FORTH(0,	"claim-address",	do_claim_addr);
334 	FORTH(0,	"master-interrupt",	do_master_interrupt);
335 	FORTH(0,	"register-vector-entry", do_register_vectory_entry);
336 	FORTH(0,	"get-interrupt-target",	do_get_interrupt_target);
337 	FORTH(0,	"device-id",		do_device_id);
338 
339 	install_dma_methods(env);
340 
341 }
342