Annotation of Examples/DriverKit/Adaptec1542B/Adaptec1542B_reloc.tproj/AHAController.m, revision 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.