|
|
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: /* ! 26: * Copyright (c) 1993, 1994 NeXT Computer, Inc. ! 27: * ! 28: * Kernel Device Object. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 1 Jul 1994 ? at NeXT ! 33: * Modifications for shared interrupts. ! 34: * 27 Feb 1994 ? at NeXT ! 35: * Major rewrite. ! 36: * 3 Oct 1993 ? at NeXT ! 37: * Created. ! 38: */ ! 39: ! 40: #import <mach/mach_types.h> ! 41: ! 42: #import <objc/List.h> ! 43: ! 44: #import <driverkit/kernelDriver.h> ! 45: #import <driverkit/interruptMsg.h> ! 46: #import <driverkit/KernDevice.h> ! 47: #import <driverkit/KernDevicePrivate.h> ! 48: #import <driverkit/KernBusInterrupt.h> ! 49: #import <driverkit/KernDeviceDescription.h> ! 50: #import <driverkit/KernLock.h> ! 51: ! 52: #import <kernserv/machine/spl.h> ! 53: ! 54: @implementation KernDevice ! 55: ! 56: - initWithDeviceDescription: deviceDescription ! 57: { ! 58: if (deviceDescription == nil) ! 59: return [self free]; ! 60: ! 61: [super init]; ! 62: ! 63: _deviceDescription = deviceDescription; ! 64: ! 65: return self; ! 66: } ! 67: ! 68: - init ! 69: { ! 70: return [self free]; ! 71: } ! 72: ! 73: - free ! 74: { ! 75: [self detachInterruptPort]; ! 76: ! 77: return [super free]; ! 78: } ! 79: ! 80: - deviceDescription ! 81: { ! 82: return _deviceDescription; ! 83: } ! 84: ! 85: - attachInterruptPort: (port_t)interruptPort ! 86: { ! 87: ipc_port_t port; ! 88: id interrupts; ! 89: int i, numInterrupts; ! 90: ! 91: if (_interruptPort != IP_NULL) ! 92: return nil; ! 93: ! 94: if (ipc_object_copyin(current_task()->itk_space, ! 95: interruptPort, MACH_MSG_TYPE_MAKE_SEND, ! 96: &port)) ! 97: return nil; ! 98: ! 99: interrupts = [_deviceDescription interrupts]; ! 100: if (interrupts == nil) { ! 101: ipc_port_release_send(port); ! 102: return self; ! 103: } ! 104: ! 105: numInterrupts = [interrupts count]; ! 106: if (numInterrupts == 0) { ! 107: ipc_port_release_send(port); ! 108: return self; ! 109: } ! 110: ! 111: _interruptPort = port; ! 112: ! 113: _interrupts = [[List alloc] initCount:numInterrupts]; ! 114: ! 115: for (i = 0; i < numInterrupts; i++) { ! 116: if (![_interrupts addObject: ! 117: [[KernDeviceInterrupt alloc] ! 118: initWithInterruptPort:_interruptPort]]) { ! 119: [self _detachInterruptSources]; ! 120: ipc_port_release_send(_interruptPort); ! 121: _interruptPort = IP_NULL; ! 122: return nil; ! 123: } ! 124: } ! 125: ! 126: return self; ! 127: } ! 128: ! 129: - detachInterruptPort ! 130: { ! 131: if (_interruptPort == IP_NULL) ! 132: return self; ! 133: ! 134: [self _detachInterruptSources]; ! 135: ! 136: ipc_port_release_send(_interruptPort); ! 137: _interruptPort = IP_NULL; ! 138: ! 139: return self; ! 140: } ! 141: ! 142: - interrupt: (int)index ! 143: { ! 144: return [_interrupts objectAt:index]; ! 145: } ! 146: ! 147: - interrupts ! 148: { ! 149: return _interrupts; ! 150: } ! 151: ! 152: @end ! 153: ! 154: @implementation KernDevice(Private) ! 155: ! 156: - (void)_detachInterruptSources ! 157: { ! 158: if (_interrupts != nil) { ! 159: [[_interrupts freeObjects] free]; ! 160: ! 161: _interrupts = nil; ! 162: } ! 163: } ! 164: ! 165: @end ! 166: ! 167: @implementation KernDeviceInterrupt ! 168: ! 169: - initWithInterruptPort: (void *)port ! 170: { ! 171: [super init]; ! 172: ! 173: _lock = [[KernLock alloc] initWithLevel:IPLHIGH]; ! 174: ! 175: _ipcMessage = _KernDeviceInterruptMsgCreate(port); ! 176: ! 177: return self; ! 178: } ! 179: ! 180: - free ! 181: { ! 182: [self detach]; ! 183: ! 184: [_lock free]; ! 185: ! 186: _KernDeviceInterruptMsgDestroy(_ipcMessage); ! 187: ! 188: return [super free]; ! 189: } ! 190: ! 191: - attachToBusInterrupt: busInterrupt ! 192: withArgument: (void *)argument ! 193: { ! 194: [_lock acquire]; ! 195: ! 196: if (_busInterrupt) { ! 197: [_lock release]; ! 198: return nil; ! 199: } ! 200: ! 201: _busInterrupt = busInterrupt; ! 202: ! 203: [_lock release]; ! 204: ! 205: [busInterrupt suspend]; ! 206: ! 207: if (![busInterrupt attachDeviceInterrupt:self]) { ! 208: [busInterrupt resume]; ! 209: ! 210: [_lock acquire]; ! 211: _busInterrupt = nil; ! 212: [_lock release]; ! 213: ! 214: return nil; ! 215: } ! 216: ! 217: [_lock acquire]; ! 218: ! 219: _handler = IOSendInterrupt; ! 220: _handlerArgument = argument; ! 221: ! 222: [_lock release]; ! 223: ! 224: [busInterrupt resume]; ! 225: ! 226: return self; ! 227: } ! 228: ! 229: - attachToBusInterrupt: busInterrupt ! 230: withSpecialHandler: (void *)handler ! 231: argument: (void *)argument ! 232: atLevel: (int)level ! 233: { ! 234: [_lock acquire]; ! 235: ! 236: if (_busInterrupt) { ! 237: [_lock release]; ! 238: return nil; ! 239: } ! 240: ! 241: _busInterrupt = busInterrupt; ! 242: ! 243: [_lock release]; ! 244: ! 245: [busInterrupt suspend]; ! 246: ! 247: if (![_busInterrupt attachDeviceInterrupt:self atLevel:level]) { ! 248: [busInterrupt resume]; ! 249: ! 250: [_lock acquire]; ! 251: _busInterrupt = nil; ! 252: [_lock release]; ! 253: ! 254: return nil; ! 255: } ! 256: ! 257: [_lock acquire]; ! 258: ! 259: _handler = handler; ! 260: _handlerArgument = argument; ! 261: ! 262: [_lock release]; ! 263: ! 264: [busInterrupt resume]; ! 265: ! 266: return self; ! 267: } ! 268: ! 269: - detach ! 270: { ! 271: id busInterrupt; ! 272: BOOL isSuspended; ! 273: ! 274: [_lock acquire]; ! 275: ! 276: if (!_busInterrupt) { ! 277: [_lock release]; ! 278: return nil; ! 279: } ! 280: ! 281: busInterrupt = _busInterrupt; _busInterrupt = nil; ! 282: isSuspended = _isSuspended; _isSuspended = NO; ! 283: ! 284: [_lock release]; ! 285: ! 286: if (!isSuspended) ! 287: [busInterrupt suspend]; ! 288: ! 289: [busInterrupt detachDeviceInterrupt:self]; ! 290: ! 291: [busInterrupt resume]; ! 292: ! 293: return self; ! 294: } ! 295: ! 296: - suspend ! 297: { ! 298: id busInterrupt; ! 299: BOOL isSuspended; ! 300: ! 301: [_lock acquire]; ! 302: ! 303: if (!_busInterrupt) { ! 304: [_lock release]; ! 305: return nil; ! 306: } ! 307: ! 308: busInterrupt = _busInterrupt; ! 309: isSuspended = _isSuspended; _isSuspended = YES; ! 310: ! 311: [_lock release]; ! 312: ! 313: if (!isSuspended) ! 314: [busInterrupt suspend]; ! 315: ! 316: return self; ! 317: } ! 318: ! 319: - resume ! 320: { ! 321: id busInterrupt; ! 322: BOOL isSuspended; ! 323: ! 324: [_lock acquire]; ! 325: ! 326: if (!_busInterrupt) { ! 327: [_lock release]; ! 328: return nil; ! 329: } ! 330: ! 331: busInterrupt = _busInterrupt; ! 332: isSuspended = _isSuspended; _isSuspended = NO; ! 333: ! 334: [_lock release]; ! 335: ! 336: if (isSuspended) ! 337: [busInterrupt resume]; ! 338: ! 339: return self; ! 340: } ! 341: ! 342: @end ! 343: ! 344: static ! 345: KernDeviceInterruptMsg * ! 346: _KernDeviceInterruptMsgCreate( ! 347: ipc_port_t interruptPort ! 348: ) ! 349: { ! 350: KernDeviceInterruptMsg *msg; ! 351: ! 352: msg = (void *)kalloc(sizeof (*msg)); ! 353: *msg = (KernDeviceInterruptMsg) { 0 }; ! 354: ! 355: msg->lock = [[KernLock alloc] initWithLevel:IPLSCHED]; ! 356: ! 357: ipc_port_reference(interruptPort); ! 358: msg->iport = interruptPort; ! 359: ! 360: msg->callout.func = (thread_call_func_t)_KernDeviceInterruptCallout; ! 361: msg->callout.spec_proto = msg; ! 362: msg->callout.status = IDLE; ! 363: ! 364: ikm_init_special(&msg->kmsg, IKM_SIZE_DEVICE); ! 365: ! 366: ipc_port_reference(msg->iport); ! 367: ! 368: return msg; ! 369: } ! 370: ! 371: static ! 372: void ! 373: _KernDeviceInterruptMsgDestroy( ! 374: KernDeviceInterruptMsg *msg ! 375: ) ! 376: { ! 377: KernLockAcquire(msg->lock); ! 378: if (msg->queued || msg->pending) { ! 379: msg->destroy = YES; ! 380: KernLockRelease(msg->lock); ! 381: return; ! 382: } ! 383: KernLockRelease(msg->lock); ! 384: ! 385: ipc_port_release(msg->iport); ! 386: ipc_port_release(msg->iport); ! 387: ! 388: [msg->lock free]; ! 389: ! 390: kfree(msg, sizeof (*msg)); ! 391: } ! 392: ! 393: void ! 394: KernDeviceInterruptMsgRelease( ! 395: void *m ! 396: ) ! 397: { ! 398: KernDeviceInterruptMsg *msg = m; ! 399: ! 400: ipc_port_reference(msg->iport); ! 401: ! 402: KernLockAcquire(msg->lock); ! 403: msg->queued = FALSE; ! 404: if (msg->destroy) { ! 405: KernLockRelease(msg->lock); ! 406: _KernDeviceInterruptMsgDestroy(msg); ! 407: } ! 408: else ! 409: KernLockRelease(msg->lock); ! 410: } ! 411: #if sparc ! 412: int ! 413: #else ! 414: void ! 415: #endif ! 416: KernDeviceInterruptDispatch( ! 417: KernDeviceInterrupt *_interrupt, ! 418: void *state ! 419: ) ! 420: { ! 421: KernDeviceInterrupt_ *interrupt = ! 422: (KernDeviceInterrupt_ *)_interrupt; ! 423: #if sparc ! 424: int (*handler)() = interrupt->_handler; ! 425: return((*handler)(interrupt, state, interrupt->_handlerArgument)); ! 426: #else ! 427: void (*handler)() = interrupt->_handler; ! 428: (*handler)(interrupt, state, interrupt->_handlerArgument); ! 429: ! 430: #endif ! 431: ! 432: } ! 433: ! 434: void ! 435: KernDeviceInterruptDispatchShared( ! 436: KernDeviceInterrupt *_interrupt, ! 437: void *state ! 438: ) ! 439: { ! 440: KernDeviceInterrupt_ *interrupt = ! 441: (KernDeviceInterrupt_ *)_interrupt; ! 442: void (*handler)() = interrupt->_handler; ! 443: ! 444: IODisableInterrupt(interrupt); ! 445: ! 446: (*handler)(interrupt, state, interrupt->_handlerArgument); ! 447: } ! 448: ! 449: void ! 450: IOEnableInterrupt( ! 451: void *_interrupt ! 452: ) ! 453: { ! 454: KernDeviceInterrupt_ *interrupt = ! 455: (KernDeviceInterrupt_ *)_interrupt; ! 456: KernBusInterrupt *busInterrupt; ! 457: BOOL isSuspended; ! 458: ! 459: KernLockAcquire(interrupt->_lock); ! 460: ! 461: busInterrupt = interrupt->_busInterrupt; ! 462: isSuspended = interrupt->_isSuspended; interrupt->_isSuspended = NO; ! 463: ! 464: KernLockRelease(interrupt->_lock); ! 465: ! 466: if (isSuspended) ! 467: KernBusInterruptResume(busInterrupt); ! 468: } ! 469: ! 470: void ! 471: IODisableInterrupt( ! 472: void *_interrupt ! 473: ) ! 474: { ! 475: KernDeviceInterrupt_ *interrupt = ! 476: (KernDeviceInterrupt_ *)_interrupt; ! 477: KernBusInterrupt *busInterrupt; ! 478: BOOL isSuspended; ! 479: ! 480: KernLockAcquire(interrupt->_lock); ! 481: ! 482: busInterrupt = interrupt->_busInterrupt; ! 483: isSuspended = interrupt->_isSuspended; interrupt->_isSuspended = YES; ! 484: ! 485: KernLockRelease(interrupt->_lock); ! 486: ! 487: if (!isSuspended) ! 488: KernBusInterruptSuspend(busInterrupt); ! 489: } ! 490: ! 491: /* ! 492: * Template for creating interrupt messages. ! 493: */ ! 494: ! 495: typedef struct _InterruptMsg { ! 496: mach_msg_header_t header; ! 497: } InterruptMsg; ! 498: ! 499: static InterruptMsg interruptMsgTemplate = { ! 500: { ! 501: MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0), ! 502: sizeof (InterruptMsg), ! 503: MACH_PORT_NULL, ! 504: MACH_PORT_NULL, ! 505: 0, ! 506: IO_DEVICE_INTERRUPT_MSG ! 507: } ! 508: }; ! 509: ! 510: void ! 511: IOSendInterrupt( ! 512: void *_interrupt, ! 513: void *state, ! 514: unsigned int msgId ! 515: ) ! 516: { ! 517: KernDeviceInterrupt_ *interrupt = _interrupt; ! 518: KernDeviceInterruptMsg *msg = interrupt->_ipcMessage; ! 519: InterruptMsg *imsg; ! 520: mach_msg_return_t result; ! 521: ! 522: if (curipl() > IPLSCHED) ! 523: return; ! 524: ! 525: KernLockAcquire(msg->lock); ! 526: if (msg->queued || msg->pending) { ! 527: KernLockRelease(msg->lock); ! 528: return; ! 529: } ! 530: msg->queued = YES; ! 531: KernLockRelease(msg->lock); ! 532: ! 533: imsg = (InterruptMsg *)&msg->kmsg.ikm_header; ! 534: *imsg = interruptMsgTemplate; ! 535: imsg->header.msgh_id = msgId; ! 536: imsg->header.msgh_remote_port = (mach_port_t)msg->iport; ! 537: ! 538: result = ipc_mqueue_send_interrupt(&msg->kmsg); ! 539: if (result != MACH_MSG_SUCCESS) { ! 540: KernLockAcquire(msg->lock); ! 541: msg->queued = NO; ! 542: msg->pending = YES; ! 543: KernLockRelease(msg->lock); ! 544: ! 545: thread_call_enter(&msg->callout); ! 546: } ! 547: } ! 548: ! 549: static ! 550: void ! 551: _KernDeviceInterruptCallout( ! 552: KernDeviceInterruptMsg *msg ! 553: ) ! 554: { ! 555: mach_msg_return_t result; ! 556: ! 557: KernLockAcquire(msg->lock); ! 558: msg->pending = NO; ! 559: msg->queued = YES; ! 560: KernLockRelease(msg->lock); ! 561: ! 562: result = ipc_mqueue_send( ! 563: &msg->kmsg, ! 564: MACH_SEND_ALWAYS | MACH_SEND_TIMEOUT, ! 565: 0, IMQ_NULL_CONTINUE); ! 566: if (result != MACH_MSG_SUCCESS) { ! 567: ipc_port_release(msg->iport); ! 568: KernDeviceInterruptMsgRelease(msg); ! 569: } ! 570: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.