Annotation of driverkit/Examples/loadable/Kernel/myDevice.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: /*     IOStub.m        1.0     01/29/91        (c) 1991 NeXT   
        !            25:  *
        !            26:  * IOStub.m - Implementation for trivial I/O device subclass.
        !            27:  *
        !            28:  * HISTORY
        !            29:  * 29-Jan-91    Doug Mitchell at NeXT
        !            30:  *      Created. 
        !            31:  */
        !            32:  
        !            33: #import "myDevice.h"
        !            34: #import <kernserv/queue.h>
        !            35: #import <kernserv/prototypes.h>
        !            36: #import <machkit/NXLock.h>
        !            37: #import <architecture/nrw/io.h>
        !            38: #import <architecture/nrw/dma_macros.h>
        !            39: #import <driverkit/generalFuncs.h>
        !            40: #import <driverkit/driverServer.h>
        !            41: 
        !            42: static volatile void myDeviceThread(id deviceId);
        !            43: 
        !            44: /*
        !            45:  * Communication between exported threads and I/O thread via a queue
        !            46:  * of these structs.
        !            47:  */
        !            48: typedef struct {
        !            49:        NXConditionLock         *lock;          // caller sleeps on this
        !            50:        myDeviceOp              op;             // operation to perform
        !            51:        IOReturn                status;         // status on completion
        !            52:        queue_chain_t           link;
        !            53: } cmdBuf;
        !            54: 
        !            55: /*
        !            56:  * States of cmdBuf.lock and of qLock.
        !            57:  */
        !            58: typedef enum {
        !            59:        LS_IDLE,
        !            60:        LS_BUSY
        !            61: } lockState;
        !            62: 
        !            63: @implementation myDevice
        !            64: 
        !            65: /*
        !            66:  * Set device port. devicePort must be a port_t in the IOTask IPC space.
        !            67:  * This is called from myHandler, which is NOT in the IOTask context, hence
        !            68:  * convertPortToIOTask() was used to generate the devicePort passed in here.
        !            69:  */
        !            70: - (void)setDevicePort : (port_t)devicePort
        !            71: {
        !            72:        myDevicePort = devicePort;
        !            73: }
        !            74: 
        !            75: /*
        !            76:  * Initialize. We assume that myDevicePort is valid at this time.
        !            77:  * Again, this is called from myHandler's context, so we start up an I/O 
        !            78:  * thread in the IOTask to enable performing actual I/O using the hardware
        !            79:  * represented by myDevicePort. 
        !            80:  */
        !            81: - init
        !            82: {
        !            83:        /*
        !            84:         * Initialize resources.
        !            85:         */
        !            86:        queue_init(&ioQueue);
        !            87:        qLock = [NXConditionLock alloc];
        !            88:        [qLock initWith:LS_IDLE];
        !            89:        IOForkThread((IOThreadFunc)myDeviceThread, self);
        !            90:        
        !            91:        /*
        !            92:         * Send an initialize command to the I/O thread.
        !            93:         */
        !            94:        [self enqueueCmd:OP_INIT];
        !            95:        
        !            96:        return self;
        !            97: }
        !            98: 
        !            99: /*
        !           100:  * Shut down, free resources (but not ourself).
        !           101:  */
        !           102: - (void)shutDown
        !           103: {
        !           104:        [self enqueueCmd:OP_SHUTDOWN];
        !           105:        [qLock free];
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * Private methods.
        !           110:  *
        !           111:  * Send a cmdBuf to the I/O thread and wait for completion. This is the
        !           112:  * means by which exported methods (-init, -shutDown) pass commands to
        !           113:  * the I/O thread.
        !           114:  */
        !           115: - (IOReturn)enqueueCmd : (myDeviceOp)op
        !           116: {      
        !           117:        cmdBuf cmd;
        !           118:        
        !           119:        /*
        !           120:         * Create a cmdBuf.
        !           121:         */
        !           122:        cmd.lock = [NXConditionLock alloc];
        !           123:        [cmd.lock initWith:LS_BUSY];
        !           124:        cmd.op = op;
        !           125:        
        !           126:        /*
        !           127:         * Enqueue on ioQueue.
        !           128:         */
        !           129:        [qLock lock];
        !           130:        queue_enter(&ioQueue, &cmd, cmdBuf *, link);
        !           131:        [qLock unlockWith:LS_BUSY];
        !           132:        
        !           133:        /*
        !           134:         * Wait for completion.
        !           135:         */
        !           136:        [cmd.lock lockWhen:LS_IDLE];
        !           137:        [cmd.lock free];
        !           138:        return cmd.status;
        !           139: }
        !           140: 
        !           141: /*
        !           142:  * Initialize device, called from within the I/O thread.
        !           143:  */
        !           144: - (IOReturn)deviceInit
        !           145: {
        !           146:        IODevicePage *devicePage;
        !           147:        IOReturn drtn;
        !           148:        unsigned intr;
        !           149:        
        !           150:        /*
        !           151:         * Map in device Page.
        !           152:         */
        !           153:        drtn = _IOMapDevicePage(myDevicePort,
        !           154:                task_self(),
        !           155:                (vm_offset_t *)&devicePage,
        !           156:                YES,                            // anywhere
        !           157:                IO_CacheOff);
        !           158:        if(drtn) {
        !           159:                IOLog("myDevice: _IOMapDevicePage() returned %s\n", 
        !           160:                        [self stringFromReturn: drtn]);
        !           161:                return IO_R_NO_MEMORY;
        !           162:        }
        !           163:        
        !           164:        /*
        !           165:         * Make sure we can access device page.
        !           166:         */
        !           167:        set_chan_intr_set(devicePage, 0, 0x5a);
        !           168:        intr = chan_intr_cause(devicePage, 0);
        !           169:        IOLog("myDevice: channel interrrupt cause 0x%x\n", intr);
        !           170:                
        !           171:        /*
        !           172:         * This should clear all cause bits.
        !           173:         */
        !           174:        set_chan_intr_cause(devicePage, 0, 0xffff);
        !           175:        intr = chan_intr_cause(devicePage, 0);
        !           176:        IOLog("myDevice: channel interrrupt cause 0x%x\n", intr);
        !           177:        set_chan_intr_mask(devicePage, 0, 0x55aa);
        !           178:        intr = chan_intr_mask(devicePage, 0);
        !           179:        IOLog("myDevice: channel interrrupt mask  0x%x\n", intr);
        !           180:        return IO_R_SUCCESS;
        !           181: }
        !           182: 
        !           183: 
        !           184: /*
        !           185:  * The I/O thread which performs all of the useful work of this example.
        !           186:  */ 
        !           187: static volatile void myDeviceThread(myDevice *deviceId)
        !           188: {
        !           189:        cmdBuf *cmdp;
        !           190:        BOOL die = NO;
        !           191:        queue_head_t *ioQ = &deviceId->ioQueue;
        !           192:        
        !           193:        IOLog("myDevice: I/O thread starting\n");
        !           194:        
        !           195:        while(1) {
        !           196:        
        !           197:                /* 
        !           198:                 * Wait for something to do.
        !           199:                 */
        !           200:                [deviceId->qLock lockWhen:LS_BUSY];
        !           201:                cmdp = (cmdBuf *)queue_first(ioQ);
        !           202:                queue_remove(ioQ, cmdp, cmdBuf *, link);
        !           203:                
        !           204:                /*
        !           205:                 * Leave qLock in appropriate state, depending on contents
        !           206:                 * of queue.
        !           207:                 */
        !           208:                if(queue_empty(ioQ)) {
        !           209:                        [deviceId->qLock unlockWith:LS_IDLE];
        !           210:                }
        !           211:                else {
        !           212:                        [deviceId->qLock unlockWith:LS_BUSY];
        !           213:                }
        !           214:                
        !           215:                /*
        !           216:                 * Execute command.
        !           217:                 */
        !           218:                switch(cmdp->op) {
        !           219:                    case OP_INIT:
        !           220:                        cmdp->status = [deviceId deviceInit];
        !           221:                        break;
        !           222:                        
        !           223:                    case OP_SHUTDOWN:
        !           224:                        /*
        !           225:                         * Kill this thread, but return good status first.
        !           226:                         */
        !           227:                        die = YES;
        !           228:                        cmdp->status = IO_R_SUCCESS;
        !           229:                }
        !           230:                
        !           231:                /*
        !           232:                 * Return cmdBuf to caller.
        !           233:                 */
        !           234:                [cmdp->lock lock];
        !           235:                [cmdp->lock unlockWith:LS_IDLE];
        !           236:                
        !           237:                /*
        !           238:                 * Terminate if necessary.
        !           239:                 */
        !           240:                if(die) {
        !           241:                        IOLog("myDriver; I/O thread terminating\n");
        !           242:                        IOExitThread();
        !           243:                }
        !           244:        }
        !           245:        
        !           246:        /* Not reached */
        !           247: }

unix.superglobalmegacorp.com

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