Annotation of Examples/DriverKit/AMDPCSCSIDriver/AMDPCSCSIDriver_reloc.tproj/AMD_x86.m, revision 1.1

1.1     ! root        1: /*     Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
        !             2:  *
        !             3:  * AMD_x86.m - architecture-specific methods for AMD SCSI driver
        !             4:  *
        !             5:  * HISTORY
        !             6:  * 21 Oct 94    Doug Mitchell at NeXT
        !             7:  *      Created. 
        !             8:  */
        !             9: 
        !            10: #import <driverkit/generalFuncs.h>
        !            11: #import <driverkit/kernelDriver.h>
        !            12: #import <driverkit/i386/IOPCIDeviceDescription.h>
        !            13: #import <kernserv/prototypes.h>
        !            14: #import <mach/kern_return.h>
        !            15: #import "AMD_x86.h"
        !            16: #import "pciconf.h"
        !            17: #import "AMD_Regs.h"
        !            18: #import "AMD_Chip.h"
        !            19: #import "bringup.h"
        !            20: #import "AMD_ddm.h"
        !            21: #import "configKeys.h"
        !            22: #import <mach/mach_interface.h>
        !            23: 
        !            24: #define TEST_DEBUG     0       /* low level I/O test before registerDevice */
        !            25: #define TEST_IPL_BUG   0       /* test IPL bug */
        !            26: 
        !            27: #if    TEST_DEBUG
        !            28: static void testDebug(id driver);
        !            29: #endif TEST_DEBUG
        !            30: 
        !            31: #if    TEST_IPL_BUG
        !            32: static void testIplBug();
        !            33: #endif TEST_IPL_BUG
        !            34: 
        !            35: #ifdef DEBUG
        !            36: AMD_SCSI *amd_g;
        !            37: #endif DEBUG
        !            38: 
        !            39: static int _atoi(const char *ip)
        !            40: {
        !            41:        unsigned rtn = 0;
        !            42:        
        !            43:        while(*ip) {
        !            44:                if((*ip < '0') || (*ip > '9')) {
        !            45:                        return rtn;     
        !            46:                }
        !            47:                rtn *= 10;
        !            48:                rtn += (*ip - '0');
        !            49:                ip++;
        !            50:        }
        !            51:        return rtn;
        !            52: }
        !            53: 
        !            54: /*
        !            55:  * Get I/O port range and IRQ from PCI config space. Set appropriate
        !            56:  * values in deviceDescription. Returns base address in *baseAddr.
        !            57:  * Returns YES if successful, else NO.
        !            58:  */
        !            59: static BOOL parseConfigSpace(
        !            60:        id deviceDescription,
        !            61:        const char *title,
        !            62:        unsigned regSize,               // in bytes
        !            63:        IOEISAPortAddress *baseAddr)    // RETURNED
        !            64: {
        !            65:        IOPCIConfigSpace        configSpace;
        !            66:        IORange                 portRange;
        !            67:        unsigned                *basePtr = 0;
        !            68:        int                     irq;
        !            69:        int                     i;
        !            70:        BOOL                    foundBase = NO;
        !            71:        IOReturn                irtn;
        !            72:        
        !            73:        /*
        !            74:         * First get our configSpace register set.
        !            75:         */
        !            76:        bzero(&configSpace, sizeof(IOPCIConfigSpace));
        !            77:        if(irtn = [IODirectDevice getPCIConfigSpace:&configSpace
        !            78:                        withDeviceDescription:deviceDescription]) {
        !            79:                IOLog("%s: Can\'t get configSpace (%s); ABORTING\n", 
        !            80:                        title, [IODirectDevice stringFromReturn:irtn]);
        !            81:                    return NO;
        !            82:        }
        !            83:        basePtr = configSpace.BaseAddress;
        !            84:        irq     = configSpace.InterruptLine;
        !            85:        if((basePtr[0] == 0) || (irq == 0)) {
        !            86:                IOLog("%s: Bogus config info (IRQ %d, Base 0x%x)\n",
        !            87:                        title, irq, (unsigned)basePtr);
        !            88:                    return NO;
        !            89:        }
        !            90:        
        !            91:        /*
        !            92:         * Scan all 6 base address registers, make sure there is exactly one
        !            93:         * I/O address.
        !            94:         */
        !            95:        for(i=0; i<PCI_NUM_BASE_ADDRESS; i++) {
        !            96:            if(basePtr[i] & PCI_BASE_IO_BIT) {
        !            97:                if(foundBase) {
        !            98:                    IOLog("%s: Multiple I/O Port Bases Found\n", title);
        !            99:                    return NO;
        !           100:                }
        !           101:                foundBase = YES;
        !           102:                portRange.start = PCI_BASE_IO(basePtr[i]);
        !           103:            }
        !           104:        }
        !           105:        if(!foundBase) {
        !           106:                IOLog("%s: No I/O Port Base Found\n", title);
        !           107:                return NO;
        !           108:        }
        !           109:        portRange.size = regSize;
        !           110:        *baseAddr = portRange.start;
        !           111:        ddm_init("irq %d base 0x%x\n", irq, *baseAddr, 3,4,5);
        !           112:        
        !           113:        /*
        !           114:         * OK, retweeze our device description. 
        !           115:         */
        !           116:        irtn = [deviceDescription setInterruptList:&irq num:1];
        !           117:        if(irtn) {
        !           118:                IOLog("%s: Can\'t set interruptList to IRQ %d (%s)\n", 
        !           119:                        title, irq, [IODirectDevice stringFromReturn:irtn]);
        !           120:                return NO;
        !           121:        }
        !           122:        irtn = [deviceDescription setPortRangeList:&portRange num:1];
        !           123:        if(irtn) {
        !           124:                IOLog("%s: Can\'t set portRangeList to port 0x%x (%s)\n", 
        !           125:                        title, portRange.start, 
        !           126:                        [IODirectDevice stringFromReturn:irtn]);
        !           127:                return NO;
        !           128:        }
        !           129:        return YES;
        !           130: }
        !           131: 
        !           132: /*
        !           133:  * Obtain a YES/NO type parameter from the config table.
        !           134:  */
        !           135: static int getConfigParam(
        !           136:        id      configTable,
        !           137:        const char *paramName)
        !           138: {
        !           139:        const char *value;
        !           140:        int rtn = 0;            // default if not present in table
        !           141:        
        !           142:        value = [configTable valueForStringKey:paramName];
        !           143:        if(value) {
        !           144:                if(strcmp(value, "YES") == 0) {
        !           145:                        rtn = 1;
        !           146:                }
        !           147:                [configTable freeString:value];
        !           148:        }
        !           149:        return rtn;
        !           150: }
        !           151: 
        !           152: @implementation AMD_SCSI(Architecture)
        !           153: 
        !           154: - archInit : deviceDescription
        !           155: {
        !           156:        id                      configTable;
        !           157:        const char              *value = NULL;
        !           158:        kern_return_t           krtn;
        !           159:        vm_offset_t             startPage, endPage;
        !           160:        unsigned                ival;
        !           161:        IOReturn                irtn;
        !           162:        unsigned char           lun;
        !           163:        
        !           164: #if    TEST_IPL_BUG
        !           165:        testIplBug();
        !           166: #endif TEST_IPL_BUG
        !           167: 
        !           168:        ddm_init("AMD archInit\n", 
        !           169:                1,2,3,4,5);
        !           170:        scState = SCS_UNINITIALIZED;
        !           171:                
        !           172:        /*
        !           173:         * Obtain I/O port base, busType dependent.
        !           174:         */
        !           175:        levelIRQ = NO;
        !           176:        configTable = [deviceDescription configTable];
        !           177:        value = [configTable valueForStringKey:"Bus Type"];
        !           178:        if(value == NULL) {
        !           179:                IOLog("AMD53C974: No Bus Type in config Table\n");
        !           180:                goto abort;
        !           181:        }
        !           182:        if(strcmp(value, "PCI") == 0) {
        !           183:                busType = BT_PCI;
        !           184:                if(parseConfigSpace(deviceDescription,
        !           185:                                "AMD53C974",
        !           186:                                AMD_PCI_REGISTER_SPACE,
        !           187:                                &ioBase) == NO) {
        !           188:                        [configTable freeString:value];
        !           189:                        goto abort;
        !           190:                }
        !           191:                ioBase += AMD_PCI_REGISTER_OFFSET;
        !           192:                if(irtn = [deviceDescription getPCIdevice : &deviceNumber
        !           193:                                            function : &functionNumber
        !           194:                                                bus : &busNumber]) {
        !           195:                        IOLog("AMD53C974: Can't find device using "
        !           196:                                "getPCIdevice (%s)\n",
        !           197:                                [self stringFromReturn:irtn]);
        !           198:                        goto abort;
        !           199:                }
        !           200:                levelIRQ = YES;
        !           201:                IOLog("AMD53C974: found at bus %d device %d function %d "
        !           202:                        "irq %d\n",
        !           203:                        busNumber, deviceNumber, functionNumber,
        !           204:                        [deviceDescription interrupt]);
        !           205:        }
        !           206:        else {
        !           207:                IOLog("AMD53C974: Bad Bus Type (%s) in config table\n",
        !           208:                        value);
        !           209:                [configTable freeString:value];
        !           210:                goto abort;
        !           211:        }       
        !           212:        [configTable freeString:value];
        !           213:        
        !           214:        if (![self probeChip]) {
        !           215:                IOLog("AMD53C974 Host Adaptor Not found at Port 0x%x\n",
        !           216:                        ioBase);
        !           217:                goto abort;
        !           218:        }
        !           219:        
        !           220:        #if     DEBUG
        !           221:        amd_g = self;
        !           222:        #endif  DEBUG
        !           223:        
        !           224:        if ([super initFromDeviceDescription:deviceDescription] == nil) {
        !           225:                goto abort;
        !           226:        }
        !           227:        ioThreadRunning = 1;
        !           228:        
        !           229:        /*
        !           230:         * Initialize local variables. Note that activeArray and 
        !           231:         * perTarget arrays are zeroed by objc runtime.
        !           232:         */
        !           233:        queue_init(&disconnectQ);
        !           234:        queue_init(&commandQ);
        !           235:        queue_init(&pendingQ);
        !           236:        commandLock = [[NXLock alloc] init];
        !           237:        activeCmd = NULL;
        !           238:        [self resetStats];
        !           239:        nextQueueTag = QUEUE_TAG_NONTAGGED + 1;
        !           240:        
        !           241:        /*
        !           242:         * Allocate some physically contiguous memory for the Memory 
        !           243:         * Descriptor List.
        !           244:         */
        !           245:        mdlFree = IOMalloc(MDL_SIZE * 2 * sizeof(vm_address_t));
        !           246:        startPage = trunc_page(mdlFree);
        !           247:        endPage = trunc_page(((vm_offset_t)&mdlFree[MDL_SIZE]) - 1);
        !           248:        if(startPage != endPage) {
        !           249:                mdl = mdlFree + MDL_SIZE;
        !           250:        }
        !           251:        else {
        !           252:                mdl = mdlFree;
        !           253:        }
        !           254:        ddm_init("&mdl[0] = 0x%x &mdl[%d] = 0x%x\n", mdl, MDL_SIZE - 1,
        !           255:                &mdl[MDL_SIZE - 1], 4,5);
        !           256:        irtn = IOPhysicalFromVirtual(IOVmTaskSelf(),
        !           257:                        (vm_offset_t)mdl,
        !           258:                        &mdlPhys);
        !           259:        if(irtn) {
        !           260:                IOLog("AMD53C974: can't get physical address of MDL\n");
        !           261:                goto abort;
        !           262:        }
        !           263:        
        !           264:        /*
        !           265:         * get tagged command queueing, sync mode, fast mode enables from
        !           266:         * configTable.
        !           267:         */
        !           268:        cmdQueueEnable = getConfigParam(configTable, CMD_QUEUE_ENABLE);
        !           269:        syncModeEnable = getConfigParam(configTable, SYNC_ENABLE);
        !           270:        fastModeEnable = getConfigParam(configTable, FAST_ENABLE);
        !           271:        extendTiming   = getConfigParam(configTable, EXTENDED_TIMING);
        !           272: 
        !           273:        /*
        !           274:         * Get clock rate, in MHz.
        !           275:         */
        !           276:        scsiClockRate = AMD_DEFAULT_CLOCK;
        !           277:        value = [configTable valueForStringKey:SCSI_CLOCK_RATE];
        !           278:        if(value) {
        !           279:                ival = _atoi(value);
        !           280:                if(ival) {
        !           281:                        scsiClockRate = ival;
        !           282:                        ddm_init("SCSI Clock Rate = %d MHz\n", 
        !           283:                                ival, 2,3,4,5);
        !           284:                }
        !           285:                [configTable freeString:value];
        !           286:        }
        !           287:        
        !           288:        autoSenseEnable = AUTO_SENSE_ENABLE;    // from bringup.h
        !           289:                
        !           290:        /*
        !           291:         * Get internal version of interruptPort; set the port queue 
        !           292:         * length to the maximum size. 
        !           293:         */
        !           294:        interruptPortKern = IOConvertPort([self interruptPort],
        !           295:                IO_KernelIOTask,
        !           296:                IO_Kernel);             
        !           297:        krtn = port_set_backlog(task_self(), [self interruptPort], 
        !           298:                PORT_BACKLOG_MAX);
        !           299:        if(krtn) {
        !           300:                IOLog("%s: error %d on port_set_backlog()\n",
        !           301:                        [self name], krtn);
        !           302:                /* Oh well... */
        !           303:        }
        !           304:        
        !           305:        /*
        !           306:         * Initialize the chip and reset the bus.
        !           307:         */
        !           308:        if([self hwReset:NULL]) {
        !           309:                goto abort;
        !           310:        }
        !           311:        
        !           312:        /*
        !           313:         * Reserve our devices. hostId is init'd at chip level in hwReset.
        !           314:         */
        !           315:        for(lun=0; lun<SCSI_NLUNS; lun++) {
        !           316:                [self reserveTarget:hostId 
        !           317:                        lun:lun
        !           318:                        forOwner:self];
        !           319:        }
        !           320:        
        !           321:        /*
        !           322:         * OK, we're ready to roll.
        !           323:         */
        !           324:        
        !           325:        #if     TEST_DEBUG
        !           326:        
        !           327:        /*
        !           328:         * Before we call registerDevice and bring all kinds of uncontrolled
        !           329:         * I/O...
        !           330:         */
        !           331:        testDebug(self);
        !           332:        #endif  TEST_DEBUG
        !           333: 
        !           334:        [self registerDevice];
        !           335: 
        !           336:        return self;
        !           337: 
        !           338: abort:
        !           339:        return [self free];
        !           340: }
        !           341: 
        !           342: /*
        !           343:  * Ensure DMA machine is in idle quiescent state.
        !           344:  */
        !           345: - (void)dmaIdle
        !           346: {
        !           347:        unsigned cmd = DC_CMD_IDLE | DC_MDL;
        !           348:        
        !           349:        /*
        !           350:         * MDL and dir bits need to be the same as they will for a 
        !           351:         * (potentially) upcoming DMA command.
        !           352:         */
        !           353:        if(activeCmd) {
        !           354:                if(activeCmd->scsiReq->read) {
        !           355:                        cmd |= DC_DIR_READ;
        !           356:                }
        !           357:                else {
        !           358:                        cmd |= DC_DIR_WRITE;
        !           359:                }
        !           360:        }
        !           361:        /* else direction is don't care */
        !           362:        
        !           363:        /*
        !           364:         * FIXME - should we do a DMA blast here?
        !           365:         */
        !           366:        WRITE_REGL(dmaCommand, cmd);
        !           367:        #if     WRITE_DMA_COMMAND_TWICE
        !           368:        WRITE_REGL(dmaCommand, cmd);
        !           369:        #endif  WRITE_DMA_COMMAND_TWICE
        !           370: }
        !           371: 
        !           372: #if    DDM_DEBUG
        !           373: static unsigned char *ddmPhys;
        !           374: #endif DDM_DEBUG
        !           375: 
        !           376: /*
        !           377:  * Start DMA transfer at activeCmd->currentPtr for activeCmd->currentByteCount.
        !           378:  * Note: this method is not strictly architecture-dependent and 
        !           379:  * chip-independent. I think it's best to do all of this work in one place,
        !           380:  * and an AMD chip for a different bus will definitely have a lot of changes
        !           381:  * here. 
        !           382:  */
        !           383: - (sc_status_t)dmaStart
        !           384: {
        !           385:        unsigned        byteCount = activeCmd->currentByteCount;
        !           386:        unsigned char   cvalue;
        !           387:        unsigned        pages;
        !           388:        vm_offset_t     virtAddr;
        !           389:        unsigned        physAddr;
        !           390:        unsigned        page;
        !           391:        unsigned        offset;
        !           392:        IOReturn        irtn;
        !           393:        unsigned        cmd;
        !           394:        
        !           395:        ddm_thr("dmaStart\n", 1,2,3,4,5);
        !           396:        ASSERT(activeCmd != NULL);
        !           397:        [self dmaIdle];
        !           398:        
        !           399:        /*
        !           400:         * Set up SCSI block transfer count registers.
        !           401:         */
        !           402:        cvalue = byteCount & 0xff;
        !           403:        WRITE_REG(startXfrCntLow, cvalue);
        !           404:        cvalue = (byteCount >> 8) & 0xff;
        !           405:        WRITE_REG(startXfrCntMid, cvalue);
        !           406:        cvalue = (byteCount >> 16) & 0xff;
        !           407:        WRITE_REG(startXfrCntHi, cvalue);
        !           408:        
        !           409:        /*
        !           410:         * Set up a memory descriptor list.
        !           411:         */
        !           412:        virtAddr = (vm_offset_t)activeCmd->currentPtr;
        !           413:        pages = (AMD_ROUND_PAGE(virtAddr + byteCount) - 
        !           414:                 AMD_TRUNC_PAGE(virtAddr)) / AMD_DMA_PAGE_SIZE;
        !           415:        for(page=0; page<pages; page++) {
        !           416:                if(page == 0) {
        !           417:                        /*
        !           418:                         * Special case, this one is allowed a page offset.
        !           419:                         */
        !           420:                        offset = virtAddr & AMD_DMA_PAGE_MASK;
        !           421:                        WRITE_REGL(dmaStartAddrs, offset);
        !           422:                        ddm_dma("    page 0 offset 0x%x\n", offset, 2,3,4,5);
        !           423:                        virtAddr = virtAddr & ~AMD_DMA_PAGE_MASK;
        !           424:                }
        !           425:                irtn = IOPhysicalFromVirtual(activeCmd->client,
        !           426:                        virtAddr,
        !           427:                        &physAddr);
        !           428:                if(irtn) {
        !           429:                        IOLog("%s: Can't get physical address (%s)\n", 
        !           430:                                [self name], [self stringFromReturn:irtn]);
        !           431:                        return SR_IOST_MEMF;
        !           432:                }
        !           433:                ddm_dma("    mdl[%d] = 0x%x\n", page, mdl[page], 3,4,5);
        !           434:                mdl[page] = physAddr;
        !           435:                virtAddr += AMD_DMA_PAGE_SIZE;
        !           436:                #if     DDM_DEBUG
        !           437:                if(page == 0) {
        !           438:                        ddmPhys = (unsigned char *)(physAddr + offset);
        !           439:                }
        !           440:                #endif  DDM_DEBUG
        !           441:        }
        !           442:        
        !           443:        /*
        !           444:         * Load byte count and address of MDL into DMA engine, and go.
        !           445:         */
        !           446:        ddm_dma("    dmaStartCount = 0x%x\n", byteCount, 2,3,4,5);
        !           447:        WRITE_REGL(dmaStartCount, byteCount);
        !           448:        WRITE_REGL(dmaStartMdlAddrs, mdlPhys);
        !           449:        if(activeCmd->scsiReq->read) {
        !           450:                cmd = DC_CMD_START | DC_MDL | DC_DIR_READ;
        !           451:        }
        !           452:        else {
        !           453:                cmd = DC_CMD_START | DC_MDL | DC_DIR_WRITE;
        !           454:        }
        !           455:        WRITE_REGL(dmaCommand, cmd);
        !           456:        #if     WRITE_DMA_COMMAND_TWICE
        !           457:        WRITE_REGL(dmaCommand, cmd);
        !           458:        #endif  WRITE_DMA_COMMAND_TWICE
        !           459:        WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO | SCMD_ENABLEDMA);
        !           460:        scState = SCS_DMAING;
        !           461:        return SR_IOST_GOOD;
        !           462: }
        !           463: 
        !           464: /*
        !           465:  * Terminate a DMA, including FIFO flush if necessary. Returns number of 
        !           466:  * bytes transferred.
        !           467:  */
        !           468: - (unsigned)dmaTerminate
        !           469: {
        !           470:        unsigned char   fifoDepth = 0;
        !           471:        unsigned        cmd;
        !           472:        int             tries;
        !           473:        unsigned        status;
        !           474:        unsigned        bytesXfrd;
        !           475:        unsigned        scsiXfrCnt;
        !           476:        unsigned        value;
        !           477:        
        !           478:        ASSERT(activeCmd != NULL);
        !           479:        
        !           480:        /*
        !           481:         * Get resid count from SCSI block.
        !           482:         */
        !           483:        scsiXfrCnt = READ_REG(currXfrCntLow);
        !           484:        value = READ_REG(currXfrCntMid);
        !           485:        scsiXfrCnt += (value << 8);
        !           486:        value = READ_REG(currXfrCntHi);
        !           487:        scsiXfrCnt += (value << 16);
        !           488:        
        !           489:        fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK;
        !           490:        if((activeCmd->scsiReq->read) && (scsiXfrCnt != 0)) {
        !           491:                /*
        !           492:                 * Make sure SCSI fifo is empty. The manual says we 
        !           493:                 * might have to wait a while.
        !           494:                 */
        !           495:                if(fifoDepth) {
        !           496:                        IODelay(1000);
        !           497:                        fifoDepth = READ_REG(currFifoState) & 
        !           498:                                FS_FIFO_LEVEL_MASK;
        !           499:                        switch(fifoDepth) {
        !           500:                            case 0:
        !           501:                                ddm_dma("dmaTerminate: fifo cleared\n",
        !           502:                                        1,2,3,4,5);
        !           503:                                break;          // normal, OK
        !           504:                            case 1:
        !           505:                                IOLog("%s: Odd Byte Disconnect on target %d\n",
        !           506:                                        [self name], 
        !           507:                                        activeCmd->scsiReq->target);
        !           508:                                break;
        !           509:                            default:
        !           510:                                IOLog("%s: SCSI FIFO hung\n", [self name]);
        !           511:                                break;
        !           512:                        
        !           513:                                /*
        !           514:                                 * I'm not sure what to do about these
        !           515:                                 * errors...
        !           516:                                 */
        !           517:                        }
        !           518:                }
        !           519:                if(activeCmd->scsiReq->read) {
        !           520:                        cmd = DC_CMD_BLAST | DC_MDL | DC_DIR_READ;
        !           521:                }
        !           522:                else {
        !           523:                        cmd = DC_CMD_BLAST | DC_MDL | DC_DIR_WRITE;
        !           524:                }
        !           525:                ddm_dma("   ...sending DMA blast\n", 1,2,3,4,5);
        !           526:                WRITE_REGL(dmaCommand, cmd);
        !           527:                #if     WRITE_DMA_COMMAND_TWICE
        !           528:                WRITE_REGL(dmaCommand, cmd);
        !           529:                #endif  WRITE_DMA_COMMAND_TWICE
        !           530:                
        !           531:                /*
        !           532:                 * Unfortunately, we have to poll for this one. No interrupt.
        !           533:                 * FIXME - documentation is unclear on this. 6.7.6, the 
        !           534:                 * description of dmaStatus, says DS_BLAST_COMPLETE is only 
        !           535:                 * complete for "SCSI Disconnect and Reselect Operation".
        !           536:                 * That doesn't make a whole lot of sense to me...
        !           537:                 */
        !           538:                for(tries=0; tries<500; tries++) {
        !           539:                        status = READ_REGL(dmaStatus);
        !           540:                        if(status & DS_BLAST_COMPLETE) {
        !           541:                                break;
        !           542:                        }
        !           543:                        IODelay(100);
        !           544:                }
        !           545:                
        !           546:                ddm_dma("DMA blast : tries = %d fifoDepth = %d\n", 
        !           547:                        tries, fifoDepth, 3,4,5);
        !           548:        }
        !           549:        
        !           550:        /*
        !           551:         * Obtain number of bytes transferred. 
        !           552:         */
        !           553:        bytesXfrd = activeCmd->currentByteCount - 
        !           554:                (scsiXfrCnt + fifoDepth);
        !           555:        ddm_chip("dmaTerminate: currentByteCount 0x%x, bytesXfrd 0x%x\n",
        !           556:                activeCmd->currentByteCount, bytesXfrd, 3,4,5);
        !           557: #if    0
        !           558:        {
        !           559:        unsigned char *vp = activeCmd->buffer;
        !           560:        
        !           561:        ddm_init("ddmPhys = %02x %02x %02x %02x %02x\n",
        !           562:                ddmPhys[0], ddmPhys[1], ddmPhys[2], ddmPhys[3], ddmPhys[4]);
        !           563:        ddm_init("          %02x %02x %02x %02x %02x\n",
        !           564:                ddmPhys[5], ddmPhys[6], ddmPhys[7], ddmPhys[8], ddmPhys[9]);
        !           565:        ddm_init("virt    = %02x %02x %02x %02x %02x\n",
        !           566:                vp[0], vp[1], vp[2], vp[3], vp[4]);
        !           567:        ddm_init("          %02x %02x %02x %02x %02x\n",
        !           568:                vp[5], vp[6], vp[7], vp[8], vp[9]);
        !           569:        }
        !           570: #endif 0
        !           571:        [self dmaIdle];
        !           572:        return bytesXfrd;
        !           573: }
        !           574: 
        !           575: @end
        !           576: 
        !           577: #if    TEST_DEBUG
        !           578: 
        !           579: /*
        !           580:  * Do some simple I/O before IODisk starts probing us.
        !           581:  */
        !           582: int    loopTest = 0;
        !           583: int    target = 0;
        !           584: 
        !           585: #define DO_INIT_SLEEP  0
        !           586: #define DO_TUR         1
        !           587: #define DO_READ                1
        !           588: #define TEST_READ_SIZE 1       // in sectors
        !           589: #define DO_TEST_ALIGN  0
        !           590: #define TEST_DISCONNECT        1
        !           591: 
        !           592: static void testDebug(id driver)
        !           593: {
        !           594:        IOSCSIRequest   scsiReq;
        !           595:        sc_status_t     srtn;
        !           596:        unsigned char   *rbuf;
        !           597:        int             block = 100000;
        !           598:        
        !           599:        ddm_init("testDebug\n", 1,2,3,4,5);
        !           600:        if(DO_INIT_SLEEP) {
        !           601:                IOLog("Sleeping for 10 seconds for DDM view\n");
        !           602:                IOSleep(10000);
        !           603:        }
        !           604:        if(DO_READ) {
        !           605:                if(DO_TEST_ALIGN) {
        !           606:                        rbuf = IOMallocLow(TEST_READ_SIZE * 512);
        !           607:                        if(rbuf == NULL) {
        !           608:                                IOLog("IOMallocLow returned NULL!\n");
        !           609:                                rbuf = IOMalloc(TEST_READ_SIZE * 512);
        !           610:                        }
        !           611:                }
        !           612:                else {
        !           613:                        rbuf = IOMalloc(TEST_READ_SIZE * 512);
        !           614:                }
        !           615:        }
        !           616:        do {
        !           617:                if(DO_TUR) {
        !           618:                        bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           619:                        scsiReq.target = target;
        !           620:                        scsiReq.cmdQueueDisable = 1;
        !           621:                
        !           622:                        /* 
        !           623:                         * cdb = all zeroes = test unit ready 
        !           624:                         */
        !           625:                        scsiReq.timeoutLength = 4;
        !           626:                        srtn = [driver executeRequest:&scsiReq
        !           627:                                buffer:NULL
        !           628:                                client:(vm_task_t)0];
        !           629:                        IOLog("testDebug: TUR result = %s\n",
        !           630:                                IOFindNameForValue(scsiReq.driverStatus, 
        !           631:                                        IOScStatusStrings));
        !           632:                }
        !           633:                
        !           634:                if(DO_READ) {
        !           635:                        cdb_6_t *cdbp = &scsiReq.cdb.cdb_c6;
        !           636:                        unsigned i;
        !           637: 
        !           638:                        bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           639:                        scsiReq.target = target;
        !           640:                        scsiReq.cmdQueueDisable = 1;
        !           641:                        scsiReq.disconnect = TEST_DISCONNECT;
        !           642:                        for(i=0; i<(TEST_READ_SIZE * 512); i++) {
        !           643:                                rbuf[i] = i;
        !           644:                        }
        !           645:                        cdbp->c6_opcode = 8;
        !           646:                        cdbp->c6_len = TEST_READ_SIZE;
        !           647:                        cdbp->c6_lba0 = block;
        !           648:                        /*
        !           649:                         * Force a disconnect eventually 
        !           650:                         */
        !           651:                        if(block == 0) {
        !           652:                                block = 100000; 
        !           653:                        }
        !           654:                        else {
        !           655:                                block = 0;
        !           656:                        }
        !           657:                        scsiReq.maxTransfer = TEST_READ_SIZE * 512;
        !           658:                        scsiReq.read = YES;
        !           659:                        scsiReq.timeoutLength = 10;
        !           660:                        srtn = [driver executeRequest:&scsiReq
        !           661:                                buffer:rbuf
        !           662:                                client:IOVmTaskSelf()];
        !           663:                        if(scsiReq.driverStatus == 0) {
        !           664:                                ddm_init("rbuf = %02x %02x %02x %02x %02x\n",
        !           665:                                   rbuf[0],rbuf[1],rbuf[2],rbuf[3],rbuf[4]);
        !           666:                                ddm_init("       %02x %02x %02x %02x %02x\n",
        !           667:                                   rbuf[5],rbuf[6],rbuf[7],rbuf[8],rbuf[9]);
        !           668:                        }
        !           669:                        IOLog("testDebug: Read result = %s\n",
        !           670:                                IOFindNameForValue(scsiReq.driverStatus, 
        !           671:                                        IOScStatusStrings));
        !           672:                }
        !           673:                IOSleep(5000);
        !           674:        } while(loopTest);
        !           675:        
        !           676: }
        !           677: 
        !           678: #endif TEST_DEBUG
        !           679: 
        !           680: #if    TEST_IPL_BUG
        !           681: 
        !           682: #define IPL_TEST_LOOPS 1000000         // # of loops
        !           683: #define IPL_TEST_TIME  0               // us delay per loop
        !           684: 
        !           685: static void testIplBug() {
        !           686:        int loopNum;
        !           687:        ns_time_t curTime, lastTime;
        !           688:        unsigned usTime;
        !           689:        
        !           690:        IOGetTimestamp(&lastTime);
        !           691:        for(loopNum=0; loopNum<IPL_TEST_LOOPS; loopNum++) {
        !           692:                if(IPL_TEST_TIME) {
        !           693:                        IODelay(IPL_TEST_TIME);
        !           694:                }
        !           695:                IOGetTimestamp(&curTime);
        !           696:                usTime = (unsigned)((curTime - lastTime) / 1000ULL);
        !           697:                if(usTime > 1000) {
        !           698:                        ddm_intr("usTime %d loopNum %d curTime 0x%x lastTime "
        !           699:                                "0x%x\n",
        !           700:                                usTime, loopNum,
        !           701:                                (unsigned)(curTime & 0xffffffffULL),
        !           702:                                (unsigned)(lastTime & 0xffffffffULL), 5);
        !           703:                }
        !           704:                lastTime = curTime;
        !           705:                
        !           706:        }
        !           707:        ddm_intr("testIplBug complete; IPL_TEST_TIME %d\n", IPL_TEST_TIME,
        !           708:                2,3,4,5);
        !           709:                
        !           710:        /*
        !           711:         * Calibrate the IODelay call...
        !           712:         *
        !           713:        for(loopNum=0; loopNum<500; loopNum++) {
        !           714:                IODelay(IPL_TEST_TIME);
        !           715:                ddm_intr("IODelay(%d) calibration\n", IPL_TEST_TIME, 2,3,4,5);
        !           716:        }
        !           717:        */
        !           718: }
        !           719: 
        !           720: #endif TEST_IPL_BUG

unix.superglobalmegacorp.com

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