1 /*
2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #define IOKIT_ENABLE_SHARED_PTR
30 
31 #include <IOKit/IODMAController.h>
32 #include <libkern/c++/OSSharedPtr.h>
33 
34 
35 #define super IOService
36 OSDefineMetaClassAndAbstractStructors(IODMAController, IOService);
37 
38 OSSharedPtr<const OSSymbol>
createControllerName(UInt32 phandle)39 IODMAController::createControllerName(UInt32 phandle)
40 {
41 #define CREATE_BUF_LEN 48
42 	char           buf[CREATE_BUF_LEN];
43 
44 	snprintf(buf, CREATE_BUF_LEN, "IODMAController%08X", (uint32_t)phandle);
45 
46 	return OSSymbol::withCString(buf);
47 }
48 
49 IODMAController *
getController(IOService * provider,UInt32 dmaIndex)50 IODMAController::getController(IOService *provider, UInt32 dmaIndex)
51 {
52 	OSData          *dmaParentData;
53 	OSSharedPtr<const OSSymbol> dmaParentName;
54 	IODMAController *dmaController;
55 
56 	// Find the name of the parent dma controller
57 	OSSharedPtr<OSObject> prop = provider->copyProperty("dma-parent");
58 	dmaParentData = OSDynamicCast(OSData, prop.get());
59 	if (dmaParentData == NULL) {
60 		return NULL;
61 	}
62 
63 	if (dmaParentData->getLength() == sizeof(UInt32)) {
64 		dmaParentName = createControllerName(*(UInt32 *)dmaParentData->getBytesNoCopy());
65 	} else {
66 		if (dmaIndex >= dmaParentData->getLength() / sizeof(UInt32)) {
67 			panic("dmaIndex out of range");
68 		}
69 		dmaParentName = createControllerName(*(UInt32 *)dmaParentData->getBytesNoCopy(dmaIndex * sizeof(UInt32), sizeof(UInt32)));
70 	}
71 	if (dmaParentName == NULL) {
72 		return NULL;
73 	}
74 
75 	// Wait for the parent dma controller
76 	dmaController = OSDynamicCast(IODMAController, IOService::waitForService( IOService::nameMatching(dmaParentName.get()).detach()));
77 
78 	return dmaController;
79 }
80 
81 
82 bool
start(IOService * provider)83 IODMAController::start(IOService *provider)
84 {
85 	if (!super::start(provider)) {
86 		return false;
87 	}
88 
89 	_provider = provider;
90 
91 	return true;
92 }
93 
94 
95 // protected
96 
97 void
registerDMAController(IOOptionBits options)98 IODMAController::registerDMAController(IOOptionBits options)
99 {
100 	OSData *phandleData;
101 
102 	OSSharedPtr<OSObject> prop = _provider->copyProperty("AAPL,phandle");
103 	phandleData = OSDynamicCast(OSData, prop.get());
104 
105 	_dmaControllerName = createControllerName(*(UInt32 *)phandleData->getBytesNoCopy());
106 
107 	setName(_dmaControllerName.get());
108 
109 	registerService(options | ((options & kIOServiceAsynchronous) ? 0 : kIOServiceSynchronous));
110 }
111 
112 void
completeDMACommand(IODMAEventSource * dmaES,IODMACommand * dmaCommand)113 IODMAController::completeDMACommand(IODMAEventSource *dmaES, IODMACommand *dmaCommand)
114 {
115 	dmaES->completeDMACommand(dmaCommand);
116 }
117 
118 void
notifyDMACommand(IODMAEventSource * dmaES,IODMACommand * dmaCommand,IOReturn status,IOByteCount actualByteCount,AbsoluteTime timeStamp)119 IODMAController::notifyDMACommand(IODMAEventSource *dmaES, IODMACommand *dmaCommand, IOReturn status, IOByteCount actualByteCount, AbsoluteTime timeStamp)
120 {
121 	dmaES->notifyDMACommand(dmaCommand, status, actualByteCount, timeStamp);
122 }
123 
124 
125 // private
126