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