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 (c) 2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
33 #include <fcode/private.h>
34 #include <fcode/log.h>
37 create_prop(fcode_env_t
*env
, char *name
)
39 push_a_string(env
, name
);
44 create_int_prop(fcode_env_t
*env
, char *name
, int val
)
48 create_prop(env
, name
);
52 create_string_prop(fcode_env_t
*env
, char *name
, char *val
)
54 push_a_string(env
, val
);
56 create_prop(env
, name
);
60 addr_cmp(void *a
, void *b
)
62 return ((uchar_t
*)a
== (uchar_t
*)b
);
66 add_property_buffer(fcode_env_t
*env
, int len
)
68 void *data
= MALLOC(len
+1);
69 return (add_resource(&env
->propbufs
, data
, addr_cmp
));
73 free_property_buffer(fcode_env_t
*env
, void *buffer
)
75 free_resource(&env
->propbufs
, buffer
, addr_cmp
);
81 * DO NOT cache the value of the head of the property list *before*
82 * looking up a property.
83 * This routine is also responsible for purging dead properties
84 * and that *can* affect the head pointer.
85 * you have been warned!
88 find_property(device_t
*d
, char *name
)
90 prop_t
*p
= d
->properties
, *prev
;
96 if (strcmp(name
, p
->name
) == 0) {
105 prev
->next
= p
->next
;
107 /* last prop in chain */
108 d
->properties
= p
->next
;
121 stack_find_property(fcode_env_t
*env
, device_t
*d
)
125 propname
= pop_a_string(env
, NULL
);
126 return (find_property(d
, propname
));
130 property(fcode_env_t
*env
)
133 char *propname
, *srcptr
;
137 CHECK_DEPTH(env
, 4, "property");
141 d
= env
->current_device
;
146 if ((buffer
= pop_a_string(env
, NULL
)) != NULL
)
147 free_property_buffer(env
, buffer
);
151 propname
= pop_a_string(env
, NULL
);
152 p
= find_property(d
, propname
);
154 p
= MALLOC(sizeof (prop_t
));
155 p
->next
= d
->properties
;
157 p
->name
= STRDUP(propname
);
159 FREE(p
->data
); /* release old resources */
160 srcptr
= pop_a_string(env
, &datalen
);
161 p
->data
= MALLOC(datalen
+1);
163 memcpy(p
->data
, srcptr
, datalen
);
164 p
->data
[datalen
] = 0;
166 free_property_buffer(env
, srcptr
);
170 lookup_package_property(fcode_env_t
*env
, char *propname
, device_t
*d
)
174 p
= find_property(d
, propname
);
178 if (d
->vectors
.get_package_prop
) {
182 /* recreate the FORTH environment for the remote call */
183 push_a_string(env
, propname
);
184 REVERT_PHANDLE(env
, n
, d
);
186 d
->vectors
.get_package_prop(env
);
191 sp
.data
= (uchar_t
*)POP(DS
);
200 get_package_property(fcode_env_t
*env
)
206 CHECK_DEPTH(env
, 3, "get-package-property");
207 CONVERT_PHANDLE(env
, d
, POP(DS
));
208 propname
= pop_a_string(env
, NULL
);
209 p
= lookup_package_property(env
, propname
, d
);
211 PUSH(DS
, (fstack_t
)p
->data
);
219 get_inherited_prop(fcode_env_t
*env
)
228 * First, we look thru the in-memory device tree for the property.
229 * If we don't find it, we call get_inherited_prop, which "knows" it's
230 * not going to find the property below the attachment point.
233 CHECK_DEPTH(env
, 2, "get-inherited-property");
234 pname
= pop_a_string(env
, &plen
);
237 for (; ih
; ih
= ih
->parent
) {
239 prop
= find_property(dev
, pname
);
241 PUSH(DS
, (fstack_t
)prop
->data
);
242 PUSH(DS
, (fstack_t
)prop
->size
);
247 if (dev
->vectors
.get_inherited_prop
) {
248 push_a_string(env
, pname
);
249 dev
->vectors
.get_inherited_prop(env
);
257 delete_property(fcode_env_t
*env
)
259 CHECK_DEPTH(env
, 2, "delete-property");
263 p
= stack_find_property(env
, MYSELF
->device
);
266 * write the name as NULL; the space will be free'd
267 * the next time a property lookup passes this node
277 get_my_property(fcode_env_t
*env
)
279 CHECK_DEPTH(env
, 2, "get-my-property");
280 PUSH(DS
, (fstack_t
)MYSELF
);
281 ihandle_to_phandle(env
);
282 get_package_property(env
);
286 encode_string(fcode_env_t
*env
)
292 CHECK_DEPTH(env
, 2, "encode-string");
293 str
= pop_a_string(env
, &len
);
295 prop
= add_property_buffer(env
, len
);
296 memcpy(prop
, str
, len
);
298 PUSH(DS
, (fstack_t
)prop
);
303 encode_int(fcode_env_t
*env
)
308 CHECK_DEPTH(env
, 1, "encode-int");
310 ptr
= add_property_buffer(env
, sizeof (uint32_t));
312 memcpy(ptr
, (char *)&p
, sizeof (uint32_t));
313 PUSH(DS
, (fstack_t
)ptr
);
314 PUSH(DS
, sizeof (uint32_t));
318 encode_phys(fcode_env_t
*env
)
322 ncells
= get_number_of_parent_address_cells(env
);
323 CHECK_DEPTH(env
, ncells
, "encode-phys");
333 get_decoded_int(uchar_t
*dp
)
337 memcpy((char *)&d
, dp
, sizeof (uint32_t));
342 get_default_intprop(fcode_env_t
*env
, char *name
, device_t
*d
, int def
)
346 if (!d
) /* Kludge for testing */
348 p
= lookup_package_property(env
, name
, d
);
351 return (get_decoded_int(p
->data
));
355 get_num_addr_cells(fcode_env_t
*env
, device_t
*d
)
357 return (get_default_intprop(env
, "#address-cells", d
, 2));
361 get_num_size_cells(fcode_env_t
*env
, device_t
*d
)
363 return (get_default_intprop(env
, "#size-cells", d
, 1));
367 decode_phys(fcode_env_t
*env
)
374 CHECK_DEPTH(env
, 2, "decode-phys");
375 ptr
= pop_a_string(env
, &len
);
377 adr_cells
= get_num_addr_cells(env
, env
->current_device
->parent
);
379 offset
= sizeof (uint32_t) * adr_cells
;
381 PUSH(DS
, (fstack_t
)(ptr
+ offset
));
382 PUSH(DS
, len
+ offset
);
384 while (adr_cells
--) {
386 offset
-= sizeof (uint32_t);
387 d
= get_decoded_int((uchar_t
*)(ptr
+ offset
));
396 reg_prop(fcode_env_t
*env
)
400 CHECK_DEPTH(env
, 1, "reg");
406 create_prop(env
, "reg");
410 encode_bytes(fcode_env_t
*env
)
416 CHECK_DEPTH(env
, 2, "encode-bytes");
417 str
= pop_a_string(env
, &len
);
418 prop
= add_property_buffer(env
, len
);
419 memcpy(prop
, str
, len
);
421 PUSH(DS
, (fstack_t
)prop
);
426 decode_int(fcode_env_t
*env
)
432 CHECK_DEPTH(env
, 2, "decode-int");
433 dp
= pop_a_string(env
, &len
);
434 PUSH(DS
, (fstack_t
)(dp
+ sizeof (uint32_t)));
435 PUSH(DS
, len
- sizeof (uint32_t));
436 d
= get_decoded_int((uchar_t
*)dp
);
441 decode_string(fcode_env_t
*env
)
446 CHECK_DEPTH(env
, 2, "decode-string");
447 dp
= pop_a_string(env
, &plen
);
448 len
= strlen(dp
) + 1;
449 PUSH(DS
, (fstack_t
)(dp
+ len
));
450 PUSH(DS
, plen
- len
);
451 PUSH(DS
, (fstack_t
)dp
);
456 encode_plus(fcode_env_t
*env
)
462 CHECK_DEPTH(env
, 4, "encode+");
463 src1
= pop_a_string(env
, &len1
);
464 src2
= pop_a_string(env
, &len2
);
465 new = add_property_buffer(env
, len1
+ len2
);
467 memcpy(new, src2
, len2
);
468 free_property_buffer(env
, src2
);
471 memcpy(new + len2
, src1
, len1
);
472 free_property_buffer(env
, src1
);
474 PUSH(DS
, (fstack_t
)new);
475 PUSH(DS
, len1
+ len2
);
479 make_special_property(fcode_env_t
*env
, char *name
)
481 push_a_string(env
, name
);
486 device_name(fcode_env_t
*env
)
488 CHECK_DEPTH(env
, 2, "device-name");
490 make_special_property(env
, "name");
494 model_prop(fcode_env_t
*env
)
496 CHECK_DEPTH(env
, 2, "model");
498 make_special_property(env
, "model");
502 device_type(fcode_env_t
*env
)
504 CHECK_DEPTH(env
, 2, "device-type");
506 make_special_property(env
, "device_type");
510 * 'next-property' Fcode implementation.
513 next_property(fcode_env_t
*env
)
519 CHECK_DEPTH(env
, 3, "next-property");
520 phandle
= (device_t
*)POP(DS
);
521 previous
= pop_a_string(env
, NULL
);
522 p
= phandle
->properties
;
523 if (previous
== NULL
)
524 p
= phandle
->properties
;
525 else if (p
= find_property(phandle
, previous
))
528 for (; p
!= NULL
&& p
->name
== NULL
; p
= p
->next
)
532 push_a_string(env
, p
->name
);
534 push_a_string(env
, "");
539 get_property(fcode_env_t
*env
)
542 get_my_property(env
);
543 else if (env
->current_device
) {
546 REVERT_PHANDLE(env
, d
, env
->current_device
);
548 get_package_property(env
);
551 log_message(MSG_WARN
, "No device context\n");
558 print_indented(char *name
)
560 log_message(MSG_INFO
, "%-28s", name
);
564 print_string(fcode_env_t
*env
, uchar_t
*data
, int len
)
567 int nlen
= (strlen((char *)data
)+1);
568 log_message(MSG_INFO
, "%s\n", data
);
577 print_ints(uchar_t
*data
, int len
, int crlf
)
582 d
= get_decoded_int(data
);
583 log_message(MSG_INFO
, "%8.8lx ", d
);
584 data
+= sizeof (uint32_t);
587 log_message(MSG_INFO
, "\n");
591 print_integer(fcode_env_t
*env
, uchar_t
*data
, int len
)
593 print_ints(data
, len
/sizeof (uint32_t), 1);
597 print_bytes(fcode_env_t
*env
, uchar_t
*data
, int len
)
600 log_message(MSG_INFO
, "%2.2x ", *data
++);
602 log_message(MSG_INFO
, "\n");
606 print_bytes_indented(fcode_env_t
*env
, uchar_t
*data
, int len
)
611 nbytes
= min(len
, 16);
612 print_bytes(env
, data
, nbytes
);
622 print_reg(fcode_env_t
*env
, uchar_t
*data
, int len
)
626 if (env
->current_device
!= NULL
&&
627 env
->current_device
->parent
!= NULL
) {
628 pcells
= get_num_size_cells(env
, env
->current_device
->parent
);
629 pcells
+= get_num_addr_cells(env
, env
->current_device
->parent
);
630 nlen
= pcells
*sizeof (uint32_t);
632 print_ints(data
, pcells
, 1);
639 print_bytes_indented(env
, data
, len
);
643 print_imap(fcode_env_t
*env
, uchar_t
*dp
, int len
)
647 if (env
->current_device
== NULL
) {
648 print_bytes_indented(env
, dp
, len
);
651 n
= get_num_addr_cells(env
, env
->current_device
);
659 data
= get_decoded_int(dp
+((n
+1)*sizeof (uint32_t)));
660 CONVERT_PHANDLE(env
, node
, data
);
661 offset
+= (n
+2)*sizeof (uint32_t);
662 print_ints(dp
, (n
+2), 0);
663 icells
= get_default_intprop(env
, "#interrupt-cells", node
, 1);
664 print_ints(dp
+offset
, icells
, 1);
665 offset
+= icells
*sizeof (uint32_t);
674 print_ranges(fcode_env_t
*env
, uchar_t
*data
, int len
)
678 if (env
->current_device
!= NULL
&&
679 env
->current_device
->parent
!= NULL
) {
680 pcells
= get_num_addr_cells(env
, env
->current_device
);
681 pcells
+= get_num_addr_cells(env
, env
->current_device
->parent
);
682 pcells
+= get_num_size_cells(env
, env
->current_device
);
683 nlen
= pcells
*sizeof (uint32_t);
685 print_ints(data
, pcells
, 1);
692 print_bytes_indented(env
, data
, len
);
695 typedef struct MAGIC_PROP
{
697 void (*fn
)(fcode_env_t
*env
, uchar_t
*data
, int len
);
700 static magic_prop_t magic_props
[] = {
701 { "name", print_string
},
702 { "device_type", print_string
},
703 { "model", print_string
},
704 { "reg", print_reg
},
705 { "assigned-addresses", print_reg
},
706 { "interrupt-map", print_imap
},
707 { "#interrupt-cells", print_integer
},
708 { "interrupt-map-mask", print_integer
},
709 { "#size-cells", print_integer
},
710 { "#address-cells", print_integer
},
711 { "ranges", print_ranges
},
712 { "device-id", print_integer
},
713 { "vendor-id", print_integer
},
714 { "class-code", print_integer
},
715 { "compatible", print_string
},
716 { "version", print_string
},
717 { "manufacturer", print_string
},
722 print_content(fcode_env_t
*env
, char *prop
, uchar_t
*data
, int len
)
726 for (p
= magic_props
; p
->name
; p
++)
727 if (strcmp(prop
, p
->name
) == 0) {
728 (*p
->fn
)(env
, data
, len
);
731 print_bytes_indented(env
, data
, len
);
735 print_property(fcode_env_t
*env
, prop_t
*p
, char *prepend
)
738 char *name
= (p
->name
? p
->name
: "<noname>");
741 sprintf(buf
, "%s %s", prepend
, name
);
744 print_indented(name
);
746 print_content(env
, p
->name
, p
->data
, p
->size
);
748 print_bytes_indented(env
, p
->data
, p
->size
);
752 dot_properties(fcode_env_t
*env
)
760 if (env
->current_device
) {
761 for (p
= env
->current_device
->properties
; p
; p
= p
->next
)
762 print_property(env
, p
, NULL
);
764 log_message(MSG_INFO
, "No device context\n");
776 fcode_env_t
*env
= initial_env
;
781 P1275(0x110, 0, "property", property
);
782 P1275(0x111, 0, "encode-int", encode_int
);
783 P1275(0x112, 0, "encode+", encode_plus
);
784 P1275(0x113, 0, "encode-phys", encode_phys
);
785 P1275(0x114, 0, "encode-string", encode_string
);
786 P1275(0x115, 0, "encode-bytes", encode_bytes
);
787 P1275(0x116, 0, "reg", reg_prop
);
788 FCODE(0x117, 0, "intr", fc_obsolete
);
789 FCODE(0x118, 0, "driver", fc_historical
);
790 P1275(0x119, 0, "model", model_prop
);
791 P1275(0x11a, 0, "device-type", device_type
);
793 P1275(0x128, 0, "decode-phys", decode_phys
);
795 P1275(0x201, 0, "device-name", device_name
);
797 P1275(0x21a, 0, "get-my-property", get_my_property
);
798 P1275(0x21b, 0, "decode-int", decode_int
);
799 P1275(0x21c, 0, "decode-string", decode_string
);
800 P1275(0x21d, 0, "get-inherited-property", get_inherited_prop
);
801 P1275(0x21e, 0, "delete-property", delete_property
);
802 P1275(0x21f, 0, "get-package-property", get_package_property
);
804 P1275(0x23d, 0, "next-property", next_property
);
806 FORTH(0, "get-property", get_property
);
807 FORTH(0, ".properties", dot_properties
);