Annotation of driverkit/libDriver/Kernel/SCSIDisk.m, revision 1.1.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: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
                     25:  *
                     26:  * SCSIDisk.m - Implementation of exported methods of SCSI Disk device class. 
                     27:  *
                     28:  * HISTORY
                     29:  *
                     30:  * 30-Jul-98   Dan Markarian at Apple. See Radar 2260508, 2258860. If the
                     31:  *             SCSIDisk driver attempts to probe a non-zero LUN and a
                     32:  *             target exists on LUN 0 that is actively doing (tagged) I/O,
                     33:  *             the target may abort all commands with an overlapped command
                     34:  *             error, causing the original command to fail without completion.
                     35:  *             Suggested work-arounds (for MacOS X Server, release 1): probe
                     36:  *             only LUN 0. If a target is discovered, reserve all LUNs for
                     37:  *             that target. This code must be revisited for IOKit.
                     38:  *
                     39:  * 11-Feb-91    Doug Mitchell at NeXT
                     40:  *      Created. 
                     41:  */
                     42:  
                     43: #define MACH_USER_API  1
                     44: #undef KERNEL_PRIVATE
                     45: 
                     46: #import <bsd/sys/types.h>
                     47: #import <driverkit/return.h>
                     48: #import <driverkit/IODisk.h>
                     49: #import <driverkit/SCSIDiskPrivate.h>
                     50: #import <driverkit/SCSIDiskTypes.h>
                     51: #import <driverkit/SCSIDisk.h> 
                     52: #import <driverkit/SCSIDiskKern.h>
                     53: #import <driverkit/SCSIStructInlines.h>
                     54: #import <bsd/dev/scsireg.h>    
                     55: #import <driverkit/xpr_mi.h>
                     56: #import <kernserv/prototypes.h>
                     57: #import <mach/mach_interface.h>
                     58: #import <driverkit/kernelDiskMethods.h>
                     59: #import <machkit/NXLock.h>
                     60: 
                     61: #ifdef DEBUG
                     62: #define SCSI_SA_TEST   0
                     63: #else  DEBUG
                     64: #define SCSI_SA_TEST   0
                     65: #endif DEBUG
                     66: 
                     67: /*
                     68:  * FIXME - ensure that diskUnit doesn't exceed NUM_SD_DEV.
                     69:  */
                     70: static int diskUnit = 0;
                     71: 
                     72: @implementation SCSIDisk
                     73: 
                     74: + (IODeviceStyle)deviceStyle
                     75: {
                     76:        return IO_IndirectDevice;
                     77: }
                     78: 
                     79: /*
                     80:  * The protocol we need as an indirect device.
                     81:  */
                     82: static Protocol *protocols[] = {
                     83:        @protocol(IOSCSIControllerExported),
                     84:        nil
                     85: };
                     86: 
                     87: + (Protocol **)requiredProtocols
                     88: {
                     89:        return protocols;
                     90: }
                     91: 
                     92: 
                     93: + initialize
                     94: {
                     95:        if(self == [SCSIDisk class]) {
                     96:                sd_init_idmap();
                     97:        }
                     98:        return [super initialize];
                     99: }  
                    100: 
                    101: /*
                    102:  * probe is invoked at load time. It determines what devices are on the
                    103:  * bus and alloc's and init:'s an instance of this class for each one.
                    104:  */
                    105: + (BOOL)probe : deviceDescription;
                    106: {
                    107:        char Target, Lun;
                    108:        sdInitReturn_t irtn = SDR_ERROR;
                    109:        SCSIDisk *diskId = nil;
                    110:        IODevAndIdInfo *idMap = sd_idmap();
                    111:        id controllerId = [deviceDescription directDevice];
                    112:        BOOL brtn = NO;
                    113:        SCSIDisk *diskIdArray[SCSI_NLUNS];
                    114:        int nLuns;
                    115:        /*
                    116:         * Radar 2005639
                    117:         */
                    118:        unsigned int paramValue[1];
                    119:        unsigned int count = 1;
                    120:        IOReturn ioReturn;
                    121:        
                    122: /* asm volatile("int3");  */
                    123: 
                    124: #if hppa
                    125:        /* search from the top down on hp since that was done before */
                    126:        for(Target=[controllerId numberOfTargets]-1; Target>=0; Target--)
                    127: #else
                    128:        for(Target=0; Target<[controllerId numberOfTargets]; Target++)
                    129: #endif
                    130:        {
                    131: 
                    132: #if 0  // Prior to Radar Fix #2260508
                    133:                for(Lun=nLuns=0; Lun<SCSI_NLUNS; Lun++) {
                    134: #else  // Radar Fix #2260508
                    135:                 for(Lun=nLuns=0; Lun<1; Lun++) {
                    136: #endif // Radar Fix #2260508
                    137:                        if(diskId == nil) {
                    138:                                /*
                    139:                                 * Create an instance, do some basic 
                    140:                                 * initialization. Set up a default 
                    141:                                 * device name for error reporting during
                    142:                                 * initialization.
                    143:                                 */
                    144:                                diskId = [SCSIDisk alloc];
                    145:                                [diskId setName:"SCSIDisk"];
                    146:                                /*
                    147:                                 * Radar 2005639. If the controller implements
                    148:                                 * the getIntValues APPLE_MAX_THREADS selector,
                    149:                                 * instantiate with the specified number of
                    150:                                 * of threads, otherwise let the diskID
                    151:                                 * instantiate itself with its default number.
                    152:                                 */
                    153:                                ioReturn = [controllerId getIntValues
                    154:                                                        : &paramValue[0]
                    155:                                        forParameter    : APPLE_MAX_THREADS
                    156:                                        count           : &count];
                    157:                                if (ioReturn == IO_R_SUCCESS && count == 1) {
                    158:                                    IOLog("%s: %s requests %d threads\n",
                    159:                                        [self name],
                    160:                                        [controllerId name],
                    161:                                        paramValue[0]
                    162:                                    );
                    163:                                    [diskId initResourcesWithThreadCount
                    164:                                                : paramValue[0]];
                    165:                                }
                    166:                                else {
                    167:                                    IOLog(
                    168:                "%s: %s does not support %s selector, using default\n",
                    169:                                        [self name],
                    170:                                        [controllerId name],
                    171:                                        APPLE_MAX_THREADS
                    172:                                    );
                    173:                                    [diskId initResources];
                    174:                                }
                    175:                                [diskId setDevAndIdInfo:&(idMap[diskUnit])];
                    176:                        }
                    177:                        if([controllerId reserveTarget:Target
                    178:                            lun:Lun
                    179:                            forOwner:diskId]) {
                    180:                                /*
                    181:                                 * Someone already has this one.
                    182:                                 */
                    183:                                continue;   
                    184:                        }
                    185:                        diskId->_isReserved = 1;
                    186: #if 1  // Radar Fix #2260508
                    187:                        /*
                    188:                         * A valid target at LUN 0 has been reserved: reserve
                    189:                          * all non-zero LUNs as well.   Note that _controller
                    190:                          * must be set before calling this next method, so go
                    191:                          * ahead and set it ourselves since the diskId object
                    192:                          * might be newly allocated (and yet-uninitialized).
                    193:                         */
                    194:                         diskId->_controller = controllerId;
                    195:                        [diskId reserveNonZeroLunsOnTarget:Target];
                    196: #endif // Radar Fix #2260508
                    197:                        irtn = [diskId SCSIDiskInit:(int)diskUnit
                    198:                                targetId:Target
                    199:                                lun:Lun
                    200:                                controller:controllerId];
                    201:                        [diskId setDeviceDescription:deviceDescription];
                    202:                        switch(irtn) {
                    203:                            case SDR_GOOD:
                    204:                                /*
                    205:                                 * Postpone registering this device
                    206:                                 * until we have looked at all other LUNs.
                    207:                                 * This prevents I/O to multiple LUNs
                    208:                                 * while we are probing, which is not handled
                    209:                                 * well by some devices.
                    210:                                 */
                    211:                                diskIdArray[nLuns++] = diskId;
                    212:                                diskUnit++;
                    213:                                diskId = nil;
                    214:                                brtn = YES;
                    215:                                break;                          
                    216:                                
                    217:                            default:
                    218: #if 1  // Radar Fix #2260508
                    219:                                 /*
                    220:                                  * LUN 0 will be unreserved: unreserve all
                    221:                                  * non-zero LUNs first.   Note _controller
                    222:                                  * is already set at this point.
                    223:                                  */
                    224:                                 [diskId releaseNonZeroLunsOnTarget:Target];
                    225: #endif // Radar Fix #2260508
                    226:                                [controllerId releaseTarget:Target
                    227:                                        lun:Lun
                    228:                                        forOwner:diskId];
                    229:                                diskId->_isReserved = 0;
                    230: 
                    231:                                if(irtn == SDR_SELECTTO) {
                    232:                                        /*
                    233:                                         * Skip the rest of the luns on 
                    234:                                         * this target.
                    235:                                         */
                    236:                                        goto nextTarget;
                    237:                                }
                    238:                                /* 
                    239:                                 * else try next lun.
                    240:                                 */
                    241:                        }
                    242:                }       /* for lun */
                    243: nextTarget:
                    244:                /* Now we have looked at all luns. */
                    245:                for (Lun=0; Lun < nLuns; Lun++) {
                    246:                        SCSIDisk *thisId = diskIdArray[Lun];
                    247:                        /*
                    248:                         * All right! Have IODisk superclass take 
                    249:                         * care of the rest.
                    250:                         */
                    251:                        [thisId setDeviceKind:"SCSIDisk"];
                    252:                        [thisId setIsPhysical:YES];
                    253:                        [thisId registerDevice];
                    254:                        thisId->_isRegistered = 1;
                    255:                }
                    256:                continue;
                    257:        }               /* for target */
                    258:        
                    259:        /*
                    260:         * Free up leftover owner and id. At this point, diskId does NOT have
                    261:         * a target/lun reserved.
                    262:         */
                    263:        if(diskId) {
                    264:                [diskId free];
                    265:        }
                    266:        
                    267: #if    SCSI_SA_TEST
                    268:        diskTest("sd0");
                    269: #endif SCSI_SA_TEST
                    270:        return brtn;
                    271: }
                    272: 
                    273: /*
                    274:  * IODiskReadingAndWriting protocol methods.
                    275:  */ 
                    276: - (IOReturn) readAt            : (unsigned)offset 
                    277:                                  length : (unsigned)length 
                    278:                                  buffer : (unsigned char *)buffer
                    279:                                  actualLength : (unsigned *)actualLength 
                    280:                                  client : (vm_task_t)client
                    281: {
                    282:        IOReturn rtn;
                    283:        
                    284:        xpr_sd("%s read: offset 0x%x length 0x%x\n",
                    285:                [self name], offset, length, 4,5);
                    286:        rtn = [self deviceRwCommon : SDOP_READ
                    287:                  block : offset
                    288:                  length : length 
                    289:                  buffer : buffer
                    290:                  client: client
                    291:                  pending : NULL
                    292:                  actualLength : actualLength];
                    293:        xpr_sd("%s read: RETURNING %s\n", [self name],
                    294:                [self stringFromReturn:rtn], 3,4,5);
                    295:        return(rtn);
                    296: }
                    297: 
                    298: - (IOReturn) readAsyncAt       : (unsigned)offset 
                    299:                                  length : (unsigned)length 
                    300:                                  buffer : (unsigned char *)buffer
                    301:                                  pending : (void *)pending
                    302:                                  client : (vm_task_t)client
                    303: {
                    304:        IOReturn rtn;
                    305:        
                    306:        xpr_sd("%s readAsync: offset 0x%x length 0x%x\n",
                    307:                [self name], offset, length, 4,5);
                    308:        rtn = [self deviceRwCommon : SDOP_READ
                    309:                  block : offset
                    310:                  length : length 
                    311:                  buffer : buffer
                    312:                  client : client
                    313:                  pending : (void *)pending
                    314:                  actualLength : NULL];
                    315:        xpr_sd("%s readAsync: RETURNING %s\n", [self name],
                    316:                [self stringFromReturn:rtn], 3,4,5);
                    317:        return(rtn);
                    318: }      
                    319: 
                    320: - (IOReturn) writeAt           : (unsigned)offset 
                    321:                                  length : (unsigned)length 
                    322:                                  buffer : (unsigned char *)buffer
                    323:                                  actualLength : (unsigned *)actualLength 
                    324:                                  client : (vm_task_t)client
                    325: {
                    326:        IOReturn rtn;
                    327:        
                    328:        xpr_sd("%s write: offset 0x%x length 0x%x\n",
                    329:                [self name], offset, length, 4,5);
                    330:        rtn = [self deviceRwCommon : SDOP_WRITE
                    331:                  block : offset
                    332:                  length : length 
                    333:                  buffer : buffer
                    334:                  client: client
                    335:                  pending : NULL
                    336:                  actualLength : actualLength];
                    337:        xpr_sd("%s deviceWrite: RETURNING %s\n", [self name],
                    338:                [self stringFromReturn:rtn], 3,4,5);
                    339:        return(rtn);
                    340: }                                      
                    341: 
                    342: - (IOReturn) writeAsyncAt      : (unsigned)offset 
                    343:                                  length : (unsigned)length 
                    344:                                  buffer : (unsigned char *)buffer
                    345:                                  pending : (void *)pending
                    346:                                  client : (vm_task_t)client
                    347: {
                    348:        IOReturn rtn;
                    349:        
                    350:        xpr_sd("%s writeAsync: offset 0x%x length 0x%x\n",
                    351:                [self name], offset, length, 4,5);
                    352:        rtn = [self deviceRwCommon : SDOP_WRITE
                    353:                  block : offset
                    354:                  length : length 
                    355:                  buffer : buffer
                    356:                  client : client
                    357:                  pending : (void *)pending
                    358:                  actualLength : NULL];
                    359:        xpr_sd("%s writeAsync: RETURNING %s\n", [self name],
                    360:                [self stringFromReturn:rtn], 3,4,5);
                    361:        return(rtn);
                    362: }
                    363: 
                    364: 
                    365: - (void) synchronizeCache
                    366: {
                    367:        IOSCSIRequest scsiReq;
                    368:        cdb_10_t *cdbp = &scsiReq.cdb.cdb_c10;
                    369:        sdBuf_t *sdBuf;
                    370:        
                    371:        bzero(&scsiReq, sizeof(IOSCSIRequest));
                    372:        scsiReq.target = _target;
                    373:        scsiReq.lun = _lun;
                    374:        scsiReq.timeoutLength = SD_TIMEOUT_SIMPLE;
                    375:        scsiReq.disconnect = 1;
                    376:        
                    377:        sdBuf = [self allocSdBuf:NULL];
                    378:        sdBuf->command = SDOP_CDB_WRITE;
                    379:        sdBuf->scsiReq = &scsiReq;
                    380:        sdBuf->retryDisable = 1;
                    381:        sdBuf->needsDisk = 0;
                    382:        
                    383:        /* Zeroing the lba and count fields will cause the drive to
                    384:         * flush everything. We should be able to zero these fields
                    385:         * explicitly, but for some reason the 10-byte commands don't
                    386:         * have the proper field definitions. 
                    387:         */
                    388:        bzero(cdbp,10);
                    389:        
                    390:        cdbp->c10_opcode = 0x35;
                    391:        cdbp->c10_lun = _lun;
                    392: 
                    393:        [self enqueueSdBuf:sdBuf];
                    394: 
                    395:        [self freeSdBuf:sdBuf];
                    396: }
                    397: 
                    398: - (IODiskReadyState)updateReadyState
                    399: {
                    400:        IOSCSIRequest scsiReq;
                    401:        cdb_6_t *cdbp = &scsiReq.cdb.cdb_c6;
                    402:        sdBuf_t *sdBuf;
                    403:        IODiskReadyState readyState;
                    404:        esense_reply_t senseReply;
                    405:        
                    406:        xpr_sd("%s updateReadyState\n", [self name], 2,3,4,5);
                    407: 
                    408:        if( NO == _isReserved) {
                    409:             return([self lastReadyState]);
                    410:        }
                    411: 
                    412:        bzero(&scsiReq, sizeof(IOSCSIRequest));
                    413:        scsiReq.target = _target;
                    414:        scsiReq.lun = _lun;
                    415:        scsiReq.timeoutLength = SD_TIMEOUT_SIMPLE;
                    416:        scsiReq.disconnect = 1;
                    417:        
                    418:        sdBuf = [self allocSdBuf:NULL];
                    419:        sdBuf->command = SDOP_CDB_WRITE;
                    420:        sdBuf->scsiReq = &scsiReq;
                    421:        sdBuf->retryDisable = 1;
                    422:        sdBuf->needsDisk = 0;
                    423:        
                    424:        cdbp->c6_opcode = C6OP_TESTRDY;
                    425:        cdbp->c6_lun = _lun;
                    426:        
                    427:        [self enqueueSdBuf:sdBuf];
                    428: 
                    429:        /*
                    430:         * FIXME - how to distinguish not ready from no disk???
                    431:         */
                    432:        switch(scsiReq.driverStatus) {
                    433:            case SR_IOST_GOOD:
                    434:                readyState = IO_Ready;
                    435:                break;
                    436:            default:
                    437:                readyState = IO_NotReady;
                    438:                break;
                    439:                
                    440:        }
                    441:        xpr_sd("%s updateReadyState: DONE; state = %s\n", 
                    442:                [self name], 
                    443:                IOFindNameForValue(readyState, readyStateValues), 3,4,5);
                    444:        [self freeSdBuf:sdBuf];
                    445:        return(readyState);
                    446: }
                    447: 
                    448: /*
                    449:  * IOPhysicalDiskMethods protocol methods.
                    450:  */
                    451: - (IOReturn) ejectPhysical
                    452: {
                    453:        return [self scsiStartStop:SS_EJECT inhibitRetry:NO];
                    454: }
                    455: 
                    456: 
                    457: /*
                    458:  * Get physical parameters (dev_size, block_size, etc.) from new disk.
                    459:  */
                    460: - (IOReturn)updatePhysicalParameters
                    461: {
                    462:        capacity_reply_t capacityData;
                    463:        mode_sel_data_t  modeData;
                    464:        sc_status_t rtn;
                    465:        int block;
                    466:        void *dataBuf;
                    467:        void *freePtr;
                    468:        unsigned freeCnt;
                    469:        u_int block_size;
                    470:        BOOL wp = NO;
                    471:        int i;
                    472:        
                    473:        rtn = [self updateReadyState];
                    474:        if(rtn) {
                    475:                return IO_R_NOT_READY;
                    476:        }
                    477:        rtn = [self sdReadCapacity:&capacityData];
                    478:        if(rtn) {
                    479:                return(IO_R_IO);
                    480:        }
                    481:        [self setDiskSize:scsi_lastlba(&capacityData) + 1];
                    482:        [self setBlockSize:scsi_blklen(&capacityData)];
                    483:        
                    484:        /*
                    485:         * Try reading a block to see if disk is formatted.
                    486:         */
                    487:        block_size = [self blockSize];
                    488:        dataBuf = [_controller allocateBufferOfLength:block_size
                    489:                        actualStart:&freePtr
                    490:                        actualLength:&freeCnt];
                    491:        block = 10;
                    492:        for(i=0; i<5; i++) {
                    493:                rtn = [self sdRawRead:block blockCnt:1 buffer:dataBuf];
                    494:                if(rtn == IO_R_SUCCESS) {
                    495:                        break;
                    496:                }
                    497:                block += 10;
                    498:        }
                    499:        if(rtn == IO_R_SUCCESS) 
                    500:                [self setFormattedInternal:1];
                    501:        else
                    502:                [self setFormattedInternal:0];
                    503: 
                    504:        IOFree(freePtr, freeCnt);
                    505:        
                    506:        /*
                    507:         * Mark CD-ROMs as write-protected; use a mode sense for the others.
                    508:         */
                    509: 
                    510:        if(_inquiryDeviceType == DEVTYPE_CDROM)
                    511:                wp = YES;
                    512:        else {
                    513:                bzero(&modeData, sizeof(mode_sel_data_t));
                    514:                rtn = [self sdModeSense:&modeData];
                    515: 
                    516:                if (modeData.msd_header.msh_wp)
                    517:                        wp = YES;
                    518:        }
                    519: 
                    520:        [self setWriteProtected: wp];
                    521: 
                    522:        return(IO_R_SUCCESS);
                    523: }
                    524: 
                    525: /*
                    526:  * Called by volCheck thread when WS has told us that a requested disk is
                    527:  * not present. Pending I/Os which require a disk to be present must be 
                    528:  * aborted.
                    529:  */
                    530: - (void)abortRequest
                    531: {
                    532:        sdBuf_t *sdBuf;
                    533:        
                    534:        xpr_sd("%s: abortRequest\n", [self name], 2,3,4,5);
                    535:        
                    536:        sdBuf = [self allocSdBuf:NULL];
                    537:        sdBuf->command = SDOP_ABORT;
                    538:        sdBuf->needsDisk = 0;
                    539:        [self enqueueSdBuf:sdBuf];
                    540:        xpr_sd("%s abortRequest: done %s\n", [self name], 2,3,4,5);
                    541:        [self freeSdBuf:sdBuf];
                    542:        return;
                    543: }
                    544: 
                    545: /*
                    546:  * Called by the volCheck thread when a transition to "ready" is detected.
                    547:  * Pending I/Os which require a disk may proceed. All we have to do is 
                    548:  * wakeup the I/O threads which are waiting for something to show up 
                    549:  * in an I/O queue.
                    550:  */
                    551: - (void)diskBecameReady
                    552: {
                    553:        xpr_sd("diskBecameReady: %s\n", [self name], 2,3,4,5);
                    554:        [_ioQLock lock];
                    555:        [_ioQLock unlockWith:WORK_AVAILABLE];
                    556: }
                    557: 
                    558: /*
                    559:  * Inquire if disk is present; if not, and 'prompt' is YES, ask for it. 
                    560:  * Returns IO_R_NO_DISK if:
                    561:  *    prompt YES, disk not present, and user cancels request for disk.
                    562:  *    prompt NO, disk not present.
                    563:  * Else returns IO_R_SUCCESS.
                    564:  */
                    565: - (IOReturn)isDiskReady        : (BOOL)prompt
                    566: {
                    567:        sdBuf_t *sdBuf;
                    568:        IOReturn rtn;
                    569:        
                    570:        xpr_sd("%s: diskBecameReady\n", [self name], 2,3,4,5);
                    571: 
                    572:        if( NO == _isReserved)
                    573:                return(IO_R_NO_DISK);
                    574: 
                    575:        if([self lastReadyState] == IO_Ready) {
                    576:                /*
                    577:                 * This one's easy...
                    578:                 */
                    579:                return(IO_R_SUCCESS);
                    580:        }
                    581:        if(!prompt) {
                    582:                return(IO_R_NO_DISK);
                    583:        }
                    584:        sdBuf = [self allocSdBuf:NULL];
                    585:        sdBuf->command = SDOP_PROBEDISK;
                    586:        sdBuf->needsDisk = 1;
                    587:        rtn = [self enqueueSdBuf:sdBuf];
                    588:        xpr_sd("%s diskBecameReady: returning %s\n", [self name], 
                    589:                [self stringFromReturn:rtn], 3,4,5);
                    590:        [self freeSdBuf:sdBuf];
                    591:        return(rtn);
                    592: }      
                    593: 
                    594: /*
                    595:  * We have to override IODisk's setLastReadyState: so we know when to 
                    596:  * clear our local ejectPending flag.
                    597:  */
                    598:  - (void)setLastReadyState : (IODiskReadyState)readyState
                    599:  {
                    600:        xpr_sd("sd setLastReadyState\n", 1,2,3,4,5);
                    601:        if(_ejectPending && (readyState != IO_Ejecting))
                    602:                _ejectPending = 0;
                    603:        [super setLastReadyState:readyState];
                    604:  }
                    605: 
                    606: /*
                    607:  * Exported methods unique to the SCSIDisk class.
                    608:  * Note caller must provide well-aligned DMA buffers.
                    609:  */
                    610: - (IOReturn) sdCdbRead                 : (IOSCSIRequest *)scsiReq       /* SCSI parameters */
                    611:                                   buffer:(void *)buffer /* data destination */
                    612:                                   client:(vm_task_t)client;
                    613: {
                    614:        sdBuf_t *sdBuf;
                    615:        IOReturn rtn;
                    616:        
                    617:        xpr_sd("sd%d sdCdbRead: opcode = 0x%x\n", [self unit],
                    618:                scsiReq->cdb.cdb_opcode, 3,4,5);
                    619:                
                    620:        sdBuf = [self allocSdBuf:NULL];
                    621:        sdBuf->command = SDOP_CDB_READ;
                    622:        sdBuf->scsiReq = scsiReq;
                    623:        sdBuf->buf = buffer;
                    624:        sdBuf->client = client;
                    625:        sdBuf->pending = NULL;
                    626:        sdBuf->needsDisk = 0;
                    627:        rtn = [self enqueueSdBuf:sdBuf];
                    628:        xpr_sd("sd%d sdCdbRead: returning %s\n", [self unit],
                    629:                [self stringFromReturn:rtn], 3,4,5);
                    630:        [self freeSdBuf:sdBuf];
                    631:        return(rtn);
                    632: }
                    633: 
                    634: - (IOReturn) sdCdbWrite                : (IOSCSIRequest *)scsiReq       /* SCSI parameters */
                    635:                                   buffer:(void *)buffer /* data destination */
                    636:                                   client:(vm_task_t)client
                    637: {
                    638:        sdBuf_t *sdBuf;
                    639:        IOReturn rtn;
                    640:        
                    641:        xpr_sd("sd%d sdCdbWrite: opcode = 0x%x\n", [self unit],
                    642:                scsiReq->cdb.cdb_opcode, 3,4,5);
                    643:                
                    644:        sdBuf = [self allocSdBuf:NULL];
                    645:        sdBuf->command = SDOP_CDB_WRITE;
                    646:        sdBuf->scsiReq = scsiReq;
                    647:        sdBuf->buf = buffer;
                    648:        sdBuf->client = client;
                    649:        sdBuf->pending = NULL;
                    650:        sdBuf->needsDisk = 0;
                    651:        rtn = [self enqueueSdBuf:sdBuf];
                    652:        xpr_sd("sd%d sdCdbWrite: returning %s\n", [self unit],
                    653:                [self stringFromReturn:rtn], 3,4,5);
                    654:        [self freeSdBuf:sdBuf];
                    655:        return(rtn);    
                    656: }
                    657: 
                    658: - (int)target
                    659: {
                    660:        return _target;
                    661: }
                    662: 
                    663: - (int)lun
                    664: {
                    665:        return _lun;
                    666: }
                    667: 
                    668: /*
                    669:  * This is mainly here for the convenience of 486 CDROM boot. It's cheap so
                    670:  * we'll leave it in for other platforms too.
                    671:  */
                    672: - (unsigned char)inquiryDeviceType
                    673: {      
                    674:        return _inquiryDeviceType;
                    675: }
                    676: 
                    677: - controller
                    678: {
                    679:        return _controller;
                    680: }
                    681: 
                    682: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
                    683: {
                    684:     if( [super getDevicePath:path maxLength:maxLen useAlias:doAlias]) {
                    685: 
                    686:        char    unitStr[ 12 ];
                    687:        int     len = maxLen - strlen( path);
                    688: 
                    689:        sprintf( unitStr, "/@%x", [self target]);
                    690:        len -= strlen( unitStr);
                    691:        if( len < 0)
                    692:            return( nil);
                    693:         strcat( path, unitStr);
                    694:        if( [self lun]) {
                    695:             sprintf( unitStr, ",%x", [self lun]);
                    696:             len -= strlen( unitStr);
                    697:             if( len < 0)
                    698:                 return( nil);
                    699:             strcat( path, unitStr);
                    700:        }
                    701:        return( self);
                    702:     }
                    703:     return( nil);
                    704: }
                    705: 
                    706: - (char *) matchDevicePath:(char *)matchPath
                    707: {
                    708:     BOOL       matches = NO;
                    709:     char    *  unitStr;
                    710:     extern long int strtol(const char *nptr, char **endptr, int base);
                    711: 
                    712:     unitStr = [super matchDevicePath:matchPath];
                    713:     if( unitStr) {
                    714:         unitStr = (char *)strchr( unitStr, '@');
                    715:         if( unitStr) {
                    716:             matches = ([self target] == strtol( unitStr + 1, &unitStr, 16));
                    717:             if( matches && (*unitStr == ','))
                    718:                 matches = ([self lun] == strtol( unitStr + 1, &unitStr, 16));
                    719:        }
                    720:     }
                    721:     if( matches)
                    722:         return( unitStr);
                    723:     else
                    724:        return( NULL);
                    725: }
                    726: 
                    727: - property_IOUnit:(char *)result length:(unsigned int *)maxLen
                    728: {
                    729:     if( [self lun])
                    730:         sprintf( result, "%d,%d", [self target], [self lun]);
                    731:     else
                    732:         sprintf( result, "%d", [self target]);
                    733: 
                    734:     return( self);
                    735: }
                    736: 
                    737: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
                    738: {
                    739:     static const char * inquiryDevTypeStrings[ 9 ] = {
                    740:        0, IOTypeTape, IOTypePrinter, 0,
                    741:        IOTypeWORM, IOTypeCDROM, IOTypeScanner, IOTypeOptical,
                    742:        IOTypeChanger
                    743:     };
                    744: 
                    745:     [super property_IODeviceType:types length:maxLen];
                    746: 
                    747:     if( (_inquiryDeviceType <= 8) && inquiryDevTypeStrings[ _inquiryDeviceType ]) {
                    748:        strcat( types, " ");
                    749:        strcat( types, inquiryDevTypeStrings[ _inquiryDeviceType ]);
                    750:     }
                    751:     return( self);
                    752: }
                    753: 
                    754: @end

unix.superglobalmegacorp.com

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