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#include <IOKit/IODMAEventSource.h> 30#include <IOKit/IOService.h> 31 32#include "IOKitKernelInternal.h" 33 34 35#define super IOEventSource 36OSDefineMetaClassAndStructors(IODMAEventSource, IOEventSource); 37 38bool IODMAEventSource::init(OSObject *inOwner, 39 IOService *inProvider, 40 Action inCompletion, 41 Action inNotification, 42 UInt32 inDMAIndex) 43{ 44 IOReturn result; 45 46 if (!super::init(inOwner)) return false; 47 48 if (inProvider == 0) return false; 49 50 dmaProvider = inProvider; 51 dmaIndex = 0xFFFFFFFF; 52 dmaCompletionAction = inCompletion; 53 dmaNotificationAction = inNotification; 54 55 dmaController = IODMAController::getController(dmaProvider, inDMAIndex); 56 if (dmaController == 0) return false; 57 dmaController->retain(); 58 59 result = dmaController->initDMAChannel(dmaProvider, this, &dmaIndex, inDMAIndex); 60 if (result != kIOReturnSuccess) return false; 61 62 queue_init(&dmaCommandsCompleted); 63 dmaCommandsCompletedLock = IOSimpleLockAlloc(); 64 65 return true; 66} 67 68void IODMAEventSource::free() 69{ 70 if (dmaCommandsCompletedLock != NULL) IOSimpleLockFree(dmaCommandsCompletedLock); 71 super::free(); 72} 73 74IODMAEventSource *IODMAEventSource::dmaEventSource(OSObject *inOwner, 75 IOService *inProvider, 76 Action inCompletion, 77 Action inNotification, 78 UInt32 inDMAIndex) 79{ 80 IODMAEventSource *dmaES = new IODMAEventSource; 81 82 if (dmaES && !dmaES->init(inOwner, inProvider, inCompletion, inNotification, inDMAIndex)) { 83 dmaES->release(); 84 return 0; 85 } 86 87 return dmaES; 88} 89 90IOReturn IODMAEventSource::startDMACommand(IODMACommand *dmaCommand, IODirection direction, IOByteCount byteCount, IOByteCount byteOffset) 91{ 92 IOReturn result; 93 94 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return kIOReturnError; 95 96 if (dmaSynchBusy) return kIOReturnBusy; 97 98 if (dmaCompletionAction == 0) dmaSynchBusy = true; 99 100 result = dmaController->startDMACommand(dmaIndex, dmaCommand, direction, byteCount, byteOffset); 101 102 if (result != kIOReturnSuccess) { 103 dmaSynchBusy = false; 104 return result; 105 } 106 107 while (dmaSynchBusy) sleepGate(&dmaSynchBusy, THREAD_UNINT); 108 109 return kIOReturnSuccess; 110} 111 112IOReturn IODMAEventSource::stopDMACommand(bool flush, uint64_t timeout) 113{ 114 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return kIOReturnError; 115 116 return dmaController->stopDMACommand(dmaIndex, flush, timeout); 117} 118 119 120IOReturn IODMAEventSource::queryDMACommand(IODMACommand **dmaCommand, IOByteCount *transferCount, bool waitForIdle) 121{ 122 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return kIOReturnError; 123 124 return dmaController->queryDMACommand(dmaIndex, dmaCommand, transferCount, waitForIdle); 125} 126 127 128IOByteCount IODMAEventSource::getFIFODepth(IODirection direction) 129{ 130 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return 0; 131 132 return dmaController->getFIFODepth(dmaIndex, direction); 133} 134 135 136IOReturn IODMAEventSource::setFIFODepth(IOByteCount depth) 137{ 138 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return kIOReturnError; 139 140 return dmaController->setFIFODepth(dmaIndex, depth); 141} 142 143 144IOByteCount IODMAEventSource::validFIFODepth(IOByteCount depth, IODirection direction) 145{ 146 if ((dmaController == 0) || (dmaIndex == 0xFFFFFFFF)) return kIOReturnError; 147 148 return dmaController->validFIFODepth(dmaIndex, depth, direction); 149} 150 151 152// protected 153 154bool IODMAEventSource::checkForWork(void) 155{ 156 IODMACommand *dmaCommand = NULL; 157 bool work, again; 158 159 IOSimpleLockLock(dmaCommandsCompletedLock); 160 work = !queue_empty(&dmaCommandsCompleted); 161 if (work) { 162 queue_remove_first(&dmaCommandsCompleted, dmaCommand, IODMACommand *, fCommandChain); 163 again = !queue_empty(&dmaCommandsCompleted); 164 } else { 165 again = false; 166 } 167 IOSimpleLockUnlock(dmaCommandsCompletedLock); 168 169 if (work) { 170 (*dmaCompletionAction)(owner, this, dmaCommand, dmaCommand->reserved->fStatus, dmaCommand->reserved->fActualByteCount, dmaCommand->reserved->fTimeStamp); 171 } 172 173 return again; 174} 175 176void IODMAEventSource::completeDMACommand(IODMACommand *dmaCommand) 177{ 178 if (dmaCompletionAction != 0) { 179 IOSimpleLockLock(dmaCommandsCompletedLock); 180 queue_enter(&dmaCommandsCompleted, dmaCommand, IODMACommand *, fCommandChain); 181 IOSimpleLockUnlock(dmaCommandsCompletedLock); 182 183 signalWorkAvailable(); 184 } else { 185 dmaSynchBusy = false; 186 wakeupGate(&dmaSynchBusy, true); 187 } 188} 189 190void IODMAEventSource::notifyDMACommand(IODMACommand *dmaCommand, IOReturn status, IOByteCount actualByteCount, AbsoluteTime timeStamp) 191{ 192 dmaCommand->reserved->fStatus = status; 193 dmaCommand->reserved->fActualByteCount = actualByteCount; 194 dmaCommand->reserved->fTimeStamp = timeStamp; 195 196 if (dmaNotificationAction != 0) (*dmaNotificationAction)(owner, this, dmaCommand, status, actualByteCount, timeStamp); 197} 198 199IOReturn IODMAEventSource::setDMAConfig(UInt32 newReqIndex) 200{ 201 return dmaController->setDMAConfig(dmaIndex, dmaProvider, newReqIndex); 202} 203 204bool IODMAEventSource::validDMAConfig(UInt32 newReqIndex) 205{ 206 return dmaController->validDMAConfig(dmaIndex, dmaProvider, newReqIndex); 207} 208