Annotation of Examples/DriverKit/Adaptec1542B/Adaptec1542B_reloc.tproj/AHAController.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1992, 1993 NeXT Computer, Inc.
                      3:  *
                      4:  * Adaptec AHA-1542 SCSI controller driver.
                      5:  *
                      6:  * HISTORY
                      7:  *
                      8:  * 13 Apr 1993 Doug Mitchell at NeXT
                      9:  *     Rewrote using I/O thread which has exclusive access to hardware.
                     10:  *
                     11:  * 22 Nov 1992         Brian Pinkerton at NeXT
                     12:  *     Created from non-driverkit driver.
                     13:  */
                     14:  
                     15: #import <sys/types.h>
                     16: #import <bsd/sys/param.h>
                     17: #import <objc/Object.h>
                     18: #import <kernserv/queue.h>
                     19: #import <kernserv/prototypes.h>
                     20: #import <driverkit/return.h>
                     21: #import <driverkit/generalFuncs.h>
                     22: #import <driverkit/kernelDriver.h>
                     23: #import <driverkit/i386/kernelDriver.h>
                     24: #import <driverkit/interruptMsg.h>
                     25: #import <driverkit/scsiTypes.h>
                     26: #import <bsd/dev/scsireg.h>
                     27: #import        "scsivar.h"
                     28: #import <mach/message.h>
                     29: #import <mach/port.h>
                     30: #import <mach/mach_interface.h>
                     31: #import <machkit/NXLock.h>
                     32: #import <kernserv/ns_timer.h>
                     33: #import <driverkit/i386/ioPorts.h>
                     34: 
                     35: #import <driverkit/i386/directDevice.h>
                     36: #import <driverkit/i386/IOEISADeviceDescription.h>
                     37: #import <driverkit/IOSCSIController.h>
                     38: #import "AHAController.h"
                     39: #import "AHATypes.h"
                     40: #import "AHAInline.h"
                     41: #import "AHAThread.h"
                     42: 
                     43: extern unsigned ffs(unsigned mask);
                     44: 
                     45: /* 
                     46:  * Template for command message sent to the I/O thread.
                     47:  */
                     48: static msg_header_t AHAMessageTemplate = {
                     49:        0,                                      // msg_unused 
                     50:        1,                                      // msg_simple 
                     51:        sizeof(msg_header_t),                   // msg_size 
                     52:        MSG_TYPE_NORMAL,                        // msg_type 
                     53:        PORT_NULL,                              // msg_local_port 
                     54:        PORT_NULL,                              // msg_remote_port - TO
                     55:                                                // BE FILLED IN 
                     56:        IO_COMMAND_MSG                          // msg_id 
                     57: };
                     58: 
                     59: /*
                     60:  * Private methods implemented in this file.
                     61:  */
                     62: @interface AHAController(PrivateMethods)
                     63: - (BOOL) probeAtPortBase       : (IOEISAPortAddress) portBase;
                     64: - (IOReturn)executeCmdBuf      : (AHACommandBuf *)cmdBuf;
                     65: @end
                     66: 
                     67: 
                     68: @implementation AHAController
                     69: 
                     70: /*
                     71:  *  Probe, configure board, and init new instance.
                     72:  */
                     73: + (BOOL)probe:deviceDescription
                     74: {
                     75:        AHAController   *aha = [self alloc];
                     76:        IORange         ioPort;
                     77: 
                     78:        ddm_init("AHAController probe\n", 1,2,3,4,5);
                     79:        aha->ioThreadRunning = NO;
                     80:        
                     81:        /*
                     82:         *  Check that we have some IO Ports assigned, and probe using the
                     83:         *  first IO Port.
                     84:         *  -probeAtPortBase returns TRUE if there's an AHA Controller present.
                     85:         */
                     86:        if ([deviceDescription numPortRanges] < 1) {
                     87:                IOLog("AHAController: can't determine port base!\n");
                     88:                [aha free];
                     89:                return NO;
                     90:        }
                     91:        ioPort = [deviceDescription portRangeList][0];
                     92:        if (![aha probeAtPortBase:ioPort.start]) {
                     93:                IOLog("Adaptec154x Not Found at port 0x%x\n", ioPort.start);
                     94:                [aha free];
                     95:                return NO;
                     96:        }
                     97:        return ([aha initFromDeviceDescription:deviceDescription] ? YES : NO);
                     98: }
                     99: 
                    100: - initFromDeviceDescription:deviceDescription
                    101: {
                    102:        unsigned Lun;
                    103:        kern_return_t krtn;
                    104:        
                    105:        ddm_init("AHAController initFromDeviceDescription\n", 1,2,3,4,5);
                    106:        
                    107:        queue_init(&outstandingQ);
                    108:        queue_init(&pendingQ);
                    109:        queue_init(&commandQ);
                    110:        commandLock      = [[NXLock alloc] init];
                    111:        outstandingCount = 0;
                    112:        dmaLockCount     = 0;
                    113:        numFreeCcbs      = AHA_QUEUE_SIZE;
                    114: 
                    115:        /*
                    116:         * Note the I/O thread provided by IOSCSIController is running 
                    117:         * upon return from the following method.
                    118:         */
                    119:        if ([super initFromDeviceDescription:deviceDescription] == nil)
                    120:                return [self free];
                    121:        interruptPortKern = IOConvertPort([self interruptPort],
                    122:                IO_KernelIOTask,
                    123:                IO_Kernel);
                    124:        ioThreadRunning = YES;
                    125:        
                    126:        /*
                    127:         *  Check the channel and irq we just found against what's in our
                    128:         *  device description.  If they don't match, print a nasty warning
                    129:         *  message and fail.
                    130:         */
                    131:        if ([deviceDescription numChannels] < 1 ||
                    132:            [deviceDescription channel] != config.dma_channel) {
                    133:                IOLog("AHAController: Actual DMA Channel (%d) doesn't match "
                    134:                      "configured value (%d)!\n", config.dma_channel,
                    135:                      ([deviceDescription numChannels] ? 
                    136:                        [deviceDescription channel] : 0));
                    137:                return [self free];
                    138:        }
                    139: 
                    140:        if ([deviceDescription numInterrupts] < 1 ||
                    141:            [deviceDescription interrupt] != config.irq) {
                    142:                IOLog("AHAController: Actual IRQ (%d) doesn't match "
                    143:                      "configured value (%d)!\n", config.irq,
                    144:                      ([deviceDescription numInterrupts] ?
                    145:                        [deviceDescription interrupt] : 0));
                    146:                return [self free];
                    147:        }
                    148:        
                    149:        /*
                    150:         *  Try to set up DMA.  Set the appropriate mode on the channel, and
                    151:         *  try to enable it.
                    152:         */
                    153:        if ([self setTransferMode:IO_Cascade forChannel:0] != IO_R_SUCCESS ||
                    154:            [self enableChannel:0] != IO_R_SUCCESS) {
                    155:                IOLog("AHAController: couldn't init DMA!\n");
                    156:                return [super free];
                    157:        }
                    158: 
                    159:        /*
                    160:         * Allocate Mailboxes and CCB's from low 16 M of memory.
                    161:         */
                    162:        ahaMbArea = IOMallocLow(sizeof(struct aha_mb_area));
                    163:        ahaCcb = IOMallocLow(sizeof(struct ccb) * AHA_QUEUE_SIZE);
                    164: 
                    165:        /*
                    166:         *  Initialize driver data structures: set up the mailbox in/out area,
                    167:         *  and initialize the CCB queues.
                    168:         *
                    169:         *  Note that if we fail, the call to [super free] will release (and
                    170:         *  disable) our resources (IRQ, DMA channel, portRanges).
                    171:         */
                    172:        if (!aha_setup_mb_area(ioBase, ahaMbArea, ahaCcb)) {
                    173:                IOLog("AHAController: couldn't set up mailbox area!\n");
                    174:                return [self free];
                    175:        }
                    176: 
                    177:        [self resetStats];
                    178:        
                    179:        /*
                    180:         * Reserve our target, enable interrupts, and go.
                    181:         */
                    182:        for(Lun=0; Lun<SCSI_NLUNS; Lun++) {
                    183:                [self reserveTarget:config.scsi_id lun:Lun forOwner:self];
                    184:        }
                    185: 
                    186:        [self enableAllInterrupts];     /* turn on interrupts */
                    187:                
                    188:        /*
                    189:         * Set the port queue length to the maximum size. 
                    190:         */
                    191:        krtn = port_set_backlog(task_self(), [self interruptPort], 
                    192:                PORT_BACKLOG_MAX);
                    193:        if(krtn) {
                    194:                IOLog("%s: error %d on port_set_backlog()\n",
                    195:                        [self name], krtn);
                    196:                /* Oh well... */
                    197:        }
                    198:        [self resetSCSIBus];
                    199:        [self registerDevice];          /* this is the last thing we do! */
                    200: 
                    201:        return self;
                    202: }
                    203: 
                    204: /*
                    205:  *  This is slightly incorrect, since we can actually handle more if some of
                    206:  *  the entries in the scatter/gather list can be more than PAGE_SIZE.  In
                    207:  *  practice, tho, they're never bigger, so we'll make this our max size.
                    208:  *  18 Mar 93 dmitch - use (AHA_SG_COUNT - 1) since requests (the first
                    209:  *  and the last) can cross page boundaries. 
                    210:  */
                    211: - (unsigned)maxTransfer
                    212: {
                    213:        return (AHA_SG_COUNT - 1) * PAGE_SIZE;
                    214: }
                    215: 
                    216: /* 
                    217:  * kill I/O thread, free up local dynamically allocated resources, 
                    218:  * then have super release resources. 
                    219:  */
                    220: - free
                    221: {
                    222:        AHACommandBuf cmdBuf;
                    223:        
                    224:        if(ioThreadRunning) {
                    225:                cmdBuf.op = AO_Abort;
                    226:                [self executeCmdBuf:&cmdBuf];
                    227:        }
                    228:        if(ahaMbArea) {
                    229:                IOFreeLow(ahaMbArea, sizeof(struct aha_mb_area));
                    230:        }
                    231:        if(ahaCcb) {
                    232:                IOFreeLow(ahaCcb, sizeof(struct ccb) * AHA_QUEUE_SIZE);
                    233:        }
                    234:        if(commandLock) {
                    235:                [commandLock free];
                    236:        }
                    237:        return [super free];
                    238: }
                    239: 
                    240: /*
                    241:  * Statistics support.
                    242:  */
                    243: - (unsigned int) numQueueSamples
                    244: {
                    245:        return totalCommands;
                    246: }
                    247: 
                    248: 
                    249: - (unsigned int) sumQueueLengths
                    250: {
                    251:        return queueLenTotal;
                    252: }
                    253: 
                    254: 
                    255: - (unsigned int) maxQueueLength
                    256: {
                    257:        return maxQueueLen;
                    258: }
                    259: 
                    260: 
                    261: - (void)resetStats
                    262: {
                    263:        totalCommands = 0;
                    264:        queueLenTotal = 0;
                    265:        maxQueueLen   = 0;
                    266: }
                    267: 
                    268: /*
                    269:  * Do a SCSI command, as specified by an IOSCSIRequest. All the 
                    270:  * work is done by the I/O thread.
                    271:  */
                    272: - (sc_status_t) executeRequest : (IOSCSIRequest *)scsiReq 
                    273:                    buffer : (void *)buffer 
                    274:                    client : (vm_task_t)client
                    275: {
                    276:        AHACommandBuf cmdBuf;
                    277:        
                    278:        ddm_exp("executeRequest: cmdBuf 0x%x\n", &cmdBuf, 2,3,4,5);
                    279:        
                    280:        cmdBuf.op      = AO_Execute;
                    281:        cmdBuf.scsiReq = scsiReq;
                    282:        cmdBuf.buffer  = buffer;
                    283:        cmdBuf.client  = client;
                    284:        
                    285:        [self executeCmdBuf:&cmdBuf];
                    286:        
                    287:        ddm_exp("executeRequest: cmdBuf 0x%x complete; result %d\n", 
                    288:                &cmdBuf, cmdBuf.result, 3,4,5);
                    289:        return cmdBuf.result;
                    290: }
                    291: 
                    292: 
                    293: /*
                    294:  *  Reset the SCSI bus. All the work is done by the I/O thread.
                    295:  */
                    296: - (sc_status_t)resetSCSIBus
                    297: {
                    298:        AHACommandBuf cmdBuf;
                    299:        
                    300:        ddm_exp("resetSCSIBus: cmdBuf 0x%x\n", &cmdBuf, 2,3,4,5);
                    301: 
                    302:        cmdBuf.op = AO_Reset;
                    303:        [self executeCmdBuf:&cmdBuf];
                    304:        return cmdBuf.result;
                    305: }
                    306: /*
                    307:  * The following 6 methods are all called from the I/O thread in 
                    308:  * IODirectDevice. 
                    309:  */
                    310:  
                    311: /*
                    312:  * Called from the I/O thread when it receives an interrupt message.
                    313:  */
                    314: - (void)interruptOccurred
                    315: {
                    316:        struct ccb      *ccb;
                    317:        aha_intr_reg_t  intr;
                    318:        aha_mb_t        *mb;
                    319:        int             i;
                    320: 
                    321:        ddm_thr("interruptOccurred\n", 1,2,3,4,5);
                    322: 
                    323:        intr = aha_get_intr(ioBase);
                    324:        aha_clr_intr(ioBase);
                    325: 
                    326:        if (!intr.mb_in_full)
                    327:                return;
                    328: 
                    329:        /*
                    330:         * Find all ccb's which the controller has marked completed
                    331:         * and commandComplete: them.
                    332:         */
                    333:        mb = ahaMbArea->mb_in;
                    334:        for (i = 0; i < AHA_MB_CNT; i++, mb++) {
                    335:                if (mb->mb_stat != AHA_MB_IN_FREE) {
                    336:                        
                    337:                        /*
                    338:                         * FIXME - need IOVirtualFromPhysical(); assume for
                    339:                         * now that we can access all physical addresses.
                    340:                         */
                    341:                        ccb = (struct ccb *)aha_get_24(mb->ccb_addr);
                    342:                        mb->mb_stat = AHA_MB_IN_FREE;   
                    343:                        queue_remove(&outstandingQ, ccb, struct ccb *, ccbQ);
                    344:                        ASSERT(outstandingCount != 0);
                    345:                        outstandingCount--;
                    346:                        
                    347:                        [self commandCompleted:ccb reason:CS_Complete];
                    348:                }
                    349:        }
                    350:        
                    351:        /*
                    352:         * Handle possible pending commands (now that we've dequeued at least
                    353:         * one CCB).
                    354:         */
                    355:        [self runPendingCommands];
                    356:        
                    357:        /*
                    358:         * One more thing - since we probably just freed up at least one
                    359:         * ccb, process possible entries waiting in commandQ.
                    360:         */
                    361:        [self commandRequestOccurred]; 
                    362:        ddm_thr("interruptOccurred: DONE\n", 1,2,3,4,5);
                    363: }
                    364: 
                    365: /*
                    366:  * These three should not occur; they are here as error traps. All three are 
                    367:  * called out from the I/O thread upon receipt of messages which it should
                    368:  * not be seeing.
                    369:  */
                    370: - (void)interruptOccurredAt:(int)localNum
                    371: {
                    372:        IOLog("%s: interruptOccurredAt:%d\n", [self name], localNum);
                    373: }
                    374: 
                    375: - (void)otherOccurred:(int)id
                    376: {
                    377:        IOLog("%s: otherOccurred:%d\n", [self name], id);
                    378: }
                    379: 
                    380: - (void)receiveMsg
                    381: {
                    382:        IOLog("%s: receiveMsg\n", [self name]);
                    383:        
                    384:        /*
                    385:         * We have to let IODirectDevice take care of this (i.e., dequeue the
                    386:         * bogus message).
                    387:         */
                    388:        [super receiveMsg];
                    389: }
                    390: 
                    391: /*
                    392:  * Called from the I/O thread when it receives a timeout
                    393:  * message. We send these messages ourself from ahaTimeout() in 
                    394:  * AHAThread.m.
                    395:  */
                    396: - (void)timeoutOccurred
                    397: {
                    398:        struct ccb      *ccb, *nextCcb;
                    399:        ns_time_t       now;
                    400:        queue_head_t    *queue;
                    401:        BOOL            ccbTimedOut = NO;
                    402:        AHACommandBuf   *cmdBuf;
                    403:        IOSCSIRequest   *scsiReq;
                    404:        
                    405:        ddm_thr("timeoutOccurred\n", 1,2,3,4,5);
                    406:        
                    407:        IOGetTimestamp(&now);
                    408: 
                    409:        /*
                    410:         *  Scan the list of outstanding and pending commands, and time
                    411:         *  out any ones whose time is past.
                    412:         */
                    413: 
                    414:        for (queue = &outstandingQ; queue != &pendingQ; queue = &pendingQ) {
                    415: 
                    416:            ccb = (struct ccb *) queue_first(&outstandingQ);
                    417:            while (!queue_end(&outstandingQ, (queue_entry_t) ccb)) {
                    418:                ns_time_t       expire;
                    419:                
                    420:                cmdBuf  = ccb->cmdBuf;
                    421:                scsiReq = cmdBuf->scsiReq;
                    422:                expire = ccb->startTime + 
                    423:                    1000000000ULL * 
                    424:                        (unsigned long long)scsiReq->timeoutLength;
                    425:                if (now >= expire) {
                    426:                        /*
                    427:                         *  Remove ccb from the oustanding queue and
                    428:                         *  complete it.
                    429:                         */
                    430:                        nextCcb = (struct ccb *) queue_next(&ccb->ccbQ);
                    431:                        queue_remove(&outstandingQ, ccb, struct ccb *, ccbQ);
                    432:                        if(queue == &outstandingQ) {
                    433:                                ASSERT(outstandingCount != 0);
                    434:                                outstandingCount--;
                    435:                        }
                    436:                        [self commandCompleted:ccb reason:CS_Timeout];
                    437:                        ccb = nextCcb;
                    438:                        ccbTimedOut = YES;
                    439:                }
                    440:                else {
                    441:                        ccb = (struct ccb *) queue_next(&ccb->ccbQ);
                    442:                }
                    443:            }
                    444:        }
                    445: 
                    446:        /*
                    447:         * Reset bus. This also completes all I/Os in outstandingQ with
                    448:         * status CS_Reset.
                    449:         */
                    450:        if(ccbTimedOut) {
                    451:                [self threadResetBus:NULL];
                    452:        }
                    453:        ddm_thr("timeoutOccurred: DONE\n", 1,2,3,4,5);
                    454: }
                    455: 
                    456: /*
                    457:  * Process all commands in commandQ. If we run out of ccb's during this 
                    458:  * method, we abort, leaving commands enqueued; these will be handled after
                    459:  * subqueuent interrupts.
                    460:  *
                    461:  * This is called either as a result of an IO_COMMAND_MSG message being 
                    462:  * received by the I/O thread, or upon completion of interrupt handling. In
                    463:  * either case, it runs in the context of the I/O thread.
                    464:  */
                    465: - (void)commandRequestOccurred
                    466: {
                    467:        AHACommandBuf *cmdBuf;
                    468:        
                    469:        ddm_thr("commandRequestOccurred: top\n", 1,2,3,4,5);
                    470:        [commandLock lock];
                    471:        while(!queue_empty(&commandQ)) {
                    472:                cmdBuf = (AHACommandBuf *) queue_first(&commandQ);
                    473:                queue_remove(&commandQ, cmdBuf, AHACommandBuf *, link);
                    474:                [commandLock unlock];
                    475:                switch(cmdBuf->op) {
                    476:                    case AO_Reset:
                    477:                        [self threadResetBus:cmdBuf];
                    478:                        break;
                    479:                        
                    480:                    case AO_Abort:
                    481:                        /*
                    482:                         * First notify caller of completion, then 
                    483:                         * self-terminate.
                    484:                         */
                    485:                        [cmdBuf->cmdLock lock];
                    486:                        [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
                    487:                        IOExitThread();
                    488:                        /* not reached */
                    489:                        
                    490:                    case AO_Execute:
                    491:                        if([self threadExecuteRequest:cmdBuf]) {
                    492:                                /*
                    493:                                 * No more CCBs available. Abort this entire
                    494:                                 * method. Enqueue this request on the head
                    495:                                 * of commandQ for future processing.
                    496:                                 */
                    497:                                [commandLock lock];
                    498:                                queue_enter_first(&commandQ, cmdBuf,
                    499:                                        AHACommandBuf *, link);
                    500:                                [commandLock unlock];
                    501:                                ddm_thr("processCommandQ: no more ccbs; "
                    502:                                        "cmdBuf 0x%x\n", cmdBuf, 2,3,4,5);
                    503:                                goto out;
                    504:                                        
                    505:                        }
                    506:                }
                    507:                [commandLock lock];
                    508:        }
                    509:        [commandLock unlock];
                    510: out:
                    511:        ddm_thr("commandRequestOccurred: DONE\n", 1,2,3,4,5);
                    512:        return;
                    513: }
                    514: 
                    515: 
                    516: @end   /* methods declared in AHAController.h */
                    517: 
                    518: @implementation AHAController(PrivateMethods)
                    519: 
                    520: - (BOOL) probeAtPortBase:(IOEISAPortAddress) portBase
                    521: {
                    522:        aha_inquiry_t   inquiry;
                    523:     
                    524:        ddm_init("AHAController probeAtPortBase\n", 1,2,3,4,5);
                    525: 
                    526:        ioBase = portBase;
                    527:        aha_reset_board(ioBase, ahaBoardId);
                    528: 
                    529:        /*
                    530:         *  Do an inquiry to find out the board id and other things that
                    531:         *  we won't check.
                    532:         */
                    533:        if (!aha_probe_cmd(ioBase, AHA_CMD_DO_INQUIRY, 0, 0,
                    534:            (unsigned char *)&inquiry, sizeof(inquiry), TRUE)) {
                    535:                ddm_init("  ..inquiry command failed\n", 1,2,3,4,5);
                    536:                return FALSE;
                    537:        }
                    538:        
                    539:        ahaBoardId = inquiry.board_id;
                    540: 
                    541:        switch (ahaBoardId) {
                    542: 
                    543:        case AHA_1540_16HEAD:
                    544:        case AHA_154xB:
                    545:        case AHA_1540_64HEAD:
                    546:        case AHA_1640:
                    547:        case AHA_174xA:
                    548:        case AHA_154xC:
                    549:                break;
                    550:        default:
                    551:                if (ahaBoardId < AHA_154xC) {
                    552:                        ddm_init("..bogus board ID (0x%x)\n", ahaBoardId, 
                    553:                                2,3,4,5);
                    554:                        return FALSE;
                    555:                }
                    556:        }
                    557: 
                    558:        /*
                    559:         *  Attempt to read the configuration data from the board.
                    560:         *  If this succeeds, then we have successfully probed.
                    561:         */
                    562:        if (!aha_probe_cmd(ioBase, AHA_CMD_GET_CONFIG, 0, 0,
                    563:                           (unsigned char *)&config, sizeof(config), TRUE)) {
                    564:                ddm_init("  ..get config command failed\n", 1,2,3,4,5);
                    565: 
                    566:                return FALSE;
                    567:        }
                    568:        
                    569:        /*
                    570:         *  Decode the values in the config struct.
                    571:         */
                    572:        config.irq = ffs((unsigned int) config.irq) + 8;
                    573:        config.dma_channel = ffs((unsigned int) config.dma_channel) - 1;
                    574: 
                    575:        IOLog("Adaptec154x at port 0x%x irq %d\n", 
                    576:                portBase, config.irq);
                    577:        return TRUE;
                    578: }
                    579: 
                    580: /*
                    581:  * Pass one AHACommandBuf to the I/O thread; wait for completion. 
                    582:  * Normal completion status is in cmdBuf->status; a non-zero return 
                    583:  * from this function indicates a Mach IPC error.
                    584:  *
                    585:  * This method allocates and frees cmdBuf->cmdLock.
                    586:  */
                    587: - (IOReturn)executeCmdBuf : (AHACommandBuf *)cmdBuf
                    588: {
                    589:        msg_header_t msg = AHAMessageTemplate;
                    590:        kern_return_t krtn;
                    591:        IOReturn rtn = IO_R_SUCCESS;
                    592:        
                    593:        cmdBuf->cmdLock = [[NXConditionLock alloc] initWith:CMD_PENDING];
                    594:        [commandLock lock];
                    595:        queue_enter(&commandQ, cmdBuf, AHACommandBuf *, link);
                    596:        [commandLock unlock];
                    597:        
                    598:        /*
                    599:         * Create a Mach message and send it in order to wake up the 
                    600:         * I/O thread.
                    601:         */
                    602:        msg.msg_remote_port = interruptPortKern;
                    603:        krtn = msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0);
                    604:        if(krtn) {
                    605:                IOLog("%s: msg_send_from_kernel() returned %d\n", 
                    606:                        [self name], krtn);
                    607:                rtn = IO_R_IPC_FAILURE;
                    608:                goto out;
                    609:        }
                    610:        
                    611:        /*
                    612:         * Wait for I/O complete.
                    613:         */
                    614:        ddm_exp("executeCmdBuf: waiting for completion on cmdBuf 0x%x\n",
                    615:                cmdBuf, 2,3,4,5);
                    616:        [cmdBuf->cmdLock lockWhen:CMD_COMPLETE];
                    617:        ddm_exp("executeCmdBuf: cmdBuf 0x%x complete\n",
                    618:                cmdBuf, 2,3,4,5);
                    619: out:
                    620:        [cmdBuf->cmdLock free];
                    621:        return rtn;
                    622: }
                    623: 
                    624: @end   /* AHAController(PrivateMethods) */
                    625: 
                    626: 
                    627: 

unix.superglobalmegacorp.com

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