Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Apple96Hardware.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:  * Set tabs every 4 characters.
        !            32:  *
        !            33:  * AppleMeshHardware.m - Architecture-specific methods for Apple96 SCSI driver.
        !            34:  *
        !            35:  * Edit History
        !            36:  * 1997.02.13  MM              Initial conversion from AMDPCSCSIDriver sources. 
        !            37:  */
        !            38: #import "Apple96SCSI.h"
        !            39: #import "Apple96SCSIPrivate.h"
        !            40: #import "Apple96Hardware.h"
        !            41: #import "Apple96HWPrivate.h"
        !            42: #import "Apple96ConfigKeys.h"
        !            43: #import "Apple96Curio.h"
        !            44: #import "Apple96CurioPublic.h"
        !            45: #import "MacSCSICommand.h"
        !            46: #import "bringup.h"
        !            47: #import <driverkit/generalFuncs.h>
        !            48: #import <driverkit/kernelDriver.h>
        !            49: #import        <driverkit/align.h>
        !            50: #import <bsd/dev/scsireg.h>
        !            51: // #import <mach/mach.h>
        !            52: // #import <mach/mach_error.h>
        !            53: #import <mach/kern_return.h>
        !            54: #import <kernserv/prototypes.h>
        !            55: 
        !            56: static int             getConfigParam(
        !            57:        id                  configTable,
        !            58:        const char          *paramName
        !            59:     );
        !            60: static unsigned int    GetSCSICommandLength(
        !            61:        const cdb_t         *cdbPtr,
        !            62:        unsigned int        defaultLength
        !            63:     );
        !            64: 
        !            65: 
        !            66: /**
        !            67:  * These are the hardware-specific methods that are not explicitly
        !            68:  * tied to Mesh and DBDMA.
        !            69:  */
        !            70: 
        !            71: @implementation Apple96_SCSI(Hardware)
        !            72: 
        !            73: /**
        !            74:  * Perform architecture-specific initialization: fetch the device's
        !            75:  * bus address and interrupt port number. Also, allocate one page
        !            76:  * of memory for the channel command. (Strictly speaking, we don't
        !            77:  * need an entire page, but we can use the rest of the page for
        !            78:  * a permanent status log).
        !            79:  *
        !            80:  * @param      deviceDescription       Specify the device to initialize.
        !            81:  * @return     self                    [self free] if failure.
        !            82:  */
        !            83: - hardwareInitialization
        !            84:                : deviceDescription
        !            85: {
        !            86:        IOReturn        ioReturn        = IO_R_SUCCESS;
        !            87:        id              result          = self;
        !            88:        kern_return_t   kernelReturn;
        !            89:        UInt8           lun;
        !            90:        id              configTable;
        !            91:        const char      *configValue;
        !            92:        UInt8           deviceNumber;
        !            93:        UInt8           functionNumber;
        !            94:        UInt8           busNumber;
        !            95:                
        !            96:        ENTRY("Hhi hardwareInitialization");
        !            97:        ddmInit("%s: hardwareInitialization\n",
        !            98:                "Apple96SCSI",
        !            99:                2,3,4,5
        !           100:        );
        !           101:        configTable = [deviceDescription configTable];
        !           102:        ASSERT(configTable != NULL);
        !           103:        configValue = [configTable valueForStringKey: "Bus Type"];
        !           104:        if (configValue == NULL) {
        !           105:            IOLog("%s: No bus type in configuration table\n",
        !           106:                        "Apple96SCSI"
        !           107:                );
        !           108:            ioReturn = IO_R_NO_DEVICE;
        !           109:        }
        !           110:        ddmInit("Bus type: \"%s\"\n", configValue, 2, 3, 4, 5);
        !           111:        if (configValue == NULL || strcmp(configValue, "PPC") != 0) {
        !           112:            IOLog("%s: Unsupported bus type \"%s\" in configuration table\n",
        !           113:                        "Apple96SCSI",
        !           114:                        configValue ? configValue :"null"
        !           115:                );
        !           116:            ioReturn = IO_R_NO_DEVICE;
        !           117:        }
        !           118:        if (ioReturn == IO_R_SUCCESS) {
        !           119: #if 0 // ** ** ** Need correct definition ** ** **
        !           120:            ioReturn = [deviceDescription getPCIDevice
        !           121:                                : &deviceNumber
        !           122:                function        : &functionNumber
        !           123:                bus             : &busNumber];
        !           124: #else
        !           125:            deviceNumber = 00;
        !           126:            functionNumber = 00;
        !           127:            busNumber = 00;
        !           128:            kernelReturn = 0;
        !           129: #endif
        !           130:            if (ioReturn != IO_R_SUCCESS) {
        !           131:                IOLog("%s: Can't get PCI device information: %s\n",
        !           132:                            "Apple96SCSI",
        !           133:                            [self stringFromReturn : ioReturn]
        !           134:                    );
        !           135:            }
        !           136:        }
        !           137:        if (ioReturn == IO_R_SUCCESS) {
        !           138: #if 0
        !           139:            IOLog("%s: Hardware device found at"
        !           140:                        " bus %u, device %u, function %u, interrupt %u\n",
        !           141:                        "Apple96SCSI",
        !           142:                        busNumber,
        !           143:                        deviceNumber,
        !           144:                        functionNumber,
        !           145:                        0
        !           146: //                     [deviceDescription interrupt]
        !           147:            );
        !           148: #endif
        !           149:        }
        !           150:        if (configValue != NULL) {
        !           151:            [configTable freeString : configValue];
        !           152:            configValue = NULL;
        !           153:        }
        !           154:        if (ioReturn == IO_R_SUCCESS) {
        !           155:            ioReturn = [self hardwareAllocateHardwareAndChannelMemory : deviceDescription];
        !           156:        }
        !           157:        if (ioReturn == IO_R_SUCCESS) {
        !           158:            /*
        !           159:             * Initialize gPerTargetData[] and the dbdma channel area.
        !           160:             */
        !           161:            [self initializePerTargetData];
        !           162:            /*
        !           163:             * All of the addresses are established. Check that the hardware
        !           164:             * is present and working.
        !           165:             */
        !           166:            ioReturn = [self hardwareChipSelfTest];
        !           167:        }
        !           168:        if (ioReturn == IO_R_SUCCESS) {
        !           169:            /*
        !           170:             * Tell the superclass to initialize our I/O thread. After this,
        !           171:             * we should be able to execute SCSI requests.
        !           172:             */
        !           173:            if ([super initFromDeviceDescription:deviceDescription] == NULL) {
        !           174:                IOLog("%s: Host Adaptor was not initialized. Fatal\n",
        !           175:                            "Apple96SCSI"
        !           176:                    );
        !           177:                ioReturn = IO_R_NO_DEVICE;
        !           178:            }
        !           179:        }
        !           180:        if (ioReturn == IO_R_SUCCESS) {
        !           181:            ddmInit("Init: I/O thread running\n", 1, 2, 3, 4, 5);
        !           182:            gFlagIOThreadRunning = 1;
        !           183:            /*
        !           184:             * Initialize local variables. Note that activeArray and 
        !           185:             * perTarget arrays are zeroed by objc runtime.
        !           186:             */
        !           187:            queue_init(&gDisconnectedCommandQueue);
        !           188:            queue_init(&gIncomingCommandQueue);
        !           189:            queue_init(&gPendingCommandQueue);
        !           190:            gIncomingCommandLock = [[NXLock alloc] init];
        !           191:            gActiveCommand = NULL;
        !           192:            [self resetStats];
        !           193:            gOptionDisconnectEnable     = ENABLE_DISCONNECT;
        !           194:            gOptionCmdQueueEnable       = ENABLE_TAGGED_QUEUEING;
        !           195:            gNextQueueTag               = QUEUE_TAG_NONTAGGED + 1;
        !           196:            gInitiatorID                = kInitiatorIDDefault;
        !           197:            /*
        !           198:             * Initiator bus ID as a bitmask for selection.
        !           199:             */
        !           200:            gInitiatorIDMask            = (1 << gInitiatorID);
        !           201:            /*
        !           202:             * Reserve the initiator ID for all LUNs.
        !           203:             */
        !           204:            for (lun = 0; lun < SCSI_NLUNS; lun++) {
        !           205:                [self reserveTarget
        !           206:                                        : gInitiatorID 
        !           207:                        lun             : lun
        !           208:                        forOwner        : self
        !           209:                    ];
        !           210:            }
        !           211:            /*
        !           212:             * get tagged command queueing, sync mode, fast mode enables from
        !           213:             * configTable.
        !           214:             */
        !           215: #ifdef CRAP    /* this requires "inspector" support:   */
        !           216:            gOptionCmdQueueEnable = getConfigParam(configTable, CMD_QUEUE_ENABLE);
        !           217: #endif /* CRAP */
        !           218:            /*
        !           219:             * Note: the external bus on PCI Mac's do not support synchronous
        !           220:             * and/or fast modes. This code should be modified to read the
        !           221:             * chip version id and configure sync/fast accordingly.
        !           222:             */
        !           223: #if 0  /* Enable for 8100 internal bus */
        !           224:            gOptionSyncModeEnable = getConfigParam(configTable, SYNC_ENABLE);
        !           225:            gOptionFastModeEnable = getConfigParam(configTable, FAST_ENABLE);
        !           226: #else
        !           227:            gOptionSyncModeEnable = 0;
        !           228:            gOptionFastModeEnable = 0;
        !           229: #endif
        !           230:            gOptionExtendTiming   = getConfigParam(configTable, EXTENDED_TIMING);
        !           231:            gOptionAutoSenseEnable = AUTO_SENSE_ENABLE; // from bringup.h
        !           232:            /*
        !           233:             * Get internal version of interruptPort; set the port queue 
        !           234:             * length to the maximum size. It is not clear if we want
        !           235:             * to do this.
        !           236:             */
        !           237:            gKernelInterruptPort = IOConvertPort(
        !           238:                [self interruptPort],
        !           239:                IO_KernelIOTask,
        !           240:                IO_Kernel
        !           241:            );
        !           242: #if 0 // ** ** ** Need correct header file ** ** **
        !           243:            kernelReturn = port_set_backlog(
        !           244:                task_self(),
        !           245:                [self interruptPort],
        !           246:                PORT_BACKLOG_MAX
        !           247:            );
        !           248:            if (kernelReturn != KERN_SUCCESS) {
        !           249:                IOLog("%s: warning, port_set_backlog error %d (%s)\n",
        !           250:                        [self name],
        !           251:                        kernelReturn,
        !           252:                        mach_error_string(kernelReturn)
        !           253:                    );
        !           254:            }
        !           255: #endif
        !           256:            /*
        !           257:             * Initialize the chip and reset the bus.
        !           258:             */
        !           259:            ioReturn = [self hardwareReset : TRUE       reason : NULL];
        !           260: 
        !           261:        }
        !           262:        if (ioReturn == IO_R_SUCCESS) {
        !           263:            /*
        !           264:             * OK, we're ready to roll.
        !           265:             */
        !           266:            [self enableInterrupt:0];
        !           267: //         [self enableAllInterrupts ];
        !           268:            [self registerDevice];
        !           269:        }
        !           270:        else {
        !           271:            /*
        !           272:             * Do we need to free the locks and similar?
        !           273:             */
        !           274:            [self free];
        !           275:            result = NULL;
        !           276:        }
        !           277:        RESULT(result);
        !           278:        return (result);
        !           279: }
        !           280: 
        !           281: /**
        !           282:  * Initialize sync mode to async for all targets at start and
        !           283:  * after bus reset.
        !           284:  */
        !           285: - (void)    initializePerTargetData
        !           286: {
        !           287:        UInt8               target;
        !           288: 
        !           289:        ENTRY("His initializeTargetSyncMode");
        !           290:        for (target = 0; target < SCSI_NTARGETS; target++) {
        !           291:            [self renegotiateSyncMode : target];
        !           292:            gPerTargetData[ target ].inquiry_7 = 0;
        !           293:        }
        !           294:        EXIT();
        !           295: }
        !           296: 
        !           297: /**
        !           298:  * Initialize the synchronous data transfer state for a target.
        !           299:  */
        !           300: - (void)    renegotiateSyncMode
        !           301:                        : (UInt8) target
        !           302: {
        !           303:        ENTRY("Hrs renegotiateSyncMode");
        !           304:        EXIT();
        !           305: }
        !           306: 
        !           307: /**
        !           308:  * Reusable CURIO init function. This includes a SCSI reset.
        !           309:  * Handling of ioComplete of active and disconnected commands must be done
        !           310:  * elsewhere. Returns IO_R_SUCCESS if successful. This is called
        !           311:  * from a Task thread. It will disable and re-enable interrupts.
        !           312:  * Reason is for error logging.
        !           313:  */
        !           314: - (IOReturn) hardwareReset
        !           315:                    : (Boolean) resetSCSIBus
        !           316:            reason  : (const char *) reason
        !           317: {
        !           318:        ENTRY("HHr hardwareReset");
        !           319:        if (reason != NULL) {
        !           320:            IOLog("%s: Bus Reset (%s)\n",
        !           321:                [self name],
        !           322:                reason
        !           323:            );
        !           324:        }
        !           325:        /*
        !           326:         * First of all, reset the hardware.
        !           327:         */
        !           328:        [self curioHardwareReset : resetSCSIBus     reason : reason];
        !           329:        /*
        !           330:         * Kill all disconnected, pending, and incoming I/O requests.
        !           331:         */
        !           332:        [self abortAllCommands : SR_IOST_RESET];
        !           333:        RESULT(IO_R_SUCCESS);
        !           334:        return (IO_R_SUCCESS);  
        !           335: }
        !           336: 
        !           337: 
        !           338: /*
        !           339:  * Start a SCSI transaction for the specified command. ActiveCmd must be 
        !           340:  * NULL. A return of kHardwareStartRejected indicates that caller may try
        !           341:  * again with another command; kHardwareStartBusy indicates a condition
        !           342:  * other than (activeCmd != NULL) which prevents the processing of the command.
        !           343:  */
        !           344: - (HardwareStartResult) hardwareStart
        !           345:                        : (CommandBuffer *) cmdBuf
        !           346: {   
        !           347:        IOSCSIRequest       *scsiReq;
        !           348:        HardwareStartResult result                      = kHardwareStartOK;
        !           349:        cdb_t                   *cdbp;
        !           350:        Boolean                 okToDisconnect  = gOptionDisconnectEnable;
        !           351: //     Boolean                 okToDisconnect  = TRUE;
        !           352:        Boolean                 okToQueue               = gOptionCmdQueueEnable;
        !           353:        UInt8                   msgByte;
        !           354:        
        !           355:        ENTRY("Hst hardwareStart");
        !           356:        /*
        !           357:         * We do not have a current command here.
        !           358:         */
        !           359:        ASSERT(cmdBuf != NULL && cmdBuf->scsiReq != NULL);
        !           360:        scsiReq = cmdBuf->scsiReq;
        !           361:        cdbp = &scsiReq->cdb;
        !           362:        ddmChip("hardwareStart[%d.%d] cmdBuf = 0x%x opcode %s\n",
        !           363:            scsiReq->target,
        !           364:            scsiReq->lun,
        !           365:            cmdBuf, 
        !           366:            IOFindNameForValue(cdbp->cdb_opcode, IOSCSIOpcodeStrings),
        !           367:            5);
        !           368:        cmdBuf->cdbLength = GetSCSICommandLength(cdbp, scsiReq->cdbLength);
        !           369:        if (cmdBuf->cdbLength == 0) {
        !           370:            /*
        !           371:             * Failure: we can't determine the length of this command.
        !           372:             */
        !           373:            [self ioComplete
        !           374:                                : cmdBuf
        !           375:                finalStatus     : SR_IOST_CMDREJ
        !           376:            ];
        !           377:            ddmChip("hardwareStart rejected: invalid cdb length\n", 1, 2, 3, 4, 5);
        !           378:                    result = kHardwareStartRejected;
        !           379:        }
        !           380:        if (result == kHardwareStartOK) {
        !           381:            /*
        !           382:             * Peek at the control byte (the last byte in the command).
        !           383:             */
        !           384:            msgByte = ((UInt8 *) cdbp)[cmdBuf->cdbLength - 1];
        !           385:            if ((msgByte & CTRL_LINKFLAG) != CTRL_NOLINK) {
        !           386:                /*
        !           387:                 * Failure: we don't support linked commands.
        !           388:                 */
        !           389:                [self ioComplete
        !           390:                                        : cmdBuf
        !           391:                        finalStatus     : SR_IOST_CMDREJ
        !           392:                ];
        !           393:                ddmChip("hardwareStart rejected: linked command\n", 1, 2, 3, 4, 5);
        !           394:                result = kHardwareStartRejected;
        !           395:            }
        !           396:        }
        !           397:        if (result == kHardwareStartOK) {
        !           398:            /*
        !           399:             * Autosense always renegotiates synchronous transfer mode.
        !           400:             * This is necessary as the target might have been reset
        !           401:             * or hit with a power-cycle.
        !           402:             */
        !           403:            if (cmdBuf->flagIsAutosense) {
        !           404:                        [self renegotiateSyncMode : gCurrentTarget];
        !           405:                        okToDisconnect = FALSE;
        !           406:            }
        !           407:            else {
        !           408:                /*
        !           409:                 * This is a real command. Setup the user data
        !           410:                 * pointers and counters and build a SCSI request
        !           411:                 * channel command list.
        !           412:                 *
        !           413:                 * First, peek at the command for some special cases.
        !           414:                 */
        !           415:                cmdBuf->queueTag = QUEUE_TAG_NONTAGGED; /* No tag just yet  */
        !           416:                switch (cdbp->cdb_opcode) {
        !           417:                case kScsiCmdInquiry:
        !           418:                    /*
        !           419:                     * The first command SCSIDisk sends us is an Inquiry
        !           420:                     * command. This never gets retried, so avoid a possible 
        !           421:                     * reject of a command queue tag. Avoid this hack if
        !           422:                     * there are any other commands outstanding for this
        !           423:                     * target/lun.
        !           424:                     */
        !           425:                    if (gActiveArray[scsiReq->target][scsiReq->lun] == 0) {
        !           426:                        scsiReq->cmdQueueDisable = TRUE;
        !           427:                    }
        !           428:                    okToDisconnect = FALSE;
        !           429:                    break;
        !           430:                case kScsiCmdRequestSense:
        !           431:                    /*
        !           432:                     * Always force sync renegotiation on any Request Sense to 
        !           433:                     * catch independent target power cycles.
        !           434:                     * (Synch renegotiation needed should be set after all
        !           435:                     * target-detected errors -- fix needed in MessageIn).
        !           436:                     * Sense is always issued with disconnect disabled to
        !           437:                     * maintain T/L/Q nexus.
        !           438:                     *
        !           439:                     * Watch it: request sense from a client is incompatible
        !           440:                     * with tagged queuing.
        !           441:                     */
        !           442:                    [self renegotiateSyncMode : gCurrentTarget];
        !           443:                    okToDisconnect      = FALSE;
        !           444:                    break;
        !           445:     
        !           446:                case kScsiCmdTestUnitReady:
        !           447:                case kScsiCmdReadCapacity:
        !           448:                    okToDisconnect = FALSE;
        !           449:                    break;
        !           450:                }
        !           451:            }
        !           452: 
        !           453:            if ( scsiReq->disconnect == FALSE )         /* If this req doesn't want */
        !           454:                        okToDisconnect = FALSE;                         /* it, clear disconnect.    */
        !           455: 
        !           456:                okToQueue       &= okToDisconnect
        !           457:                                        && (scsiReq->cmdQueueDisable == FALSE)
        !           458:                                        && (gPerTargetData[ scsiReq->target ].inquiry_7 & 0x02);
        !           459: 
        !           460:            cmdBuf->flagActive              = 0;        /* Init flags for this command  */
        !           461:            /*
        !           462:             * Make sure that the chip is stable before we try to start
        !           463:             * a request.
        !           464:             */
        !           465:            /*
        !           466:             * Currently, the only expected reason we return kHardwareStartBusy
        !           467:             * is if we have a reselect pending.
        !           468:             * ** ** ** I don't think this can happen ** ** **
        !           469:             */
        !           470:            if (gFlagBusBusy) {
        !           471:                queue_enter(&gPendingCommandQueue, cmdBuf, CommandBuffer *, link);
        !           472:                ddmChip("hardwareStart deferred: bus busy\n", 1, 2, 3, 4, 5);
        !           473:                result = kHardwareStartBusy;
        !           474:            }
        !           475:        }
        !           476:        if (result == kHardwareStartOK) {
        !           477:            if (gActiveCommand != NULL) {
        !           478:                /*
        !           479:                 * This should never happen. It ensures that there are
        !           480:                 * no race conditions that reselect us between the time
        !           481:                 * threadExecuteRequest looked at gActiveCommand and the
        !           482:                 * time we disabled interrupts.
        !           483:                 */
        !           484:                queue_enter(&gPendingCommandQueue, cmdBuf, CommandBuffer *, link);
        !           485:                ddmChip("hardwareStart deferred: there is an active command\n", 1, 2, 3, 4, 5);
        !           486:                result = kHardwareStartBusy;
        !           487:            }
        !           488:        }
        !           489:        if (result == kHardwareStartOK) {
        !           490:            /*
        !           491:             * Activate this command - if we fail later, we'll de-activate it.
        !           492:             */
        !           493: #if SERIOUS_DEBUGGING
        !           494:            /*
        !           495:             * If we're reading, preset the buffer to a known data.
        !           496:             */
        !           497:            if (cmdBuf->scsiReq != NULL
        !           498:             && cmdBuf->scsiReq->read
        !           499:             && cmdBuf->buffer != NULL
        !           500:             && (((UInt32) cmdBuf->buffer) & 0x03) == 0) {
        !           501:                int             i;
        !           502:                UInt32          *ptr = (UInt32 *) cmdBuf->buffer;
        !           503:                for (i = 0; i < cmdBuf->scsiReq->maxTransfer; i += sizeof (UInt32)) {
        !           504:                    *ptr++ = 0xDEADBEEF;
        !           505:                }
        !           506:            }
        !           507: #endif /* SERIOUS_DEBUGGING */
        !           508: #if SERIOUS_DEBUGGING || LOG_COMMAND_AND_RESULT
        !           509:            [self logCommand
        !           510:                        : cmdBuf
        !           511:                logMemory   : FALSE
        !           512:                reason  : "Command at commandStart"
        !           513:            ];
        !           514: #endif /* SERIOUS_DEBUGGING || LOG_COMMAND_AND_RESULT */
        !           515:            ASSERT(gActiveCommand == NULL);
        !           516:            [self activateCommand : cmdBuf];
        !           517:            ASSERT(scsiReq->target == gCurrentTarget && scsiReq->lun == gCurrentLUN);
        !           518:            /* MESH only: [self clearChannelCommandResults];    */
        !           519:            /*
        !           520:             * Reset the message out buffer pointers.
        !           521:             */
        !           522:            gMsgOutPtr = gMsgOutBuffer;
        !           523:            gMsgPutPtr = gMsgOutBuffer;
        !           524:            msgByte = kScsiMsgIdentify | scsiReq->lun;
        !           525:            if (okToDisconnect)
        !           526:                msgByte |= kScsiMsgEnableDisconnectMask;
        !           527:            *gMsgOutPtr++ = msgByte;
        !           528:            /*
        !           529:             * According to the SCSI Spec, the tag command immediately
        !           530:             * follows the selection.
        !           531:             */
        !           532:            /*
        !           533:             * Note that autosense is issued on the current tag.
        !           534:             * The command was initialized with QUEUE_TAG_NONTAGGED.
        !           535:             */
        !           536:                /***** Driver Kit supports only simple queue tags.      *****/
        !           537:            if ( okToQueue ) {
        !           538:                                /* Avoid using tag QUEUE_TAG_NONTAGGED (zero).  */
        !           539:                        cmdBuf->queueTag = gNextQueueTag;
        !           540:                        if (++gNextQueueTag == QUEUE_TAG_NONTAGGED) {
        !           541:                                gNextQueueTag++;
        !           542:                        }
        !           543:                        *gMsgOutPtr++   = kScsiMsgSimpleQueueTag;
        !           544:                        *gMsgOutPtr++   = cmdBuf->queueTag;
        !           545:            }
        !           546:            if (cmdBuf->flagIsAutosense == 0) {
        !           547:                cmdBuf->currentDataIndex    = 0;
        !           548:                cmdBuf->savedDataIndex      = 0;
        !           549:                if (gActiveCommand->mem != NULL) {
        !           550:                    [gActiveCommand->mem setPosition : 0];  /* Needed?  */
        !           551:                }
        !           552:                scsiReq->driverStatus       = SR_IOST_INVALID;
        !           553:                scsiReq->totalTime          = 0ULL;
        !           554:                scsiReq->latentTime         = 0ULL;
        !           555:            }
        !           556:            [self hardwareStartSCSIRequest];
        !           557:            IOGetTimestamp(&cmdBuf->startTime);
        !           558:        }
        !           559:        RESULT(result);
        !           560:        return (result);
        !           561: }
        !           562: 
        !           563: 
        !           564: @end /* Apple96_SCSI(Hardware) */
        !           565: 
        !           566: 
        !           567: 
        !           568: /*
        !           569:  * Obtain a YES/NO type parameter from the config table.
        !           570:  * @param   configTable The table to examine.
        !           571:  * @param   paramName  The parameter to look for.
        !           572:  * @result  Zero if missing from the table or the table value is
        !           573:  *     not YES. One if present in the table and the table
        !           574:  *     value is YES.
        !           575:  */
        !           576: static int                  getConfigParam(
        !           577:        id                      configTable,
        !           578:        const char              *paramName
        !           579:     )
        !           580: {
        !           581:        const char              *value;
        !           582:        int                     result = 0; // default if not present in table
        !           583:        
        !           584:        ENTRY("Hgc getConfigParam");
        !           585:        value = [configTable valueForStringKey:paramName];
        !           586:        if (value != NULL) {
        !           587:            if (strcmp(value, "YES") == 0) {
        !           588:                result = 1;
        !           589:            }
        !           590:            [configTable freeString:value];
        !           591:        }
        !           592:        RESULT(result);
        !           593:        return (result);
        !           594: }
        !           595: 
        !           596: static unsigned int
        !           597: GetSCSICommandLength(
        !           598:        const cdb_t             *cdbPtr,
        !           599:        unsigned int            defaultLength
        !           600:     )
        !           601: {
        !           602:        unsigned int            result;
        !           603:        
        !           604:        /*
        !           605:         * Warning: don't use sizeof here - the compiler rounds the
        !           606:         * value up to the next word boundary.
        !           607:         */
        !           608:        switch (((UInt8 *) cdbPtr)[0] & 0xE0) {
        !           609:        case (0 << 5):
        !           610:            result = 6;
        !           611:            break;
        !           612:        case (1 << 5):
        !           613:        case (2 << 5):
        !           614:            result = 10;
        !           615:            break;
        !           616:        case (5 << 5):
        !           617:            result = 12;
        !           618:            break;
        !           619:        case (6 << 5):
        !           620:            result = (defaultLength != 0) ? defaultLength : 6;
        !           621:            break;
        !           622:        case (7 << 5):
        !           623:            result = (defaultLength != 0) ? defaultLength : 10;
        !           624:            break;
        !           625:        default:
        !           626:            result = 0;
        !           627:            break;
        !           628:        }
        !           629:        return (result);
        !           630: }

unix.superglobalmegacorp.com

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