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