Annotation of kernel/driverkit/KernDevice.m, revision 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.