4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include <fcode/private.h>
33 #include <fcode/log.h>
35 #include <fcdriver/fcdriver.h>
37 #include <sys/opl_cfg.h>
39 /* VA for HardWare Descriptor */
40 static hwd_cmu_chan_t hwd_va_cmu
;
41 static hwd_leaf_t hwd_va_pci
;
43 /* Macro to get I/O portid */
44 #define DO_GET_IO_PORTID(env, lo, hi, portid) \
47 do_get_io_portid(env); \
48 portid = (uint32_t)POP(DS)
51 mem_map_in(fcode_env_t
*env
, fstack_t hi
, fstack_t lo
, fstack_t len
)
53 private_data_t
*pdp
= DEVICE_PRIVATE(env
);
55 fstack_t mcookie
= NULL
;
56 char *service
= "map-in";
61 * The calculation of the offset, lo and len are left here
62 * due to historical precedence.
65 offset
= lo
& PAGEOFFSET
;
67 len
= (len
+ offset
+ PAGEOFFSET
) & PAGEMASK
;
69 error
= fc_run_priv(pdp
->common
, service
, 3, 1, fc_size2cell(len
),
70 fc_uint32_t2cell(hi
), fc_uint32_t2cell(lo
), &virt
);
73 throw_from_fclib(env
, 1, "jupiter:%s: failed\n", service
);
75 mcookie
= mapping_to_mcookie(virt
, len
, NULL
, NULL
);
78 throw_from_fclib(env
, 1,
79 "jupiter:%s: mapping_to_mcookie failed\n", service
);
83 debug_msg(DEBUG_REG_ACCESS
, "jupiter:%s: %llx -> %x\n", service
,
84 (long long)virt
, (uint32_t)mcookie
);
90 mem_map_out(fcode_env_t
*env
, fstack_t mcookie
, fstack_t len
)
92 private_data_t
*pdp
= DEVICE_PRIVATE(env
);
94 char *service
= "map-out";
99 * The calculation of the offset, lo and len are left here
100 * due to historical precedence.
103 offset
= mcookie
& PAGEOFFSET
;
105 len
= (len
+ offset
+ PAGEOFFSET
) & PAGEMASK
;
107 if (!is_mcookie(mcookie
)) {
108 log_message(MSG_ERROR
, "jupiter:%s: %x not an mcookie!\n",
109 service
, (int)mcookie
);
112 virt
= mcookie_to_addr(mcookie
);
113 debug_msg(DEBUG_REG_ACCESS
, "jupiter:%s: %x -> %llx\n",
114 service
, (int)mcookie
, (long long)virt
);
115 delete_mapping(mcookie
);
118 error
= fc_run_priv(pdp
->common
, service
, 2, 0,
119 fc_size2cell(len
), virt
);
121 log_message(MSG_ERROR
, "jupiter:%s: failed\n", service
);
125 do_map_in(fcode_env_t
*env
)
127 fstack_t phi
, plo
, len
, addr
;
129 CHECK_DEPTH(env
, 3, "jupiter:map-in");
133 addr
= mem_map_in(env
, phi
, plo
, len
);
138 do_map_out(fcode_env_t
*env
)
142 CHECK_DEPTH(env
, 2, "jupiter:map-out");
145 mem_map_out(env
, addr
, len
);
149 do_get_io_portid(fcode_env_t
*env
)
152 unsigned int portid
, lsb
, ch
, leaf
;
154 CHECK_DEPTH(env
, 2, "jupiter:get-portid");
159 lsb
= OPL_ADDR_TO_LSB(phi
);
160 ch
= OPL_ADDR_TO_CHANNEL(phi
);
161 leaf
= OPL_ADDR_TO_LEAF(phi
, plo
);
163 portid
= OPL_IO_PORTID(lsb
, ch
, leaf
);
165 debug_msg(DEBUG_REG_ACCESS
, "jupiter:get-portid ( %x %x ) -> %x\n",
166 (int)phi
, (int)plo
, (int)portid
);
171 do_encode_unit(fcode_env_t
*env
)
178 CHECK_DEPTH(env
, 2, "jupiter:encode-unit");
182 off
= (long long)(((hi
& 0x1F) << 32) | lo
);
184 /* Convert physical address to portid */
185 DO_GET_IO_PORTID(env
, lo
, hi
, id
);
188 (void) sprintf(enc_buf
, "%x,%llx", id
, off
);
190 (void) sprintf(enc_buf
, "%x", id
);
193 debug_msg(DEBUG_REG_ACCESS
, "jupiter:encode_unit ( %x %x ) -> '%s'\n",
194 (uint32_t)hi
, (uint32_t)lo
, enc_buf
);
196 push_a_string(env
, STRDUP(enc_buf
));
200 do_decode_unit(fcode_env_t
*env
)
204 unsigned int portid
, lsb
, ch
;
207 CHECK_DEPTH(env
, 2, "jupiter:decode-unit");
209 buf
= pop_a_string(env
, NULL
);
210 if (sscanf(buf
, "%x,%llx", &portid
, &lo
) != 2) {
211 if (sscanf(buf
, "%x", &portid
) != 1) {
212 throw_from_fclib(env
, 1, "jupiter:decode_unit:%s",
218 lsb
= OPL_IO_PORTID_TO_LSB(portid
);
219 ch
= OPL_PORTID_TO_CHANNEL(portid
);
220 hi
= OPL_ADDR_HI(lsb
, ch
);
222 debug_msg(DEBUG_REG_ACCESS
,
223 "jupiter:decode_unit ( '%s' ) -> %x %llx\n", buf
, hi
, lo
);
225 PUSH(DS
, (fstack_t
)lo
);
226 PUSH(DS
, (fstack_t
)hi
);
230 do_device_id(fcode_env_t
*env
)
232 common_data_t
*cdp
= COMMON_PRIVATE(env
);
236 uint32_t portid
, ch
, leaf
;
238 CHECK_DEPTH(env
, 2, "jupiter:device-id");
244 if (cdp
&& cdp
->fc
.unit_address
&&
245 ((buf
= strdup(cdp
->fc
.unit_address
)) != NULL
)) {
247 * Get portid number from unit_address
248 * Because of no leaf information in physical address
250 if (sscanf(buf
, "%x,%llx", &portid
, &lo
) != 2) {
251 if (sscanf(buf
, "%x", &portid
) != 1) {
252 throw_from_fclib(env
, 1,
253 "jupiter:do_device_id: invalid %s", buf
);
258 * Non existence unit_address case.
259 * Convert physical address to portid.
261 throw_from_fclib(env
, 1,
262 "jupiter:do_device_id: failed unit address");
263 DO_GET_IO_PORTID(env
, lo
, hi
, portid
);
266 debug_msg(DEBUG_FIND_FCODE
,
267 "jupiter:do_device_id:(%x,%llx)\n", portid
, lo
);
269 /* Pick up each ID from portid */
270 ch
= OPL_PORTID_TO_CHANNEL(portid
);
271 leaf
= OPL_PORTID_TO_LEAF(portid
);
273 if (ch
== OPL_CMU_CHANNEL
) {
275 * CMU-CH: PCICMU CHANNEL
277 debug_msg(DEBUG_FIND_FCODE
,
278 "jupiter:do_device_id:cmu-ch\n");
279 push_a_string(env
, "cmu-ch");
280 } else if (OPL_OBERON_CHANNEL(ch
) && OPL_VALID_LEAF(leaf
)) {
282 * PCI-CH: Oberon Leaves CHANNEL
286 debug_msg(DEBUG_FIND_FCODE
,
287 "jupiter:do_device_id:jup-oberon-pci1\n");
288 push_a_string(env
, "jup-oberon-pci1");
291 debug_msg(DEBUG_FIND_FCODE
,
292 "jupiter:do_device_id:jup-oberon-pci0\n");
293 push_a_string(env
, "jup-oberon-pci0");
296 /* Not matched to any channels */
297 throw_from_fclib(env
, 1,
298 "jupiter:do_device_id: invalid portid %x", portid
);
299 push_a_string(env
, "");
302 /* Free the duplicated buf */
308 do_get_hwd_va(fcode_env_t
*env
)
310 private_data_t
*pdp
= DEVICE_PRIVATE(env
);
311 char *service
= "get-hwd-va";
319 CHECK_DEPTH(env
, 2, "jupiter:get-hwd-va");
321 /* Get a portid with string format */
322 buf
= pop_a_string(env
, NULL
);
324 /* Convert to the integer from the string */
325 if (sscanf(buf
, "%x", &portid
) != 1) {
326 throw_from_fclib(env
, 1, "jupiter:%s: invalid portid",
330 ch
= OPL_PORTID_TO_CHANNEL(portid
);
331 if (!OPL_VALID_CHANNEL(ch
)) {
332 throw_from_fclib(env
, 1, "jupiter:%s: invalid poritd",
338 if (ch
== OPL_CMU_CHANNEL
) {
339 hwd_va
= (void *)&hwd_va_cmu
;
341 hwd_va
= (void *)&hwd_va_pci
;
345 * Get the virtual address of hwd specified with portid.
347 error
= fc_run_priv(pdp
->common
, service
, 2, 1,
348 fc_uint32_t2cell(portid
), fc_ptr2cell(hwd_va
), &status
);
350 if (error
|| !status
)
351 throw_from_fclib(env
, 1, "jupiter:%s: failed\n", service
);
354 PUSH(DS
, (fstack_t
)hwd_va
);
358 do_get_intrp_name(fcode_env_t
*env
)
361 * Just pass the "eFCode" string.
364 debug_msg(DEBUG_FIND_FCODE
,
365 "jupiter: do_get_intrp_name: eFCode\n");
367 push_a_string(env
, "eFCode");
371 do_master_interrupt(fcode_env_t
*env
)
373 private_data_t
*pdp
= DEVICE_PRIVATE(env
);
374 char *service
= "master-interrupt";
380 CHECK_DEPTH(env
, 2, "jupiter:master-interrupt");
385 * Install the master interrupt handler for this port id.
387 error
= fc_run_priv(pdp
->common
, service
, 2, 1,
388 fc_uint32_t2cell(portid
), fc_uint32_t2cell(xt
), &status
);
390 if (error
|| !status
)
391 throw_from_fclib(env
, 1, "jupiter:%s: failed\n", service
);
395 debug_msg(DEBUG_REG_ACCESS
,
396 "jupiter:master-interrupt ( %x %x ) -> %x\n",
397 portid
, xt
, (int)FALSE
);
401 do_register_vector_entry(fcode_env_t
*env
)
405 CHECK_DEPTH(env
, 3, "jupiter:register-vector-entry");
411 debug_msg(DEBUG_REG_ACCESS
,
412 "jupiter:register-vector-entry ( %x %x %x ) -> %x\n",
413 ign
, ino
, level
, (int)FALSE
);
417 do_get_interrupt_target(fcode_env_t
*env
)
422 debug_msg(DEBUG_REG_ACCESS
,
423 "jupiter:get-interrupt-target ( ) -> %x\n", mid
);
432 fcode_env_t
*env
= initial_env
;
435 ASSERT(env
->current_device
);
438 create_int_prop(env
, "#address-cells", 2);
440 FORTH(0, "map-in", do_map_in
);
441 FORTH(0, "map-out", do_map_out
);
442 FORTH(0, "get-portid", do_get_io_portid
);
443 FORTH(0, "decode-unit", do_decode_unit
);
444 FORTH(0, "encode-unit", do_encode_unit
);
445 FORTH(0, "device-id", do_device_id
);
446 FORTH(0, "get-hwd-va", do_get_hwd_va
);
447 FORTH(0, "get-fcinterp-name", do_get_intrp_name
);
448 FORTH(0, "master-interrupt", do_master_interrupt
);
449 FORTH(0, "register-vector-entry", do_register_vector_entry
);
450 FORTH(0, "get-interrupt-target", do_get_interrupt_target
);