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
mem_map_in(fcode_env_t * env,fstack_t hi,fstack_t lo,fstack_t len)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
mem_map_out(fcode_env_t * env,fstack_t mcookie,fstack_t len)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
do_get_portid(fcode_env_t * env)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
do_map_in(fcode_env_t * env)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
do_map_out(fcode_env_t * env)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
do_encode_unit(fcode_env_t * env)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
do_decode_unit(fcode_env_t * env)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
do_claim_addr(fcode_env_t * env)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
do_master_interrupt(fcode_env_t * env)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
do_register_vectory_entry(fcode_env_t * env)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
do_get_interrupt_target(fcode_env_t * env)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
do_device_id(fcode_env_t * env)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
_init(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