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