Annotation of Examples/DriverKit/Adaptec1542B/Adaptec1542B_reloc.tproj/AHAThread.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1993 NeXT Computer, Inc.
        !             3:  *
        !             4:  * AHAThread.m - I/O thread methods for Adaptec 1542 driver. 
        !             5:  *
        !             6:  * HISTORY
        !             7:  *
        !             8:  * 13 Apr 1993 Doug Mitchell at NeXT
        !             9:  *     Split off from AHAController.m.
        !            10:  */
        !            11: 
        !            12: #import "AHAThread.h"
        !            13: #import "AHATypes.h"
        !            14: #import "AHAInline.h"
        !            15: #import "AHAControllerPrivate.h"
        !            16: #import "scsivar.h"
        !            17: #import <driverkit/generalFuncs.h>
        !            18: #import <driverkit/kernelDriver.h>
        !            19: #import <kernserv/prototypes.h>
        !            20: #import <sys/param.h>
        !            21: 
        !            22: static void ahaTimeout(void *arg);
        !            23: 
        !            24: #define AUTO_SENSE_ENABLE      1
        !            25: 
        !            26: /*
        !            27:  * Template for timeout message.
        !            28:  */
        !            29: static msg_header_t timeoutMsgTemplate = {
        !            30:        0,                                      // msg_unused 
        !            31:        1,                                      // msg_simple 
        !            32:        sizeof(msg_header_t),                   // msg_size 
        !            33:        MSG_TYPE_NORMAL,                        // msg_type 
        !            34:        PORT_NULL,                              // msg_local_port 
        !            35:        PORT_NULL,                              // msg_remote_port - TO
        !            36:                                                // BE FILLED IN 
        !            37:        IO_TIMEOUT_MSG                          // msg_id 
        !            38: };
        !            39: 
        !            40: @implementation AHAController(IOThread)
        !            41: 
        !            42: /*
        !            43:  * I/O thread version of -executeRequest:buffer:client.
        !            44:  * The approximate logic is:
        !            45:  *     Build up an internal ccb describing this request
        !            46:  *     Put it on the queue of pending commands
        !            47:  *     Run as many pending commands as possible
        !            48:  *
        !            49:  * Returns non-zero if no ccb was available for the command. This case 
        !            50:  * must be handled gracefully by the caller by enqueueing the request on
        !            51:  * commandQ.
        !            52:  */
        !            53: - (int)threadExecuteRequest    : (AHACommandBuf *)cmdBuf
        !            54: {
        !            55:        struct ccb      *ccb;
        !            56:        IOSCSIRequest   *scsiReq = cmdBuf->scsiReq;
        !            57:        
        !            58:        ddm_thr("threadExecuteRequest cmdBuf 0x%x\n", cmdBuf, 2,3,4,5);
        !            59:        
        !            60:        ccb = [self allocCcb:(scsiReq->maxTransfer ? YES : NO)];
        !            61:        if(ccb == NULL) {
        !            62:                return 1;
        !            63:        }
        !            64:        if([self ccbFromCmd:cmdBuf ccb:ccb]) {
        !            65:                /*
        !            66:                 * Command reject. Error status is in 
        !            67:                 * cmdBuf->scsiReq->driverStatus. 
        !            68:                 * Notify caller and clean up.
        !            69:                 */
        !            70:                [self freeCcb:ccb];
        !            71:                [cmdBuf->cmdLock lock];
        !            72:                [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
        !            73:                return 0;
        !            74:        }
        !            75: 
        !            76:        /*
        !            77:         *  Make sure we'll be able to time this command out.  This should be
        !            78:         *  rare, so we don't particularly care about how efficient it is.
        !            79:         */
        !            80:        ccb->timeoutPort = interruptPortKern;
        !            81:        IOScheduleFunc(ahaTimeout, ccb, scsiReq->timeoutLength);
        !            82: 
        !            83:        /*
        !            84:         * Stick this command on the list of pending ones, and run them.
        !            85:         */
        !            86:        queue_enter(&pendingQ, ccb, struct ccb *, ccbQ);
        !            87:        [self runPendingCommands];
        !            88:        return 0;
        !            89: 
        !            90: }
        !            91: 
        !            92: /*
        !            93:  * I/O thread version of -resetSCSIBus.
        !            94:  * We also interpret this to mean we should reset the board.
        !            95:  * cmdBuf == NULL indicates a call from within the I/O thread for
        !            96:  * a reason other than -resetSCSIBus (e.g., timeout recovery). 
        !            97:  */
        !            98: - (void)threadResetBus : (AHACommandBuf *)cmdBuf
        !            99: {
        !           100: 
        !           101:        aha_ctrl_reg_t  ctrl = { 0 };
        !           102:        struct ccb *ccb;
        !           103:        queue_head_t *q;
        !           104:        
        !           105:        ddm_thr("threadResetBus\n", 1,2,3,4,5);
        !           106:        
        !           107:        /*
        !           108:         * Abort all outstanding and pending commands. 
        !           109:         */
        !           110:        for(q=&outstandingQ; q!=&pendingQ; q=&pendingQ) {
        !           111:                while(!queue_empty(q)) {
        !           112:                        ccb = (struct ccb *)queue_first(q);
        !           113:                        queue_remove(q, ccb, struct ccb *, ccbQ);
        !           114:                        if(q == &outstandingQ) {
        !           115:                                ASSERT(outstandingCount != 0);
        !           116:                                outstandingCount--;
        !           117:                        }
        !           118:                        [self commandCompleted:ccb reason:CS_Reset];
        !           119:                }
        !           120:        }
        !           121:        
        !           122:        /*
        !           123:         * Now reset the hardware.
        !           124:         */
        !           125:        aha_reset_board(ioBase, ahaBoardId);
        !           126:        aha_setup_mb_area(ioBase, ahaMbArea, ahaCcb);
        !           127: 
        !           128:        ctrl.scsi_rst = 1;
        !           129:        aha_put_ctrl(ioBase, ctrl);
        !           130: 
        !           131:        IOLog("Resetting SCSI Bus...\n");
        !           132:        IOSleep(10000);
        !           133:        
        !           134:        /*
        !           135:         * Notify caller of completion if appropriate.
        !           136:         */
        !           137:        if(cmdBuf) {
        !           138:                ddm_thr("threadResetBus: I/O complete on cmdBuf 0x%x\n",
        !           139:                        cmdBuf, 2,3,4,5);
        !           140:                cmdBuf->result = SR_IOST_GOOD;
        !           141:                [cmdBuf->cmdLock lock];
        !           142:                [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
        !           143:        }
        !           144: }
        !           145: 
        !           146: /*
        !           147:  * Build a ccb from the specified AHACommandBuf. Returns non-zero on error
        !           148:  * (i.e., on command reject from this method). In that case, error status 
        !           149:  * is in cmdBuf->scsiReq->driverStatus.
        !           150:  */
        !           151: - (int) ccbFromCmd:(AHACommandBuf *)cmdBuf ccb:(struct ccb *)ccb
        !           152: {
        !           153:        IOSCSIRequest           *scsiReq = cmdBuf->scsiReq;
        !           154:        union cdb               *cdbp = &scsiReq->cdb;
        !           155:        int                     cdb_ctrl;
        !           156:        vm_offset_t             addr, phys;
        !           157:        vm_size_t               len;
        !           158:        unsigned int            pages;
        !           159:        unsigned int            cmdlen;
        !           160:        
        !           161:        /*
        !           162:         * Figure out what kind of cdb we've been given
        !           163:         * and snag the ctrl byte
        !           164:         */
        !           165:        switch (SCSI_OPGROUP(cdbp->cdb_opcode)) {
        !           166: 
        !           167:            case OPGROUP_0:
        !           168:                cmdlen = sizeof (struct cdb_6);
        !           169:                cdb_ctrl = cdbp->cdb_c6.c6_ctrl;
        !           170:                break;
        !           171:        
        !           172:            case OPGROUP_1:
        !           173:            case OPGROUP_2:
        !           174:                cmdlen = sizeof (struct cdb_10);
        !           175:                cdb_ctrl = cdbp->cdb_c10.c10_ctrl;
        !           176:                break;
        !           177:        
        !           178:            case OPGROUP_5:
        !           179:                cmdlen = sizeof (struct cdb_12);
        !           180:                cdb_ctrl = cdbp->cdb_c12.c12_ctrl;
        !           181:                break;
        !           182:     
        !           183:            /*
        !           184:             * Group 6 and 7 commands allow a user-specified CDB length.
        !           185:             */
        !           186:            case OPGROUP_6:
        !           187:                if(scsiReq->cdbLength)
        !           188:                        cmdlen = scsiReq->cdbLength;
        !           189:                else
        !           190:                        cmdlen = sizeof (struct cdb_6);
        !           191:                cdb_ctrl = 0;
        !           192:                break;
        !           193:     
        !           194:            case OPGROUP_7:
        !           195:                if(scsiReq->cdbLength)
        !           196:                        cmdlen = scsiReq->cdbLength;
        !           197:                else
        !           198:                        cmdlen = sizeof (struct cdb_10);
        !           199:                cdb_ctrl = 0;
        !           200:                break;
        !           201:     
        !           202:            default:
        !           203:                scsiReq->driverStatus = SR_IOST_CMDREJ;
        !           204:                return 1;
        !           205:        }
        !           206: 
        !           207:        /*
        !           208:         * Make sure nothing unreasonable has been asked of us
        !           209:         */
        !           210:        if ((cdb_ctrl & CTRL_LINKFLAG) != CTRL_NOLINK) {
        !           211:                scsiReq->driverStatus = SR_IOST_CMDREJ;
        !           212:                return 1;
        !           213:        }
        !           214: 
        !           215:        addr = (vm_offset_t)cmdBuf->buffer;
        !           216:        len = scsiReq->maxTransfer;
        !           217: 
        !           218:        if (len > 0) 
        !           219:                pages = (round_page(addr+len) - trunc_page(addr)) / PAGE_SIZE;
        !           220:        else
        !           221:                pages = 0;
        !           222:            
        !           223:        ccb->cdb                = *cdbp;
        !           224:        ccb->cdb_len            = cmdlen;
        !           225:     
        !           226:        ccb->data_in            = scsiReq->read;
        !           227:        ccb->data_out           = !scsiReq->read;
        !           228:        ccb->target             = scsiReq->target;
        !           229:        ccb->lun                = scsiReq->lun;
        !           230:        #if     AUTO_SENSE_ENABLE
        !           231:        ccb->reqsense_len      = sizeof(esense_reply_t);
        !           232:        #else   AUTO_SENSE_ENABLE
        !           233:        ccb->reqsense_len       = 1;    /* no auto reqsense */
        !           234:        #endif  AUTO_SENSE_ENABLE
        !           235: 
        !           236:        /* 
        !           237:         * Note Adaptec does not support command queueing. Synchronous
        !           238:         * negotiation can only be disabled by jumper. Disconnects can
        !           239:         * not be disabled.
        !           240:         */
        !           241: 
        !           242:        ccb->cmdBuf = cmdBuf;
        !           243:        ccb->total_xfer_len = 0;
        !           244:        IOGetTimestamp(&ccb->startTime);
        !           245: 
        !           246:        /*
        !           247:         *  Set up the DMA address and length.  If we have more than one page,
        !           248:         *  then chances are that we'll have to use scatter/gather to collect
        !           249:         *  all the physical pages into a single transfer.
        !           250:         */
        !           251:        if (pages == 0) {
        !           252:                aha_put_24(0, ccb->data_addr);
        !           253:                aha_put_24(0, ccb->data_len);
        !           254:                ccb->oper = AHA_CCB_INITIATOR_RESID;
        !           255:        }
        !           256:        else if (pages == 1) {          
        !           257:        
        !           258:                if(IOPhysicalFromVirtual(cmdBuf->client, addr, &phys)) {
        !           259:                        IOLog("%s: Can\'t get physical address\n",
        !           260:                                [self name]);
        !           261:                        scsiReq->driverStatus = SR_IOST_INT;
        !           262:                        return 1;
        !           263:                }
        !           264: 
        !           265:                ccb->dmaList[0] = [self createDMABufferFor:&phys
        !           266:                                length:len read:scsiReq->read
        !           267:                                needsLowMemory:YES limitSize:NO];
        !           268: 
        !           269:                if (ccb->dmaList[0] == NULL) {
        !           270:                        [self abortDMA:ccb->dmaList length:len];
        !           271:                        scsiReq->driverStatus = SR_IOST_INT;
        !           272:                        return 1;
        !           273:                }
        !           274: 
        !           275:                aha_put_24(phys, ccb->data_addr);
        !           276:                aha_put_24(len, ccb->data_len);
        !           277:        
        !           278:                ccb->oper = AHA_CCB_INITIATOR_RESID;
        !           279:                ccb->total_xfer_len = len;
        !           280:        }
        !           281:        else {
        !           282:                vm_offset_t     lastPhys = 0;
        !           283:                unsigned int    sgEntry = 0;
        !           284:                unsigned int    maxEntries = MIN(pages, AHA_SG_COUNT);
        !           285:                IOEISADMABuffer *dmaBuf = ccb->dmaList;
        !           286: 
        !           287:                for (sgEntry=0;  sgEntry < maxEntries;  sgEntry++) {
        !           288:                        struct aha_sg   *sg = &ccb->sg_list[sgEntry];
        !           289:                        unsigned int    thisLength;
        !           290:                        
        !           291:                        thisLength = MIN(len, round_page(addr+1) - addr);
        !           292:                        
        !           293:                        if(IOPhysicalFromVirtual(cmdBuf->client, 
        !           294:                                        addr, &phys)) {
        !           295:                                IOLog("%s: Can\'t get physical address\n",
        !           296:                                        [self name]);
        !           297:                                [self abortDMA:ccb->dmaList
        !           298:                                        length:ccb->total_xfer_len];
        !           299:                                scsiReq->driverStatus = SR_IOST_INT;
        !           300:                                return 1;
        !           301:                        }
        !           302:                        *dmaBuf = [self createDMABufferFor:&phys
        !           303:                                        length:thisLength
        !           304:                                        read:scsiReq->read
        !           305:                                        needsLowMemory:YES limitSize:NO];
        !           306: 
        !           307:                        if (*dmaBuf == NULL) {
        !           308:                                [self abortDMA:ccb->dmaList
        !           309:                                        length:ccb->total_xfer_len];
        !           310:                                scsiReq->driverStatus = SR_IOST_INT;
        !           311:                                return 1;
        !           312:                        }
        !           313: 
        !           314:                        aha_put_24(phys, sg->addr);
        !           315:                        aha_put_24(thisLength, sg->len);
        !           316:     
        !           317:                        ccb->total_xfer_len += thisLength;
        !           318:                        
        !           319:                        addr += thisLength;
        !           320:                        len -= thisLength;
        !           321:                        lastPhys = phys;
        !           322:                        dmaBuf++;
        !           323:                }
        !           324:        
        !           325:                if(IOPhysicalFromVirtual(IOVmTaskSelf(), 
        !           326:                                (unsigned)ccb->sg_list, 
        !           327:                                &phys)) {
        !           328:                        IOLog("%s: Can\'t get physical address of ccb\n", 
        !           329:                                [self name]);
        !           330:                        IOPanic("AHAController");
        !           331:                }
        !           332:                aha_put_24(phys, ccb->data_addr);
        !           333:                aha_put_24(sgEntry * sizeof(struct aha_sg), ccb->data_len);
        !           334: 
        !           335:                ccb->oper = AHA_CCB_INITIATOR_RESID_SG;
        !           336:        }
        !           337: 
        !           338:        return 0;
        !           339: }
        !           340: 
        !           341: /*
        !           342:  * If any commands pending, and the controller's queue is not full,
        !           343:  * run the new commands. 
        !           344:  */
        !           345: - runPendingCommands
        !           346: {
        !           347:        unsigned int    cmdsToRun;
        !           348:        struct ccb      *ccb;
        !           349: 
        !           350:        cmdsToRun = AHA_QUEUE_SIZE - outstandingCount;
        !           351: 
        !           352:        while (cmdsToRun > 0 && !queue_empty(&pendingQ)) {
        !           353: 
        !           354:                /*
        !           355:                 *  Dequeue pending command and add to the outstanding queue.
        !           356:                 */
        !           357:                ccb = (struct ccb *) queue_first(&pendingQ);
        !           358:                queue_remove(&pendingQ, ccb, struct ccb *, ccbQ);
        !           359:                if (!ccb)
        !           360:                        break;
        !           361: 
        !           362:                queue_enter(&outstandingQ, ccb, struct ccb *, ccbQ);
        !           363:                outstandingCount++;
        !           364:                
        !           365:                /*
        !           366:                 *  Let 'er rip...
        !           367:                 */
        !           368:                ccb->mb_out->mb_stat = AHA_MB_OUT_START;
        !           369:                aha_start_scsi(ioBase);
        !           370:        
        !           371:                /*
        !           372:                 *  Accumulate some simple statistics: the max queue length
        !           373:                 *  and enough info to compute a running average of the queue
        !           374:                 *  length.
        !           375:                 */
        !           376:                maxQueueLen = MAX(maxQueueLen, outstandingCount);
        !           377:                queueLenTotal += outstandingCount;
        !           378:                totalCommands++;
        !           379: 
        !           380:                cmdsToRun--;
        !           381:        }
        !           382:        return self;
        !           383: }
        !           384: 
        !           385: /*
        !           386:  * A command is done.  Figure out what happened, and notify the
        !           387:  * client appropriately. Called upon detection of I/O complete interrupt,
        !           388:  * timeout detection, or when we reset the bus and blow off pending 
        !           389:  * commands.
        !           390:  */
        !           391: - (void)commandCompleted : (struct ccb *) ccb 
        !           392:                  reason : (completeStatus)reason
        !           393: {
        !           394:        ns_time_t               currentTime;
        !           395:        IOSCSIRequest           *scsiReq;
        !           396:        AHACommandBuf           *cmdBuf = ccb->cmdBuf;
        !           397:        
        !           398:        ASSERT(cmdBuf != NULL);
        !           399:        scsiReq = cmdBuf->scsiReq;
        !           400:        ASSERT(scsiReq != NULL);
        !           401: 
        !           402:        ddm_thr("commandCompleted: ccb 0x%x cmdBuf 0x%x reason %d\n", 
        !           403:                ccb, cmdBuf, reason, 4,5);
        !           404:                
        !           405:        scsiReq->scsiStatus = ccb->target_status;
        !           406: 
        !           407:        switch(reason) {
        !           408:            case CS_Timeout:
        !           409:                scsiReq->driverStatus = SR_IOST_IOTO;
        !           410:                break;
        !           411:            case CS_Reset:
        !           412:                scsiReq->driverStatus = SR_IOST_RESET;
        !           413:                break;
        !           414:            case CS_Complete:
        !           415:                switch (ccb->host_status) {
        !           416:     
        !           417:                /*
        !           418:                 * Handle success and data overrun/underrun.  We can handle
        !           419:                 * overrun/underrun as a normal case because the controller 
        !           420:                 * sets the data_len field to be the actual number of bytes 
        !           421:                 * transferred regardless of overrun.
        !           422:                 */
        !           423:                case AHA_HOST_SUCCESS:
        !           424:                case AHA_HOST_DATA_OVRUN:
        !           425:                    [self completeDMA:ccb->dmaList 
        !           426:                        length:scsiReq->maxTransfer];
        !           427:                    scsiReq->bytesTransferred = ccb->total_xfer_len -  
        !           428:                                        aha_get_24(ccb->data_len);
        !           429:     
        !           430:                    /*
        !           431:                     *  Everything looks good.  Make sure the SCSI status byte
        !           432:                     *  is cool before we really say everything is hunky-dory.
        !           433:                     */
        !           434:                    if (scsiReq->scsiStatus == STAT_GOOD)
        !           435:                            scsiReq->driverStatus = SR_IOST_GOOD;
        !           436:                    else if (scsiReq->scsiStatus == STAT_CHECK) {
        !           437:                        if(AUTO_SENSE_ENABLE) {
        !           438:                        
        !           439:                            esense_reply_t *sensePtr;
        !           440:                            
        !           441:                            scsiReq->driverStatus = SR_IOST_CHKSV;
        !           442:                            
        !           443:                            /*
        !           444:                             * Sense data starts immediately after the actual
        !           445:                             * cdb area we use, not an entire union cdb.
        !           446:                             */
        !           447:                            sensePtr = (esense_reply_t *)
        !           448:                                (((char *)&ccb->cdb) + ccb->cdb_len);
        !           449:                            scsiReq->senseData = *sensePtr;
        !           450:                        }
        !           451:                        else {
        !           452:                            scsiReq->driverStatus = SR_IOST_CHKSNV;
        !           453:                        }
        !           454:                    }
        !           455:                    else
        !           456:                            scsiReq->driverStatus = ST_IOST_BADST;
        !           457:                    break;
        !           458:     
        !           459:                case AHA_HOST_SEL_TIMEOUT:
        !           460:                    [self abortDMA:ccb->dmaList length:scsiReq->maxTransfer];
        !           461:                    scsiReq->driverStatus = SR_IOST_SELTO;
        !           462:                    break;
        !           463:                
        !           464:                default:
        !           465:                    IOLog("AHA interrupt: bad status %x\n", ccb->host_status);
        !           466:                    [self abortDMA:ccb->dmaList length:scsiReq->maxTransfer];
        !           467:                    scsiReq->driverStatus = SR_IOST_INVALID;
        !           468:                    break;
        !           469:            }   /*  switch host_status */
        !           470:        }       /*  switch status */
        !           471: 
        !           472:        IOGetTimestamp(&currentTime);
        !           473:        scsiReq->totalTime = currentTime - ccb->startTime;
        !           474:        cmdBuf->result = scsiReq->driverStatus;
        !           475:        
        !           476:        /*
        !           477:         * Wake up client.
        !           478:         */
        !           479:        ddm_thr("commandCompleted: I/O complete on cmdBuf 0x%x\n",
        !           480:                        cmdBuf, 2,3,4,5);
        !           481:        [cmdBuf->cmdLock lock];
        !           482:        [cmdBuf->cmdLock unlockWith:CMD_COMPLETE];
        !           483: 
        !           484:        /*
        !           485:         * Free the CCB and clean up possible pending timeout.
        !           486:         */     
        !           487:        (void) IOUnscheduleFunc(ahaTimeout, ccb);
        !           488:        [self freeCcb:ccb];
        !           489: }
        !           490: 
        !           491: /*
        !           492:  * Alloc/free ccb's. These only come from the array ahaCcb[]. 
        !           493:  * If we can't find one, return NULL - caller will have to try 
        !           494:  * again later.
        !           495:  */
        !           496: - (struct ccb *)allocCcb : (BOOL)doDMA
        !           497: {
        !           498:        struct ccb *ccb;
        !           499:        int i;
        !           500:        
        !           501:        if(numFreeCcbs == 0) {
        !           502:                ddm_thr("allocCcb: numFreeCcbs = 0\n", 1,2,3,4,5);
        !           503:                return NULL;
        !           504:        }
        !           505: 
        !           506:        /*
        !           507:         * Since numFreeCcbs is non-zero, there has to be one available 
        !           508:         * in ahaCcb[].
        !           509:         */
        !           510:        ccb = ahaCcb;
        !           511:        while (ccb <= &ahaCcb[AHA_QUEUE_SIZE - 1] && ccb->in_use) {
        !           512:                ccb++;
        !           513:        }
        !           514:        if (ccb > &ahaCcb[AHA_QUEUE_SIZE - 1]) {
        !           515:                IOPanic("AHAController: out of ccbs");
        !           516:        }
        !           517:        numFreeCcbs--;
        !           518:        ccb->in_use = TRUE;
        !           519:        
        !           520:        /*
        !           521:         * Null out dmaList.
        !           522:         */
        !           523:        for(i=0; i<AHA_SG_COUNT; i++) {
        !           524:                ccb->dmaList[i] = NULL;
        !           525:        }
        !           526:        
        !           527:        /*
        !           528:         * Acquire the reentrant DMA lock. This is a nop on EISA machines.
        !           529:         * 
        !           530:         * Although -reserveDMALock is reentrant for multiple threads on
        !           531:         * one device, it is *not* reentrant for one thread. Thus we should 
        !           532:         * only call it if we don't already hold the lock.
        !           533:         * Also, avoid this if we're not going to do any DMA. 
        !           534:         */
        !           535:        if(doDMA && (++dmaLockCount == 1)) {
        !           536:                ddm_thr("allocCcb: calling reserveDMALock\n", 1,2,3,4,5);
        !           537:                [super reserveDMALock];
        !           538:        }
        !           539:        ddm_thr("allocCcb: returning 0x%x\n", ccb, 2,3,4,5);
        !           540:        
        !           541:        return ccb;     
        !           542: }
        !           543: 
        !           544: - (void)freeCcb : (struct ccb *)ccb
        !           545: {
        !           546:        BOOL    didDMA = (ccb->total_xfer_len ? YES : NO);
        !           547: 
        !           548:        ddm_thr("freeCcb: ccb 0x%x\n", ccb, 2,3,4,5);
        !           549:        ccb->in_use = FALSE;
        !           550:        numFreeCcbs++;
        !           551:        if(didDMA && (--dmaLockCount == 0)) {
        !           552:                ddm_thr("freeCcb: calling releaseDMALock\n", 
        !           553:                        1,2,3,4,5);
        !           554:                [super releaseDMALock];
        !           555:        }
        !           556: }
        !           557: 
        !           558: - (void) completeDMA:(IOEISADMABuffer *) dmaList length:(unsigned int) xferLen
        !           559: {
        !           560:        IOEISADMABuffer *buf = &dmaList[0];
        !           561:        int             i;
        !           562:        
        !           563:        for (i = 0; i < AHA_SG_COUNT; i++, buf++) {
        !           564:                if(*buf) {
        !           565:                        [self freeDMABuffer:*buf];
        !           566:                }
        !           567:                else {
        !           568:                        return;
        !           569:                }
        !           570:        }
        !           571: }
        !           572: 
        !           573: 
        !           574: - (void) abortDMA:(IOEISADMABuffer *) dmaList length:(unsigned int) xferLen
        !           575: {
        !           576:        IOEISADMABuffer *buf = &dmaList[0];
        !           577:        int             i;
        !           578:        
        !           579:        for (i = 0; i < AHA_SG_COUNT; i++, buf++) {
        !           580:                if(*buf) {
        !           581:                        [self abortDMABuffer:*buf];
        !           582:                }
        !           583:                else {
        !           584:                        return;
        !           585:                }
        !           586:        }
        !           587: }
        !           588: 
        !           589: @end
        !           590: 
        !           591: 
        !           592: /*
        !           593:  *  Handle timeouts.  We just send a timeout message to the I/O thread
        !           594:  *  so it wakes up.
        !           595:  */
        !           596: static void
        !           597: ahaTimeout(void *arg)
        !           598: {
        !           599:        
        !           600:        struct ccb      *ccb = arg;
        !           601:        msg_header_t    msg = timeoutMsgTemplate;
        !           602:        msg_return_t    mrtn;
        !           603:        
        !           604:        if(!ccb->in_use) {
        !           605:                /* 
        !           606:                 * Race condition - this CCB got completed another way. 
        !           607:                 * No problem.
        !           608:                 */
        !           609:                return;
        !           610:        }       
        !           611:        msg.msg_remote_port = ccb->timeoutPort;
        !           612:        IOLog("AHA timeout\n");
        !           613:        if(mrtn = msg_send_from_kernel(&msg, MSG_OPTION_NONE, 0)) {
        !           614:                IOLog("ahaTimeout: msg_send_from_kernel() returned %d\n",
        !           615:                        mrtn);
        !           616:        }
        !           617: }
        !           618: 

unix.superglobalmegacorp.com

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