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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
41 #include <fcode/private.h>
42 #include <fcode/log.h>
44 #include <fcdriver/fcdriver.h>
46 static char *pkg_my_args
;
47 static char fcode_dev
[] = "/dev/fcode";
50 dot_request(fcode_env_t
*env
)
52 common_data_t
*cdp
= env
->private;
54 log_message(MSG_INFO
, "request: cfgadd: %x fc_size: %x unitadd: %s"
55 " attach: %x args: '%s'\n", cdp
->fc
.config_address
,
56 cdp
->fc
.fcode_size
, cdp
->fc
.unit_address
, cdp
->attach
,
57 pkg_my_args
? pkg_my_args
: "<null>");
61 * Get next request from /dev/fcode.
64 fc_get_request(common_data_t
*cdp
)
69 if (cdp
->fcode_fd
< 0) {
70 log_message(MSG_FATAL
, "fc_get_request: fcode_fd not open\n");
74 if ((nbytes
= read(cdp
->fcode_fd
, &c
, sizeof (c
))) < 0) {
75 log_perror(MSG_FATAL
, "read(%s) failed", fcode_dev
);
79 if (ioctl(cdp
->fcode_fd
, FC_GET_PARAMETERS
, &cdp
->fc
) < 0) {
80 log_perror(MSG_FATAL
, "ioctl(FC_GET_PARAMETERS) failed");
84 if ((cdp
->attach
= fc_get_ap(cdp
)) == NULL
)
91 get_my_args(fcode_env_t
*env
)
93 common_data_t
*cdp
= env
->private;
97 * Don't get if already set.
102 if (ioctl(cdp
->fcode_fd
, FC_GET_MY_ARGS
, buffer
) < 0) {
105 pkg_my_args
= STRDUP(buffer
);
109 set_my_args(fcode_env_t
*env
)
115 pkg_my_args
= pop_a_duped_string(env
, NULL
);
119 dot_my_args(fcode_env_t
*env
)
122 log_message(MSG_INFO
, "%s\n", pkg_my_args
);
124 log_message(MSG_INFO
, "NULL\n");
128 push_my_args(fcode_env_t
*env
)
130 push_a_string(env
, pkg_my_args
);
134 get_fcode_from_device(fcode_env_t
*env
)
136 common_data_t
*cdp
= env
->private;
138 static char func_name
[] = "get_fcode_from_device";
139 fc_fcode_info_t fcode_info
;
141 if (!cdp
->fc
.fcode_size
) {
142 debug_msg(DEBUG_FIND_FCODE
, "%s: Fcode zero length\n",
144 push_a_string(env
, NULL
);
147 fcode_info
.fcode_size
= cdp
->fc
.fcode_size
;
148 fcode_info
.fcode_ptr
= MALLOC(cdp
->fc
.fcode_size
);
149 if (ioctl(cdp
->fcode_fd
, FC_GET_FCODE_DATA
, &fcode_info
) < 0) {
150 log_perror(MSG_FATAL
, "ioctl(FC_GET_FCODE_DATA) failed");
151 push_a_string(env
, NULL
);
153 debug_msg(DEBUG_FIND_FCODE
,
154 "%s: Fcode from device: len: 0x%x\n", func_name
,
155 (int)cdp
->fc
.fcode_size
);
156 PUSH(DS
, (fstack_t
)fcode_info
.fcode_ptr
);
157 PUSH(DS
, (fstack_t
)cdp
->fc
.fcode_size
);
162 save_fcode_to_file(fcode_env_t
*env
)
168 CHECK_DEPTH(env
, 4, "save-fcode-to-file");
169 if ((fname
= pop_a_string(env
, NULL
)) == NULL
) {
170 log_message(MSG_DEBUG
, "fname?\n");
173 if ((buf
= pop_a_string(env
, &len
)) == NULL
) {
174 log_message(MSG_INFO
, "buf?\n");
177 if ((fd
= fopen(fname
, "w")) == NULL
) {
178 log_perror(MSG_DEBUG
, "Save_fcode_to_file: Can't open '%s'",
182 log_message(MSG_INFO
, "Fcode %p,%x to file '%s'\n", buf
, len
, fname
);
183 fwrite(buf
, len
, sizeof (char), fd
);
188 exec_fcode_builtin_method(fcode_env_t
*env
)
192 extern void exec_parent_method(fcode_env_t
*);
193 extern void exec_builtin_driver(fcode_env_t
*);
195 method
= (char *)DS
[-1];
196 exec_parent_method(env
);
199 debug_msg(DEBUG_FIND_FCODE
, "builtin-driver: %s -> %s found\n",
200 method
, (char *)DS
[-1]);
201 exec_builtin_driver(env
);
202 debug_msg(DEBUG_FIND_FCODE
, "builtin-driver-exec: %p %x\n",
203 (char *)DS
[-1], (int)TOS
);
205 debug_msg(DEBUG_FIND_FCODE
, "builtin-driver: %s not found\n",
212 get_fcode_from_filesystem(fcode_env_t
*env
)
215 char *method
, *fc_name
, *path
;
216 extern void exec_parent_method(fcode_env_t
*);
217 static char fname
[] = "get-fcode-from-filesystem";
219 method
= (char *)DS
[-1];
220 exec_parent_method(env
);
223 fc_name
= pop_a_string(env
, NULL
);
224 debug_msg(DEBUG_FIND_FCODE
, "%s: %s -> %s found\n", fname
,
226 if ((path
= search_for_fcode_file(env
, fc_name
)) != NULL
) {
227 debug_msg(DEBUG_FIND_FCODE
, "%s: file: %s FOUND\n",
229 push_a_string(env
, path
);
232 debug_msg(DEBUG_FIND_FCODE
, "%s: file '%s' not found\n",
237 debug_msg(DEBUG_FIND_FCODE
, "%s: method '%s' not found\n",
244 * Looks for "device-id" and "class-id" methods in parent, if there,
245 * executes them to get "builtin drivers" file name or method name, then
246 * executes the builtin-driver method. If both those fail, try getting the
247 * fcode from the device. Note that we sleaze resetting the data stack.
248 * This would be cleaner if we had a way to do the equivalent of "catch/throw"
249 * from within C code.
252 find_fcode(fcode_env_t
*env
)
254 fstack_t
*dp
= env
->ds
;
255 common_data_t
*cdp
= env
->private;
256 static char func_name
[] = "find_fcode";
260 push_a_string(env
, "device-id");
261 get_fcode_from_filesystem(env
);
263 debug_msg(DEBUG_FIND_FCODE
, "%s: FS dev-id: len: 0x%x\n",
270 push_a_string(env
, "class-id");
271 get_fcode_from_filesystem(env
);
273 debug_msg(DEBUG_FIND_FCODE
, "%s: FS cls-id len: 0x%x\n",
279 get_fcode_from_device(env
);
281 debug_msg(DEBUG_FIND_FCODE
, "%s: DEV fcode len: 0x%x\n",
288 push_a_string(env
, "device-id");
289 exec_fcode_builtin_method(env
);
291 debug_msg(DEBUG_FIND_FCODE
, "%s: dropin dev-id len: 0x%x\n",
298 push_a_string(env
, "class-id");
299 exec_fcode_builtin_method(env
);
301 debug_msg(DEBUG_FIND_FCODE
, "%s: dropin cls-id len: 0x%x\n",
306 debug_msg(DEBUG_FIND_FCODE
, "%s: not found\n", func_name
);
308 if (ioctl(cdp
->fcode_fd
, FC_SET_FCODE_ERROR
, &error
) < 0) {
309 log_perror(MSG_FATAL
, "ioctl(FC_SET_FCODE_ERROR) failed");
315 open_fcode_dev(fcode_env_t
*env
)
317 common_data_t
*cdp
= env
->private;
319 if ((cdp
->fcode_fd
= open(fcode_dev
, O_RDONLY
)) < 0)
320 log_perror(MSG_ERROR
, "Can't open '%s'", fcode_dev
);
321 return (cdp
->fcode_fd
>= 0);
325 get_request(fcode_env_t
*env
)
327 common_data_t
*cdp
= env
->private;
329 if (cdp
->fcode_fd
>= 0)
330 close(cdp
->fcode_fd
);
331 if (!open_fcode_dev(env
))
333 if (!fc_get_request(cdp
)) {
334 log_message(MSG_FATAL
, "fc_get_request failed\n");
340 DEBUGF(UPLOAD
, dot_request(env
));
344 * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened
345 * file descriptor is fd 0.
348 get_efdaemon_request(fcode_env_t
*env
)
350 common_data_t
*cdp
= env
->private;
353 if (ioctl(cdp
->fcode_fd
, FC_GET_PARAMETERS
, &cdp
->fc
) < 0) {
354 log_perror(MSG_FATAL
, "ioctl(FC_GET_PARAMETERS) failed");
358 if ((cdp
->attach
= fc_get_ap(cdp
)) == NULL
)
363 DEBUGF(UPLOAD
, dot_request(env
));
367 process_request(fcode_env_t
*env
)
369 common_data_t
*cdp
= env
->private;
374 install_builtin_nodes(env
);
376 push_a_string(env
, cdp
->fc
.unit_address
);
377 if ((path
= get_path(env
, env
->attachment_pt
)) == NULL
) {
378 log_message(MSG_FATAL
, "Can't get_path of"
379 " attachment_pt %p\n", env
->attachment_pt
);
382 debug_msg(DEBUG_UPLOAD
, "Attach Point: %s\n", path
);
384 push_a_string(env
, path
);
390 debug_msg(DEBUG_UPLOAD
, "Zero length Fcode\n");
394 debug_msg(DEBUG_UPLOAD
, "byte-load fcode_len: %x\n",
402 debug_msg(DEBUG_UPLOAD
, "Upload Done\n");
406 finish_request(fcode_env_t
*env
)
408 common_data_t
*cdp
= env
->private;
410 close(cdp
->fcode_fd
);
414 * Non-daemon "do-request", for debugging
417 do_request(fcode_env_t
*env
)
420 process_request(env
);
425 * This process one request from efdaemon, we know that /dev/fcode is already
426 * open and passed in fd0 (stdin). If it's not, we throw up our hands.
429 run_one_efdaemon_request(fcode_env_t
*env
)
431 get_efdaemon_request(env
);
432 process_request(env
);
438 probe_space(fcode_env_t
*env
)
443 error
= fc_run_priv(env
->private, FC_PROBE_SPACE
, 0, 1, &cfg
);
445 throw_from_fclib(env
, 1, "FC_PROBE_SPACE failed\n");
446 PUSH(DS
, fc_cell2uint32_t(cfg
));
454 fcode_env_t
*env
= initial_env
;
459 FORTH(0, "get-fcode-from-device", get_fcode_from_device
);
460 FORTH(0, "save-fcode-to-file", save_fcode_to_file
);
461 FORTH(0, "get-my-args", get_my_args
);
462 FORTH(0, "set-my-args", set_my_args
);
463 FORTH(0, ".my-args", dot_my_args
);
464 FORTH(0, ".request", dot_request
);
465 FORTH(0, "get-request", get_request
);
466 FORTH(0, "process-request", process_request
);
467 FORTH(0, "finish-request", finish_request
);
468 FORTH(0, "do-request", do_request
);
469 FORTH(0, "find-fcode", find_fcode
);
470 FORTH(0, "exec-fcode-builtin-method", exec_fcode_builtin_method
);
471 FORTH(0, "run-one-efdaemon-request", run_one_efdaemon_request
);
472 FORTH(0, "get-efdaemon-request", get_efdaemon_request
);
473 FORTH(0, "probe-space", probe_space
);