Annotation of driverkit/Examples/loadable/Kernel/myDevice.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: /*     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.