Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Apple96HWPrivate.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /**
        !            26:  * Copyright (c) 1994-1996 NeXT Software, Inc.  All rights reserved. 
        !            27:  * Copyright 1997 Apple Computer Inc. All Rights Reserved.
        !            28:  * @author  Martin Minow    mailto:[email protected]
        !            29:  * @revision   1997.02.13  Initial conversion from AMDPCSCSIDriver sources.
        !            30:  *
        !            31:  * Apple96PCISCSI.m - Architecture-specific methods for Apple96 SCSI driver.
        !            32:  *
        !            33:  * Edit History
        !            34:  * 1997.02.13  MM              Initial conversion from AMDPCSCSIDriver sources. 
        !            35:  * 1997.07.31  MM              Radar 1670762: Correct transfer length for > 64K transfers.
        !            36:  *                                             rewrote hardwareGetNextContiguousPhysicalTransferRange.
        !            37:  *                                             This no longer combines adjacent physical pages, which
        !            38:  *                                             greatly simplifies hardwareInitializeRequestCCL (which was
        !            39:  *                                             also rewritten). Remove hard-wired logical page size values.
        !            40:  */
        !            41: #import "Apple96SCSI.h"
        !            42: #import <driverkit/generalFuncs.h>
        !            43: #import <driverkit/kernelDriver.h>
        !            44: #import        <driverkit/align.h>
        !            45: #import <kernserv/prototypes.h>
        !            46: #import <mach/kern_return.h>
        !            47: #import <mach/mach_interface.h>
        !            48: #import "Apple96SCSIPrivate.h"
        !            49: #import "Apple96HWPrivate.h"
        !            50: #import "Apple96CurioDBDMA.h"
        !            51: #import "Apple96CurioPrivate.h"
        !            52: #import "bringup.h"
        !            53: #import "Apple96Curio.h"
        !            54: #import "MacSCSICommand.h"
        !            55: /* bzero is defined in string.h */
        !            56: #import <string.h>
        !            57: 
        !            58: enum {
        !            59:        kCURIORegisterBase      = 0,
        !            60:        kDBDMARegisterBase      = 1
        !            61: };
        !            62: 
        !            63: /**
        !            64:  * These are the hardware-specific methods.
        !            65:  */
        !            66: @implementation Apple96_SCSI(HardwarePrivate)
        !            67: 
        !            68: /**
        !            69:  * Fetch the device's bus address and allocate one page
        !            70:  * of memory for the channel command. (Strictly speaking, we don't
        !            71:  * need an entire page, but we can use the rest of the page for
        !            72:  * a permanent status log).
        !            73:  *
        !            74:  * @param      deviceDescription       Specify the device to initialize.
        !            75:  * @return     IO_R_SUCCESS if successful, else an error status.
        !            76:  */
        !            77: - (IOReturn) hardwareAllocateHardwareAndChannelMemory
        !            78:                                                : deviceDescription
        !            79: {
        !            80:                IOReturn                        ioReturn = IO_R_SUCCESS;
        !            81:                enum {
        !            82:                        kCurioRegisterBase      = 0,
        !            83:                        kDBDMARegisterBase      = 1,
        !            84:                        kNumberRegisters        = 2
        !            85:                };
        !            86:                                
        !            87:                ENTRY("Hal hardwareAllocateHardwareAndChannelMemory");
        !            88:                gSCSIPhysicalAddress    = 0;
        !            89:                gSCSIRegisterLength             = 0;
        !            90:                gSCSILogicalAddress             = NULL;
        !            91:                gDBDMAPhysicalAddress   = 0;
        !            92:                gDBDMARegisterLength    = 0;
        !            93:                gDBDMALogicalAddress    = NULL;
        !            94:                /*
        !            95:                 * Set the default selection timeout to the MESH value (10 msec units).
        !            96:                 */
        !            97:        //      gSelectionTimeout               = 250 / 10;
        !            98:                /*
        !            99:                 * Retrieve the system-wide logical page size and define a mask that
        !           100:                 * contains only the low-order bits. Part of Radar 1670762.
        !           101:                 */
        !           102:                gPageSize                               = page_size;
        !           103:                gPageMask                               = gPageSize - 1;
        !           104:                /*
        !           105:                 * Allocate a page of wired-down memory in the kernel. Although
        !           106:                 * Driver Kit provides a memory allocator, IOMalloc, it does
        !           107:                 * not guarantee page alignment. Thus, we call the Mach kernel
        !           108:                 * routine. According to the description of kalloc(), 4096 is
        !           109:                 * the smallest amount of memory we can allocate. The channel
        !           110:                 * command area will fit into the start of this area and the
        !           111:                 * autosense area will be placed at the end.
        !           112:                 */
        !           113:                gChannelCommandAreaSize = gPageSize;
        !           114:                gChannelCommandArea = (DBDMADescriptor *) kalloc(gChannelCommandAreaSize);
        !           115:                if (gChannelCommandArea == NULL) {
        !           116:            IOLog("%s: Cannot allocate channel command area %d bytes, fatal.\n",
        !           117:                                [self name],
        !           118:                                gChannelCommandAreaSize
        !           119:                        );
        !           120:                        ioReturn = IO_R_NO_MEMORY;
        !           121:                }
        !           122:                if (ioReturn == IO_R_SUCCESS) {
        !           123:                        if (IOIsAligned(gChannelCommandArea, gPageSize) == 0) {
        !           124:                IOLog("%s: Command area at %08x is not page-aligned.\n",
        !           125:                                        [self name],
        !           126:                                        (UInt32) gChannelCommandArea
        !           127:                                );
        !           128:                                ioReturn = IO_R_NO_MEMORY;
        !           129:                        }
        !           130:                }
        !           131:                if (ioReturn == IO_R_SUCCESS) {
        !           132: 
        !           133:                        /*
        !           134:                         * Curio-specific: use the high-end of the descriptor area for
        !           135:                         * the bit bucket and autosense buffer.
        !           136:                         */
        !           137:                        UInt32                  autosenseSize;
        !           138:                        
        !           139:                        autosenseSize = kMaxAutosenseByteCount;
        !           140:                        gAutosenseArea = (esense_reply_t *)
        !           141:                                (((UInt32) gChannelCommandArea)
        !           142:                                + gChannelCommandAreaSize
        !           143:                                - autosenseSize);
        !           144:                        /*
        !           145:                         * Determine the number of DBDMA descriptors that fit in
        !           146:                         * the channel command area.
        !           147:                         */
        !           148:                        gDBDMADescriptorMax = (gChannelCommandAreaSize - autosenseSize)
        !           149:                                                                / sizeof (DBDMADescriptor);
        !           150:                        /*
        !           151:                         * Fetch the logical and physical addresses for the
        !           152:                         * Curio and DBDMA chips.
        !           153:                         */
        !           154: #if 0
        !           155:            do {
        !           156:                IORange     *memoryRangeList;
        !           157:                UInt32      numMemoryRanges;
        !           158:                int     i;
        !           159: 
        !           160:                        memoryRangeList         = [deviceDescription memoryRangeList];
        !           161:                        numMemoryRanges         = [deviceDescription numMemoryRanges];
        !           162:                        for (i = 0; i < numMemoryRanges; i++) {
        !           163:                    ddmDMA("%s: memory range[%d] %08x (%d)\n",
        !           164:                                        [self name],
        !           165:                                        i,
        !           166:                                        memoryRangeList[i].start,
        !           167:                                        memoryRangeList[i].size
        !           168:                                );
        !           169:                        }
        !           170:                        if (numMemoryRanges != kNumberRegisters) {
        !           171:                    ddmDMA("%s: Expect %d memory ranges, got %d. Fatal.\n",
        !           172:                                        [self name],
        !           173:                                        kNumberRegisters,
        !           174:                                        numMemoryRanges
        !           175:                                );
        !           176:                                ioReturn = IO_R_INVALID;        /* This "can't happen"  */
        !           177:                        }
        !           178:            } while (0);
        !           179: #endif
        !           180:                }
        !           181: #if 0
        !           182:                if (ioReturn == IO_R_SUCCESS) {         
        !           183:                        /*
        !           184:                         * We know that the first range describes the SCSI chip,
        !           185:                         * and the second range describes the DBDMA chip.
        !           186:                         */
        !           187:            gSCSIPhysicalAddress    = (PhysicalAddress) memoryRangeList[kCURIORegisterBase].start;
        !           188:                        gSCSIRegisterLength             = memoryRangeList[kCURIORegisterBase].size;
        !           189:            gDBDMAPhysicalAddress   = (PhysicalAddress) memoryRangeList[kDBDMARegisterBase].start;
        !           190:            gDBDMARegisterLength    = memoryRangeList[kDBDMARegisterBase].size;
        !           191:                        /*
        !           192:                         * Weave together the logical and physical addresses.
        !           193:                         * First, map the SCSI and DBDMA chips into our address space.
        !           194:                         */
        !           195:                        ioReturn = IOMapPhysicalIntoIOTask(
        !           196:                                                (UInt32) gSCSIPhysicalAddress,
        !           197:                                                gSCSIRegisterLength,
        !           198:                                                (vm_offset_t *) &gSCSILogicalAddress
        !           199:                                        );
        !           200:                        if (ioReturn != IO_R_SUCCESS) {
        !           201:                ddmDMA("%s: Mapping SCSI chip at %08x [%d] to virtual address:"
        !           202:                                        " error %d (%s), fatal.\n",
        !           203:                                        [self name],
        !           204:                                        gSCSIPhysicalAddress,
        !           205:                                        gSCSIRegisterLength,
        !           206:                                        ioReturn,
        !           207:                                        [self stringFromReturn:ioReturn]
        !           208:                                );
        !           209:                        }
        !           210:                }
        !           211:                if (ioReturn == IO_R_SUCCESS) {         
        !           212:                        ioReturn = IOMapPhysicalIntoIOTask(
        !           213:                                                (UInt32) gDBDMAPhysicalAddress,
        !           214:                                                gDBDMARegisterLength,
        !           215:                                                (vm_offset_t *) &gDBDMALogicalAddress
        !           216:                                        );
        !           217:                        if (ioReturn != IO_R_SUCCESS) {
        !           218:                ddmDMA("%s: Mapping DBDMA at %08x [%d] to virtual address:"
        !           219:                                        " error %d (%s), fatal.\n",
        !           220:                                        [self name],
        !           221:                                        gDBDMAPhysicalAddress,
        !           222:                                        gDBDMARegisterLength,
        !           223:                                        ioReturn,
        !           224:                                        [self stringFromReturn:ioReturn]
        !           225:                                );
        !           226:                        }
        !           227:                }
        !           228: #else
        !           229:                /*
        !           230:                 * Temp (?) Use hard-wired addresses until the registry is complete.
        !           231:                 */
        !           232:                if (ioReturn == IO_R_SUCCESS) {         
        !           233:            gSCSILogicalAddress     = (UInt8 *) PCI_ASC_BASE_PHYS;
        !           234:            gSCSIPhysicalAddress    = (PhysicalAddress) PCI_ASC_BASE_PHYS;
        !           235:            gSCSIRegisterLength = 0x100;
        !           236:            gDBDMALogicalAddress    = (DBDMAChannelRegisters *) PCI_DMA_BASE_PHYS;
        !           237:            gDBDMAPhysicalAddress   = (PhysicalAddress) PCI_DMA_BASE_PHYS;
        !           238:            gDBDMARegisterLength    = 0x20;
        !           239:                }
        !           240: #endif
        !           241:                if (ioReturn == IO_R_SUCCESS) {         
        !           242:                        /*
        !           243:                         * Ensure that the addresses are valid.
        !           244:                         */
        !           245: #if 0 /* probe_rb is not present (yet?) */
        !           246:                        ASSERT(probe_rb((UInt8 *) gSCSILogicalAddress) == 0);
        !           247:                        ASSERT(probe_rb((UInt8 *) gDBDMALogicalAddress) == 0);
        !           248: #endif
        !           249:                        /*
        !           250:                         * Get the physical address corresponding the DBDMA channel area.
        !           251:                         */
        !           252:                        ioReturn = IOPhysicalFromVirtual(
        !           253:                                                IOVmTaskSelf(),
        !           254:                                                (vm_offset_t) gChannelCommandArea,
        !           255:                                                (vm_offset_t *) &gDBDMAChannelAddress
        !           256:                                        );
        !           257:                        if (ioReturn != IO_R_SUCCESS) {
        !           258:                IOLog("%s: Mapping channel at %08x to physical address: error %d (%s), fatal.\n",
        !           259:                                        [self name],
        !           260:                                        (UInt32) gChannelCommandArea,
        !           261:                                        ioReturn,
        !           262:                                        [self stringFromReturn:ioReturn]
        !           263:                                );
        !           264:                        }
        !           265:                }
        !           266:                if (ioReturn == IO_R_SUCCESS) {
        !           267:                        gAutosenseAddress = gDBDMAChannelAddress
        !           268:                                + (((UInt32) gAutosenseArea) - ((UInt32) gChannelCommandArea));
        !           269:                        [self initializeChannelProgram];
        !           270:                }
        !           271:                /*
        !           272:                 * What do we do on failure? Should we try to deallocate the stuff
        !           273:                 * we created, or will the system do this for us?
        !           274:                 */
        !           275:                RESULT(ioReturn);
        !           276:                return (ioReturn);
        !           277: }
        !           278: 
        !           279: /**
        !           280:  * Perform one-time-only channel command program initialization.
        !           281:  */
        !           282: - (void) initializeChannelProgram
        !           283: {
        !           284:                ENTRY("Hic initializeChanelProgram");
        !           285:                /*
        !           286:                 * Set the interrupt, branch, and wait DBDMA registers.
        !           287:                 * Caution: the following MESH interrupt register bits are
        !           288:                 * reverse polarity and are in a different position.
        !           289:                 * The pattern is: 0x00MM00VV, where MM is a mask byte
        !           290:                 * and VV is a value byte to match.
        !           291:                 *      0x80    means NO errors                 (kMeshIntrError)
        !           292:                 *      0x40    means NO exceptions             (kMeshIntrException)
        !           293:                 *      0x20    means NO command done   (kMeshIntrCmdDone)
        !           294:                 *      Branch Select is used with BRANCH_FALSE
        !           295:                 */
        !           296:                DBDMASetInterruptSelect(0x00000000);    /* Never let DBDMA interrupt    */
        !           297:                DBDMASetWaitSelect(0x00200020);                 /* Wait until command done              */
        !           298:                DBDMASetBranchSelect(0x00000000);               /* Never branch on error                */
        !           299:                EXIT();
        !           300: }
        !           301: 
        !           302: /**
        !           303:  * When a (legitimate) data phase starts, this method is called to configure
        !           304:  * the DBDMA Channel Command list. Autosense is simple (as we "cannot" be
        !           305:  * called more than once), while ordinary data transfers are arbitrarily complex.
        !           306:  */
        !           307: - (IOReturn) hardwareInitializeCCL
        !           308: {
        !           309:                IOReturn                        ioReturn;
        !           310:                
        !           311:                ENTRY("Hcc hardwareInitializeCCL");
        !           312:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           313:                /**
        !           314:                 * First, make sure that the DBDMA chip is idle.
        !           315:                 */
        !           316:        DBDMAreset();
        !           317:        DBDMAspinUntilIdle();
        !           318:                if (gActiveCommand->flagIsAutosense) {
        !           319:                        UInt32                          actualAutosenseTransferLength;
        !           320:                        /*
        !           321:                         * This should be provided by the client (and checked that it is
        !           322:                         * less than or equal to kMaxAutosenseByteCount). Note that this
        !           323:                         * sequence is duplicated in Apple96Curio.m.
        !           324:                         */
        !           325:                        actualAutosenseTransferLength = sizeof (esense_reply_t);
        !           326:                        ASSERT(actualAutosenseTransferLength <= kMaxAutosenseByteCount);
        !           327:                        ASSERT(actualAutosenseTransferLength <= 255);
        !           328:                        bzero(gAutosenseArea, actualAutosenseTransferLength);
        !           329:                        MakeCCDescriptor(
        !           330:                                &gChannelCommandArea[0],
        !           331:                                INPUT_LAST | actualAutosenseTransferLength,
        !           332:                                (UInt32) gAutosenseAddress
        !           333:                        );
        !           334:                        MakeCCDescriptor(&gChannelCommandArea[1], STOP_CMD, 0);
        !           335:                        flush_cache_v((vm_offset_t) gChannelCommandArea, sizeof (DBDMADescriptor) * 2);
        !           336:                        gActiveCommand->thisTransferLength = actualAutosenseTransferLength;
        !           337:                        ioReturn = IO_R_SUCCESS;
        !           338:                }
        !           339:                else {
        !           340:                        ioReturn = [self hardwareInitializeRequestCCL];
        !           341:                }
        !           342:                RESULT(ioReturn);
        !           343:                return (ioReturn);
        !           344: }
        !           345: 
        !           346: /**
        !           347:  * Initialize the data transfer channel command list for a normal SCSI command.
        !           348:  * This is not an optimal implementation, but it simplifies maintaining a
        !           349:  * common code base with the NuBus Curio/AMIC hardware interface.
        !           350:  * Note that the last DBDMA command must be INPUT_LAST or OUTPUT_LAST to handle
        !           351:  * synchronous transfer odd-byte disconnect. 
        !           352:  *
        !           353:  * Significantly revised for Radar 1670762.
        !           354:  */
        !           355: - (IOReturn) hardwareInitializeRequestCCL
        !           356: {
        !           357:                CommandBuffer           *cmdBuf;
        !           358:                IOSCSIRequest           *scsiReq;
        !           359:        DBDMADescriptor     *descriptorPtr;     /* -> the current data descriptor   */
        !           360:        DBDMADescriptor     *descriptorMax;     /* -> beyond the last data descr.   */
        !           361:                IOReturn                        ioReturn = IO_R_SUCCESS;
        !           362:                UInt32                          dbdmaOp;                        /* Opcode for DBDMA request                     */
        !           363:        unsigned int    rangeByteCount;
        !           364:        unsigned int    actualRanges;
        !           365:        unsigned int    i;
        !           366: #define kMaxPhysicalRange   16
        !           367:        PhysicalRange       range[kMaxPhysicalRange];
        !           368:                
        !           369:                ENTRY("Hir hardwareInitializeRequestCCL");
        !           370:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           371:                cmdBuf = gActiveCommand;
        !           372:                scsiReq = cmdBuf->scsiReq;
        !           373:                ASSERT(scsiReq->target == gCurrentTarget && scsiReq->lun == gCurrentLUN);
        !           374:                /*
        !           375:                 * Select the correct DBDMA command for this command.
        !           376:                 */
        !           377:                if (scsiReq->read) {
        !           378:                        dbdmaOp                         = INPUT_MORE;
        !           379:                }
        !           380:                else {
        !           381:                        dbdmaOp                         = OUTPUT_MORE;
        !           382:                }
        !           383:                /*
        !           384:                 * How many descriptors can we store (need some slop for the terminator commands).
        !           385:                 * Get a pointer to the first free descriptor and the total number of bytes left
        !           386:                 * to transfer in this I/O request.
        !           387:                 */
        !           388:                descriptorPtr                   = gChannelCommandArea;
        !           389:                descriptorMax                   = &descriptorPtr[gDBDMADescriptorMax];
        !           390:                /*
        !           391:                 * cmdBuf->thisTransferLength will contain the actual number of bytes we
        !           392:                 * intend to transfer in this DMA request, which is needed when DMA completes
        !           393:                 * to recover the residual transfer length.
        !           394:                 */
        !           395:        cmdBuf->thisTransferLength  = 0;
        !           396:        ddmDMA("Req CCL, start %8d, max size %8d\n",
        !           397:                                cmdBuf->currentDataIndex,
        !           398:                                scsiReq->maxTransfer - cmdBuf->currentDataIndex,
        !           399:                                3, 4, 5
        !           400:                        );
        !           401: /* + Radar xxxxxx -- Use IOMemoryDescriptors */
        !           402:        while (descriptorPtr < descriptorMax
        !           403:            && cmdBuf->thisTransferLength < kMaxDMATransfer) {
        !           404:            rangeByteCount = [cmdBuf->mem getPhysicalRanges
        !           405:                                    : kMaxPhysicalRange
        !           406:                    maxByteCount    : (kMaxDMATransfer - cmdBuf->thisTransferLength)
        !           407:                    newPosition     : NULL
        !           408:                    actualRanges    : &actualRanges
        !           409:                    physicalRanges  : range
        !           410:                ];
        !           411: #if 0
        !           412:            IOLog("rangeByteCount %d, actualRanges %d, range[0] = %08x, %d\n",
        !           413:                rangeByteCount, actualRanges,
        !           414:                (UInt32) range[0].address,
        !           415:                range[0].length
        !           416:                                        );
        !           417: #endif
        !           418:            if (rangeByteCount == 0) {
        !           419:                break;
        !           420:                                }
        !           421:            for (i = 0; i < actualRanges; i++) {
        !           422: #if 0
        !           423:            IOLog("%d: %08x for %d\n",
        !           424:                i, (UInt32) range[i].address, range[i].length);
        !           425: #endif
        !           426: #if 1
        !           427:            if (range[i].length == 0) {
        !           428:                IOLog("%d: %08x for %d\n",
        !           429:                i, (UInt32) range[i].address, range[i].length);
        !           430:                [self logIOMemoryDescriptor : "Bogus length"];
        !           431:                MakeCCDescriptor(descriptorPtr + 1, STOP_CMD, 0);
        !           432:                [self logChannelCommandArea : "Bogus length"];
        !           433:                IOPanic("Bogus length\n");
        !           434:                        }
        !           435: #endif
        !           436:                MakeCCDescriptor(descriptorPtr,
        !           437:                    (dbdmaOp | range[i].length),
        !           438:                    (unsigned int) range[i].address
        !           439:                                );
        !           440:            descriptorPtr++;
        !           441:                        }
        !           442:            cmdBuf->thisTransferLength += rangeByteCount;
        !           443:                        }
        !           444: /* - Radar xxxxxx -- Use IOMemoryDescriptors */
        !           445:                if (descriptorPtr > gChannelCommandArea) {
        !           446:                        /*
        !           447:                         * We stored at least one descriptor. Change the last one so it
        !           448:                         * is an INPUT_LAST or OUTPUT_LAST.
        !           449:                         */
        !           450:                        SetCCOperation(
        !           451:                                &descriptorPtr[-1],
        !           452:                                GetCCOperation(&descriptorPtr[-1]) ^ OUTPUT_LAST
        !           453:                        );
        !           454:                } /* Set "last operation" bit in the command */
        !           455:                MakeCCDescriptor(descriptorPtr, STOP_CMD, 0);
        !           456:                descriptorPtr++;
        !           457:                ASSERT(descriptorPtr < &gChannelCommandArea[gDBDMADescriptorMax]);
        !           458:                flush_cache_v(
        !           459:                        (vm_offset_t) gChannelCommandArea,
        !           460:                        ((UInt32) descriptorPtr) - ((UInt32) gChannelCommandArea)
        !           461:                );
        !           462: #if 0  // ddmDMA
        !           463:        IOLog("DMA setup, %d descriptors: thisTransferLength %d\n",
        !           464:                        descriptorPtr - gChannelCommandArea,
        !           465:                        cmdBuf->thisTransferLength,
        !           466:                        3, 4, 5
        !           467:                );
        !           468: #endif
        !           469:                RESULT(ioReturn);
        !           470:                return (ioReturn);
        !           471: }
        !           472: 
        !           473: 
        !           474: /**
        !           475:  * Start a request after [self hardwareStart] has figured out what to do.
        !           476:  */
        !           477: - (void)    hardwareStartSCSIRequest
        !           478: {
        !           479:                register CommandBuffer  *cmdBuf;
        !           480:                IOSCSIRequest                   *scsiReq;
        !           481:                UInt8                                   selectCmd;
        !           482: 
        !           483:                ENTRY("Hsr hardwareStartSCSIRequest");
        !           484:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           485:                cmdBuf                                  = gActiveCommand;
        !           486:                scsiReq                                 = cmdBuf->scsiReq;
        !           487:                ASSERT(scsiReq->target == gCurrentTarget && scsiReq->lun == gCurrentLUN);
        !           488:                /*
        !           489:                 * Flush the fifo, then load synchronous registers and the target bus ID
        !           490:                 */
        !           491:        CURIOflushFifo();
        !           492:        CURIOsetDestinationID(scsiReq->target);
        !           493:                /*
        !           494:                 * Put the contents of the message buffer into the fifo. The Curio makes this
        !           495:                 * slightly messy. The command depends on the number of message bytes. The
        !           496:                 * "select ATN and stop" case only occurs when we negotiate synchronous transfers.
        !           497:                 */
        !           498:                switch (gMsgOutPtr - gMsgPutPtr) {
        !           499:                case 0:                         /* Select, no ATN, send CDB             */
        !           500:                        gLastMsgOut[0] = gLastMsgOut[1] = kScsiMsgNop;
        !           501:                        selectCmd = cSlctNoAtn;
        !           502:                        break;                                                  
        !           503:        case 1:                 /* Select, ATN, 1 Msg, send CDB */
        !           504:                        gLastMsgOut[0] = gMsgPutPtr[0];
        !           505:                        gLastMsgOut[1] = kScsiMsgNop;
        !           506:                        selectCmd = cSlctAtn;
        !           507:                        break;
        !           508:        case 3:                 /* Select, ATN, 3 Msg, send CDB */
        !           509:                        gLastMsgOut[0] = gMsgPutPtr[0];
        !           510:                        gLastMsgOut[1] = gMsgPutPtr[1];
        !           511:                        selectCmd = cSlctAtn3;
        !           512:                        break;
        !           513:                default:                                /* Select, ATN, 1 Msg, stop             */
        !           514:                        gLastMsgOut[0] = gMsgPutPtr[0];
        !           515:                        gLastMsgOut[1] = kScsiMsgNop;
        !           516:                        selectCmd = cSlctAtnStp;
        !           517:                        break;
        !           518:                }
        !           519:                if ((gMsgOutPtr - gMsgPutPtr) > 3
        !           520:                 || (cmdBuf->flagIsAutosense == FALSE
        !           521:                  && (gMsgOutPtr - gMsgPutPtr) + gActiveCommand->cdbLength >= 16)) {
        !           522:            CURIOputByteIntoFifo(*gMsgPutPtr++);
        !           523:                        selectCmd = cSlctAtnStp;
        !           524:                }
        !           525:                else {
        !           526:                        while (gMsgPutPtr < gMsgOutPtr) {
        !           527:                CURIOputByteIntoFifo(*gMsgPutPtr++);
        !           528:                        }
        !           529:                }
        !           530:                if (selectCmd != cSlctAtnStp) {
        !           531:            CURIOputCommandIntoFifo();
        !           532:        }   
        !           533:                /* ** ** **
        !           534:                 * ** ** ** Can a caller override the default timeout?
        !           535:                 * ** ** **
        !           536:                 */
        !           537: //     CURIOsetSelectionTimeout(gSelectionTimeout);
        !           538:                /*
        !           539:                 * Initialize the finite state automaton and start the Curio.
        !           540:                 */
        !           541:                gBusState = SCS_SELECTING;
        !           542:                gCurrentBusPhase = kBusPhaseBusFree;
        !           543:        CURIOsetCommandRegister(selectCmd);
        !           544:                EXIT();
        !           545: }
        !           546: 
        !           547: - (void) clearChannelCommandResults
        !           548: {
        !           549:                ENTRY("Hcc clearChannelCommandResults");
        !           550:                EXIT();
        !           551: }
        !           552: 
        !           553: /**
        !           554:  * Debug log channel command area
        !           555:  */
        !           556: - (void) logChannelCommandArea
        !           557:                        : (const char *) reason
        !           558: {
        !           559: #if DEBUG
        !           560:        DBDMADescriptor     *descriptorPtr;     /* -> the current data descriptor   */
        !           561:        DBDMADescriptor     *descriptorMax;     /* -> beyond the last data descr.   */
        !           562:                UInt32                          operation;
        !           563:                UInt32                          address;
        !           564:                UInt32                          cmdDep;
        !           565:                UInt32                          result;
        !           566:                UInt32                          status;
        !           567:                const char                      *opName;
        !           568:                const char                      *keyName;
        !           569:        const char          *intName    = "";
        !           570:        const char          *branchName = "";
        !           571:        const char          *waitName   = "";
        !           572:                Boolean                         first;
        !           573:                
        !           574:                ENTRY("Dlo logChannelCommandArea");
        !           575:                status = DBDMAGetChannelStatus();
        !           576:                if (reason != NULL) {
        !           577:                        IOLog("%s: *** %s\n", [self name], reason);
        !           578:                }
        !           579:                IOLog("%s: *** DBDMA sts %08x, cmdPtr %08x,"
        !           580:                        " branchSel %08x, byteCount %08x, ccl @ %08x\n",
        !           581:                        [self name],
        !           582:                        status,
        !           583:                        DBDMAGetCommandPtr(),
        !           584:                        (UInt32) DBDMAGetBranchSelect(),
        !           585:                        (UInt32) DBDMAGetWaitSelect(),
        !           586:                        (UInt32) gChannelCommandArea
        !           587:                );
        !           588:                if ((status & 0x00008000) != 0) {
        !           589:                        IOLog("%s: *** status: run\n", [self name]);
        !           590:                }
        !           591:                if ((status & 0x00004000) != 0) {
        !           592:                        IOLog("%s: *** status: pause\n", [self name]);
        !           593:                }
        !           594:                if ((status & 0x00002000) != 0) {
        !           595:                        IOLog("%s: *** status: flush\n", [self name]);
        !           596:                }
        !           597:                if ((status & 0x00001000) != 0) {
        !           598:                        IOLog("%s: *** status: wake\n", [self name]);
        !           599:                }
        !           600:                if ((status & 0x00000800) != 0) {
        !           601:                        IOLog("%s: *** status: dead\n", [self name]);
        !           602:                }
        !           603:                if ((status & 0x00000400) != 0) {
        !           604:                        IOLog("%s: *** status: active\n", [self name]);
        !           605:                }
        !           606:                if ((status & 0x000000100) != 0) {
        !           607:                        IOLog("%s: *** status: bt\n", [self name]);
        !           608:                }
        !           609:                if ((status & 0xFFFF02FF) != 0) {
        !           610:                        IOLog("%s: *** other status set\n", [self name]);
        !           611:                }
        !           612:                descriptorPtr                   = gChannelCommandArea;
        !           613:                descriptorMax                   = &descriptorPtr[gDBDMADescriptorMax];
        !           614:                for (; descriptorPtr < descriptorMax; descriptorPtr++) {
        !           615:                        operation       = GetCCOperation(descriptorPtr);
        !           616:                        address         = GetCCAddress(descriptorPtr);
        !           617:                        cmdDep          = GetCCCmdDep(descriptorPtr);
        !           618:                        result          = GetCCResult(descriptorPtr);
        !           619:            IOLog("%s: *** dma[%2d]: op %08x, addr %08x, cmddep %08x, res %08x\n",
        !           620:                                [self name],
        !           621:                                descriptorPtr - gChannelCommandArea,
        !           622:                                operation,
        !           623:                                address,
        !           624:                                cmdDep,
        !           625:                                result
        !           626:                        );
        !           627:                        switch (operation & kdbdmaCmdMask) {
        !           628:                        case OUTPUT_MORE:               opName = "Output More";         break;
        !           629:                        case OUTPUT_LAST:               opName = "Output Last";         break;
        !           630:                        case INPUT_MORE:                opName = "Input More";          break;
        !           631:                        case INPUT_LAST:                opName = "Input Last";          break;
        !           632:                        case STORE_QUAD:                opName = "Store Quad";          break;
        !           633:                        case LOAD_QUAD:                 opName = "Load Quad";           break;
        !           634:                        case NOP_CMD:                   opName = "NOP";                         break;
        !           635:                        case STOP_CMD:                  opName = "Stop";                        break;
        !           636:                        default:                                opName = "Op Unknown";          break;
        !           637:                        }
        !           638:                        switch (operation & kdbdmaKeyMask) {
        !           639:                        case KEY_STREAM0:               keyName = "Stream 0";           break;
        !           640:                        case KEY_STREAM1:               keyName = "Stream 1";           break;
        !           641:                        case KEY_STREAM2:               keyName = "Stream 2";           break;
        !           642:                        case KEY_STREAM3:               keyName = "Stream 3";           break;
        !           643:                        case KEY_REGS:                  keyName = "Regs";                       break;
        !           644:                        case KEY_SYSTEM:                keyName = "System";                     break;
        !           645:                        case KEY_DEVICE:                keyName = "System";                     break;
        !           646:                        default:                                keyName = "Unknown";            break;
        !           647:                        }
        !           648:                        switch (operation & kdbdmaIMask) {
        !           649:                        case kIntNever:                 intName = "never";                      break;
        !           650:                        case kIntIfTrue:                intName = "if True";            break;
        !           651:                        case kIntIfFalse:               intName = "if False";           break;
        !           652:            case kIntAlways:        intName = "always";         break;
        !           653:                        }
        !           654:                        switch (operation & kdbdmaBMask) {
        !           655:                        case kBranchNever:              branchName = "never";           break;
        !           656:                        case kBranchIfTrue:             branchName = "if True";         break;
        !           657:            case kBranchIfFalse:    branchName = "if False";    break;
        !           658:                        case kBranchAlways:             branchName      = "always";             break;
        !           659:                        }
        !           660:                        switch (operation & kdbdmaWMask) {
        !           661:                        case kWaitNever:                waitName = "never";                     break;
        !           662:                        case kWaitIfTrue:               waitName = "if True";           break;
        !           663:                        case kWaitIfFalse:              waitName = "if False";          break;
        !           664:                        case kWaitAlways:               waitName = "always";            break;
        !           665:                        }
        !           666:                        IOLog("%s: ***    [%2d]: op %s, key %s, int %s, branch %s, wait %s, count %d,"
        !           667:                                " residual %d, status %04x",
        !           668:                                [self name],
        !           669:                                descriptorPtr - gChannelCommandArea,
        !           670:                                opName,
        !           671:                                keyName,
        !           672:                                intName,
        !           673:                                branchName,
        !           674:                                waitName,
        !           675:                                (operation & kdbdmaReqCountMask),
        !           676:                                result & kdbdmaResCountMask,
        !           677:                                (result & kdbdmaXferStatusMask) >> 16
        !           678:                        );
        !           679:                        first = TRUE;
        !           680:                        if ((result & kdbdmaXferStatusMask) == 0) {
        !           681:                                IOLog(" (no status)\n");
        !           682:                        }
        !           683:                        else {
        !           684:                                if ((result & kXferStatusRun) != 0) {
        !           685:                                        IOLog(": Run");
        !           686:                                        result &= ~kXferStatusRun;
        !           687:                                        first = FALSE;
        !           688:                                }
        !           689:                                if ((result & kXferStatusPause) != 0) {
        !           690:                                        IOLog("%s Pause", (first) ? ":" : ",");
        !           691:                                        result &= kXferStatusPause;
        !           692:                                        first = FALSE;
        !           693:                                }
        !           694:                                if ((result & kXferStatusFlush) != 0) {
        !           695:                                        IOLog("%s Flush", (first) ? ":" : ",");
        !           696:                                        result &= kXferStatusFlush;
        !           697:                                        first = FALSE;
        !           698:                                }
        !           699:                                if ((result & kXferStatusWake) != 0) {
        !           700:                                        IOLog("%s Wake", (first) ? ":" : ",");
        !           701:                                        result &= kXferStatusWake;
        !           702:                                        first = FALSE;
        !           703:                                }
        !           704:                                if ((result & kXferStatusDead) != 0) {
        !           705:                                        IOLog("%s Dead", (first) ? ":" : ",");
        !           706:                                        result &= kXferStatusDead;
        !           707:                                        first = FALSE;
        !           708:                                }
        !           709:                                if ((result & kXferStatusActive) != 0) {
        !           710:                                        IOLog("%s Active", (first) ? ":" : ",");
        !           711:                                        result &= kXferStatusActive;
        !           712:                                        first = FALSE;
        !           713:                                }
        !           714:                                if ((result & kXferStatusBt) != 0) {
        !           715:                                        IOLog("%s Branch True", (first) ? ":" : ",");
        !           716:                                        result &= kXferStatusBt;
        !           717:                                        first = FALSE;
        !           718:                                }
        !           719:                                if (result != 0) {
        !           720:                                        IOLog("%s Other", (first) ? ":" : ",");
        !           721:                                }
        !           722:                                IOLog("\n");
        !           723:                        }
        !           724:                        if ((operation & kdbdmaCmdMask) == STOP_CMD || operation == 0) {
        !           725:                                break;
        !           726:                        }
        !           727:                }
        !           728:                EXIT();
        !           729: #endif /* DEBUG */
        !           730: }
        !           731: 
        !           732: - (void)           logIOMemoryDescriptor
        !           733:            : (const char *) info
        !           734: {
        !           735: #if DEBUG
        !           736:     const char *intro  = " \"";
        !           737:     const char *outro  = "\"";
        !           738:     IOMemoryDescriptorState    state;
        !           739: 
        !           740:     if (gActiveCommand != NULL && gActiveCommand->mem != NULL) {
        !           741:        [gActiveCommand->mem state : &state];
        !           742:        if (info == NULL || info[0] == '\0') {
        !           743:        info = intro = outro = "";
        !           744:        }
        !           745:        IOLog("IOMemoryDescriptor%s%s%s: %d offset in %d, %d maxSeg\n",
        !           746:            intro, info, outro,
        !           747:            [gActiveCommand->mem currentOffset],
        !           748:            [gActiveCommand->mem totalByteCount],
        !           749:            [gActiveCommand->mem maxSegmentCount]
        !           750:        );
        !           751:        IOLog("IOMemoryDescriptor%s%s%s: range %d, logical %d in %d, physical %d in %d\n",
        !           752:            intro, info, outro,
        !           753:            state.rangeIndex,
        !           754:            state.logicalOffset,
        !           755:            state.ioRange.size,
        !           756:            state.physicalOffset,
        !           757:            state.physical.length
        !           758:        );
        !           759:     }
        !           760:     else {
        !           761:        IOLog("Null IOMemoryDescriptor\n");
        !           762:     }
        !           763: #endif /* DEBUG */
        !           764: }
        !           765: 
        !           766: 
        !           767: @end /* Apple96_SCSI(HardwarePrivate) */
        !           768: 

unix.superglobalmegacorp.com

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