Annotation of driverkit/libDriver/IODirectDevice.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: /*     Copyright (c) 1993 NeXT Computer, Inc.  All rights reserved. 
        !            25:  *
        !            26:  * IODirectDevice class implementation.
        !            27:  *
        !            28:  * HISTORY
        !            29:  * 08-Jan-93    Doug Mitchell at NeXT
        !            30:  *      Created. 
        !            31:  */
        !            32: 
        !            33: #ifdef KERNEL
        !            34: #define MACH_USER_API  1
        !            35: #endif KERNEL
        !            36: 
        !            37: #import <objc/List.h>
        !            38: #import <driverkit/IODirectDevice.h>
        !            39: #import <driverkit/IODirectDevicePrivate.h>
        !            40: #import <driverkit/IODeviceDescriptionPrivate.h>
        !            41: #import <driverkit/generalFuncs.h>
        !            42: #import <driverkit/KernDeviceDescription.h>
        !            43: #import <driverkit/KernDevice.h>
        !            44: #import <driverkit/KernBusMemory.h>
        !            45: #import <driverkit/interruptMsg.h>
        !            46: #import <mach/mach_types.h>
        !            47: #import <mach/mach_interface.h>
        !            48: 
        !            49: @interface IODirectDevice(EISAPrivate)
        !            50: - initEISA;
        !            51: - freeEISA;
        !            52: @end
        !            53: @interface IODirectDevice(HPPAPrivate)
        !            54: - initHPPA;
        !            55: - freeHPPA;
        !            56: @end
        !            57: @interface IODirectDevice(SPARCPrivate)
        !            58: - initSPARC;
        !            59: - freeSPARC;
        !            60: @end
        !            61: @interface IODirectDevice(PPCPrivate)
        !            62: - initPPC;
        !            63: - freePPC;
        !            64: @end
        !            65: 
        !            66: @interface IODirectDevice(InterruptPrivate)
        !            67: - (IOReturn) _changeInterrupt:(unsigned int) localInterrupt to:(BOOL) enable;
        !            68: @end
        !            69: 
        !            70: #define NUM_LOCAL_INTS         4
        !            71: 
        !            72: typedef struct _IODirectDevicePrivate {
        !            73:     id         memory_mappings;
        !            74:     id         device_interrupts;
        !            75:     id         local_device_interrupts[ NUM_LOCAL_INTS ];
        !            76: } IODirectDevicePrivate;
        !            77: 
        !            78: #define IO_EXIT_THREAD_MSG     IO_FIRST_UNRESERVED_INTERRUPT_MSG
        !            79: 
        !            80: @implementation IODirectDevice
        !            81: 
        !            82: /*
        !            83:  * By defintion, all subclasses of this class are of style IO_DirectDevice.
        !            84:  * Subclasses need not implement this method.
        !            85:  */
        !            86: + (IODeviceStyle)deviceStyle
        !            87: {
        !            88:        return IO_DirectDevice;
        !            89: }
        !            90: 
        !            91: - initFromDeviceDescription: deviceDescription
        !            92: {
        !            93:     IODirectDevicePrivate      *private;
        !            94:     [super init];
        !            95: 
        !            96:     [self setDeviceDescription:deviceDescription];
        !            97:     
        !            98: #if i386
        !            99:     [self initEISA];
        !           100: #elif ppc
        !           101:        [self initPPC];
        !           102: #elif hppa
        !           103:     [self initHPPA];
        !           104: #elif sparc
        !           105:        [self initSPARC];
        !           106: #endif
        !           107:     private = _private = (void *)IOMalloc(sizeof (*private));
        !           108:     bzero( private, sizeof (*private));
        !           109: 
        !           110:     return self;
        !           111: }
        !           112: 
        !           113: - init
        !           114: {
        !           115:     return [self free];
        !           116: }
        !           117: 
        !           118: - free
        !           119: {
        !           120:     IODirectDevicePrivate      *private = _private;
        !           121:     struct _private            *busPrivate = _busPrivate;
        !           122:     msg_header_t               msg = { 0 };
        !           123:     
        !           124:     if (_interruptPort) {
        !           125:        if (_ioThread) {
        !           126:            msg.msg_size = sizeof (msg);
        !           127:            msg.msg_id =  IO_EXIT_THREAD_MSG;
        !           128: #ifdef KERNEL
        !           129:            msg.msg_remote_port = IOGetKernPort(_interruptPort);
        !           130:            msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
        !           131: #else
        !           132:            msg.msg_remote_port = _interruptPort;
        !           133:            msg_send(&msg, MSG_OPTION_NONE, 0);
        !           134: #endif KERNEL
        !           135:        }
        !           136: 
        !           137:        [[_deviceDescriptionDelegate device] detachInterruptPort];
        !           138:        (void) port_deallocate(task_self(), _interruptPort);
        !           139:        _interruptPort = PORT_NULL;
        !           140:     }
        !           141:     
        !           142:     if (busPrivate) {
        !           143:        if (busPrivate->type == EISA)
        !           144:            [self freeEISA];
        !           145:        else if (busPrivate->type == ArchPPC)
        !           146:            [self freePPC];
        !           147:        else if (busPrivate->type == HPPA)
        !           148:            [self freeHPPA];
        !           149:        else if (busPrivate->type == SPARC)
        !           150:            [self freeSPARC];
        !           151:     }
        !           152: 
        !           153:     if (private) {
        !           154:        if (private->memory_mappings)
        !           155:            [private->memory_mappings free];
        !           156:        if (private->device_interrupts)
        !           157:            [private->device_interrupts free];
        !           158:        IOFree((void *)private, sizeof (*private));
        !           159:     }
        !           160: 
        !           161:     return [super free];
        !           162: }
        !           163: 
        !           164: - (void)setDeviceDescription : deviceDescription
        !           165: {
        !           166:     [super setDeviceDescription:deviceDescription];
        !           167:     _deviceDescription = deviceDescription;
        !           168:     _deviceDescriptionDelegate = [deviceDescription _delegate];
        !           169: }
        !           170: 
        !           171: - (port_t)interruptPort
        !           172: {
        !           173:     return _interruptPort;
        !           174: }
        !           175: 
        !           176: - (IOReturn) attachInterruptPort
        !           177: {
        !           178:     if (_interruptPort == PORT_NULL) {
        !           179:        if (port_allocate(task_self(), &_interruptPort))
        !           180:            return IO_R_NOT_ATTACHED;
        !           181:            
        !           182:        /*
        !           183:         * Don't attach unless interrupts have been configured.
        !           184:         */
        !           185:        if ([[_deviceDescriptionDelegate device]
        !           186:                                attachInterruptPort:_interruptPort] == nil) {
        !           187:            (void) port_deallocate(task_self(), _interruptPort);
        !           188:            _interruptPort = PORT_NULL;
        !           189: 
        !           190:            return IO_R_NOT_ATTACHED;
        !           191:        }
        !           192:     }
        !           193:     
        !           194:     return IO_R_SUCCESS;
        !           195: }
        !           196: 
        !           197: static void
        !           198: IODirectDeviceThread(id                device);
        !           199: 
        !           200: - (IOReturn)startIOThreadWithPriority:(int)priority
        !           201: {
        !           202:     IOReturn           result = IO_R_SUCCESS;
        !           203:     
        !           204:     if (_ioThread == NULL) {
        !           205:        result = [self attachInterruptPort];
        !           206:     
        !           207:        if (result == IO_R_SUCCESS) {
        !           208:            _ioThread = IOForkThread((IOThreadFunc)IODirectDeviceThread, self);
        !           209:            if (priority >= 0)
        !           210:                (void) IOSetThreadPriority(_ioThread, priority);
        !           211:        }
        !           212:     }
        !           213:     
        !           214:     return (result);
        !           215: }
        !           216: 
        !           217: - (IOReturn)startIOThreadWithFixedPriority:(int)priority
        !           218: {
        !           219:     IOReturn           result = IO_R_SUCCESS;
        !           220: 
        !           221:     if (_ioThread == NULL) {
        !           222:        result = [self startIOThreadWithPriority:priority];
        !           223:        if (result == IO_R_SUCCESS)
        !           224:            (void) IOSetThreadPolicy(_ioThread, POLICY_FIXEDPRI);
        !           225:     }
        !           226:        
        !           227:     return (result);
        !           228: }
        !           229: 
        !           230: - (IOReturn)startIOThread
        !           231: {
        !           232:     return [self startIOThreadWithPriority:-1];
        !           233: }
        !           234: 
        !           235: - (IOReturn)waitForInterrupt:(int *)id
        !           236: {
        !           237:     IOInterruptMsg             interruptMsg;
        !           238:     kern_return_t              result;
        !           239:     msg_option_t               option = RCV_TIMEOUT | RCV_LARGE;
        !           240: 
        !           241:     if (_interruptPort == PORT_NULL)
        !           242:        return (IO_R_NO_INTERRUPT);
        !           243:        
        !           244:     do {
        !           245:        interruptMsg.header.msg_size = sizeof (interruptMsg);
        !           246:        interruptMsg.header.msg_local_port = _interruptPort;
        !           247:        
        !           248:        result = msg_receive(&interruptMsg.header, option, 0);
        !           249:        if (result == RCV_TOO_LARGE)
        !           250:            return (IO_R_MSG_TOO_LARGE);
        !           251: 
        !           252:        if (result != RCV_SUCCESS && result != RCV_TIMED_OUT) {
        !           253:            IOLog("%s: %s waitForInterrupt: msg_receive returns %d\n",
        !           254:                [self name], [self deviceKind], result);
        !           255:            return (IO_R_IPC_FAILURE);
        !           256:        }
        !           257:        
        !           258:        if (option & RCV_TIMEOUT) {
        !           259:            if (result == RCV_TIMED_OUT)
        !           260:                option = RCV_LARGE;
        !           261:            else /* if (result == RCV_SUCCESS) */
        !           262:                (void) thread_block();
        !           263:        }
        !           264:     } while (result != RCV_SUCCESS);
        !           265:     
        !           266:     *id = interruptMsg.header.msg_id;
        !           267:     
        !           268:     return (IO_R_SUCCESS);
        !           269: }
        !           270: 
        !           271: - (void)receiveMsg
        !           272: {
        !           273:     IOInterruptMsg             interruptMsg;
        !           274:     
        !           275:     if (_interruptPort == PORT_NULL)
        !           276:        return;
        !           277:        
        !           278:     interruptMsg.header.msg_size = sizeof (interruptMsg);
        !           279:     interruptMsg.header.msg_local_port = _interruptPort;
        !           280:     
        !           281:     (void) msg_receive(&interruptMsg.header, MSG_OPTION_NONE, 0);
        !           282: }
        !           283: 
        !           284: - (void)timeoutOccurred
        !           285: {
        !           286: }
        !           287: 
        !           288: - (void)interruptOccurred
        !           289: {
        !           290:     [self interruptOccurredAt:0];
        !           291: }
        !           292: 
        !           293: - (void)interruptOccurredAt:(int)localNum
        !           294: {
        !           295: }
        !           296: 
        !           297: - (void)commandRequestOccurred
        !           298: {
        !           299: }
        !           300: 
        !           301: - (void)otherOccurred:(int)id
        !           302: {
        !           303: }
        !           304: 
        !           305: @end   /* IODirectDevice */
        !           306: 
        !           307: @implementation IODirectDevice(IOInterrupts)
        !           308: 
        !           309: - (IOReturn) enableAllInterrupts
        !           310: {
        !           311:        unsigned int    i, max = [_deviceDescription numInterrupts];
        !           312: 
        !           313:        for (i=0;  i < max;  i++) {
        !           314:                if ([self enableInterrupt:i] != IO_R_SUCCESS) {
        !           315:                        [self disableAllInterrupts];
        !           316:                        return IO_R_NOT_ATTACHED;
        !           317:                }
        !           318:        }
        !           319:        return IO_R_SUCCESS;
        !           320: }
        !           321: 
        !           322: 
        !           323: - (void) disableAllInterrupts
        !           324: {
        !           325:        unsigned int    i, max = [_deviceDescription numInterrupts];
        !           326: 
        !           327:        for (i=0;  i < max;  i++)
        !           328:                [self disableInterrupt:i];
        !           329: }
        !           330: 
        !           331: - (IOReturn) enableInterrupt:(unsigned int) localInterrupt
        !           332: {
        !           333:     IODirectDevicePrivate      *private = _private;
        !           334: 
        !           335:         if( (localInterrupt < NUM_LOCAL_INTS) && private->local_device_interrupts[ localInterrupt ]) {
        !           336:             [private->local_device_interrupts[ localInterrupt ] resume];
        !           337:             return IO_R_SUCCESS;
        !           338:         }
        !           339: 
        !           340:        if ([self attachInterruptPort] != IO_R_SUCCESS)
        !           341:                return IO_R_NOT_ATTACHED;
        !           342:        return [self _changeInterrupt:localInterrupt to:YES];
        !           343: }
        !           344: 
        !           345: 
        !           346: - (void) disableInterrupt:(unsigned int) localInterrupt
        !           347: {
        !           348:     IODirectDevicePrivate      *private = _private;
        !           349: 
        !           350:     if( (localInterrupt < NUM_LOCAL_INTS) && private->local_device_interrupts[ localInterrupt ]) {
        !           351:         [private->local_device_interrupts[ localInterrupt ] suspend];
        !           352:         return;
        !           353:     }
        !           354:     [self _changeInterrupt:localInterrupt to:NO];
        !           355: }
        !           356: 
        !           357: /*
        !           358:  *  The subclass overrides this method.  In the superclass, we just
        !           359:  *  return NO.
        !           360:  */
        !           361: - (BOOL) getHandler:(IOInterruptHandler *)handler
        !           362:               level:(unsigned int *)ipl
        !           363:           argument:(unsigned int *) arg
        !           364:        forInterrupt:(unsigned int) localInterrupt
        !           365: {
        !           366:        return NO;
        !           367: }
        !           368: 
        !           369: @end
        !           370: 
        !           371: @implementation IODirectDevice(InterruptPrivate)
        !           372: 
        !           373: - (IOReturn) _changeInterrupt:(unsigned int) localInterrupt to:(BOOL) enable
        !           374: {
        !           375:        IODirectDevicePrivate   *private = _private;
        !           376:        id                      interrupt;
        !           377: 
        !           378:        if (localInterrupt >= [_deviceDescription numInterrupts])
        !           379:                return IO_R_INVALID_ARG;
        !           380:                
        !           381:        if (private->device_interrupts == nil)
        !           382:                private->device_interrupts =
        !           383:                                [[HashTable alloc] initKeyDesc:"i"];
        !           384:        interrupt = [private->device_interrupts
        !           385:                                valueForKey:(void *)localInterrupt];
        !           386:        if (interrupt == nil) {
        !           387:                IOInterruptHandler      handler;
        !           388:                unsigned int            ipl = 3;        /* XXX */
        !           389:                unsigned int            arg = 0;
        !           390:                id                      busInterrupt;
        !           391: 
        !           392:                interrupt = [[_deviceDescriptionDelegate device]
        !           393:                                interrupt:localInterrupt];
        !           394:                [private->device_interrupts
        !           395:                        insertKey:(void *)localInterrupt
        !           396:                            value:interrupt];
        !           397:                if( localInterrupt < NUM_LOCAL_INTS)
        !           398:                     private->local_device_interrupts[ localInterrupt ] = interrupt;
        !           399:                busInterrupt = [[_deviceDescriptionDelegate
        !           400:                                        resourcesForKey:IRQ_LEVELS_KEY]
        !           401:                                                objectAt:localInterrupt];
        !           402:                if ([self getHandler:&handler
        !           403:                                level:&ipl
        !           404:                                argument:&arg
        !           405:                            forInterrupt:localInterrupt])
        !           406:                        [interrupt attachToBusInterrupt:busInterrupt
        !           407:                                        withSpecialHandler:handler
        !           408:                                                argument:(void *)arg
        !           409:                                                atLevel:ipl];
        !           410:                else
        !           411:                        [interrupt attachToBusInterrupt:busInterrupt
        !           412:                                    withArgument:(void *)
        !           413:                                        (IO_DEVICE_INTERRUPT_MSG +
        !           414:                                                localInterrupt)];
        !           415:        }
        !           416: 
        !           417:        if (enable)
        !           418:                [interrupt resume];
        !           419:        else
        !           420:                [interrupt suspend];
        !           421:        
        !           422:        return IO_R_SUCCESS;
        !           423: }
        !           424: 
        !           425: 
        !           426: @end
        !           427: 
        !           428: @implementation IODirectDevice(IOMemory)
        !           429: /*
        !           430:  *  Methods to map device memory into the calling task's address space.
        !           431:  */
        !           432: - (IOReturn) mapMemoryRange:(unsigned int) localRange
        !           433:                        to:(vm_address_t *) destAddr
        !           434:                        findSpace:(BOOL) findSpace
        !           435:                        cache:(IOCache) cache
        !           436: {
        !           437:        IODirectDevicePrivate           *private = _private;
        !           438:        id                              mapping;
        !           439:        id                              resource;
        !           440: 
        !           441:        if (localRange >= [_deviceDescription numMemoryRanges])
        !           442:                return IO_R_INVALID_ARG;
        !           443: 
        !           444:        resource = [[_deviceDescriptionDelegate resourcesForKey:MEM_MAPS_KEY]
        !           445:                        objectAt:localRange];
        !           446:        if (findSpace)
        !           447:                mapping =
        !           448:                    [resource mapInTarget:current_task_EXTERNAL()
        !           449:                              cache:cache];
        !           450:        else
        !           451:                mapping =
        !           452:                    [resource mapToAddress:*destAddr
        !           453:                              inTarget:current_task_EXTERNAL()
        !           454:                              cache:cache];
        !           455: 
        !           456:        if (mapping == nil)
        !           457:                return IO_R_NO_MEMORY;
        !           458:                
        !           459:        *destAddr = [mapping address];
        !           460: 
        !           461:        if (private->memory_mappings == nil)
        !           462:                private->memory_mappings = [[HashTable alloc] initKeyDesc:"i"];
        !           463: 
        !           464:        [private->memory_mappings insertKey:(void *)*destAddr value:mapping];   
        !           465:                
        !           466:        return IO_R_SUCCESS;
        !           467: }
        !           468: 
        !           469: - (void) unmapMemoryRange:(unsigned int) localRange
        !           470:                        from:(vm_address_t) virtAddr;
        !           471: {
        !           472:        IODirectDevicePrivate           *private = _private;
        !           473:        id                              mapping;
        !           474: 
        !           475:        if (localRange >= [_deviceDescription numMemoryRanges])
        !           476:                return;
        !           477:                
        !           478:        mapping = [private->memory_mappings valueForKey:(void *)virtAddr];
        !           479:        if (mapping == nil)
        !           480:                return;
        !           481:                
        !           482:        [private->memory_mappings removeKey:(void *)virtAddr];
        !           483:        
        !           484:        [mapping free];
        !           485: }
        !           486: 
        !           487: 
        !           488: @end
        !           489: 
        !           490: static void
        !           491: IODirectDeviceThread(
        !           492:     id         device
        !           493: )
        !           494: {
        !           495:     IOReturn           result;
        !           496:     int                        id;
        !           497:     
        !           498:     while (TRUE) {
        !           499:        result = [device waitForInterrupt:&id];
        !           500:        if (result == IO_R_MSG_TOO_LARGE)
        !           501:            [device receiveMsg];
        !           502:        else if (result != IO_R_SUCCESS)
        !           503:            IOLog("%s: %s thread: waitForInterrupt: returns %d\n",
        !           504:                [device name], [device deviceKind], result);
        !           505:        else {
        !           506:            switch (id) {
        !           507: 
        !           508:            case IO_TIMEOUT_MSG:
        !           509:                [device timeoutOccurred];
        !           510:                break;
        !           511:                
        !           512:            case IO_COMMAND_MSG:
        !           513:                [device commandRequestOccurred];
        !           514:                break;
        !           515:                
        !           516:            case IO_DEVICE_INTERRUPT_MSG:
        !           517:                [device interruptOccurred];
        !           518:                break;
        !           519:            
        !           520:            case IO_EXIT_THREAD_MSG:
        !           521:                IOExitThread();
        !           522:                break;
        !           523:                
        !           524:            default:
        !           525:                if (            id >= IO_DEVICE_INTERRUPT_MSG_FIRST
        !           526:                        &&      id <= IO_DEVICE_INTERRUPT_MSG_LAST) {
        !           527:                    int         localNum = id - IO_DEVICE_INTERRUPT_MSG_FIRST;
        !           528:                    
        !           529:                    [device interruptOccurredAt:localNum];
        !           530:                }
        !           531:                else
        !           532:                    [device otherOccurred:id];
        !           533:            }
        !           534:        }
        !           535:     }
        !           536: }
        !           537: 
        !           538: @implementation IODirectDevice(Private)
        !           539: 
        !           540: - _deviceDescriptionDelegate
        !           541: {
        !           542:     return _deviceDescriptionDelegate;
        !           543: }
        !           544: 
        !           545: @end

unix.superglobalmegacorp.com

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