Annotation of Examples/DriverKit/SCSITape/SCSITape_reloc.tproj/SCSITape.m, revision 1.1

1.1     ! root        1: /* 
        !             2:  * SCSITape.m -- implementation of scsi tape driver routines
        !             3:  *
        !             4:  * HISTORY
        !             5:  * 31-Mar-93   Phillip Dibner at NeXT
        !             6:  *     Created.
        !             7:  *
        !             8:  */ 
        !             9:  
        !            10: 
        !            11: #import <sys/errno.h>
        !            12: #import <sys/types.h>
        !            13: #import <sys/time.h>
        !            14: #import <sys/conf.h>
        !            15: #import <sys/uio.h>
        !            16: #import <sys/mtio.h>
        !            17: #import <bsd/dev/scsireg.h>
        !            18: 
        !            19: #import <driverkit/scsiTypes.h>
        !            20: #import <driverkit/align.h>
        !            21: #import <driverkit/kernelDriver.h>
        !            22: #import <driverkit/scsiTypes.h>
        !            23: #import <driverkit/return.h>
        !            24: #import <machkit/NXLock.h>
        !            25: #import <kernserv/prototypes.h>
        !            26: #import <kernserv/kern_server_types.h>
        !            27: #import "SCSITape.h"
        !            28: #import "SCSITapeTypes.h"
        !            29: 
        !            30: #define DRIVE_TYPE_LENGTH 80
        !            31: 
        !            32: #define USE_EBD        1               /* use "even byte disconnect" rather than 
        !            33:                                 * "no disconnect during data xfer" for exabyte
        !            34:                                 */
        !            35: 
        !            36: extern int st_devsw_init();
        !            37: 
        !            38: static int moveString();       /* rmv nulls & blanks from inquiry strings */
        !            39: void assign_cdb_c6s_len();     /* store length data in little-endian cdb_6s */
        !            40: void assign_msbd_numblocks();  /* store nblks in little-endian modesel bd */
        !            41: void assign_msbd_blocklength();        /* store blklen in little-endian modesel bd */
        !            42: int cdb_c6s_len_value();       /* byte swap to read length data in cdb */
        !            43: int er_info_value ();          /* byte swapping for sense reply info data */
        !            44: 
        !            45: id             stIdMap [NST];
        !            46: 
        !            47: @implementation SCSITape
        !            48: 
        !            49: + (IODeviceStyle)deviceStyle
        !            50: {
        !            51:        return IO_IndirectDevice;
        !            52: }
        !            53: 
        !            54: /*
        !            55:  * The protocol we need as an indirect device.
        !            56:  */
        !            57: static Protocol *protocols[] = {
        !            58:     @protocol(IOSCSIControllerExported),
        !            59:     nil
        !            60: };
        !            61: 
        !            62: + (Protocol **)requiredProtocols
        !            63: {
        !            64:     return protocols;
        !            65: }
        !            66: 
        !            67: static unsigned int tapeUnit = 0;
        !            68: 
        !            69: + (BOOL) probe: deviceDescription
        !            70: {
        !            71:     SCSITape                   *tapeId = nil;
        !            72:     unsigned char              stTarget, stLun;
        !            73:     id                         controllerId = 
        !            74:                                        [deviceDescription directDevice];
        !            75:     stInitReturn_t             irtn = STR_ERROR;
        !            76:     BOOL                       brtn = NO;
        !            77:     int                                major;
        !            78:        
        !            79: /* asm volatile("int3");  */ // Early break to debugger
        !            80:     
        !            81:     if ((major = st_devsw_init()) < 0) {
        !            82:        return NO;
        !            83:     }
        !            84: 
        !            85:     for (stTarget=0; stTarget<SCSI_NTARGETS; stTarget++) {
        !            86:        for(stLun=0; stLun<SCSI_NLUNS; stLun++) {
        !            87: 
        !            88: #ifdef DEBUG
        !            89: IOLog ("SCSITape probe: target %d  lun %d\n", stTarget, stLun);
        !            90: #endif DEBUG
        !            91: 
        !            92:            if(tapeId == nil) {
        !            93:                /*
        !            94:                 * Create an instance, do some basic 
        !            95:                 * initialization. Set up a default 
        !            96:                 * device name for error reporting during
        !            97:                 * initialization.
        !            98:                 */
        !            99:                tapeId = [SCSITape alloc];
        !           100:            }
        !           101: 
        !           102:            if ([controllerId reserveTarget:stTarget
        !           103:                lun:stLun
        !           104:                forOwner:tapeId]) {
        !           105:                /*
        !           106:                 * Someone already has this one.
        !           107:                 */
        !           108:                continue;   
        !           109:            }
        !           110:            else {
        !           111:                [tapeId setReservedTargetLun: YES];
        !           112:            }
        !           113: 
        !           114: #ifdef DEBUG
        !           115: IOLog ("SCSITape probe: about to init\n");
        !           116: #endif DEBUG
        !           117: 
        !           118:            irtn = [tapeId initSCSITape:(int)tapeUnit
        !           119:                target: stTarget
        !           120:                lun: stLun
        !           121:                controller: controllerId
        !           122:                majorDeviceNumber: major];
        !           123: 
        !           124: #ifdef DEBUG
        !           125: IOLog ("SCSITape probe: irtn is %d\n", irtn);
        !           126: #endif DEBUG
        !           127: 
        !           128:            switch (irtn) {
        !           129:                case STR_GOOD:
        !           130:                    /*
        !           131:                     * Init'd OK - still must register device.
        !           132:                     */
        !           133:                    [tapeId registerDevice];
        !           134:                    stIdMap [tapeUnit] = tapeId;
        !           135:                    tapeId = nil;
        !           136:                    tapeUnit++;
        !           137:                    if (tapeUnit >= NST) goto done;
        !           138:                    brtn = YES;
        !           139:                    break;
        !           140:                                
        !           141:                default:
        !           142:                    [controllerId releaseTarget: stTarget
        !           143:                        lun: stLun
        !           144:                        forOwner: tapeId];
        !           145:                    [tapeId setReservedTargetLun: NO];
        !           146:                    if(irtn == STR_SELECTTO) {
        !           147:                        /*
        !           148:                         * Skip the rest of the luns on 
        !           149:                         * this target.
        !           150:                         */
        !           151:                        goto nextTarget;
        !           152:                    }
        !           153:            /* 
        !           154:             * else try next lun.
        !           155:             */
        !           156:            }   /* switch (irtn) */
        !           157:        }       /* for lun */
        !           158: 
        !           159: nextTarget:
        !           160: 
        !           161:        continue;
        !           162:     }          /* for target */
        !           163:        
        !           164: done:
        !           165:     /*
        !           166:      * Free up leftover owner and id.  At this point, tapeId does NOT have
        !           167:      * a target/lun reserved.
        !           168:      */
        !           169:     if(tapeId) {
        !           170:        [tapeId free];
        !           171:     }
        !           172:        
        !           173:     return brtn;
        !           174: }
        !           175: 
        !           176: 
        !           177: - (stInitReturn_t) initSCSITape:(int)iunit     /* IODevice unit # */
        !           178:     target:            (u_char) stTarget
        !           179:     lun:               (u_char) stLun
        !           180:     controller:                controllerId
        !           181:     majorDeviceNumber: (int) major
        !           182: {
        !           183:     inquiry_reply_t    inquiryData;
        !           184:     sc_status_t                rtn;
        !           185:     char               driveType[DRIVE_TYPE_LENGTH];   /* name from Inquiry */
        !           186:     char               *outp;
        !           187:     char               deviceName[30];
        !           188:     char               location[IO_STRING_LENGTH];
        !           189:        
        !           190:        
        !           191:     /*
        !           192:      * Initialize common instance variables.
        !           193:      */
        !           194:     _controller = controllerId;
        !           195:     _target = stTarget;
        !           196:     _lun = stLun;
        !           197:     sprintf(deviceName, "st%d", iunit);
        !           198:     [self setName: deviceName];
        !           199:     [self setDeviceKind:"SCSITape"];
        !           200:     [self setLocation:[_controller name]];
        !           201:     [self setUnit: iunit];
        !           202: 
        !           203: #ifdef DEBUG
        !           204: IOLog 
        !           205:     ("InitSCSITape: target %d  lun %d  unit %d  deviceName %s  location %s\n",
        !           206:     stTarget, stLun, iunit, deviceName, [_controller name]);
        !           207: #endif DEBUG
        !           208: 
        !           209:     /*
        !           210:      * Resources for commands during initialization.
        !           211:      */
        !           212:     _senseDataPtr = IOMalloc (sizeof (struct esense_reply));
        !           213:     _senseDataValid = NO;
        !           214: 
        !           215:     /*
        !           216:      * Other instance variables
        !           217:      */
        !           218:     _didWrite = NO;
        !           219:     _suppressIllegalLength = NO;
        !           220:     _isInitialized = NO;
        !           221:     _devLock = nil;                    // Until we know we're a tape
        !           222: 
        !           223:     /*
        !           224:      * Test Unit Ready to clear possible Unit Attention.   Success is
        !           225:      * not important.
        !           226:      */
        !           227:     [self stTestReady];
        !           228: 
        !           229:     /*
        !           230:      * Try an Inquiry command.
        !           231:      */
        !           232:     bzero(&inquiryData, sizeof(inquiry_reply_t));
        !           233:     rtn = [self stInquiry:&inquiryData];
        !           234: 
        !           235: #ifdef DEBUG
        !           236: IOLog ("InitSCSITape inquiry returned %d\n", rtn);
        !           237: #endif DEBUG
        !           238: 
        !           239:     switch(rtn) {
        !           240:        case SR_IOST_GOOD:
        !           241:            break;
        !           242:        case SR_IOST_SELTO:
        !           243:            return STR_SELECTTO;
        !           244:        default:
        !           245:            return STR_ERROR;
        !           246:     }
        !           247: 
        !           248:     /*
        !           249:      * Is it a tape?  
        !           250:      */
        !           251:     if(inquiryData.ir_qual != DEVQUAL_OK ||
        !           252:        inquiryData.ir_devicetype != DEVTYPE_TAPE) {
        !           253: 
        !           254: #ifdef DEBUG
        !           255: IOLog ("InitSCSITape: not a tape\n");
        !           256: #endif DEBUG
        !           257: 
        !           258:        return(STR_NOTATAPE);
        !           259:     }
        !           260:        
        !           261:     /*
        !           262:      * Set up resources for exclusive open.
        !           263:      */
        !           264:     _devLock = [[NXLock alloc] init];
        !           265:     _devAcquired = NO;
        !           266: 
        !           267:     /*
        !           268:      * Compress multiple blanks out of the vendor id and product ID. 
        !           269:      */
        !           270:     bzero (driveType, DRIVE_TYPE_LENGTH);
        !           271:     outp = driveType;
        !           272:     outp += moveString((char *)&inquiryData.ir_vendorid,
        !           273:        outp, 
        !           274:        8,
        !           275:        &driveType[DRIVE_TYPE_LENGTH] - outp);
        !           276:     if(*(outp - 1) != ' ')
        !           277:        *outp++ = ' ';
        !           278:     outp += moveString((char *)&inquiryData.ir_productid,
        !           279:        outp, 
        !           280:        16,
        !           281:        &driveType[DRIVE_TYPE_LENGTH] - outp);
        !           282:     if(*(outp - 1) != ' ')
        !           283:        *outp++ = ' ';
        !           284:     outp += moveString((char *)&inquiryData.ir_revision,
        !           285:        outp, 
        !           286:        4,
        !           287:        &driveType[DRIVE_TYPE_LENGTH] - outp);
        !           288:     *outp = '\0';
        !           289: 
        !           290:     sprintf(location, "Target %d LUN %d at %s", _target, _lun,
        !           291:        [controllerId name]);
        !           292:     [self setLocation: location];
        !           293:     IOLog("%s: %s\n", deviceName, driveType);
        !           294: 
        !           295: 
        !           296:     /*
        !           297:      * Do another Test Unit Ready to clear a possible Unit Attention
        !           298:      * condition.  We don't care about the result.
        !           299:      */
        !           300:     [self stTestReady];
        !           301: 
        !           302:     /*
        !           303:      * Init to variable blk size.
        !           304:      */
        !           305:     [self setBlockSize: 0];
        !           306: 
        !           307:     /*
        !           308:      * Store the major number in our instance.
        !           309:      */
        !           310:     _majorDevNum = major;
        !           311: 
        !           312:     [super init];
        !           313:     _isInitialized = YES;
        !           314:     return(STR_GOOD);
        !           315: } /* - initSCSITape: */
        !           316: 
        !           317: 
        !           318: - free
        !           319: {
        !           320:     if (_senseDataPtr)
        !           321:        IOFree (_senseDataPtr, sizeof (struct esense_reply));
        !           322:     if (_devLock)
        !           323:        [_devLock free];
        !           324:     if (_reservedTargetLun)
        !           325:        [_controller releaseTarget: _target lun: _lun forOwner: _controller];
        !           326:     return [super free];
        !           327: }
        !           328: 
        !           329: 
        !           330: - (IOReturn) getIntValues: (unsigned int *)values
        !           331:     forParameter: (IOParameterName) parameter
        !           332:     count: (unsigned int *) count
        !           333: {
        !           334:     int maxCount = *count;
        !           335: 
        !           336:     if(maxCount == 0) {
        !           337:         maxCount = IO_MAX_PARAMETER_ARRAY_LENGTH;
        !           338:     }
        !           339: 
        !           340:     if(strcmp(parameter, "IOMajorDevice") == 0) {
        !           341:        values [0] = [self majorDevNum];
        !           342:        *count = 1;       
        !           343:        return IO_R_SUCCESS;
        !           344:     }
        !           345: 
        !           346:     if (strcmp(parameter, "Unit") == 0) {
        !           347:        values [0] = [self unit];
        !           348:        *count = 1;       
        !           349:         return IO_R_SUCCESS;
        !           350: 
        !           351:     }
        !           352:         
        !           353:     return [super getIntValues:values 
        !           354:        forParameter:parameter
        !           355:        count:&maxCount];
        !           356: }
        !           357: 
        !           358: 
        !           359: 
        !           360: /*
        !           361:  * Gets and sets for instance variables.
        !           362:  */
        !           363: 
        !           364: - (int) target                 /* Set only during initialization */
        !           365: {
        !           366:     return (int) _target;
        !           367: }
        !           368: 
        !           369: - (int) lun                    /* Set only during initialization */
        !           370: {
        !           371:     return (int) _lun;
        !           372: }
        !           373: 
        !           374: - controller                   /* Set only during initialization */
        !           375: {
        !           376:     return _controller;
        !           377: }
        !           378: 
        !           379: - (BOOL) isInitialized         /* Object has been initialized */
        !           380: {
        !           381:     return _isInitialized;
        !           382: }
        !           383: 
        !           384: - (BOOL) didWrite              /* Last command was a write */
        !           385: {
        !           386:     return _didWrite;
        !           387: }
        !           388: 
        !           389: - (BOOL) isFixedBlock
        !           390: {
        !           391:     if (_blockSize) {          /* Zero blocksize means variable block size */
        !           392:        return YES;
        !           393:     } else {
        !           394:        return NO;
        !           395:     }
        !           396: }
        !           397: 
        !           398: - (BOOL) senseDataValid
        !           399: {
        !           400:     return _senseDataValid;
        !           401: }
        !           402: 
        !           403: - forceSenseDataInvalid                /* for MTIOCGET and friends */
        !           404: {
        !           405:     _senseDataValid = NO;
        !           406:     return self;
        !           407: }
        !           408: 
        !           409: - (struct esense_reply *) senseDataPtr
        !           410: {
        !           411:     return _senseDataPtr;
        !           412: }
        !           413: 
        !           414: - (int) blockSize              /* Set only via setBlockSize SCSI operation */
        !           415: {
        !           416:     return _blockSize;
        !           417: }
        !           418: 
        !           419: - (BOOL) suppressIllegalLength
        !           420: {
        !           421:     return _suppressIllegalLength;
        !           422: }
        !           423: 
        !           424: - setSuppressIllegalLength: (BOOL) condition
        !           425: {
        !           426:     _suppressIllegalLength = condition;
        !           427:     return self;
        !           428: }
        !           429: 
        !           430: - (BOOL) ignoreCheckCondition
        !           431: {
        !           432:     return _ignoreCheckCondition;
        !           433: }
        !           434: 
        !           435: - setIgnoreCheckCondition: (BOOL) condition
        !           436: {
        !           437:     _ignoreCheckCondition = condition;
        !           438:     return self;
        !           439: }
        !           440: 
        !           441: - (int) majorDevNum
        !           442: {
        !           443:     return _majorDevNum;
        !           444: }
        !           445: 
        !           446: - setReservedTargetLun: (BOOL) condition
        !           447: {
        !           448:     _reservedTargetLun = condition;
        !           449:     return self;
        !           450: }
        !           451: 
        !           452: - (BOOL) reservedTargetLun
        !           453: {
        !           454:     return _reservedTargetLun;
        !           455: }
        !           456: 
        !           457: - (IOReturn) acquireDevice
        !           458: {
        !           459:     IOReturn           ret = IO_R_INVALID;
        !           460: 
        !           461:     [_devLock lock];
        !           462:     if (_devAcquired == YES) {
        !           463:        ret = IO_R_BUSY;
        !           464:     } else {
        !           465:        _devAcquired = YES;
        !           466:        ret = IO_R_SUCCESS;
        !           467:     }
        !           468:     [_devLock unlock];
        !           469:     return ret;
        !           470: }
        !           471: 
        !           472: - (IOReturn) releaseDevice
        !           473: {
        !           474:     [_devLock lock];
        !           475:     _devAcquired = NO;
        !           476:     [_devLock unlock];
        !           477:     return IO_R_SUCCESS;
        !           478: }
        !           479: 
        !           480: 
        !           481: /*
        !           482:  * General SCSI commands
        !           483:  */
        !           484: - (sc_status_t) stInquiry: (inquiry_reply_t *) inquiryReply
        !           485: {
        !           486:     IOSCSIRequest              scsiReq;
        !           487:     cdb_6_t                    *cdbp = &scsiReq.cdb.cdb_c6;
        !           488:     inquiry_reply_t            *alignedReply;
        !           489:     void                       *freePtr;
        !           490:     int                        freeCnt;
        !           491:     sc_status_t                rtn;
        !           492:     IODMAAlignment             dmaAlign;
        !           493:        
        !           494:        
        !           495:     /*
        !           496:      * Get some well-aligned memory.
        !           497:      */
        !           498:     alignedReply = [_controller
        !           499:        allocateBufferOfLength: sizeof(inquiry_reply_t)
        !           500:        actualStart:&freePtr
        !           501:        actualLength:&freeCnt];
        !           502:     bzero(alignedReply, sizeof(inquiry_reply_t));
        !           503:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           504:     scsiReq.target = _target;
        !           505:     scsiReq.lun = _lun;
        !           506:     scsiReq.read = YES;
        !           507:        
        !           508:     /*
        !           509:      * Get appropriate alignment from controller. 
        !           510:      */
        !           511:     [_controller getDMAAlignment:&dmaAlign];
        !           512:     if(dmaAlign.readLength > 1) {
        !           513:        scsiReq.maxTransfer = IOAlign(int, sizeof(inquiry_reply_t), 
        !           514:            dmaAlign.readLength);
        !           515:     }
        !           516:     else {
        !           517:        scsiReq.maxTransfer = sizeof(inquiry_reply_t);
        !           518:     }
        !           519: 
        !           520:     scsiReq.timeoutLength = ST_IOTO_NORM;
        !           521:     scsiReq.disconnect = 1;
        !           522: 
        !           523:     cdbp->c6_opcode = C6OP_INQUIRY;
        !           524:     cdbp->c6_lun = _lun;
        !           525:     cdbp->c6_len = sizeof(inquiry_reply_t);
        !           526:        
        !           527:     [self executeRequest: &scsiReq
        !           528:        buffer: alignedReply
        !           529:        client: IOVmTaskSelf()
        !           530:        senseBuf: _senseDataPtr];
        !           531: 
        !           532:     if(scsiReq.driverStatus == SR_IOST_GOOD) {
        !           533:        unsigned required = (char *)(&alignedReply->ir_zero3[0]) - 
        !           534:            (char *)(alignedReply);
        !           535:        if(scsiReq.bytesTransferred < required) {
        !           536:            IOLog("%s: bad DMA Transfer count (%d) on Inquiry\n", 
        !           537:                [self name], scsiReq.bytesTransferred);
        !           538:            rtn = SR_IOST_HW;
        !           539:        }
        !           540:        else {
        !           541:        /*
        !           542:         * Copy data back to caller's struct. Zero the 
        !           543:         * portion of alignedReply which did not get valid
        !           544:         * data; the last flush out of the DMA pipe could
        !           545:         * have written trash to it (and our caller
        !           546:         * expects NULL data).
        !           547:         */
        !           548:            unsigned zeroSize;
        !           549:                        
        !           550:            zeroSize = sizeof(*alignedReply) - scsiReq.bytesTransferred;
        !           551:            if(zeroSize) {
        !           552:                bzero((char *)alignedReply + scsiReq.bytesTransferred,
        !           553:                    zeroSize);
        !           554:            }
        !           555:            *inquiryReply = *alignedReply;
        !           556:            rtn = scsiReq.driverStatus;
        !           557:        }
        !           558:     }
        !           559:     else {
        !           560:        rtn = scsiReq.driverStatus;
        !           561:     }
        !           562: 
        !           563:     IOFree(freePtr, freeCnt);
        !           564:     return rtn;
        !           565: } /* - stInquiry: */
        !           566: 
        !           567: 
        !           568: 
        !           569: - (BOOL) stTestReady
        !           570: {
        !           571:     IOSCSIRequest      scsiReq;
        !           572:     cdb_6_t            *cdbp = &scsiReq.cdb.cdb_c6;
        !           573:     BOOL               rtn;
        !           574:        
        !           575:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           576:     scsiReq.target = _target;
        !           577:     scsiReq.lun = _lun;
        !           578:     scsiReq.timeoutLength = ST_IOTO_NORM;
        !           579:     scsiReq.disconnect = 1;
        !           580:        
        !           581:     cdbp->c6_opcode = C6OP_TESTRDY;
        !           582:     cdbp->c6_lun = _lun;
        !           583: 
        !           584:     [self executeRequest: &scsiReq
        !           585:        buffer: (void *) NULL
        !           586:        client: IOVmTaskSelf()
        !           587:        senseBuf: _senseDataPtr];
        !           588: 
        !           589:     /*
        !           590:      * XXX Do we need to distinguish not ready from no tape?
        !           591:      */
        !           592:     switch(scsiReq.driverStatus) {
        !           593:        case SR_IOST_GOOD:
        !           594:            rtn = YES;
        !           595:            break;
        !           596:        default:
        !           597:            rtn = NO;
        !           598:            break;              
        !           599:     }
        !           600: 
        !           601:     return rtn;
        !           602: } /* - stTestReady: */
        !           603: 
        !           604: 
        !           605: 
        !           606: - (sc_status_t) stCloseFile
        !           607: {
        !           608:     IOSCSIRequest              scsiReq;
        !           609:     cdb_6s_t                   *cdbp = &scsiReq.cdb.cdb_c6s;
        !           610:        
        !           611:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           612:     scsiReq.target = _target;
        !           613:     scsiReq.lun = _lun;
        !           614:     scsiReq.timeoutLength = ST_IOTO_NORM;
        !           615:     scsiReq.disconnect = 1;
        !           616:     cdbp->c6s_opcode = C6OP_WRTFM;
        !           617:     assign_cdb_c6s_len (cdbp, 1);              /* one file mark */
        !           618:     
        !           619:     return [self executeRequest: &scsiReq
        !           620:        buffer: NULL
        !           621:        client: IOVmTaskSelf()
        !           622:        senseBuf: _senseDataPtr];
        !           623: } /* - stCloseFile */
        !           624: 
        !           625: 
        !           626: - (sc_status_t) stRewind
        !           627: {
        !           628:     IOSCSIRequest              scsiReq;
        !           629:     cdb_6s_t                   *cdbp = &scsiReq.cdb.cdb_c6s;
        !           630:        
        !           631:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           632:     scsiReq.target = _target;
        !           633:     scsiReq.lun = _lun;
        !           634:     scsiReq.timeoutLength = ST_IOTO_RWD;
        !           635:     scsiReq.disconnect = 1;
        !           636:     cdbp->c6s_opcode = C6OP_REWIND;
        !           637:     
        !           638:     return [self executeRequest: &scsiReq
        !           639:        buffer: NULL
        !           640:        client: IOVmTaskSelf()
        !           641:        senseBuf: _senseDataPtr];
        !           642: } /* - stRewind */
        !           643: 
        !           644: 
        !           645: /*
        !           646:  * Get sense data. senseBuf does not have to be well aligned.
        !           647:  */
        !           648: - (sc_status_t) requestSense: (esense_reply_t *)senseBuf
        !           649: {
        !           650:     IOSCSIRequest      scsiReq;
        !           651:     cdb_6_t            *cdbp = &scsiReq.cdb.cdb_c6;
        !           652:     esense_reply_t     *alignedBuf;
        !           653:     void               *freePtr;
        !           654:     int                freeCnt;
        !           655:     sc_status_t        rtn;
        !           656:     IODMAAlignment     dmaAlign;
        !           657:        
        !           658:     alignedBuf = [_controller allocateBufferOfLength: sizeof(esense_reply_t)
        !           659:        actualStart: &freePtr
        !           660:        actualLength: &freeCnt];
        !           661:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           662:     [_controller getDMAAlignment:&dmaAlign];
        !           663: 
        !           664:     scsiReq.target             = _target;
        !           665:     scsiReq.lun                = _lun;
        !           666:     scsiReq.read               = YES;
        !           667: 
        !           668:     if(dmaAlign.readLength > 1) {
        !           669:        scsiReq.maxTransfer = IOAlign(int, sizeof(esense_reply_t), 
        !           670:            dmaAlign.readLength);
        !           671: 
        !           672:     } else {
        !           673:        scsiReq.maxTransfer = sizeof(esense_reply_t);
        !           674:     }
        !           675: 
        !           676:     scsiReq.timeoutLength = ST_IOTO_NORM;  // XXX Should be ST_IOTO_SENSE??
        !           677:     scsiReq.disconnect = 0;
        !           678:     cdbp->c6_opcode = C6OP_REQSENSE;
        !           679:     cdbp->c6_lun = _lun;
        !           680:     cdbp->c6_len = sizeof(esense_reply_t);
        !           681: 
        !           682:     rtn = [_controller executeRequest:&scsiReq
        !           683:        buffer:alignedBuf
        !           684:        client:IOVmTaskSelf()];
        !           685:     if(rtn == SR_IOST_GOOD) {
        !           686:        *senseBuf = *alignedBuf;
        !           687:        _senseDataValid = YES;
        !           688:     }
        !           689:     IOFree(freePtr, freeCnt);
        !           690:     return rtn;
        !           691: } /* - requestSense: */
        !           692: 
        !           693: 
        !           694: 
        !           695: 
        !           696: - (sc_status_t) stModeSelect: (struct modesel_parms *) modeSelectParmsPtr
        !           697: {
        !           698:     IOSCSIRequest              scsiReq;
        !           699:     cdb_6_t                    *cdbp = &scsiReq.cdb.cdb_c6;
        !           700:     int                                count = modeSelectParmsPtr->msp_bcount;
        !           701:     struct mode_sel_data       *alignedBuf;
        !           702:     void                       *freePtr;
        !           703:     int                        freeCnt;
        !           704:     sc_status_t                rtn;
        !           705:     IODMAAlignment             dmaAlign;
        !           706:        
        !           707:     alignedBuf = [_controller 
        !           708:        allocateBufferOfLength: count
        !           709:        actualStart: &freePtr
        !           710:        actualLength: &freeCnt];
        !           711: 
        !           712: 
        !           713:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           714: 
        !           715:     scsiReq.target             = _target;
        !           716:     scsiReq.lun                = _lun;
        !           717:     scsiReq.read               = NO;
        !           718: 
        !           719:     [_controller getDMAAlignment:&dmaAlign];
        !           720:     if(dmaAlign.readLength > 1) {
        !           721:        scsiReq.maxTransfer = IOAlign(int, count, 
        !           722:            dmaAlign.readLength);
        !           723: 
        !           724:     } else {
        !           725:        scsiReq.maxTransfer = count;
        !           726:     }
        !           727: 
        !           728:     scsiReq.timeoutLength = ST_IOTO_NORM;
        !           729:     scsiReq.disconnect = 1;
        !           730:     cdbp->c6_opcode = C6OP_MODESELECT;
        !           731:     cdbp->c6_lun = _lun;
        !           732:     cdbp->c6_len = count;
        !           733: 
        !           734:     bcopy (&modeSelectParmsPtr->msp_data, alignedBuf, count);
        !           735: 
        !           736:     rtn = [self executeRequest:&scsiReq
        !           737:        buffer:alignedBuf
        !           738:        client:IOVmTaskSelf()
        !           739:        senseBuf: _senseDataPtr];
        !           740: 
        !           741:     IOFree(freePtr, freeCnt);
        !           742:     return rtn;
        !           743: } /* - stModeSelect: */
        !           744: 
        !           745: 
        !           746: 
        !           747: 
        !           748: - (sc_status_t) stModeSense: (struct modesel_parms *) modeSenseParmsPtr
        !           749: {
        !           750:     IOSCSIRequest              scsiReq;
        !           751:     cdb_6_t                    *cdbp = &scsiReq.cdb.cdb_c6;
        !           752:     int                                count = modeSenseParmsPtr->msp_bcount;
        !           753:     struct mode_sel_data       *alignedBuf;
        !           754:     void                       *freePtr;
        !           755:     int                        freeCnt;
        !           756:     sc_status_t                rtn;
        !           757:     IODMAAlignment             dmaAlign;
        !           758:        
        !           759:     alignedBuf = [_controller 
        !           760:        allocateBufferOfLength: count
        !           761:        actualStart: &freePtr
        !           762:        actualLength: &freeCnt];
        !           763: 
        !           764: 
        !           765:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           766: 
        !           767:     scsiReq.target             = _target;
        !           768:     scsiReq.lun                = _lun;
        !           769:     scsiReq.read               = YES;
        !           770: 
        !           771:     [_controller getDMAAlignment:&dmaAlign];
        !           772:     if(dmaAlign.readLength > 1) {
        !           773:        scsiReq.maxTransfer = IOAlign(int, count, 
        !           774:            dmaAlign.readLength);
        !           775: 
        !           776:     } else {
        !           777:        scsiReq.maxTransfer = count;
        !           778:     }
        !           779: 
        !           780:     scsiReq.timeoutLength = ST_IOTO_NORM;
        !           781:     scsiReq.disconnect = 1;
        !           782:     cdbp->c6_opcode = C6OP_MODESENSE;
        !           783:     cdbp->c6_lun = _lun;
        !           784:     cdbp->c6_len = count;
        !           785: 
        !           786:     rtn = [self executeRequest:&scsiReq
        !           787:        buffer:alignedBuf
        !           788:        client:IOVmTaskSelf()
        !           789:        senseBuf: _senseDataPtr];
        !           790: 
        !           791:     if(rtn == SR_IOST_GOOD) {
        !           792:        bcopy (alignedBuf, &modeSenseParmsPtr->msp_data, count);
        !           793:     }
        !           794: 
        !           795:     IOFree(freePtr, freeCnt);
        !           796:     return rtn;
        !           797: } /* - stModeSense: */
        !           798: 
        !           799: 
        !           800: 
        !           801: - (sc_status_t) executeMTOperation: (struct mtop *) mtopp
        !           802: {
        !           803:     IOSCSIRequest              scsiReq;
        !           804:     cdb_6s_t                   *cdbp = &scsiReq.cdb.cdb_c6s;
        !           805:     int                                count;
        !           806:     sc_status_t                        rtn;
        !           807:        
        !           808:     bzero(&scsiReq, sizeof(IOSCSIRequest));
        !           809:     scsiReq.target = _target;
        !           810:     scsiReq.lun = _lun;
        !           811:     scsiReq.timeoutLength = ST_IOTO_NORM;      /* Some ops override this */
        !           812:     scsiReq.disconnect = 1;  // XXX - maybe not for all ops.
        !           813: 
        !           814:     /* 
        !           815:      * none of these operations performs DMA. For each, just fill in
        !           816:      * the cdb, and pass it to the controller.
        !           817:      */
        !           818:         
        !           819:     /* build a CDB */
        !           820:        
        !           821:     switch(mtopp->mt_op) {
        !           822:        case MTWEOF:            /* write file marks */
        !           823:            cdbp->c6s_opcode = C6OP_WRTFM;
        !           824:            goto setcount_f;
        !           825:                
        !           826:        case MTFSF:             /* space file marks forward */
        !           827:            cdbp->c6s_opcode = C6OP_SPACE;
        !           828:            cdbp->c6s_opt = C6OPT_SPACE_FM;
        !           829:            scsiReq.timeoutLength = mtopp->mt_count * ST_IOTO_SPFM;
        !           830:            goto setcount_f;
        !           831:                
        !           832:        case MTBSF:             /* space file marks backward */
        !           833:            cdbp->c6s_opcode = C6OP_SPACE;
        !           834:            cdbp->c6s_opt = C6OPT_SPACE_FM;
        !           835:            scsiReq.timeoutLength = mtopp->mt_count * ST_IOTO_SPFM;
        !           836:            goto setcount_b;
        !           837:                
        !           838:        case MTFSR:             /* space records forward */
        !           839:            cdbp->c6s_opcode = C6OP_SPACE;
        !           840:            cdbp->c6s_opt = C6OPT_SPACE_LB;
        !           841:            scsiReq.timeoutLength = ST_IOTO_SPR;
        !           842: setcount_f:
        !           843:            assign_cdb_c6s_len (cdbp, mtopp->mt_count);
        !           844:            break;
        !           845: 
        !           846:        case MTBSR:                     /* space records backward */
        !           847:            cdbp->c6s_opcode = C6OP_SPACE;
        !           848:            cdbp->c6s_opt = C6OPT_SPACE_LB;
        !           849:            scsiReq.timeoutLength = ST_IOTO_SPR;
        !           850: setcount_b:
        !           851:            count = 0 - mtopp->mt_count;
        !           852:            assign_cdb_c6s_len (cdbp, count);
        !           853:            break;
        !           854:                        
        !           855:        case MTREW:                     /* rewind */
        !           856:            cdbp->c6s_opcode = C6OP_REWIND;
        !           857:            scsiReq.timeoutLength = ST_IOTO_RWD;
        !           858:            break;
        !           859:                
        !           860:        case MTOFFL:                    /* set offline */
        !           861:            cdbp->c6s_opcode = C6OP_STARTSTOP;
        !           862:                                        /* note load bit is 0 */
        !           863:            scsiReq.timeoutLength = ST_IOTO_RWD;
        !           864:            break;
        !           865:                
        !           866:        case MTNOP:             /* nop / get status */
        !           867:        case MTCACHE:           /* enable cache */
        !           868:        case MTNOCACHE:         /* disable cache */
        !           869:        case MTRETEN:
        !           870:        case MTERASE:
        !           871:        default:
        !           872:            rtn = SR_IOST_CMDREJ;       /* FIXME: unsupported? */
        !           873:            goto out;
        !           874:     }
        !           875: 
        !           876:     rtn = [self executeRequest: &scsiReq
        !           877:        buffer: NULL
        !           878:        client: IOVmTaskSelf()
        !           879:        senseBuf: _senseDataPtr];   
        !           880: out:
        !           881:     return rtn;
        !           882: } /* - executeMTOperation: */
        !           883: 
        !           884:        
        !           885: 
        !           886: /*
        !           887:  * Set block size for SCSI tape device.   
        !           888:  *
        !           889:  * blocksize == 0 --> variable
        !           890:  * blocksize != 0 --> fixed @ blocksize
        !           891:  *
        !           892:  * First, execute mode sense, then mode select with block length
        !           893:  * set to 0 (variable) or blocksize (fixed)
        !           894:  */
        !           895: - (IOReturn) setBlockSize: (int) blockSize
        !           896: {
        !           897:     int                                rtn;
        !           898:     struct modesel_parms       *mspp;
        !           899:     struct mode_sel_hdr                *mshp;
        !           900: 
        !           901:     mspp = IOMalloc (sizeof(struct modesel_parms));
        !           902:     mspp->msp_bcount = sizeof(struct mode_sel_hdr) + 
        !           903:        sizeof(struct mode_sel_bd);
        !           904: 
        !           905:     if((rtn = [self stModeSense: mspp]) != SR_IOST_GOOD) {
        !           906:        IOFree (mspp, sizeof (struct modesel_parms));
        !           907:        return [_controller returnFromScStatus: rtn];
        !           908:     }
        !           909: 
        !           910:     mshp = &mspp->msp_data.msd_header; 
        !           911:     mshp->msh_sd_length_0 = 0;
        !           912:     mshp-> msh_med_type = 0;
        !           913:     mshp-> msh_wp = 0;
        !           914:     mshp-> msh_bd_length = sizeof(struct mode_sel_bd);
        !           915:     assign_msbd_blocklength 
        !           916:        (&mspp->msp_data.msd_blockdescript, blockSize);
        !           917:     assign_msbd_numblocks
        !           918:        (&mspp->msp_data.msd_blockdescript, 0);
        !           919: 
        !           920:     if((rtn = [self stModeSelect: mspp]) != SR_IOST_GOOD) {
        !           921:        IOFree (mspp, sizeof (struct modesel_parms));
        !           922:        return [_controller returnFromScStatus: rtn];
        !           923:     }
        !           924: 
        !           925:     _blockSize = blockSize;
        !           926: 
        !           927:     IOFree (mspp, sizeof (struct modesel_parms));
        !           928:     return IO_R_SUCCESS;
        !           929: } /* - setBlockSize: */
        !           930: 
        !           931: 
        !           932: 
        !           933: 
        !           934: /*
        !           935:  * Execute CDB.   Buffer must be well aligned.   If command results 
        !           936:  * in Check Status, return the sense data in *senseBuf.
        !           937:  */
        !           938: - (sc_status_t) executeRequest: (IOSCSIRequest *)scsiReq
        !           939:     buffer:(void *) buffer /* data destination */
        !           940:     client:(vm_task_t) client
        !           941:     senseBuf:(esense_reply_t *) senseBuf
        !           942: {
        !           943:     sc_status_t                        rtn;
        !           944: 
        !           945:     _senseDataValid = NO;
        !           946: 
        !           947: #ifdef DEBUG
        !           948: IOLog("Entered SCSI Tape executeRequest: op %s, maxTransfer %d, len %d\n",
        !           949:     IOFindNameForValue(scsiReq->cdb.cdb_opcode,
        !           950:        IOSCSIOpcodeStrings),
        !           951:     scsiReq->maxTransfer,
        !           952:     (scsiReq->cdb.cdb_c6s.c6s_len2 << 16) | 
        !           953:        (scsiReq->cdb.cdb_c6s.c6s_len1 << 8) |
        !           954:        (scsiReq->cdb.cdb_c6s.c6s_len0));
        !           955: #endif DEBUG
        !           956: 
        !           957:     rtn = [_controller executeRequest:scsiReq
        !           958:        buffer:buffer
        !           959:        client:client];
        !           960: 
        !           961: #ifdef DEBUG
        !           962: IOLog ("Length %d on return from executeRequest\n", scsiReq->bytesTransferred);
        !           963: #endif DEBUG
        !           964: 
        !           965:     /*
        !           966:      * Log error returns.
        !           967:      */
        !           968:     if (rtn != SR_IOST_GOOD) {
        !           969:        /*
        !           970:         * If result is Check Condition, do a Request Sense, unless suppressed.
        !           971:         */
        !           972:        if(rtn == SR_IOST_CHKSV) {
        !           973:                /* 
        !           974:                 * Host Adaptor already got us sense data. Give sense data
        !           975:                 * to user and save it.
        !           976:                 */
        !           977:                *senseBuf = *_senseDataPtr = scsiReq->senseData;
        !           978:                _senseDataValid = YES;
        !           979:        }
        !           980:        if (((rtn == SR_IOST_CHKSNV) || (rtn == SR_IOST_CHKSV)) &&
        !           981:                !_ignoreCheckCondition) {
        !           982:            if(rtn == SR_IOST_CHKSV) {
        !           983:                rtn = SR_IOST_GOOD;
        !           984:            }
        !           985:            else {
        !           986:                rtn = [self requestSense: senseBuf];
        !           987:            }
        !           988:            if(rtn == SR_IOST_GOOD) {
        !           989:                /*
        !           990:                 * If the error is a filemark, and we are reading,
        !           991:                 * then return no error.   Otherwise, return
        !           992:                 * check sense, with valid sense data.
        !           993:                 */
        !           994:                if ((scsiReq->cdb.cdb_c6.c6_opcode == C6OP_READ) &&
        !           995:                    (senseBuf->er_filemark)) {
        !           996: 
        !           997:                    /*
        !           998:                     * Check for correct reporting of bytes transferred.
        !           999:                     * (This works around a DPT firmware bug.)
        !          1000:                     */
        !          1001:                    int transferLength = 
        !          1002:                        cdb_c6s_len_value (&scsiReq->cdb.cdb_c6s) -
        !          1003:                        er_info_value (senseBuf);
        !          1004: 
        !          1005:                    if ([self isFixedBlock]) {
        !          1006:                        transferLength = transferLength * _blockSize;
        !          1007:                    }
        !          1008:                                        
        !          1009:                    if (scsiReq->bytesTransferred != transferLength) {
        !          1010: #ifdef DEBUG
        !          1011: IOLog ("%s: Incorrect byte count reported - "
        !          1012:     "corrected to %d\n", [self name], transferLength);
        !          1013: #endif DEBUG
        !          1014:                        scsiReq->bytesTransferred = transferLength;
        !          1015:                    }
        !          1016: 
        !          1017:                    rtn = SR_IOST_GOOD;
        !          1018:                    scsiReq->driverStatus = SR_IOST_GOOD;
        !          1019: 
        !          1020: #ifdef DEBUG
        !          1021: IOLog ("execReq sense: er_filemark %d, er_badlen %d, er_sensekey %d, er_addsensecode %d, er_qualifier %d, er_info %d\n", 
        !          1022:        senseBuf->er_filemark, senseBuf->er_badlen, senseBuf->er_sensekey,
        !          1023:        senseBuf->er_addsensecode, senseBuf->er_qualifier,
        !          1024:        er_info_value (senseBuf));
        !          1025: #endif DEBUG
        !          1026: 
        !          1027:                }
        !          1028:                else {
        !          1029:                    rtn = SR_IOST_CHKSV;
        !          1030:                }
        !          1031:            }
        !          1032:            else {
        !          1033:                if (_isInitialized) {
        !          1034:                    IOLog("%s: Request Sense on target %d lun %d "
        !          1035:                        "failed (%s)\n",
        !          1036:                        [self name], _target, _lun, 
        !          1037:                        IOFindNameForValue(rtn, IOScStatusStrings));
        !          1038:                }
        !          1039:                rtn = SR_IOST_CHKSNV;
        !          1040:            }
        !          1041:        }
        !          1042: 
        !          1043:        /*
        !          1044:         * Log error messages, except the spate of timeouts and
        !          1045:         * device not ready messages during initialization.
        !          1046:         */
        !          1047:        if (_isInitialized &&
        !          1048:            (rtn != SR_IOST_GOOD) &&
        !          1049:            !_ignoreCheckCondition) {
        !          1050: 
        !          1051:            IOLog("%s, target %d, lun %d: op %s returned %s\n",
        !          1052:                [self name], _target, _lun,
        !          1053:                IOFindNameForValue(scsiReq->cdb.cdb_opcode,
        !          1054:                    IOSCSIOpcodeStrings),
        !          1055:                IOFindNameForValue(rtn, IOScStatusStrings));
        !          1056: 
        !          1057:            if (rtn == SR_IOST_CHKSV) {
        !          1058:                IOLog ("    Sense key = 0x%x  Sense Code = 0x%x\n",
        !          1059:                    senseBuf->er_sensekey, senseBuf->er_addsensecode);
        !          1060:            }
        !          1061:        }
        !          1062: 
        !          1063:        _didWrite = NO;
        !          1064:     }
        !          1065: 
        !          1066:     else {
        !          1067:        /* Remember good writes for device close */
        !          1068:        if (scsiReq->cdb.cdb_opcode == C6OP_WRITE) {
        !          1069:            _didWrite = YES;
        !          1070:        } else {
        !          1071:            _didWrite = NO;
        !          1072:        }
        !          1073:     }
        !          1074: 
        !          1075:     return rtn;
        !          1076: } /* executeRequest: */                           
        !          1077:                          
        !          1078: @end
        !          1079: 
        !          1080: /*
        !          1081:  * Supporting functions.
        !          1082:  */
        !          1083: 
        !          1084: /*
        !          1085:  * moveString is taken directly from SCSIDiskPrivate.m.    
        !          1086:  * It's used by -initSCSITape:
        !          1087:  *
        !          1088:  * Copy inp to outp for up to inlength input characters or outlength output
        !          1089:  * characters. Compress multiple spaces and eliminate nulls. Returns number
        !          1090:  * of characters copied to outp.
        !          1091:  */
        !          1092: static int 
        !          1093: moveString(char *inp, char *outp, int inlength, int outlength)
        !          1094: {
        !          1095:     int lastCharSpace = 0;
        !          1096:     char *outpStart = outp;
        !          1097: 
        !          1098:     while(inlength && outlength) {
        !          1099:        switch(*inp) {
        !          1100:            case '\0':
        !          1101:                inp++;
        !          1102:                inlength--;
        !          1103:                continue;
        !          1104:            case ' ':
        !          1105:                if(lastCharSpace) {
        !          1106:                    inp++;
        !          1107:                    inlength--;
        !          1108:                    continue;
        !          1109:                }
        !          1110:                lastCharSpace = 1;
        !          1111:                goto copyit;
        !          1112:            default:
        !          1113:                lastCharSpace = 0;
        !          1114: copyit:
        !          1115:                *outp++ = *inp++;
        !          1116:                inlength--;
        !          1117:                outlength--;
        !          1118:                break;
        !          1119:            }
        !          1120:     }
        !          1121:     return(outp - outpStart);
        !          1122: }
        !          1123: 
        !          1124: 
        !          1125: 
        !          1126: void
        !          1127: assign_cdb_c6s_len (struct cdb_6s *cdbp, int length)
        !          1128: {
        !          1129: #if    __BIG_ENDIAN__
        !          1130: #if    __NATURAL_ALIGNMENT__
        !          1131:     cdbp->c6s_len[0] = (length >> 16) & 0xff;
        !          1132:     cdbp->c6s_len[1] = (length >> 8) & 0xff;
        !          1133:     cdbp->c6s_len[2] = length & 0xff;
        !          1134: 
        !          1135: #else  __NATURAL_ALIGNMENT__
        !          1136: 
        !          1137:     cdbp->c6s_len = length;
        !          1138: 
        !          1139: #endif __NATURAL_ALIGNMENT__
        !          1140: 
        !          1141: 
        !          1142: #elif  __LITTLE_ENDIAN__
        !          1143: 
        !          1144:     cdbp->c6s_len0 = (u_char) length & 0xff;
        !          1145:     cdbp->c6s_len1 = (u_char) (length >> 8) & 0xff;
        !          1146:     cdbp->c6s_len2 = (u_char) (length >> 16) & 0xff;
        !          1147: 
        !          1148: #endif
        !          1149: 
        !          1150:     return;
        !          1151: }
        !          1152: 
        !          1153: void
        !          1154: assign_msbd_numblocks (struct mode_sel_bd *msbdp, int numblocks)
        !          1155: {
        !          1156: #if    __BIG_ENDIAN__
        !          1157:     msbdp->msbd_numblocks = numblocks;
        !          1158: #elif  __LITTLE_ENDIAN__
        !          1159:     msbdp->msbd_numblocks0 = (u_char) numblocks & 0xff;
        !          1160:     msbdp->msbd_numblocks1 = (u_char) (numblocks >> 8) & 0xff;
        !          1161:     msbdp->msbd_numblocks2 = (u_char) (numblocks >> 16) & 0xff;
        !          1162: #endif
        !          1163:     return;
        !          1164: }
        !          1165: 
        !          1166: void
        !          1167: assign_msbd_blocklength (struct mode_sel_bd *msbdp, int length)
        !          1168: {
        !          1169: #if    __BIG_ENDIAN__
        !          1170:     msbdp->msbd_blocklength = length;
        !          1171: #elif  __LITTLE_ENDIAN__
        !          1172:     msbdp->msbd_blocklength0 = (u_char) length & 0xff;
        !          1173:     msbdp->msbd_blocklength1 = (u_char) (length >> 8) & 0xff;
        !          1174:     msbdp->msbd_blocklength2 = (u_char) (length >> 16) & 0xff;
        !          1175: #endif
        !          1176:     return;
        !          1177: }
        !          1178: 
        !          1179: int
        !          1180: cdb_c6s_len_value (struct cdb_6s *cdbp)
        !          1181: {
        !          1182: #if    __BIG_ENDIAN__
        !          1183:     return (cdbp->c6s_len);
        !          1184: #elif  __LITTLE_ENDIAN__
        !          1185:     return (cdbp->c6s_len0 | (cdbp->c6s_len1 << 8) | (cdbp->c6s_len2 << 16));
        !          1186: #endif
        !          1187: }
        !          1188: 
        !          1189: int
        !          1190: er_info_value (struct esense_reply *esrp)
        !          1191: {
        !          1192: #if    __BIG_ENDIAN__
        !          1193:     return (esrp->er_info);
        !          1194: #elif  __LITTLE_ENDIAN__
        !          1195:     return (esrp->er_info0 | (esrp->er_info1 << 8) |
        !          1196:        (esrp->er_info2 << 16) | (esrp->er_info3 << 24));
        !          1197: #endif
        !          1198: }
        !          1199:     

unix.superglobalmegacorp.com

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