dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / efcode / engine / properties.c
blobff14c1f03c5c7207f6ddbb3dcabb9342b353ece0
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
33 #include <fcode/private.h>
34 #include <fcode/log.h>
36 void
37 create_prop(fcode_env_t *env, char *name)
39 push_a_string(env, name);
40 property(env);
43 void
44 create_int_prop(fcode_env_t *env, char *name, int val)
46 PUSH(DS, val);
47 encode_int(env);
48 create_prop(env, name);
51 void
52 create_string_prop(fcode_env_t *env, char *name, char *val)
54 push_a_string(env, val);
55 encode_string(env);
56 create_prop(env, name);
59 static int
60 addr_cmp(void *a, void *b)
62 return ((uchar_t *)a == (uchar_t *)b);
65 static void *
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));
72 static void
73 free_property_buffer(fcode_env_t *env, void *buffer)
75 free_resource(&env->propbufs, buffer, addr_cmp);
76 FREE(buffer);
80 * Golden Rule:
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!
87 prop_t *
88 find_property(device_t *d, char *name)
90 prop_t *p = d->properties, *prev;
91 prop_t *found = NULL;
93 prev = NULL;
94 while (p && !found) {
95 if (p->name) {
96 if (strcmp(name, p->name) == 0) {
97 found = p;
99 prev = p;
100 p = p->next;
101 } else {
102 prop_t *dead;
104 if (prev)
105 prev->next = p->next;
106 else {
107 /* last prop in chain */
108 d->properties = p->next;
110 dead = p;
111 p = p->next;
112 FREE(dead->name);
113 FREE(dead->data);
114 FREE(dead);
117 return (found);
120 static prop_t *
121 stack_find_property(fcode_env_t *env, device_t *d)
123 char *propname;
125 propname = pop_a_string(env, NULL);
126 return (find_property(d, propname));
129 void
130 property(fcode_env_t *env)
132 int datalen;
133 char *propname, *srcptr;
134 prop_t *p;
135 device_t *d;
137 CHECK_DEPTH(env, 4, "property");
138 if (MYSELF) {
139 d = MYSELF->device;
140 } else {
141 d = env->current_device;
142 if (!d) {
143 void *buffer;
145 two_drop(env);
146 if ((buffer = pop_a_string(env, NULL)) != NULL)
147 free_property_buffer(env, buffer);
148 return;
151 propname = pop_a_string(env, NULL);
152 p = find_property(d, propname);
153 if (p == NULL) {
154 p = MALLOC(sizeof (prop_t));
155 p->next = d->properties;
156 d->properties = p;
157 p->name = STRDUP(propname);
158 } else if (p->data)
159 FREE(p->data); /* release old resources */
160 srcptr = pop_a_string(env, &datalen);
161 p->data = MALLOC(datalen+1);
162 p->size = datalen;
163 memcpy(p->data, srcptr, datalen);
164 p->data[datalen] = 0;
165 if (srcptr)
166 free_property_buffer(env, srcptr);
169 prop_t *
170 lookup_package_property(fcode_env_t *env, char *propname, device_t *d)
172 prop_t *p;
174 p = find_property(d, propname);
175 if (p) {
176 return (p);
178 if (d->vectors.get_package_prop) {
179 static prop_t sp;
180 fstack_t fail, n;
182 /* recreate the FORTH environment for the remote call */
183 push_a_string(env, propname);
184 REVERT_PHANDLE(env, n, d);
185 PUSH(DS, n);
186 d->vectors.get_package_prop(env);
187 fail = POP(DS);
188 if (fail)
189 return (NULL);
190 sp.size = POP(DS);
191 sp.data = (uchar_t *)POP(DS);
192 sp.name = propname;
193 sp.next = NULL;
194 return (&sp);
196 return (NULL);
199 void
200 get_package_property(fcode_env_t *env)
202 prop_t *p;
203 device_t *d;
204 char *propname;
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);
210 if (p) {
211 PUSH(DS, (fstack_t)p->data);
212 PUSH(DS, p->size);
213 PUSH(DS, FALSE);
214 } else
215 PUSH(DS, TRUE);
218 void
219 get_inherited_prop(fcode_env_t *env)
221 instance_t *ih;
222 device_t *dev;
223 prop_t *prop;
224 char *pname;
225 int plen;
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);
235 ih = MYSELF;
236 if (ih) {
237 for (; ih; ih = ih->parent) {
238 dev = ih->device;
239 prop = find_property(dev, pname);
240 if (prop) {
241 PUSH(DS, (fstack_t)prop->data);
242 PUSH(DS, (fstack_t)prop->size);
243 PUSH(DS, FALSE);
244 return;
247 if (dev->vectors.get_inherited_prop) {
248 push_a_string(env, pname);
249 dev->vectors.get_inherited_prop(env);
250 return;
253 PUSH(DS, TRUE);
256 void
257 delete_property(fcode_env_t *env)
259 CHECK_DEPTH(env, 2, "delete-property");
260 if (MYSELF) {
261 prop_t *p;
263 p = stack_find_property(env, MYSELF->device);
264 if (p) {
266 * write the name as NULL; the space will be free'd
267 * the next time a property lookup passes this node
269 p->name = NULL;
271 } else {
272 two_drop(env);
276 void
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);
285 void
286 encode_string(fcode_env_t *env)
288 char *str;
289 char *prop;
290 int len;
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);
297 prop[len] = 0;
298 PUSH(DS, (fstack_t)prop);
299 PUSH(DS, len + 1);
302 void
303 encode_int(fcode_env_t *env)
305 uchar_t *ptr;
306 uint32_t p;
308 CHECK_DEPTH(env, 1, "encode-int");
309 p = POP(DS);
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));
317 void
318 encode_phys(fcode_env_t *env)
320 uint_t ncells;
322 ncells = get_number_of_parent_address_cells(env);
323 CHECK_DEPTH(env, ncells, "encode-phys");
324 encode_int(env);
325 while (--ncells) {
326 rot(env);
327 encode_int(env);
328 encode_plus(env);
332 static fstack_t
333 get_decoded_int(uchar_t *dp)
335 uint32_t d;
337 memcpy((char *)&d, dp, sizeof (uint32_t));
338 return (d);
342 get_default_intprop(fcode_env_t *env, char *name, device_t *d, int def)
344 prop_t *p;
346 if (!d) /* Kludge for testing */
347 return (def);
348 p = lookup_package_property(env, name, d);
349 if (p == NULL)
350 return (def);
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));
366 void
367 decode_phys(fcode_env_t *env)
369 char *ptr;
370 int len;
371 int adr_cells;
372 int offset;
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--) {
385 fstack_t d;
386 offset -= sizeof (uint32_t);
387 d = get_decoded_int((uchar_t *)(ptr + offset));
388 PUSH(DS, d);
393 * 'reg' Fcode 0x116
395 void
396 reg_prop(fcode_env_t *env)
398 fstack_t size;
400 CHECK_DEPTH(env, 1, "reg");
401 size = POP(DS);
402 encode_phys(env);
403 PUSH(DS, size);
404 encode_int(env);
405 encode_plus(env);
406 create_prop(env, "reg");
409 void
410 encode_bytes(fcode_env_t *env)
412 char *str;
413 char *prop;
414 int len;
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);
420 prop[len] = 0;
421 PUSH(DS, (fstack_t)prop);
422 PUSH(DS, len);
425 void
426 decode_int(fcode_env_t *env)
428 char *dp;
429 fstack_t d;
430 int len;
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);
437 PUSH(DS, d);
440 void
441 decode_string(fcode_env_t *env)
443 int plen, len;
444 char *dp;
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);
452 PUSH(DS, len - 1);
455 void
456 encode_plus(fcode_env_t *env)
458 int len1, len2;
459 char *src1, *src2;
460 uchar_t *new;
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);
466 if (src2) {
467 memcpy(new, src2, len2);
468 free_property_buffer(env, src2);
470 if (src1) {
471 memcpy(new + len2, src1, len1);
472 free_property_buffer(env, src1);
474 PUSH(DS, (fstack_t)new);
475 PUSH(DS, len1 + len2);
478 static void
479 make_special_property(fcode_env_t *env, char *name)
481 push_a_string(env, name);
482 property(env);
485 void
486 device_name(fcode_env_t *env)
488 CHECK_DEPTH(env, 2, "device-name");
489 encode_string(env);
490 make_special_property(env, "name");
493 void
494 model_prop(fcode_env_t *env)
496 CHECK_DEPTH(env, 2, "model");
497 encode_string(env);
498 make_special_property(env, "model");
501 void
502 device_type(fcode_env_t *env)
504 CHECK_DEPTH(env, 2, "device-type");
505 encode_string(env);
506 make_special_property(env, "device_type");
510 * 'next-property' Fcode implementation.
512 void
513 next_property(fcode_env_t *env)
515 device_t *phandle;
516 char *previous;
517 prop_t *p;
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))
526 p = p->next;
528 for (; p != NULL && p->name == NULL; p = p->next)
531 if (p)
532 push_a_string(env, p->name);
533 else
534 push_a_string(env, "");
535 PUSH(DS, TRUE);
538 void
539 get_property(fcode_env_t *env)
541 if (MYSELF)
542 get_my_property(env);
543 else if (env->current_device) {
544 fstack_t d;
546 REVERT_PHANDLE(env, d, env->current_device);
547 PUSH(DS, d);
548 get_package_property(env);
549 } else {
550 two_drop(env);
551 log_message(MSG_WARN, "No device context\n");
555 #ifdef DEBUG
557 static void
558 print_indented(char *name)
560 log_message(MSG_INFO, "%-28s", name);
563 static void
564 print_string(fcode_env_t *env, uchar_t *data, int len)
566 while (len > 0) {
567 int nlen = (strlen((char *)data)+1);
568 log_message(MSG_INFO, "%s\n", data);
569 len -= nlen;
570 data += nlen;
571 if (len > 0)
572 print_indented("");
576 static void
577 print_ints(uchar_t *data, int len, int crlf)
579 uint32_t d;
581 while (len--) {
582 d = get_decoded_int(data);
583 log_message(MSG_INFO, "%8.8lx ", d);
584 data += sizeof (uint32_t);
586 if (crlf)
587 log_message(MSG_INFO, "\n");
590 static void
591 print_integer(fcode_env_t *env, uchar_t *data, int len)
593 print_ints(data, len/sizeof (uint32_t), 1);
596 static void
597 print_bytes(fcode_env_t *env, uchar_t *data, int len)
599 while (len--) {
600 log_message(MSG_INFO, "%2.2x ", *data++);
602 log_message(MSG_INFO, "\n");
605 static void
606 print_bytes_indented(fcode_env_t *env, uchar_t *data, int len)
608 int nbytes;
610 for (; ; ) {
611 nbytes = min(len, 16);
612 print_bytes(env, data, nbytes);
613 len -= nbytes;
614 data += nbytes;
615 if (len == 0)
616 break;
617 print_indented("");
621 static void
622 print_reg(fcode_env_t *env, uchar_t *data, int len)
624 int pcells, nlen;
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);
631 while (len > 0) {
632 print_ints(data, pcells, 1);
633 len -= nlen;
634 data += nlen;
635 if (len > 0)
636 print_indented("");
638 } else
639 print_bytes_indented(env, data, len);
642 static void
643 print_imap(fcode_env_t *env, uchar_t *dp, int len)
645 int n, icells;
647 if (env->current_device == NULL) {
648 print_bytes_indented(env, dp, len);
649 return;
651 n = get_num_addr_cells(env, env->current_device);
653 while (len) {
654 int offset;
655 fstack_t data;
656 device_t *node;
658 offset = 0;
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);
666 dp += offset;
667 len -= offset;
668 if (len)
669 print_indented("");
673 static void
674 print_ranges(fcode_env_t *env, uchar_t *data, int len)
676 int pcells, nlen;
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);
684 while (len > 0) {
685 print_ints(data, pcells, 1);
686 len -= nlen;
687 data += nlen;
688 if (len > 0)
689 print_indented("");
691 } else
692 print_bytes_indented(env, data, len);
695 typedef struct MAGIC_PROP {
696 char *name;
697 void (*fn)(fcode_env_t *env, uchar_t *data, int len);
698 } magic_prop_t;
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 },
718 { NULL, NULL }
721 static void
722 print_content(fcode_env_t *env, char *prop, uchar_t *data, int len)
724 magic_prop_t *p;
726 for (p = magic_props; p->name; p++)
727 if (strcmp(prop, p->name) == 0) {
728 (*p->fn)(env, data, len);
729 return;
731 print_bytes_indented(env, data, len);
734 void
735 print_property(fcode_env_t *env, prop_t *p, char *prepend)
737 char buf[40];
738 char *name = (p->name ? p->name : "<noname>");
740 if (prepend) {
741 sprintf(buf, "%s %s", prepend, name);
742 name = buf;
744 print_indented(name);
745 if (p->name)
746 print_content(env, p->name, p->data, p->size);
747 else
748 print_bytes_indented(env, p->data, p->size);
751 void
752 dot_properties(fcode_env_t *env)
754 prop_t *p;
755 instance_t *omyself;
757 omyself = MYSELF;
758 MYSELF = NULL;
760 if (env->current_device) {
761 for (p = env->current_device->properties; p; p = p->next)
762 print_property(env, p, NULL);
763 } else {
764 log_message(MSG_INFO, "No device context\n");
766 MYSELF = omyself;
769 #endif
771 #pragma init(_init)
773 static void
774 _init(void)
776 fcode_env_t *env = initial_env;
778 ASSERT(env);
779 NOTICE;
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);