1/*
2 * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23// public
24#import <IOKit/firewire/IOLocalConfigDirectory.h>
25
26// private
27#import "FWDebugging.h"
28
29// system
30#import <libkern/c++/OSIterator.h>
31#import <libkern/c++/OSData.h>
32#import <libkern/c++/OSArray.h>
33
34#import "IOConfigEntry.h"
35
36OSDefineMetaClassAndStructors(IOConfigEntry, OSObject);
37
38// free
39//
40//
41
42void IOConfigEntry::free()
43{
44    if (fData) {
45        fData->release();
46        fData = NULL;
47    }
48
49    OSObject::free();
50}
51
52// create
53//
54//
55
56IOConfigEntry* IOConfigEntry::create(UInt32 key, IOConfigKeyType type, OSObject *obj)
57{
58    IOConfigEntry* entry;
59    entry = OSTypeAlloc( IOConfigEntry );
60    if(!entry)
61        return NULL;
62    if(!entry->init()) {
63        entry->release();
64        return NULL;
65    }
66    assert(type == kConfigLeafKeyType ||
67           type == kConfigDirectoryKeyType);
68    entry->fKey = key;
69    entry->fType = type;
70
71	obj->retain() ;
72    entry->fData = obj;
73
74    return entry;
75}
76
77// create
78//
79//
80
81IOConfigEntry* IOConfigEntry::create(UInt32 key, UInt32 value)
82{
83    IOConfigEntry* entry;
84
85    if(value > kConfigEntryValue)
86        return NULL;	// Too big to fit!!
87    entry = OSTypeAlloc( IOConfigEntry );
88    if(!entry)
89        return NULL;
90    if(!entry->init()) {
91        entry->release();
92        return NULL;
93    }
94    entry->fKey = key;
95    entry->fType = kConfigImmediateKeyType;
96    entry->fValue = value;
97    return entry;
98}
99
100// create
101//
102//
103
104IOConfigEntry* IOConfigEntry::create(UInt32 key, FWAddress address)
105{
106    IOConfigEntry* entry;
107    entry = OSTypeAlloc( IOConfigEntry );
108    if(!entry)
109        return NULL;
110    if(!entry->init()) {
111        entry->release();
112        return NULL;
113    }
114    entry->fKey = key;
115    entry->fType = kConfigOffsetKeyType;
116    entry->fAddr = address;
117    return entry;
118}
119
120// totalSize
121//
122//
123
124unsigned int IOConfigEntry::totalSize()
125{
126    unsigned int size = 0;
127    switch(fType) {
128	default:
129            break;
130        case kConfigLeafKeyType:
131        {
132            OSData *data = OSDynamicCast(OSData, fData);
133            if(!data)
134                return 0;
135            // Round up size to multiple of 4, plus header
136            size = (data->getLength()-1) / sizeof(UInt32) + 2;
137            break;
138
139        }
140        case kConfigDirectoryKeyType:
141        {
142            IOLocalConfigDirectory *dir = OSDynamicCast(IOLocalConfigDirectory,
143                                                            fData);
144            if(!dir)
145                return 0;	// Oops!
146            const OSArray *entries = dir->getEntries();
147            unsigned int i;
148            size = 1 + entries->getCount();
149            for(i=0; i<entries->getCount(); i++) {
150                IOConfigEntry *entry = OSDynamicCast(IOConfigEntry, entries->getObject(i));
151                if(!entry)
152                    return 0;	// Oops!
153                size += entry->totalSize();
154            }
155            break;
156        }
157    }
158    return size;
159}
160