Annotation of Examples/DriverKit/AMDPCSCSIDriver/AMDPCSCSIDriver_reloc.tproj/AMD_x86.m, revision 1.1.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.