Annotation of kernel/driverkit/KernDevice.m, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.