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 (c) 1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <strings.h>
30 #include <fcode/private.h>
31 #include <fcode/log.h>
32 
33 #include <fcdriver/fcdriver.h>
34 
35 
36 static int use_os_handle = 1;
37 
38 void
do_use_os_handles(fcode_env_t * env)39 do_use_os_handles(fcode_env_t *env)
40 {
41 	use_os_handle = 1;
42 }
43 
44 void
do_use_fake_handles(fcode_env_t * env)45 do_use_fake_handles(fcode_env_t *env)
46 {
47 	log_message(MSG_ERROR, "WARNING: using fake phandles, test only\n");
48 	use_os_handle = 0;
49 }
50 
51 static int
match_nodeid(void * s,void * d)52 match_nodeid(void *s, void *d)
53 {
54 	my_nodeid_t *src = s;
55 	my_nodeid_t *dest = d;
56 	return ((src->node) == (dest->node));
57 }
58 
59 static int
match_handle(void * s,void * d)60 match_handle(void *s, void *d)
61 {
62 	my_nodeid_t *src = s;
63 	my_nodeid_t *dest = d;
64 	return ((src->my_handle) == (dest->my_handle));
65 }
66 
67 /*
68  * Convert from an OS phandle to an interpreter phandle
69  */
70 device_t *
convert_phandle(fcode_env_t * env,fstack_t d)71 convert_phandle(fcode_env_t *env, fstack_t d)
72 {
73 	fc_resource_t *t;
74 	common_data_t *cdp = env->private;
75 	device_t *r;
76 
77 	if (use_os_handle) {
78 		my_nodeid_t nh;
79 		nh.my_handle = (fc_phandle_t)d;
80 		t = find_resource(&cdp->nodeids, &nh, match_handle);
81 		if (t == NULL) {
82 			r = 0;
83 		} else {
84 			my_nodeid_t *p = (my_nodeid_t *)t->data;
85 			r = (device_t *)p->node;
86 		}
87 	} else
88 		r = (device_t *)d;
89 	return (r);
90 }
91 
92 /*
93  * Interpreter phandle to OS phandle
94  */
95 fstack_t
revert_phandle(fcode_env_t * env,device_t * d)96 revert_phandle(fcode_env_t *env, device_t *d)
97 {
98 	fc_resource_t *t;
99 	common_data_t *cdp = env->private;
100 	fstack_t r;
101 
102 	if (use_os_handle) {
103 		my_nodeid_t nh;
104 		nh.node = d;
105 		t = find_resource(&cdp->nodeids, &nh, match_nodeid);
106 		if (t == NULL) {
107 			r = 0;
108 		} else {
109 			my_nodeid_t *p = (my_nodeid_t *)t->data;
110 			r = (fstack_t)p->my_handle;
111 		}
112 	} else
113 		r = (fstack_t)d;
114 	return (r);
115 }
116 
117 void
add_my_handle(fcode_env_t * env,fc_phandle_t mh,device_t * d)118 add_my_handle(fcode_env_t *env, fc_phandle_t mh, device_t *d)
119 {
120 	my_nodeid_t *nh;
121 	common_data_t *cdp = env->private;
122 
123 	nh = MALLOC(sizeof (my_nodeid_t));
124 	nh->my_handle = mh;
125 	nh->node = d;
126 	if (add_resource(&cdp->nodeids, nh, match_handle) == NULL) {
127 		log_message(MSG_ERROR, "add_my_handle: add_resource failed\n");
128 	}
129 }
130 
131 void
allocate_phandle(fcode_env_t * env)132 allocate_phandle(fcode_env_t *env)
133 {
134 	private_data_t *pd;
135 	common_data_t *cdp;
136 	char *service;
137 	device_t *current;
138 	fc_cell_t hcell;
139 
140 	if ((cdp = env->private) == NULL) {
141 		log_message(MSG_ERROR, "allocate_phandle: NULL common\n");
142 		return;
143 	}
144 
145 	if (!cdp->init_done)
146 		return;
147 
148 	current = MYSELF->device;
149 	ASSERT(current);
150 
151 	if (cdp->first_node) {
152 		service = FC_CONFIG_CHILD;
153 		cdp->first_node = 0;
154 	} else {
155 		service = FC_ALLOC_PHANDLE;
156 	}
157 
158 	pd = MALLOC(sizeof (private_data_t));
159 	pd->common = cdp;
160 	pd->parent = (fc_phandle_t)revert_phandle(env, current->parent);
161 	pd->upload = (cdp->init_done == 1);
162 	current->private = pd;
163 
164 	(void) fc_run_priv(cdp, service, 0, 1, &hcell);
165 
166 	pd->node = fc_cell2phandle(hcell);
167 
168 	add_my_handle(env, pd->node, current);
169 }
170 
171 fc_phandle_t
fc_get_ap(common_data_t * cdp)172 fc_get_ap(common_data_t *cdp)
173 {
174 	fc_cell_t hcell;
175 	int error;
176 
177 	error = fc_run_priv(cdp, FC_AP_PHANDLE, 0, 1, &hcell);
178 
179 	if (error)
180 		exit(1);
181 
182 	return (fc_cell2phandle(hcell));
183 }
184 
185 
186 #pragma init(_init)
187 
188 static void
_init(void)189 _init(void)
190 {
191 	fcode_env_t *env = initial_env;
192 
193 	ASSERT(env);
194 	NOTICE;
195 
196 	env->convert_phandle = convert_phandle;
197 	env->revert_phandle = revert_phandle;
198 	env->allocate_phandle = allocate_phandle;
199 	FORTH(0,	"use-os-handles",	do_use_os_handles);
200 	FORTH(0,	"use-fake-handles",	do_use_fake_handles);
201 }
202