mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
738 lines
24 KiB
C
738 lines
24 KiB
C
/*
|
|
File: DeviceTree.c
|
|
|
|
Contains: Expansion Mgr Device Tree Manipulation Routines
|
|
|
|
Written by: Al Kossow
|
|
|
|
Copyright: © 1993-1994 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<SM5> 2/7/94 AK fix warning in universal builds
|
|
|
|
<SM5> 2/07/94 aek get rid of warning on universal builds
|
|
<SM4> 1/18/94 AK fix device tree init
|
|
*/
|
|
|
|
/*
|
|
* <4> 01/18/94 aek make sure adrs aren't updated on restart
|
|
* <3> 01/18/94 aek correct tree initialization code
|
|
* <2> 01/17/94 aek wire into Open Boot
|
|
* <1> 10/20/93 aek Created
|
|
*
|
|
*
|
|
* Device nodes can have other device nodes as children.
|
|
*
|
|
* The bulk of the Device Tree is built at system initialization time in
|
|
* the system heap from information passed to StartInit from Open Boot.
|
|
*
|
|
* It is slightly different from the Device Tree in Open Boot, since there
|
|
* are client calls to remove as well as add devices and properties to
|
|
* the tree.
|
|
*
|
|
* No assuptions should be made about what a nodeid represents. It may be
|
|
* a pointer, a handle, or a small integer, depending upon the underlying
|
|
* implemetation of the device tree routines.
|
|
*
|
|
*
|
|
* pascal NodeID DevTreeRoot();
|
|
* pascal OSErr DevTreeNodeInfo(NodeID node, NodeInfoPtr p);
|
|
* pascal NodeID DevTreeAddNode(NodeID parentNode, ulong attrib, char *name);
|
|
* pascal OSErr DevTreeDelNode(NodeID theNode);
|
|
* pascal OSErr DevTreeSetProperty(NodeID theNode, unsigned char *buf, long size);
|
|
* pascal OSErr DevTreeGetProperty(NodeID theNode, unsigned char *buf, long size);
|
|
*
|
|
*
|
|
* TODO:
|
|
* Real error code #'s
|
|
* Non-volatile properties
|
|
* Properties saved in the system file
|
|
*
|
|
*/
|
|
|
|
#include "ExpansionMgrInternal.h"
|
|
#include "Memory.h"
|
|
|
|
#ifndef TEST
|
|
|
|
|
|
#ifndef __ERRORS__
|
|
#include <Errors.h>
|
|
#endif
|
|
|
|
#ifndef __EXPANDMEMPRIV__
|
|
#include "ExpandMemPriv.h"
|
|
#endif
|
|
#endif
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* Private Device Tree Interface Routines */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
* Internal routine to allocate memory for a tree node
|
|
* Returns NIL if allocation fails
|
|
*/
|
|
|
|
Ptr AllocTreeMem(size)
|
|
{
|
|
#ifdef TEST
|
|
return(NewPtrClear(size));
|
|
#else
|
|
return(NewPtrSysClear(size));
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Internal routine to free memory for a tree node
|
|
*/
|
|
FreeTreeMem(ptr)
|
|
Ptr ptr;
|
|
{
|
|
DisposPtr(ptr);
|
|
}
|
|
|
|
/*
|
|
* Internal routine to free data associated with a property
|
|
* Checks to make sure data isn't in ROM or is indirectly referenced
|
|
*/
|
|
FreePropData(pp)
|
|
PropertyNodePtr pp;
|
|
{
|
|
if(pp->attrib & (kAttribROMProp | kAttribDefProp))
|
|
return(-1);
|
|
DisposPtr((Ptr)pp);
|
|
}
|
|
|
|
/*
|
|
* CheckNodeName(name)
|
|
*
|
|
* Verify that name is a valid device tree name
|
|
* 31 chrs max, letters, digits ,',' ,'_', '+', or '-'
|
|
*
|
|
* Returns the number of characters in the name, or zero
|
|
* if there was an error
|
|
*
|
|
* TODO: really verify it..
|
|
*/
|
|
int CheckNodeName(name)
|
|
char *name;
|
|
{
|
|
register char *cp = name;
|
|
register int len = 0;
|
|
|
|
while( *cp && (len < 32)){
|
|
len++, cp++;
|
|
}
|
|
if(len == 32)
|
|
return(0);
|
|
else
|
|
return(len);
|
|
}
|
|
|
|
/*
|
|
* CheckPropertyName(name)
|
|
*
|
|
* Verify that the name is a valid property name
|
|
* 31 chrs max, no upper case, '/', '\', ':', '[', ']' or '@'
|
|
* Returns the number of characters in the name, or zero
|
|
* if there was an error
|
|
*
|
|
* TODO: really verify it..
|
|
*/
|
|
int CheckPropertyName(name)
|
|
char *name;
|
|
{
|
|
register char *cp = name;
|
|
register int len = 0;
|
|
|
|
while( *cp && (len < 32)){
|
|
len++, cp++;
|
|
}
|
|
if(len == 32)
|
|
return(0);
|
|
else
|
|
return(len);
|
|
}
|
|
|
|
/*
|
|
* Validate the NodeID that was passed to us
|
|
* Returns TRUE if NodeID actually exists in
|
|
* the tree by looking at all nodes starting
|
|
* at the root
|
|
*
|
|
* TODO: really verify it..
|
|
*/
|
|
Boolean CheckNodeID(theNode)
|
|
NodeID theNode;
|
|
{
|
|
|
|
#pragma unused(theNode);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* Munge the tree passed to us by open boot */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
cvtDevNode(dp, depth, DTBase)
|
|
DeviceNodePtr dp;
|
|
int depth;
|
|
unsigned long DTBase;
|
|
{
|
|
register DeviceNodePtr childptr;
|
|
register PropertyNodePtr propptr;
|
|
|
|
if(dp->parent)
|
|
dp->parent = (DeviceNodePtr)((unsigned long)(dp->parent) + DTBase);
|
|
|
|
dp->peer = (DeviceNodePtr)((unsigned long)(dp->peer) + DTBase);
|
|
if(dp->propertyList){
|
|
dp->propertyList = (PropertyNodePtr)((unsigned long)dp->propertyList + DTBase);
|
|
dp->propertyTail = (PropertyNodePtr)((unsigned long)dp->propertyTail + DTBase);
|
|
propptr = dp->propertyList;
|
|
do {
|
|
propptr->parent = (DeviceNodePtr)((unsigned long)propptr->parent + DTBase);
|
|
propptr->peer = (PropertyNodePtr)((unsigned long)propptr->peer + DTBase);
|
|
if(propptr->dataPtr)
|
|
propptr->dataPtr = (unsigned char *)propptr->dataPtr + DTBase;
|
|
propptr = propptr->peer;
|
|
} while (propptr != dp->propertyList);
|
|
}
|
|
if(dp->childList){
|
|
dp->childList = (DeviceNodePtr)((unsigned long)(dp->childList) + DTBase);
|
|
dp->childTail = (DeviceNodePtr)((unsigned long)(dp->childTail) + DTBase);
|
|
childptr = (DeviceNodePtr)dp->childList;
|
|
do {
|
|
cvtDevNode(childptr, depth+1, DTBase);
|
|
childptr = childptr->peer;
|
|
} while (childptr != (DeviceNodePtr)dp->childList);
|
|
}
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* Public Device Tree Interface Routines */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeRoot() */
|
|
/* */
|
|
/* Return the root node ID in the nodeID field of the parameter block */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
pascal NodeID DevTreeRoot()
|
|
{
|
|
register DeviceNodePtr dp;
|
|
register unsigned short i;
|
|
|
|
/*
|
|
* get the saved tree base address
|
|
*/
|
|
|
|
dp = (DeviceNodePtr)GetExpandMemExpansionBusGlobals();
|
|
|
|
/*
|
|
* test if the device tree has been initialized
|
|
* return node id of root if it has been
|
|
*/
|
|
|
|
if(dp)
|
|
return((NodeID)dp);
|
|
|
|
/*
|
|
* If we're running on a machine with Open Firmware
|
|
* we get device tree info at startup
|
|
* Wire the info in as the initial device tree
|
|
*/
|
|
|
|
#ifdef forTNTDebug
|
|
i = *(unsigned short *)0x5ff00000;
|
|
if((i & 0x8000) == 0){
|
|
cvtDevNode(0x5ff00004, 1, (unsigned long)0x5ff00000L);
|
|
*(unsigned short *)0x5ff00000 = i | 0x8000;
|
|
}
|
|
dp = (DeviceNodePtr)0x5ff00004;
|
|
#endif
|
|
|
|
/*
|
|
* Create a device tree in the system heap if there
|
|
* wasn't one passed to us.
|
|
*/
|
|
#ifndef forTNTDebug
|
|
dp = (DeviceNodePtr)AllocTreeMem(sizeof(DeviceNode));
|
|
dp->attrib = kDeviceNode | kAttribLocked;
|
|
dp->name[0] = 'r'; dp->name[1] = 'o'; dp->name[2] = 'o'; dp->name[3] = 't';
|
|
#endif
|
|
|
|
SetExpandMemExpansionBusGlobals((Ptr)dp); /* remember where the root is */
|
|
return((NodeID)dp);
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeNodeInfo() */
|
|
/* */
|
|
/* Return info about a node in the device tree */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
pascal OSErr DevTreeNodeInfo(node, p)
|
|
NodeID node;
|
|
NodeInfoPtr p;
|
|
{
|
|
register DeviceNodePtr dp;
|
|
register PropertyNodePtr pp;
|
|
register char *src, *dst;
|
|
register int cnt;
|
|
|
|
dp = (DeviceNodePtr)node;
|
|
|
|
/*
|
|
* Fill in values unique to each node type
|
|
*/
|
|
switch(dp->attrib & kTypeMask) {
|
|
|
|
case(kDeviceNode):
|
|
p->childNode = (NodeID)dp->childList;
|
|
p->propertyNode = (NodeID)dp->propertyList;
|
|
src = dp->name;
|
|
break;
|
|
|
|
case(kPropertyNode):
|
|
pp = (PropertyNodePtr)dp; // convert to prop node ptr
|
|
p->childNode = 0; // properties don't have children
|
|
p->propertySize = pp->size;
|
|
p->propertyNode = 0;
|
|
src = pp->name;
|
|
break;
|
|
|
|
default:
|
|
return(-1); // all other node types are bogus
|
|
}
|
|
|
|
/*
|
|
* Fill in info common to all nodes;
|
|
* attributes, parent, peer, and name.
|
|
*/
|
|
p->attrib = dp->attrib & (kTypeMask | kAttribMask); // return only user-settable bits
|
|
p->parentNode = (NodeID)dp->parent;
|
|
p->peerNode = (NodeID)dp->peer;
|
|
|
|
/*
|
|
* Copy node name using src pointer formed in node-specific
|
|
* code
|
|
*/
|
|
dst = p->name;
|
|
for(cnt = 32; cnt; cnt--)
|
|
*dst++ = *src++; // copy name into record
|
|
return(noErr);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeAddNode() */
|
|
/* */
|
|
/* Add a node to the Device Tree */
|
|
/* Creating nodes with special attributes are done through a non-exported */
|
|
/* node creation routine */
|
|
/* */
|
|
/* The naming conventions for Device and Property nodes are the same as */
|
|
/* the conventions for Open Boot: */
|
|
/* */
|
|
/* Device Nodes: Mixed-case letters, digits, ',' '_' '+' '-' */
|
|
/* */
|
|
/* ' ' ! " # $ % & ' ( ) * + , - . / */
|
|
/* _ _ _ */
|
|
/* */
|
|
/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
|
|
/* _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* @ A B C D E F G H I J K L M N O */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* P Q R S T U V W X Y Z [ \ ] ^ _ */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* ` a b c d e f g h i j k l m n o */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* p q r s t u v w x y z { | } ~ */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* */
|
|
/* Properties: All printable characters except upper case letters, */
|
|
/* '/' '\' ':' '[' ']' '@' */
|
|
/* */
|
|
/* ' ' ! " # $ % & ' ( ) * + , - . / */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* @ A B C D E F G H I J K L M N O */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* P Q R S T U V W X Y Z [ \ ] ^ _ */
|
|
/* _ _ _ _ _ _ _ _ _ _ _ _ _ */
|
|
/* */
|
|
/* ` a b c d e f g h i j k l m n o */
|
|
/* _ */
|
|
/* */
|
|
/* p q r s t u v w x y z { | } ~ */
|
|
/* _ _ _ _ */
|
|
/* */
|
|
/* Note: Open Boot defines Printable Characters as 0x21 -> 0x7e and */
|
|
/* 0xa1 -> 0xfe */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
pascal NodeID DevTreeAddNode( parentNode ,attrib, name)
|
|
NodeID parentNode;
|
|
unsigned long attrib;
|
|
char *name;
|
|
{
|
|
register nameLen;
|
|
char *src, *dst;
|
|
DeviceNodePtr dp;
|
|
PropertyNodePtr pp;
|
|
NodeID retVal;
|
|
|
|
if(!CheckNodeID(parentNode))
|
|
return(-1); // make sure parent exists
|
|
src = name;
|
|
dp = (DeviceNodePtr)parentNode;
|
|
if((dp->attrib & kTypeMask) != kDeviceNode)
|
|
return(-1); // parent must be device node
|
|
switch(attrib & kTypeMask) { // check for valid node types
|
|
|
|
/*
|
|
* create a new device node
|
|
*/
|
|
case(kDeviceNode):
|
|
if((nameLen = CheckNodeName(name)) == 0)
|
|
return(-1); // something wrong with name
|
|
if(attrib & (kAttribNVRAM | kAttribSysSav))
|
|
return(-1); // only properties are non-volatile
|
|
dp = (DeviceNodePtr)AllocTreeMem(sizeof(DeviceNode));
|
|
retVal = (NodeID)dp;
|
|
dst = dp->name;
|
|
dp->attrib = attrib & (kTypeMask | kAttribMask); // set user-settable bits
|
|
dp->parent = (DeviceNodePtr)parentNode;
|
|
if(dp->parent->childList == 0){ // first child node
|
|
dp->parent->childList = dp; // new node is head of child list
|
|
dp->parent->childTail = dp; // and is at the tail of the list
|
|
dp->peer = dp; // no other peers
|
|
}
|
|
else { // add node to others in child list
|
|
dp->peer = dp->parent->childList;
|
|
dp->parent->childTail->peer = dp;
|
|
dp->parent->childTail = dp;
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* create a new property node
|
|
*/
|
|
case(kPropertyNode):
|
|
if((attrib & kTypeMask) == kDeviceNode)
|
|
return(-1); // can't attach dev node to property
|
|
if((nameLen = CheckPropertyName(name)) == 0)
|
|
return(-1); // something wrong with name
|
|
pp = (PropertyNodePtr)AllocTreeMem(sizeof(PropertyNode));
|
|
retVal = (NodeID)pp;
|
|
dst = pp->name;
|
|
pp->attrib = attrib & (kTypeMask | kAttribMask); // set user-settable bits
|
|
pp->parent = (DeviceNodePtr)parentNode;
|
|
if(pp->parent->propertyList == 0){ // first property node
|
|
pp->parent->propertyList = pp;
|
|
pp->parent->propertyTail = pp;
|
|
pp->peer = pp;
|
|
}
|
|
else { // add node to others in property list
|
|
pp->peer = pp->parent->propertyList;
|
|
pp->parent->propertyTail->peer = pp;
|
|
pp->parent->propertyTail = pp;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
* copy name into the node
|
|
*/
|
|
while(nameLen){
|
|
*dst++ = *src++;
|
|
nameLen--;
|
|
}
|
|
*dst = '\0';
|
|
return(retVal);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeDelNode() */
|
|
/* */
|
|
/* Delete a node, and child nodes from the Device Tree */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
pascal OSErr DevTreeDelNode(theNode)
|
|
NodeID theNode;
|
|
{
|
|
register DeviceNodePtr dp, chldp, parentp, peerp;
|
|
register PropertyNodePtr pp, prevprop;
|
|
register OSErr status;
|
|
|
|
if(!CheckNodeID(theNode))
|
|
return(-1); // make sure node exists
|
|
switch(((DeviceNodePtr)theNode)->attrib & kTypeMask) {
|
|
|
|
/*
|
|
* Delete a device tree node, its property nodes
|
|
* and its decendents.
|
|
* ..checking to make sure it's not locked
|
|
*
|
|
* NOTE: locks on any child nodes are cheerfully ignored!
|
|
*
|
|
*/
|
|
case(kDeviceNode):
|
|
|
|
dp = (DeviceNodePtr)theNode;
|
|
if(dp->attrib & kAttribLocked)
|
|
return(-1);
|
|
/*
|
|
* start recursive deletion for all child nodes
|
|
*/
|
|
while(dp->childList){ // while there are child nodes
|
|
chldp = dp->childList;
|
|
peerp = chldp->peer;
|
|
status = DevTreeDelNode((NodeID)chldp); // recurse down one branch
|
|
}
|
|
|
|
/*
|
|
* Free all the property nodes (if any attached)
|
|
* Break condition is when the node you've just deleted
|
|
* is the tail node.
|
|
*/
|
|
while(dp->propertyList){
|
|
status = DevTreeDelNode((NodeID)dp->propertyList);
|
|
}
|
|
|
|
/*
|
|
* If we're at the bottom of the recursion,
|
|
* free memory used for the device node,
|
|
* and return. Note that if you try to delete the
|
|
* root node, it deletes all of the root node's
|
|
* properties and children, but not the node itself
|
|
*
|
|
*/
|
|
if(dp->parent == 0)
|
|
return(noErr);
|
|
|
|
parentp = dp->parent;
|
|
|
|
if(parentp->childList == dp){ // delete child at list head
|
|
if(parentp->childTail == dp){ // only one node in list
|
|
parentp->childList = 0;
|
|
parentp->childTail = 0;
|
|
}
|
|
else{
|
|
parentp->childTail->peer = dp->peer;
|
|
parentp->childList = dp->peer;
|
|
}
|
|
}
|
|
else{
|
|
chldp = parentp->childList;
|
|
while(chldp->peer != dp){
|
|
chldp = chldp->peer;
|
|
}
|
|
/*
|
|
* chldp points to prev node, so squeeze out
|
|
* the node we're deleting, updating childTail too
|
|
*/
|
|
if(parentp->childTail == dp){
|
|
parentp->childTail = chldp;
|
|
}
|
|
chldp->peer = dp->peer;
|
|
}
|
|
|
|
if(dp->childList == 0){ // if we have no children
|
|
FreeTreeMem((Ptr)dp); // delete ourselves..
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Delete a property node from a device, making sure
|
|
* it's not locked. Backing storage is released for properties
|
|
* with NVRAM and SYSSAVED attributes
|
|
* (take care of this in FreeTreeMem??)
|
|
*/
|
|
case(kPropertyNode):
|
|
pp = (PropertyNodePtr)theNode;
|
|
if(pp->attrib & kAttribLocked){
|
|
return(-1);
|
|
}
|
|
/*
|
|
* delete property specified by theNode
|
|
*/
|
|
dp = pp->parent;
|
|
if(dp->propertyList == pp){ // node to del at head
|
|
if(dp->propertyTail == pp){
|
|
dp->propertyList = 0; // only one property
|
|
dp->propertyTail = 0;
|
|
if(pp->size)
|
|
FreePropData(pp); // free property data
|
|
FreeTreeMem((Ptr)pp);
|
|
break;
|
|
}
|
|
else{
|
|
dp->propertyTail->peer = pp->peer; // move back-link in tail node
|
|
dp->propertyList = pp->peer; // move list head down one
|
|
if(pp->size)
|
|
FreePropData(pp); // free property data
|
|
FreeTreeMem((Ptr)pp);
|
|
break;
|
|
}
|
|
}
|
|
else{
|
|
/*
|
|
* since there are no back pointers, spin around the list to
|
|
* find the node just before us
|
|
*/
|
|
prevprop = pp;
|
|
pp = pp->peer;
|
|
while(pp != (PropertyNodePtr)theNode){
|
|
prevprop = pp;
|
|
pp = pp->peer;
|
|
}
|
|
/*
|
|
* prevprop now points to the node before us in the list.
|
|
* Squish out the node we want to delete. If the node being
|
|
* deleted is the last node in the list, make sure the tail
|
|
* pointer is backed up one.
|
|
*/
|
|
if(dp->propertyTail == pp)
|
|
dp->propertyTail = prevprop;
|
|
prevprop->peer = pp->peer;
|
|
|
|
/*
|
|
* NOTE: only works for direct property data
|
|
*/
|
|
if(pp->size)
|
|
FreePropData(pp); // free property data
|
|
|
|
FreeTreeMem((Ptr)pp);
|
|
}
|
|
break;
|
|
|
|
default: // all other node types fail
|
|
return(-1);
|
|
}
|
|
|
|
return(noErr);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeSetProperty() */
|
|
/* */
|
|
/* Change the value of a property */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
pascal OSErr DevTreeSetProperty(theNode, buf, size)
|
|
NodeID theNode;
|
|
unsigned char *buf;
|
|
long size;
|
|
{
|
|
PropertyNodePtr pp;
|
|
|
|
switch(((DeviceNodePtr)theNode)->attrib & kTypeMask) {
|
|
|
|
case(kDeviceNode):
|
|
return(-1); // dev nodes have no value attached
|
|
|
|
case(kPropertyNode):
|
|
pp = (PropertyNodePtr)theNode;
|
|
if(pp->attrib & kAttribROMProp)
|
|
return(-1); // can't change a ROM property
|
|
if(pp->attrib & kAttribDefProp)
|
|
return(-1); // can't set a Defered property (for now)
|
|
if(pp->size){ // already has a prop?
|
|
FreeTreeMem((Ptr)pp->dataPtr); // replace with new value
|
|
}
|
|
pp->dataPtr = (unsigned char *)AllocTreeMem(size);
|
|
pp->size = size;
|
|
BlockMove(buf, pp->dataPtr, size);
|
|
break;
|
|
|
|
default:
|
|
return(-1);
|
|
}
|
|
|
|
return(noErr);
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* */
|
|
/* DevTreeGetProperty() */
|
|
/* */
|
|
/* Get the value of a property */
|
|
/* */
|
|
/* */
|
|
/**************************************************************************/
|
|
pascal OSErr DevTreeGetProperty(theNode, buf, size)
|
|
NodeID theNode;
|
|
unsigned char *buf;
|
|
long size;
|
|
{
|
|
PropertyNodePtr pp;
|
|
|
|
switch(((DeviceNodePtr)theNode)->attrib & kTypeMask) {
|
|
|
|
case(kDeviceNode):
|
|
return(-1); // dev nodes have no value attached
|
|
|
|
case(kPropertyNode):
|
|
pp = (PropertyNodePtr)theNode;
|
|
if(pp->attrib & kAttribDefProp) // no defered properties yet
|
|
return(-1);
|
|
if((pp->size == 0)||(pp->dataPtr == 0))
|
|
return(-1); // node has no property value
|
|
if(pp->size < size)
|
|
size = pp->size; // return only as much as is there
|
|
BlockMove(pp->dataPtr, buf, size);
|
|
break;
|
|
|
|
default:
|
|
return(-1);
|
|
}
|
|
|
|
return(noErr);
|
|
}
|