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 <fcntl.h>
30*0Sstevel@tonic-gate #include <unistd.h>
31*0Sstevel@tonic-gate #include <stdlib.h>
32*0Sstevel@tonic-gate #include <stdio.h>
33*0Sstevel@tonic-gate #include <strings.h>
34*0Sstevel@tonic-gate #include <errno.h>
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <sys/mman.h>
37*0Sstevel@tonic-gate #include <sys/pci.h>
38*0Sstevel@tonic-gate #include <sys/stat.h>
39*0Sstevel@tonic-gate #include <sys/wait.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #include <fcode/private.h>
42*0Sstevel@tonic-gate #include <fcode/log.h>
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate #include <fcdriver/fcdriver.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate static char *pkg_my_args;
47*0Sstevel@tonic-gate static char fcode_dev[] = "/dev/fcode";
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate static void
50*0Sstevel@tonic-gate dot_request(fcode_env_t *env)
51*0Sstevel@tonic-gate {
52*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate 	log_message(MSG_INFO, "request: cfgadd: %x fc_size: %x unitadd: %s"
55*0Sstevel@tonic-gate 	    " attach: %x args: '%s'\n", cdp->fc.config_address,
56*0Sstevel@tonic-gate 	    cdp->fc.fcode_size, cdp->fc.unit_address, cdp->attach,
57*0Sstevel@tonic-gate 	    pkg_my_args ? pkg_my_args : "<null>");
58*0Sstevel@tonic-gate }
59*0Sstevel@tonic-gate 
60*0Sstevel@tonic-gate /*
61*0Sstevel@tonic-gate  * Get next request from /dev/fcode.
62*0Sstevel@tonic-gate  */
63*0Sstevel@tonic-gate int
64*0Sstevel@tonic-gate fc_get_request(common_data_t *cdp)
65*0Sstevel@tonic-gate {
66*0Sstevel@tonic-gate 	char c;
67*0Sstevel@tonic-gate 	int nbytes;
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate 	if (cdp->fcode_fd < 0) {
70*0Sstevel@tonic-gate 		log_message(MSG_FATAL, "fc_get_request: fcode_fd not open\n");
71*0Sstevel@tonic-gate 		return (0);
72*0Sstevel@tonic-gate 	}
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 	if ((nbytes = read(cdp->fcode_fd, &c, sizeof (c))) < 0) {
75*0Sstevel@tonic-gate 		log_perror(MSG_FATAL, "read(%s) failed", fcode_dev);
76*0Sstevel@tonic-gate 		return (0);
77*0Sstevel@tonic-gate 	}
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
80*0Sstevel@tonic-gate 		log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
81*0Sstevel@tonic-gate 		return (0);
82*0Sstevel@tonic-gate 	}
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate 	if ((cdp->attach = fc_get_ap(cdp)) == NULL)
85*0Sstevel@tonic-gate 		return (0);
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	return (1);
88*0Sstevel@tonic-gate }
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate static void
91*0Sstevel@tonic-gate get_my_args(fcode_env_t *env)
92*0Sstevel@tonic-gate {
93*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
94*0Sstevel@tonic-gate 	char buffer[BUFSIZ];
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	/*
97*0Sstevel@tonic-gate 	 * Don't get if already set.
98*0Sstevel@tonic-gate 	 */
99*0Sstevel@tonic-gate 	if (pkg_my_args)
100*0Sstevel@tonic-gate 		return;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	if (ioctl(cdp->fcode_fd, FC_GET_MY_ARGS, buffer) < 0) {
103*0Sstevel@tonic-gate 		return;
104*0Sstevel@tonic-gate 	}
105*0Sstevel@tonic-gate 	pkg_my_args = STRDUP(buffer);
106*0Sstevel@tonic-gate }
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate static void
109*0Sstevel@tonic-gate set_my_args(fcode_env_t *env)
110*0Sstevel@tonic-gate {
111*0Sstevel@tonic-gate 	if (pkg_my_args)
112*0Sstevel@tonic-gate 		FREE(pkg_my_args);
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	parse_word(env);
115*0Sstevel@tonic-gate 	pkg_my_args = pop_a_duped_string(env, NULL);
116*0Sstevel@tonic-gate }
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate static void
119*0Sstevel@tonic-gate dot_my_args(fcode_env_t *env)
120*0Sstevel@tonic-gate {
121*0Sstevel@tonic-gate 	if (pkg_my_args)
122*0Sstevel@tonic-gate 		log_message(MSG_INFO, "%s\n", pkg_my_args);
123*0Sstevel@tonic-gate 	else
124*0Sstevel@tonic-gate 		log_message(MSG_INFO, "NULL\n");
125*0Sstevel@tonic-gate }
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate void
128*0Sstevel@tonic-gate push_my_args(fcode_env_t *env)
129*0Sstevel@tonic-gate {
130*0Sstevel@tonic-gate 	push_a_string(env, pkg_my_args);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate void
134*0Sstevel@tonic-gate get_fcode_from_device(fcode_env_t *env)
135*0Sstevel@tonic-gate {
136*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
137*0Sstevel@tonic-gate 	char *p, *buf;
138*0Sstevel@tonic-gate 	static char func_name[] = "get_fcode_from_device";
139*0Sstevel@tonic-gate 	fc_fcode_info_t fcode_info;
140*0Sstevel@tonic-gate 
141*0Sstevel@tonic-gate 	if (!cdp->fc.fcode_size) {
142*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: Fcode zero length\n",
143*0Sstevel@tonic-gate 		    func_name);
144*0Sstevel@tonic-gate 		push_a_string(env, NULL);
145*0Sstevel@tonic-gate 		return;
146*0Sstevel@tonic-gate 	}
147*0Sstevel@tonic-gate 	fcode_info.fcode_size = cdp->fc.fcode_size;
148*0Sstevel@tonic-gate 	fcode_info.fcode_ptr = MALLOC(cdp->fc.fcode_size);
149*0Sstevel@tonic-gate 	if (ioctl(cdp->fcode_fd, FC_GET_FCODE_DATA, &fcode_info) < 0) {
150*0Sstevel@tonic-gate 		log_perror(MSG_FATAL, "ioctl(FC_GET_FCODE_DATA) failed");
151*0Sstevel@tonic-gate 		push_a_string(env, NULL);
152*0Sstevel@tonic-gate 	} else {
153*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE,
154*0Sstevel@tonic-gate 		    "%s: Fcode from device: len: 0x%x\n", func_name,
155*0Sstevel@tonic-gate 		    (int)cdp->fc.fcode_size);
156*0Sstevel@tonic-gate 		PUSH(DS, (fstack_t)fcode_info.fcode_ptr);
157*0Sstevel@tonic-gate 		PUSH(DS, (fstack_t)cdp->fc.fcode_size);
158*0Sstevel@tonic-gate 	}
159*0Sstevel@tonic-gate }
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate static void
162*0Sstevel@tonic-gate save_fcode_to_file(fcode_env_t *env)
163*0Sstevel@tonic-gate {
164*0Sstevel@tonic-gate 	char *buf, *fname;
165*0Sstevel@tonic-gate 	int len;
166*0Sstevel@tonic-gate 	FILE *fd;
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate 	CHECK_DEPTH(env, 4, "save-fcode-to-file");
169*0Sstevel@tonic-gate 	if ((fname = pop_a_string(env, NULL)) == NULL) {
170*0Sstevel@tonic-gate 		log_message(MSG_DEBUG, "fname?\n");
171*0Sstevel@tonic-gate 		return;
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 	if ((buf = pop_a_string(env, &len)) == NULL) {
174*0Sstevel@tonic-gate 		log_message(MSG_INFO, "buf?\n");
175*0Sstevel@tonic-gate 		return;
176*0Sstevel@tonic-gate 	}
177*0Sstevel@tonic-gate 	if ((fd = fopen(fname, "w")) == NULL) {
178*0Sstevel@tonic-gate 		log_perror(MSG_DEBUG, "Save_fcode_to_file: Can't open '%s'",
179*0Sstevel@tonic-gate 		    fname);
180*0Sstevel@tonic-gate 		return;
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 	log_message(MSG_INFO, "Fcode %p,%x to file '%s'\n", buf, len, fname);
183*0Sstevel@tonic-gate 	fwrite(buf, len, sizeof (char), fd);
184*0Sstevel@tonic-gate 	fclose(fd);
185*0Sstevel@tonic-gate }
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate void
188*0Sstevel@tonic-gate exec_fcode_builtin_method(fcode_env_t *env)
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate 	fstack_t d;
191*0Sstevel@tonic-gate 	char *method;
192*0Sstevel@tonic-gate 	extern void exec_parent_method(fcode_env_t *);
193*0Sstevel@tonic-gate 	extern void exec_builtin_driver(fcode_env_t *);
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 	method = (char *)DS[-1];
196*0Sstevel@tonic-gate 	exec_parent_method(env);
197*0Sstevel@tonic-gate 	d = POP(DS);
198*0Sstevel@tonic-gate 	if (d) {
199*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s -> %s found\n",
200*0Sstevel@tonic-gate 		    method, (char *)DS[-1]);
201*0Sstevel@tonic-gate 		exec_builtin_driver(env);
202*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver-exec: %p %x\n",
203*0Sstevel@tonic-gate 		    (char *)DS[-1], (int)TOS);
204*0Sstevel@tonic-gate 	} else {
205*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "builtin-driver: %s not found\n",
206*0Sstevel@tonic-gate 		    method);
207*0Sstevel@tonic-gate 		PUSH(DS, FALSE);
208*0Sstevel@tonic-gate 	}
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate void
212*0Sstevel@tonic-gate get_fcode_from_filesystem(fcode_env_t *env)
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate 	fstack_t d;
215*0Sstevel@tonic-gate 	char *method, *fc_name, *path;
216*0Sstevel@tonic-gate 	extern void exec_parent_method(fcode_env_t *);
217*0Sstevel@tonic-gate 	static char fname[] = "get-fcode-from-filesystem";
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 	method = (char *)DS[-1];
220*0Sstevel@tonic-gate 	exec_parent_method(env);
221*0Sstevel@tonic-gate 	d = POP(DS);
222*0Sstevel@tonic-gate 	if (d) {
223*0Sstevel@tonic-gate 		fc_name = pop_a_string(env, NULL);
224*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: %s -> %s found\n", fname,
225*0Sstevel@tonic-gate 		    method, fc_name);
226*0Sstevel@tonic-gate 		if ((path = search_for_fcode_file(env, fc_name)) != NULL) {
227*0Sstevel@tonic-gate 			debug_msg(DEBUG_FIND_FCODE, "%s: file: %s FOUND\n",
228*0Sstevel@tonic-gate 			    fname, path);
229*0Sstevel@tonic-gate 			push_a_string(env, path);
230*0Sstevel@tonic-gate 			load_file(env);
231*0Sstevel@tonic-gate 		} else {
232*0Sstevel@tonic-gate 			debug_msg(DEBUG_FIND_FCODE, "%s: file '%s' not found\n",
233*0Sstevel@tonic-gate 			    fname, fc_name);
234*0Sstevel@tonic-gate 			PUSH(DS, FALSE);
235*0Sstevel@tonic-gate 		}
236*0Sstevel@tonic-gate 	} else {
237*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: method '%s' not found\n",
238*0Sstevel@tonic-gate 		    fname, method);
239*0Sstevel@tonic-gate 		PUSH(DS, FALSE);
240*0Sstevel@tonic-gate 	}
241*0Sstevel@tonic-gate }
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate /*
244*0Sstevel@tonic-gate  * Looks for "device-id" and "class-id" methods in parent, if there,
245*0Sstevel@tonic-gate  * executes them to get "builtin drivers" file name or method name, then
246*0Sstevel@tonic-gate  * executes the builtin-driver method.  If both those fail, try getting the
247*0Sstevel@tonic-gate  * fcode from the device.  Note that we sleaze resetting the data stack.
248*0Sstevel@tonic-gate  * This would be cleaner if we had a way to do the equivalent of "catch/throw"
249*0Sstevel@tonic-gate  * from within C code.
250*0Sstevel@tonic-gate  */
251*0Sstevel@tonic-gate void
252*0Sstevel@tonic-gate find_fcode(fcode_env_t *env)
253*0Sstevel@tonic-gate {
254*0Sstevel@tonic-gate 	fstack_t *dp = env->ds;
255*0Sstevel@tonic-gate 	static char func_name[] = "find_fcode";
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 	my_unit(env);
258*0Sstevel@tonic-gate 	push_a_string(env, "device-id");
259*0Sstevel@tonic-gate 	get_fcode_from_filesystem(env);
260*0Sstevel@tonic-gate 	if (TOS) {
261*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: FS dev-id: len: 0x%x\n",
262*0Sstevel@tonic-gate 		    func_name, TOS);
263*0Sstevel@tonic-gate 		return;
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	env->ds = dp;
267*0Sstevel@tonic-gate 	my_unit(env);
268*0Sstevel@tonic-gate 	push_a_string(env, "class-id");
269*0Sstevel@tonic-gate 	get_fcode_from_filesystem(env);
270*0Sstevel@tonic-gate 	if (TOS) {
271*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: FS cls-id len: 0x%x\n",
272*0Sstevel@tonic-gate 		    func_name, TOS);
273*0Sstevel@tonic-gate 		return;
274*0Sstevel@tonic-gate 	}
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	env->ds = dp;
277*0Sstevel@tonic-gate 	get_fcode_from_device(env);
278*0Sstevel@tonic-gate 	if (TOS) {
279*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: DEV fcode len: 0x%x\n",
280*0Sstevel@tonic-gate 		    func_name, TOS);
281*0Sstevel@tonic-gate 		return;
282*0Sstevel@tonic-gate 	}
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	env->ds = dp;
285*0Sstevel@tonic-gate 	my_unit(env);
286*0Sstevel@tonic-gate 	push_a_string(env, "device-id");
287*0Sstevel@tonic-gate 	exec_fcode_builtin_method(env);
288*0Sstevel@tonic-gate 	if (TOS) {
289*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin dev-id len: 0x%x\n",
290*0Sstevel@tonic-gate 		    func_name, TOS);
291*0Sstevel@tonic-gate 		return;
292*0Sstevel@tonic-gate 	}
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	env->ds = dp;
295*0Sstevel@tonic-gate 	my_unit(env);
296*0Sstevel@tonic-gate 	push_a_string(env, "class-id");
297*0Sstevel@tonic-gate 	exec_fcode_builtin_method(env);
298*0Sstevel@tonic-gate 	if (TOS) {
299*0Sstevel@tonic-gate 		debug_msg(DEBUG_FIND_FCODE, "%s: dropin cls-id len: 0x%x\n",
300*0Sstevel@tonic-gate 		    func_name, TOS);
301*0Sstevel@tonic-gate 		return;
302*0Sstevel@tonic-gate 	}
303*0Sstevel@tonic-gate 	debug_msg(DEBUG_FIND_FCODE, "%s: not found\n", func_name);
304*0Sstevel@tonic-gate }
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate int
307*0Sstevel@tonic-gate open_fcode_dev(fcode_env_t *env)
308*0Sstevel@tonic-gate {
309*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	if ((cdp->fcode_fd = open(fcode_dev, O_RDONLY)) < 0)
312*0Sstevel@tonic-gate 		log_perror(MSG_ERROR, "Can't open '%s'", fcode_dev);
313*0Sstevel@tonic-gate 	return (cdp->fcode_fd >= 0);
314*0Sstevel@tonic-gate }
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate static void
317*0Sstevel@tonic-gate get_request(fcode_env_t *env)
318*0Sstevel@tonic-gate {
319*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate 	if (cdp->fcode_fd >= 0)
322*0Sstevel@tonic-gate 		close(cdp->fcode_fd);
323*0Sstevel@tonic-gate 	if (!open_fcode_dev(env))
324*0Sstevel@tonic-gate 		exit(1);
325*0Sstevel@tonic-gate 	if (!fc_get_request(cdp)) {
326*0Sstevel@tonic-gate 		log_message(MSG_FATAL, "fc_get_request failed\n");
327*0Sstevel@tonic-gate 		exit(1);
328*0Sstevel@tonic-gate 	}
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	get_my_args(env);
331*0Sstevel@tonic-gate 
332*0Sstevel@tonic-gate 	DEBUGF(UPLOAD, dot_request(env));
333*0Sstevel@tonic-gate }
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate /*
336*0Sstevel@tonic-gate  * invoked from efdaemon, /dev/fcode event has been read and /dev/fcode opened
337*0Sstevel@tonic-gate  * file descriptor is fd 0.
338*0Sstevel@tonic-gate  */
339*0Sstevel@tonic-gate static void
340*0Sstevel@tonic-gate get_efdaemon_request(fcode_env_t *env)
341*0Sstevel@tonic-gate {
342*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	cdp->fcode_fd = 0;
345*0Sstevel@tonic-gate 	if (ioctl(cdp->fcode_fd, FC_GET_PARAMETERS, &cdp->fc) < 0) {
346*0Sstevel@tonic-gate 		log_perror(MSG_FATAL, "ioctl(FC_GET_PARAMETERS) failed");
347*0Sstevel@tonic-gate 		exit(1);
348*0Sstevel@tonic-gate 	}
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	if ((cdp->attach = fc_get_ap(cdp)) == NULL)
351*0Sstevel@tonic-gate 		exit(1);
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 	get_my_args(env);
354*0Sstevel@tonic-gate 
355*0Sstevel@tonic-gate 	DEBUGF(UPLOAD, dot_request(env));
356*0Sstevel@tonic-gate }
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate static void
359*0Sstevel@tonic-gate process_request(fcode_env_t *env)
360*0Sstevel@tonic-gate {
361*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
362*0Sstevel@tonic-gate 	fstack_t fcode_len;
363*0Sstevel@tonic-gate 	char *path;
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	build_tree(env);
366*0Sstevel@tonic-gate 	install_builtin_nodes(env);
367*0Sstevel@tonic-gate 	push_my_args(env);
368*0Sstevel@tonic-gate 	push_a_string(env, cdp->fc.unit_address);
369*0Sstevel@tonic-gate 	if ((path = get_path(env, env->attachment_pt)) == NULL) {
370*0Sstevel@tonic-gate 		log_message(MSG_FATAL, "Can't get_path of"
371*0Sstevel@tonic-gate 		    " attachment_pt %p\n", env->attachment_pt);
372*0Sstevel@tonic-gate 		exit(1);
373*0Sstevel@tonic-gate 	}
374*0Sstevel@tonic-gate 	debug_msg(DEBUG_UPLOAD, "Attach Point: %s\n", path);
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 	push_a_string(env, path);
377*0Sstevel@tonic-gate 	begin_package(env);
378*0Sstevel@tonic-gate 	find_fcode(env);
379*0Sstevel@tonic-gate 	fcode_len = POP(DS);
380*0Sstevel@tonic-gate 	if (!fcode_len) {
381*0Sstevel@tonic-gate 		(void) POP(DS);
382*0Sstevel@tonic-gate 		debug_msg(DEBUG_UPLOAD, "Zero length Fcode\n");
383*0Sstevel@tonic-gate 		return;
384*0Sstevel@tonic-gate 	}
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	debug_msg(DEBUG_UPLOAD, "byte-load fcode_len: %x\n",
387*0Sstevel@tonic-gate 	    fcode_len);
388*0Sstevel@tonic-gate 
389*0Sstevel@tonic-gate 	PUSH(DS, 1);
390*0Sstevel@tonic-gate 	byte_load(env);
391*0Sstevel@tonic-gate 	end_package(env);
392*0Sstevel@tonic-gate 	upload_nodes(env);
393*0Sstevel@tonic-gate 	validate_nodes(env);
394*0Sstevel@tonic-gate 	debug_msg(DEBUG_UPLOAD, "Upload Done\n");
395*0Sstevel@tonic-gate }
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate static void
398*0Sstevel@tonic-gate finish_request(fcode_env_t *env)
399*0Sstevel@tonic-gate {
400*0Sstevel@tonic-gate 	common_data_t *cdp = env->private;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	close(cdp->fcode_fd);
403*0Sstevel@tonic-gate }
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate /*
406*0Sstevel@tonic-gate  * Non-daemon "do-request", for debugging
407*0Sstevel@tonic-gate  */
408*0Sstevel@tonic-gate static void
409*0Sstevel@tonic-gate do_request(fcode_env_t *env)
410*0Sstevel@tonic-gate {
411*0Sstevel@tonic-gate 	get_request(env);
412*0Sstevel@tonic-gate 	process_request(env);
413*0Sstevel@tonic-gate 	finish_request(env);
414*0Sstevel@tonic-gate }
415*0Sstevel@tonic-gate 
416*0Sstevel@tonic-gate /*
417*0Sstevel@tonic-gate  * This process one request from efdaemon, we know that /dev/fcode is already
418*0Sstevel@tonic-gate  * open and passed in fd0 (stdin).  If it's not, we throw up our hands.
419*0Sstevel@tonic-gate  */
420*0Sstevel@tonic-gate void
421*0Sstevel@tonic-gate run_one_efdaemon_request(fcode_env_t *env)
422*0Sstevel@tonic-gate {
423*0Sstevel@tonic-gate 	get_efdaemon_request(env);
424*0Sstevel@tonic-gate 	process_request(env);
425*0Sstevel@tonic-gate 	finish_request(env);
426*0Sstevel@tonic-gate 	exit(0);
427*0Sstevel@tonic-gate }
428*0Sstevel@tonic-gate 
429*0Sstevel@tonic-gate void
430*0Sstevel@tonic-gate probe_space(fcode_env_t *env)
431*0Sstevel@tonic-gate {
432*0Sstevel@tonic-gate 	fc_cell_t cfg = 0;
433*0Sstevel@tonic-gate 	int error;
434*0Sstevel@tonic-gate 
435*0Sstevel@tonic-gate 	error = fc_run_priv(env->private, FC_PROBE_SPACE, 0, 1, &cfg);
436*0Sstevel@tonic-gate 	if (error)
437*0Sstevel@tonic-gate 		throw_from_fclib(env, 1, "FC_PROBE_SPACE failed\n");
438*0Sstevel@tonic-gate 	PUSH(DS, fc_cell2uint32_t(cfg));
439*0Sstevel@tonic-gate }
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate #pragma init(_init)
442*0Sstevel@tonic-gate 
443*0Sstevel@tonic-gate static void
444*0Sstevel@tonic-gate _init(void)
445*0Sstevel@tonic-gate {
446*0Sstevel@tonic-gate 	fcode_env_t *env = initial_env;
447*0Sstevel@tonic-gate 
448*0Sstevel@tonic-gate 	ASSERT(env);
449*0Sstevel@tonic-gate 	NOTICE;
450*0Sstevel@tonic-gate 
451*0Sstevel@tonic-gate 	FORTH(0,	"get-fcode-from-device",	get_fcode_from_device);
452*0Sstevel@tonic-gate 	FORTH(0,	"save-fcode-to-file",		save_fcode_to_file);
453*0Sstevel@tonic-gate 	FORTH(0,	"get-my-args",			get_my_args);
454*0Sstevel@tonic-gate 	FORTH(0,	"set-my-args",			set_my_args);
455*0Sstevel@tonic-gate 	FORTH(0,	".my-args",			dot_my_args);
456*0Sstevel@tonic-gate 	FORTH(0,	".request",			dot_request);
457*0Sstevel@tonic-gate 	FORTH(0,	"get-request",			get_request);
458*0Sstevel@tonic-gate 	FORTH(0,	"process-request",		process_request);
459*0Sstevel@tonic-gate 	FORTH(0,	"finish-request",		finish_request);
460*0Sstevel@tonic-gate 	FORTH(0,	"do-request",			do_request);
461*0Sstevel@tonic-gate 	FORTH(0,	"find-fcode",			find_fcode);
462*0Sstevel@tonic-gate 	FORTH(0,	"exec-fcode-builtin-method", exec_fcode_builtin_method);
463*0Sstevel@tonic-gate 	FORTH(0,	"run-one-efdaemon-request",  run_one_efdaemon_request);
464*0Sstevel@tonic-gate 	FORTH(0,	"get-efdaemon-request",		get_efdaemon_request);
465*0Sstevel@tonic-gate 	FORTH(0,	"probe-space",			probe_space);
466*0Sstevel@tonic-gate }
467