|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: // Copyright 1997 by Apple Computer, Inc., all rights reserved. ! 26: /* ! 27: * Copyright (c) 1995-1997 NeXT Software, Inc. All rights reserved. ! 28: * ! 29: * AtapiCntInternal.m - Implementation of ATAPI controller class. ! 30: * ! 31: * ! 32: * HISTORY ! 33: * ! 34: * 05-Mar-1996 Rakesh Dubey at NeXT ! 35: * Modified so that no memory is allocated at run-time. ! 36: * ! 37: * 21-Mar-1995 Rakesh Dubey at NeXT ! 38: * Created. ! 39: */ ! 40: ! 41: #import "IdeCnt.h" ! 42: #import "AtapiCntInternal.h" ! 43: #import <kern/assert.h> ! 44: #import <driverkit/kernelDriver.h> ! 45: #import <driverkit/interruptMsg.h> ! 46: #import <mach/mach_interface.h> ! 47: #import <driverkit/IODevice.h> ! 48: #import <machkit/NXLock.h> ! 49: #import <kernserv/prototypes.h> ! 50: ! 51: @implementation AtapiController(Internal) ! 52: ! 53: - initResources:direct ! 54: { ! 55: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 56: int i; ! 57: atapiBuf_t *atapiBuf; ! 58: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 59: ! 60: _ataController = direct; ! 61: ! 62: queue_init(&_ioQueueNodisk); ! 63: ! 64: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 65: ! 66: /* Set up a queue of ideBufs */ ! 67: queue_init(&_atapiBufQueue); ! 68: _atapiBufLock = [NXLock new]; ! 69: [_atapiBufLock lock]; ! 70: ! 71: for (i = 0; i < MAX_NUM_ATAPIBUF; i++) { ! 72: atapiBuf = &_atapiBufPool[i]; ! 73: atapiBuf->waitLock = [NXConditionLock alloc]; ! 74: [atapiBuf->waitLock initWith:NO]; ! 75: queue_enter(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink); ! 76: } ! 77: [_atapiBufLock unlock]; ! 78: ! 79: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 80: ! 81: _ioQLock = [NXConditionLock alloc]; ! 82: [_ioQLock initWith:NO_WORK_AVAILABLE]; ! 83: ! 84: IOForkThread((IOThreadFunc)atapiThread, self); ! 85: ! 86: return self; ! 87: } ! 88: ! 89: /* ! 90: * Free up local resources. ! 91: */ ! 92: - free ! 93: { ! 94: /* ! 95: * First kill the I/O thread, then free alloc'd instance variables. ! 96: */ ! 97: atapiBuf_t *atapiBuf; ! 98: int i; ! 99: ! 100: atapiBuf = [self allocAtapiBuf]; ! 101: [self enqueueAtapiBuf:atapiBuf]; ! 102: ! 103: [self freeAtapiBuf:atapiBuf]; ! 104: [_ioQLock free]; ! 105: ! 106: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 107: if (_atapiBufLock) ! 108: [_atapiBufLock free]; ! 109: ! 110: for (i = 0; i < MAX_NUM_ATAPIBUF; i++) { ! 111: if (_atapiBufPool[i].waitLock) ! 112: [_atapiBufPool[i].waitLock free]; ! 113: } ! 114: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 115: ! 116: return ([super free]); ! 117: } ! 118: ! 119: /* ! 120: * Allocate and free AtapiBuf_t's. ! 121: */ ! 122: ! 123: #ifdef NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 124: - (atapiBuf_t *) allocAtapiBuf ! 125: { ! 126: atapiBuf_t *atapiBuf; ! 127: id waitLock; ! 128: ! 129: while (1) { ! 130: [_atapiBufLock lock]; ! 131: if (!queue_empty(&_atapiBufQueue)) ! 132: break; ! 133: [_atapiBufLock unlock]; ! 134: IOSleep(20); // the system is overloaded ! 135: } ! 136: ! 137: ASSERT(queue_empty(&_atapiBufQueue) != 0); ! 138: atapiBuf = (atapiBuf_t *) queue_first(&_atapiBufQueue); ! 139: ASSERT(atapiBuf != 0); ! 140: queue_remove(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink); ! 141: ! 142: waitLock = atapiBuf->waitLock; ! 143: bzero(atapiBuf, sizeof(atapiBuf_t)); ! 144: atapiBuf->waitLock = waitLock; ! 145: [atapiBuf->waitLock initWith:NO]; ! 146: ! 147: [_atapiBufLock unlock]; ! 148: return (atapiBuf); ! 149: } ! 150: ! 151: - (void)freeAtapiBuf:(atapiBuf_t *) atapiBuf ! 152: { ! 153: [_atapiBufLock lock]; ! 154: queue_enter(&_atapiBufQueue, atapiBuf, atapiBuf_t *, bufLink); ! 155: ASSERT(queue_empty(&_atapiBufQueue) != 0); ! 156: [_atapiBufLock unlock]; ! 157: } ! 158: ! 159: #else NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 160: ! 161: - (atapiBuf_t *) allocAtapiBuf ! 162: { ! 163: atapiBuf_t *atapiBuf = IOMalloc(sizeof(atapiBuf_t)); ! 164: ! 165: bzero(atapiBuf, sizeof(atapiBuf_t)); ! 166: atapiBuf->waitLock = [NXConditionLock alloc]; ! 167: [atapiBuf->waitLock initWith:NO]; ! 168: ! 169: return (atapiBuf); ! 170: } ! 171: ! 172: - (void)freeAtapiBuf:(atapiBuf_t *) atapiBuf ! 173: { ! 174: if (atapiBuf->waitLock) { ! 175: [atapiBuf->waitLock free]; ! 176: } ! 177: IOFree(atapiBuf, sizeof(atapiBuf_t)); ! 178: } ! 179: #endif NO_ATAPI_RUNTIME_MEMORY_ALLOCATION ! 180: ! 181: /* ! 182: * -- Enqueue an AtapiBuf_t on ioQueue<Disk,Nodisk> ! 183: * -- wake up the I/O thread ! 184: * -- wait for I/O complete (if atapiBuf->pending == NULL) ! 185: * ! 186: * All I/O goes thru here; this is the last method called by exported methods ! 187: * before the I/O thread takes over. ! 188: */ ! 189: - (IOReturn) enqueueAtapiBuf:(atapiBuf_t *) atapiBuf ! 190: { ! 191: queue_head_t *q; ! 192: ! 193: [_ioQLock lock]; ! 194: q = &_ioQueueNodisk; ! 195: queue_enter(q, atapiBuf, atapiBuf_t *, link); ! 196: [_ioQLock unlockWith:WORK_AVAILABLE]; ! 197: ! 198: /* ! 199: * Wait for I/O complete. ! 200: */ ! 201: [atapiBuf->waitLock lockWhen:YES]; ! 202: [atapiBuf->waitLock unlock]; ! 203: ! 204: /* FIXME: What should this value be?? */ ! 205: return (atapiBuf->status); ! 206: } ! 207: ! 208: ! 209: /* ! 210: * Either wake up the thread which is waiting on the ideCmdBuf, or send an ! 211: * ioComplete back to client. ideCmdBuf->status must be valid. ! 212: */ ! 213: - (void)atapiIoComplete:(atapiBuf_t *) atapiBuf ! 214: { ! 215: /* ! 216: * Sync I/O. Just wake up the waiting thread. ! 217: */ ! 218: [atapiBuf->waitLock lock]; ! 219: [atapiBuf->waitLock unlockWith:YES]; ! 220: } ! 221: ! 222: /* ! 223: * Main command dispatch method. ! 224: */ ! 225: - (void)atapiCmdDispatch:(atapiBuf_t *)atapiBuf ! 226: { ! 227: sc_status_t ret; ! 228: ! 229: switch (atapiBuf->command) { ! 230: ! 231: case ATAPI_CNT_IOREQ: ! 232: ret = [_ataController atapiExecuteCmd:atapiBuf->atapiIoReq ! 233: buffer:atapiBuf->buffer client:atapiBuf->client]; ! 234: atapiBuf->status = ret; ! 235: break; ! 236: ! 237: case ATAPI_CNT_THREAD_ABORT: ! 238: ! 239: /* ! 240: * First give I/O complete before we die. ! 241: */ ! 242: atapiBuf->status = STAT_GOOD; ! 243: [self atapiIoComplete:atapiBuf]; ! 244: IOExitThread(); ! 245: ! 246: default: ! 247: IOLog("%s: Bogus atapiBuf->command 0x%0x in atapiCmdDispatch\n", ! 248: [self name], atapiBuf->command); ! 249: IOPanic("atapiThread"); ! 250: } ! 251: ! 252: [self atapiIoComplete:atapiBuf]; ! 253: return; ! 254: } ! 255: ! 256: /* ! 257: * Unlock ioQLock, updating condition variable as appropriate. ! 258: */ ! 259: - (void)unlockIoQLock ! 260: { ! 261: int queue_state; ! 262: ! 263: if (!queue_empty(&_ioQueueNodisk)) ! 264: queue_state = WORK_AVAILABLE; ! 265: else ! 266: queue_state = NO_WORK_AVAILABLE; ! 267: [_ioQLock unlockWith:queue_state]; ! 268: } ! 269: ! 270: ! 271: @end ! 272: ! 273: /* ! 274: * I/O thread. Each one of these sits around waiting for work to do on ! 275: * ioQueue; when something appears, the thread grabs it and disptahes it. ! 276: */ ! 277: ! 278: volatile void atapiThread(AtapiController *atapiCnt) ! 279: { ! 280: atapiBuf_t *atapiBuf; ! 281: queue_head_t *q; ! 282: ! 283: while (1) { ! 284: ! 285: /* ! 286: * Wait for some work to do. ! 287: */ ! 288: [atapiCnt->_ioQLock lockWhen:WORK_AVAILABLE]; ! 289: ! 290: /* ! 291: * Service all requests which do not require a disk. ! 292: */ ! 293: q = &atapiCnt->_ioQueueNodisk; ! 294: while (!queue_empty(q)) { ! 295: atapiBuf = (atapiBuf_t *) queue_first(q); ! 296: queue_remove(q, atapiBuf, atapiBuf_t *, link); ! 297: [atapiCnt->_ioQLock unlock]; ! 298: [atapiCnt atapiCmdDispatch:atapiBuf]; ! 299: [atapiCnt->_ioQLock lock]; ! 300: } ! 301: ! 302: [atapiCnt unlockIoQLock]; ! 303: } ! 304: ! 305: /* NOT REACHED */ ! 306: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.