Annotation of driverkit/libDriver/IODirectDevice.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: /*     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.