|
|
1.1 root 1: /*
2: * Copyright (c) 1998-2000 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: *
24: * IOFWAddressSpace.cpp
25: *
26: * Classes which describe addresses in the local node which are accessable to other nodes
27: * via firewire asynchronous read/write/lock requests.
28: */
29: #include <IOKit/firewire/IOFWAddressSpace.h>
30:
31: /*
32: * Base class for FireWire address space objects
33: */
34: OSDefineMetaClass( IOFWAddressSpace, OSObject )
35: OSDefineAbstractStructors(IOFWAddressSpace, OSObject)
36:
37: /*
38: * Direct physical memory <-> FireWire address.
39: * Accesses to these addresses will be handled automatically by the
40: * hardware without notification.
41: *
42: * The 64 bit FireWire address of (32 bit) physical addr xxxx:xxxx is hostNode:0000:xxxx:xxxx
43: */
44: OSDefineMetaClassAndStructors(IOFWPhysicalAddressSpace, IOFWAddressSpace)
45:
46: bool IOFWPhysicalAddressSpace::initWithDesc(IOMemoryDescriptor *mem)
47: {
48: if(!IOFWAddressSpace::init())
49: return false;
50: fMem = mem;
51: fLen = mem->getLength();
52: {
53: vm_size_t pos;
54: IOPhysicalAddress phys;
55: pos = 0;
56: while(pos < fLen) {
57: IOPhysicalLength lengthOfSegment;
58: phys = fMem->getPhysicalSegment(pos, &lengthOfSegment);
59: pos += PAGE_SIZE - (phys & (PAGE_SIZE-1));
60: }
61: }
62:
63: return true;
64: }
65:
66: UInt32 IOFWPhysicalAddressSpace::doRead(UInt16 nodeID, FWAddress addr, UInt32 len,
67: IOMemoryDescriptor **buf, IOByteCount * offset,
68: bool lockRead)
69: {
70: UInt32 res = kFWResponseAddressError;
71: vm_size_t pos;
72: IOPhysicalAddress phys;
73: if(addr.addressHi != 0)
74: return kFWResponseAddressError;
75:
76: pos = 0;
77: while(pos < fLen) {
78: IOPhysicalLength lengthOfSegment;
79: phys = fMem->getPhysicalSegment(pos, &lengthOfSegment);
80: if(addr.addressLo >= phys && addr.addressLo+len <= phys+lengthOfSegment) {
81: // OK, block is in space and is within one VM page
82: // Set position to exact start
83: *offset = pos + addr.addressLo - phys;
84: *buf = fMem;
85: res = kFWResponseComplete;
86: break;
87: }
88: pos += PAGE_SIZE - (phys & (PAGE_SIZE-1));
89: }
90: return res;
91: }
92:
93: UInt32 IOFWPhysicalAddressSpace::doWrite(UInt16 nodeID, FWAddress addr, UInt32 len,
94: const void *buf, bool lockWrite)
95: {
96: UInt32 res = kFWResponseAddressError;
97: vm_size_t pos;
98: IOPhysicalAddress phys;
99: if(addr.addressHi != 0)
100: return kFWResponseAddressError;
101:
102: pos = 0;
103: while(pos < fLen) {
104: IOPhysicalLength lengthOfSegment;
105: phys = fMem->getPhysicalSegment(pos, &lengthOfSegment);
106: if(addr.addressLo >= phys && addr.addressLo+len <= phys+lengthOfSegment) {
107: // OK, block is in space and is within one VM page
108: // Set position to exact start
109: fMem->writeBytes(pos + addr.addressLo - phys, buf, len);
110: res = kFWResponseComplete;
111: break;
112: }
113: pos += PAGE_SIZE - (phys & (PAGE_SIZE-1));
114: }
115: return res;
116: }
117:
118: /*
119: * Pseudo firewire addresses usually represent emulated registers of some kind.
120: * Accesses to these addresses will result in the owner being notified.
121: *
122: * Virtual addresses should not have zero as the top 16 bits of the 48 bit local address,
123: * since that may look like a physical address to hardware (eg. OHCI).
124: * if reader is NULL then reads will not be allowed.
125: * if writer is NULL then writes will not be allowed.
126: * if either is NULL then lock requests will not be allowed.
127: * refcon is passed back as the first argument of read and write callbacks.
128: */
129: OSDefineMetaClassAndStructors(IOFWPseudoAddressSpace, IOFWAddressSpace)
130:
131: UInt32 IOFWPseudoAddressSpace::simpleReader(void *refcon, UInt16 nodeID,
132: FWAddress addr, UInt32 len, IOMemoryDescriptor **buf,
133: IOByteCount * offset, bool lockRead)
134: {
135: IOFWPseudoAddressSpace * space = (IOFWPseudoAddressSpace *)refcon;
136: *buf = space->fDesc;
137: *offset = addr.addressLo - space->fBase.addressLo;
138:
139: return kFWResponseComplete;
140: }
141:
142: UInt32 IOFWPseudoAddressSpace::simpleWriter(void *refcon, UInt16 nodeID,
143: FWAddress addr, UInt32 len, const void *buf, bool lockRead)
144: {
145: IOFWPseudoAddressSpace * space = (IOFWPseudoAddressSpace *)refcon;
146: space->fDesc->writeBytes(addr.addressLo - space->fBase.addressLo, buf, len);
147:
148: return kFWResponseComplete;
149: }
150:
151: IOFWPseudoAddressSpace *
152: IOFWPseudoAddressSpace::simpleRead(FWAddress addr, UInt32 len, const void *data)
153: {
154: IOFWPseudoAddressSpace * me;
155: me = new IOFWPseudoAddressSpace;
156: do {
157: if(!me)
158: break;
159: if(!me->initAll(addr, len, simpleReader, NULL, (void *)me)) {
160: me->release();
161: me = NULL;
162: break;
163: }
164: me->fDesc = IOMemoryDescriptor::withAddress((void *)data, len, kIODirectionOut);
165: if(!me->fDesc) {
166: me->release();
167: me = NULL;
168: }
169: } while(false);
170:
171: return me;
172: }
173:
174: IOFWPseudoAddressSpace *IOFWPseudoAddressSpace::simpleRW(FWAddress addr, UInt32 len, void *data)
175: {
176: IOFWPseudoAddressSpace * me;
177: me = new IOFWPseudoAddressSpace;
178: do {
179: if(!me)
180: break;
181: if(!me->initAll(addr, len, simpleReader, simpleWriter, (void *)me)) {
182: me->release();
183: me = NULL;
184: break;
185: }
186: me->fDesc = IOMemoryDescriptor::withAddress(data, len, kIODirectionOut);
187: if(!me->fDesc) {
188: me->release();
189: me = NULL;
190: }
191: } while(false);
192:
193: return me;
194: }
195:
196: bool IOFWPseudoAddressSpace::initAll(FWAddress addr, UInt32 len,
197: FWReadCallback reader, FWWriteCallback writer, void *refCon)
198: {
199: if(!IOFWAddressSpace::init())
200: return false;
201:
202: fBase = addr;
203: fBase.addressHi &= 0xFFFF; // Mask off nodeID part.
204: fLen = len;
205: fDesc = NULL; // Only used by simpleRead case.
206: fRefCon = refCon;
207: fReader = reader;
208: fWriter = writer;
209: return true;
210: }
211:
212: void IOFWPseudoAddressSpace::free()
213: {
214: if(fDesc)
215: fDesc->release();
216: IOFWAddressSpace::free();
217: }
218:
219: UInt32 IOFWPseudoAddressSpace::doRead(UInt16 nodeID, FWAddress addr, UInt32 len,
220: IOMemoryDescriptor **buf, IOByteCount * offset,
221: bool lockRead)
222: {
223: if(addr.addressHi != fBase.addressHi)
224: return kFWResponseAddressError;
225: if(addr.addressLo < fBase.addressLo)
226: return kFWResponseAddressError;
227: if(addr.addressLo > fBase.addressLo+fLen)
228: return kFWResponseAddressError;
229: if(!fReader)
230: return kFWResponseTypeError;
231: if(lockRead && !fWriter)
232: return kFWResponseTypeError;
233:
234: return fReader(fRefCon, nodeID, addr, len, buf, offset, lockRead);
235: }
236:
237: UInt32 IOFWPseudoAddressSpace::doWrite(UInt16 nodeID, FWAddress addr, UInt32 len,
238: const void *buf, bool lockWrite)
239: {
240: if(addr.addressHi != fBase.addressHi)
241: return kFWResponseAddressError;
242: if(addr.addressLo < fBase.addressLo)
243: return kFWResponseAddressError;
244: if(addr.addressLo > fBase.addressLo+fLen)
245: return kFWResponseAddressError;
246: if(!fWriter)
247: return kFWResponseTypeError;
248: if(lockWrite && !fReader)
249: return kFWResponseTypeError;
250:
251: return fWriter(fRefCon, nodeID, addr, len, buf, lockWrite);
252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.