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