Annotation of driverkit/libDriver/Kernel/SCSIDisk.m, revision 1.1.1.2

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) {
1.1.1.2 ! root      158: #if 0 /* Radar 2291688: supress IOLog */
1.1       root      159:                                    IOLog("%s: %s requests %d threads\n",
                    160:                                        [self name],
                    161:                                        [controllerId name],
                    162:                                        paramValue[0]
                    163:                                    );
1.1.1.2 ! root      164: #endif
1.1       root      165:                                    [diskId initResourcesWithThreadCount
                    166:                                                : paramValue[0]];
                    167:                                }
                    168:                                else {
1.1.1.2 ! root      169: #if 0 /* Radar 2291688: supress IOLog */
1.1       root      170:                                    IOLog(
                    171:                "%s: %s does not support %s selector, using default\n",
                    172:                                        [self name],
                    173:                                        [controllerId name],
                    174:                                        APPLE_MAX_THREADS
                    175:                                    );
1.1.1.2 ! root      176: #endif
1.1       root      177:                                    [diskId initResources];
                    178:                                }
                    179:                                [diskId setDevAndIdInfo:&(idMap[diskUnit])];
                    180:                        }
                    181:                        if([controllerId reserveTarget:Target
                    182:                            lun:Lun
                    183:                            forOwner:diskId]) {
                    184:                                /*
                    185:                                 * Someone already has this one.
                    186:                                 */
                    187:                                continue;   
                    188:                        }
                    189:                        diskId->_isReserved = 1;
                    190: #if 1  // Radar Fix #2260508
                    191:                        /*
                    192:                         * A valid target at LUN 0 has been reserved: reserve
                    193:                          * all non-zero LUNs as well.   Note that _controller
                    194:                          * must be set before calling this next method, so go
                    195:                          * ahead and set it ourselves since the diskId object
                    196:                          * might be newly allocated (and yet-uninitialized).
                    197:                         */
                    198:                         diskId->_controller = controllerId;
                    199:                        [diskId reserveNonZeroLunsOnTarget:Target];
                    200: #endif // Radar Fix #2260508
                    201:                        irtn = [diskId SCSIDiskInit:(int)diskUnit
                    202:                                targetId:Target
                    203:                                lun:Lun
                    204:                                controller:controllerId];
                    205:                        [diskId setDeviceDescription:deviceDescription];
                    206:                        switch(irtn) {
                    207:                            case SDR_GOOD:
                    208:                                /*
                    209:                                 * Postpone registering this device
                    210:                                 * until we have looked at all other LUNs.
                    211:                                 * This prevents I/O to multiple LUNs
                    212:                                 * while we are probing, which is not handled
                    213:                                 * well by some devices.
                    214:                                 */
                    215:                                diskIdArray[nLuns++] = diskId;
                    216:                                diskUnit++;
                    217:                                diskId = nil;
                    218:                                brtn = YES;
                    219:                                break;                          
                    220:                                
                    221:                            default:
                    222: #if 1  // Radar Fix #2260508
                    223:                                 /*
                    224:                                  * LUN 0 will be unreserved: unreserve all
                    225:                                  * non-zero LUNs first.   Note _controller
                    226:                                  * is already set at this point.
                    227:                                  */
                    228:                                 [diskId releaseNonZeroLunsOnTarget:Target];
                    229: #endif // Radar Fix #2260508
                    230:                                [controllerId releaseTarget:Target
                    231:                                        lun:Lun
                    232:                                        forOwner:diskId];
                    233:                                diskId->_isReserved = 0;
                    234: 
                    235:                                if(irtn == SDR_SELECTTO) {
                    236:                                        /*
                    237:                                         * Skip the rest of the luns on 
                    238:                                         * this target.
                    239:                                         */
                    240:                                        goto nextTarget;
                    241:                                }
                    242:                                /* 
                    243:                                 * else try next lun.
                    244:                                 */
                    245:                        }
                    246:                }       /* for lun */
                    247: nextTarget:
                    248:                /* Now we have looked at all luns. */
                    249:                for (Lun=0; Lun < nLuns; Lun++) {
                    250:                        SCSIDisk *thisId = diskIdArray[Lun];
                    251:                        /*
                    252:                         * All right! Have IODisk superclass take 
                    253:                         * care of the rest.
                    254:                         */
                    255:                        [thisId setDeviceKind:"SCSIDisk"];
                    256:                        [thisId setIsPhysical:YES];
                    257:                        [thisId registerDevice];
                    258:                        thisId->_isRegistered = 1;
                    259:                }
                    260:                continue;
                    261:        }               /* for target */
                    262:        
                    263:        /*
                    264:         * Free up leftover owner and id. At this point, diskId does NOT have
                    265:         * a target/lun reserved.
                    266:         */
                    267:        if(diskId) {
                    268:                [diskId free];
                    269:        }
                    270:        
                    271: #if    SCSI_SA_TEST
                    272:        diskTest("sd0");
                    273: #endif SCSI_SA_TEST
                    274:        return brtn;
                    275: }
                    276: 
                    277: /*
                    278:  * IODiskReadingAndWriting protocol methods.
                    279:  */ 
                    280: - (IOReturn) readAt            : (unsigned)offset 
                    281:                                  length : (unsigned)length 
                    282:                                  buffer : (unsigned char *)buffer
                    283:                                  actualLength : (unsigned *)actualLength 
                    284:                                  client : (vm_task_t)client
                    285: {
                    286:        IOReturn rtn;
                    287:        
                    288:        xpr_sd("%s read: offset 0x%x length 0x%x\n",
                    289:                [self name], offset, length, 4,5);
                    290:        rtn = [self deviceRwCommon : SDOP_READ
                    291:                  block : offset
                    292:                  length : length 
                    293:                  buffer : buffer
                    294:                  client: client
                    295:                  pending : NULL
                    296:                  actualLength : actualLength];
                    297:        xpr_sd("%s read: RETURNING %s\n", [self name],
                    298:                [self stringFromReturn:rtn], 3,4,5);
                    299:        return(rtn);
                    300: }
                    301: 
                    302: - (IOReturn) readAsyncAt       : (unsigned)offset 
                    303:                                  length : (unsigned)length 
                    304:                                  buffer : (unsigned char *)buffer
                    305:                                  pending : (void *)pending
                    306:                                  client : (vm_task_t)client
                    307: {
                    308:        IOReturn rtn;
                    309:        
                    310:        xpr_sd("%s readAsync: offset 0x%x length 0x%x\n",
                    311:                [self name], offset, length, 4,5);
                    312:        rtn = [self deviceRwCommon : SDOP_READ
                    313:                  block : offset
                    314:                  length : length 
                    315:                  buffer : buffer
                    316:                  client : client
                    317:                  pending : (void *)pending
                    318:                  actualLength : NULL];
                    319:        xpr_sd("%s readAsync: RETURNING %s\n", [self name],
                    320:                [self stringFromReturn:rtn], 3,4,5);
                    321:        return(rtn);
                    322: }      
                    323: 
                    324: - (IOReturn) writeAt           : (unsigned)offset 
                    325:                                  length : (unsigned)length 
                    326:                                  buffer : (unsigned char *)buffer
                    327:                                  actualLength : (unsigned *)actualLength 
                    328:                                  client : (vm_task_t)client
                    329: {
                    330:        IOReturn rtn;
                    331:        
                    332:        xpr_sd("%s write: offset 0x%x length 0x%x\n",
                    333:                [self name], offset, length, 4,5);
                    334:        rtn = [self deviceRwCommon : SDOP_WRITE
                    335:                  block : offset
                    336:                  length : length 
                    337:                  buffer : buffer
                    338:                  client: client
                    339:                  pending : NULL
                    340:                  actualLength : actualLength];
                    341:        xpr_sd("%s deviceWrite: RETURNING %s\n", [self name],
                    342:                [self stringFromReturn:rtn], 3,4,5);
                    343:        return(rtn);
                    344: }                                      
                    345: 
                    346: - (IOReturn) writeAsyncAt      : (unsigned)offset 
                    347:                                  length : (unsigned)length 
                    348:                                  buffer : (unsigned char *)buffer
                    349:                                  pending : (void *)pending
                    350:                                  client : (vm_task_t)client
                    351: {
                    352:        IOReturn rtn;
                    353:        
                    354:        xpr_sd("%s writeAsync: offset 0x%x length 0x%x\n",
                    355:                [self name], offset, length, 4,5);
                    356:        rtn = [self deviceRwCommon : SDOP_WRITE
                    357:                  block : offset
                    358:                  length : length 
                    359:                  buffer : buffer
                    360:                  client : client
                    361:                  pending : (void *)pending
                    362:                  actualLength : NULL];
                    363:        xpr_sd("%s writeAsync: RETURNING %s\n", [self name],
                    364:                [self stringFromReturn:rtn], 3,4,5);
                    365:        return(rtn);
                    366: }
                    367: 
                    368: 
                    369: - (void) synchronizeCache
                    370: {
                    371:        IOSCSIRequest scsiReq;
                    372:        cdb_10_t *cdbp = &scsiReq.cdb.cdb_c10;
                    373:        sdBuf_t *sdBuf;
                    374:        
                    375:        bzero(&scsiReq, sizeof(IOSCSIRequest));
                    376:        scsiReq.target = _target;
                    377:        scsiReq.lun = _lun;
                    378:        scsiReq.timeoutLength = SD_TIMEOUT_SIMPLE;
                    379:        scsiReq.disconnect = 1;
                    380:        
                    381:        sdBuf = [self allocSdBuf:NULL];
                    382:        sdBuf->command = SDOP_CDB_WRITE;
                    383:        sdBuf->scsiReq = &scsiReq;
                    384:        sdBuf->retryDisable = 1;
                    385:        sdBuf->needsDisk = 0;
                    386:        
                    387:        /* Zeroing the lba and count fields will cause the drive to
                    388:         * flush everything. We should be able to zero these fields
                    389:         * explicitly, but for some reason the 10-byte commands don't
                    390:         * have the proper field definitions. 
                    391:         */
                    392:        bzero(cdbp,10);
                    393:        
                    394:        cdbp->c10_opcode = 0x35;
                    395:        cdbp->c10_lun = _lun;
                    396: 
                    397:        [self enqueueSdBuf:sdBuf];
                    398: 
                    399:        [self freeSdBuf:sdBuf];
                    400: }
                    401: 
                    402: - (IODiskReadyState)updateReadyState
                    403: {
                    404:        IOSCSIRequest scsiReq;
                    405:        cdb_6_t *cdbp = &scsiReq.cdb.cdb_c6;
                    406:        sdBuf_t *sdBuf;
                    407:        IODiskReadyState readyState;
                    408:        esense_reply_t senseReply;
                    409:        
                    410:        xpr_sd("%s updateReadyState\n", [self name], 2,3,4,5);
                    411: 
                    412:        if( NO == _isReserved) {
                    413:             return([self lastReadyState]);
                    414:        }
                    415: 
                    416:        bzero(&scsiReq, sizeof(IOSCSIRequest));
                    417:        scsiReq.target = _target;
                    418:        scsiReq.lun = _lun;
                    419:        scsiReq.timeoutLength = SD_TIMEOUT_SIMPLE;
                    420:        scsiReq.disconnect = 1;
                    421:        
                    422:        sdBuf = [self allocSdBuf:NULL];
                    423:        sdBuf->command = SDOP_CDB_WRITE;
                    424:        sdBuf->scsiReq = &scsiReq;
                    425:        sdBuf->retryDisable = 1;
                    426:        sdBuf->needsDisk = 0;
                    427:        
                    428:        cdbp->c6_opcode = C6OP_TESTRDY;
                    429:        cdbp->c6_lun = _lun;
                    430:        
                    431:        [self enqueueSdBuf:sdBuf];
                    432: 
                    433:        /*
                    434:         * FIXME - how to distinguish not ready from no disk???
                    435:         */
                    436:        switch(scsiReq.driverStatus) {
                    437:            case SR_IOST_GOOD:
                    438:                readyState = IO_Ready;
                    439:                break;
                    440:            default:
                    441:                readyState = IO_NotReady;
                    442:                break;
                    443:                
                    444:        }
                    445:        xpr_sd("%s updateReadyState: DONE; state = %s\n", 
                    446:                [self name], 
                    447:                IOFindNameForValue(readyState, readyStateValues), 3,4,5);
                    448:        [self freeSdBuf:sdBuf];
                    449:        return(readyState);
                    450: }
                    451: 
                    452: /*
                    453:  * IOPhysicalDiskMethods protocol methods.
                    454:  */
                    455: - (IOReturn) ejectPhysical
                    456: {
                    457:        return [self scsiStartStop:SS_EJECT inhibitRetry:NO];
                    458: }
                    459: 
                    460: 
                    461: /*
                    462:  * Get physical parameters (dev_size, block_size, etc.) from new disk.
                    463:  */
                    464: - (IOReturn)updatePhysicalParameters
                    465: {
                    466:        capacity_reply_t capacityData;
                    467:        mode_sel_data_t  modeData;
                    468:        sc_status_t rtn;
                    469:        int block;
                    470:        void *dataBuf;
                    471:        void *freePtr;
                    472:        unsigned freeCnt;
                    473:        u_int block_size;
                    474:        BOOL wp = NO;
                    475:        int i;
                    476:        
                    477:        rtn = [self updateReadyState];
                    478:        if(rtn) {
                    479:                return IO_R_NOT_READY;
                    480:        }
                    481:        rtn = [self sdReadCapacity:&capacityData];
                    482:        if(rtn) {
                    483:                return(IO_R_IO);
                    484:        }
                    485:        [self setDiskSize:scsi_lastlba(&capacityData) + 1];
                    486:        [self setBlockSize:scsi_blklen(&capacityData)];
                    487:        
                    488:        /*
                    489:         * Try reading a block to see if disk is formatted.
                    490:         */
                    491:        block_size = [self blockSize];
                    492:        dataBuf = [_controller allocateBufferOfLength:block_size
                    493:                        actualStart:&freePtr
                    494:                        actualLength:&freeCnt];
                    495:        block = 10;
                    496:        for(i=0; i<5; i++) {
                    497:                rtn = [self sdRawRead:block blockCnt:1 buffer:dataBuf];
                    498:                if(rtn == IO_R_SUCCESS) {
                    499:                        break;
                    500:                }
                    501:                block += 10;
                    502:        }
                    503:        if(rtn == IO_R_SUCCESS) 
                    504:                [self setFormattedInternal:1];
                    505:        else
                    506:                [self setFormattedInternal:0];
                    507: 
                    508:        IOFree(freePtr, freeCnt);
                    509:        
                    510:        /*
                    511:         * Mark CD-ROMs as write-protected; use a mode sense for the others.
                    512:         */
                    513: 
                    514:        if(_inquiryDeviceType == DEVTYPE_CDROM)
                    515:                wp = YES;
                    516:        else {
                    517:                bzero(&modeData, sizeof(mode_sel_data_t));
                    518:                rtn = [self sdModeSense:&modeData];
                    519: 
                    520:                if (modeData.msd_header.msh_wp)
                    521:                        wp = YES;
                    522:        }
                    523: 
                    524:        [self setWriteProtected: wp];
                    525: 
                    526:        return(IO_R_SUCCESS);
                    527: }
                    528: 
                    529: /*
                    530:  * Called by volCheck thread when WS has told us that a requested disk is
                    531:  * not present. Pending I/Os which require a disk to be present must be 
                    532:  * aborted.
                    533:  */
                    534: - (void)abortRequest
                    535: {
                    536:        sdBuf_t *sdBuf;
                    537:        
                    538:        xpr_sd("%s: abortRequest\n", [self name], 2,3,4,5);
                    539:        
                    540:        sdBuf = [self allocSdBuf:NULL];
                    541:        sdBuf->command = SDOP_ABORT;
                    542:        sdBuf->needsDisk = 0;
                    543:        [self enqueueSdBuf:sdBuf];
                    544:        xpr_sd("%s abortRequest: done %s\n", [self name], 2,3,4,5);
                    545:        [self freeSdBuf:sdBuf];
                    546:        return;
                    547: }
                    548: 
                    549: /*
                    550:  * Called by the volCheck thread when a transition to "ready" is detected.
                    551:  * Pending I/Os which require a disk may proceed. All we have to do is 
                    552:  * wakeup the I/O threads which are waiting for something to show up 
                    553:  * in an I/O queue.
                    554:  */
                    555: - (void)diskBecameReady
                    556: {
                    557:        xpr_sd("diskBecameReady: %s\n", [self name], 2,3,4,5);
                    558:        [_ioQLock lock];
                    559:        [_ioQLock unlockWith:WORK_AVAILABLE];
                    560: }
                    561: 
                    562: /*
                    563:  * Inquire if disk is present; if not, and 'prompt' is YES, ask for it. 
                    564:  * Returns IO_R_NO_DISK if:
                    565:  *    prompt YES, disk not present, and user cancels request for disk.
                    566:  *    prompt NO, disk not present.
                    567:  * Else returns IO_R_SUCCESS.
                    568:  */
                    569: - (IOReturn)isDiskReady        : (BOOL)prompt
                    570: {
                    571:        sdBuf_t *sdBuf;
                    572:        IOReturn rtn;
                    573:        
                    574:        xpr_sd("%s: diskBecameReady\n", [self name], 2,3,4,5);
                    575: 
                    576:        if( NO == _isReserved)
                    577:                return(IO_R_NO_DISK);
                    578: 
                    579:        if([self lastReadyState] == IO_Ready) {
                    580:                /*
                    581:                 * This one's easy...
                    582:                 */
                    583:                return(IO_R_SUCCESS);
                    584:        }
                    585:        if(!prompt) {
                    586:                return(IO_R_NO_DISK);
                    587:        }
                    588:        sdBuf = [self allocSdBuf:NULL];
                    589:        sdBuf->command = SDOP_PROBEDISK;
                    590:        sdBuf->needsDisk = 1;
                    591:        rtn = [self enqueueSdBuf:sdBuf];
                    592:        xpr_sd("%s diskBecameReady: returning %s\n", [self name], 
                    593:                [self stringFromReturn:rtn], 3,4,5);
                    594:        [self freeSdBuf:sdBuf];
                    595:        return(rtn);
                    596: }      
                    597: 
                    598: /*
                    599:  * We have to override IODisk's setLastReadyState: so we know when to 
                    600:  * clear our local ejectPending flag.
                    601:  */
                    602:  - (void)setLastReadyState : (IODiskReadyState)readyState
                    603:  {
                    604:        xpr_sd("sd setLastReadyState\n", 1,2,3,4,5);
                    605:        if(_ejectPending && (readyState != IO_Ejecting))
                    606:                _ejectPending = 0;
                    607:        [super setLastReadyState:readyState];
                    608:  }
                    609: 
                    610: /*
                    611:  * Exported methods unique to the SCSIDisk class.
                    612:  * Note caller must provide well-aligned DMA buffers.
                    613:  */
                    614: - (IOReturn) sdCdbRead                 : (IOSCSIRequest *)scsiReq       /* SCSI parameters */
                    615:                                   buffer:(void *)buffer /* data destination */
                    616:                                   client:(vm_task_t)client;
                    617: {
                    618:        sdBuf_t *sdBuf;
                    619:        IOReturn rtn;
                    620:        
                    621:        xpr_sd("sd%d sdCdbRead: opcode = 0x%x\n", [self unit],
                    622:                scsiReq->cdb.cdb_opcode, 3,4,5);
                    623:                
                    624:        sdBuf = [self allocSdBuf:NULL];
                    625:        sdBuf->command = SDOP_CDB_READ;
                    626:        sdBuf->scsiReq = scsiReq;
                    627:        sdBuf->buf = buffer;
                    628:        sdBuf->client = client;
                    629:        sdBuf->pending = NULL;
                    630:        sdBuf->needsDisk = 0;
                    631:        rtn = [self enqueueSdBuf:sdBuf];
                    632:        xpr_sd("sd%d sdCdbRead: returning %s\n", [self unit],
                    633:                [self stringFromReturn:rtn], 3,4,5);
                    634:        [self freeSdBuf:sdBuf];
                    635:        return(rtn);
                    636: }
                    637: 
                    638: - (IOReturn) sdCdbWrite                : (IOSCSIRequest *)scsiReq       /* SCSI parameters */
                    639:                                   buffer:(void *)buffer /* data destination */
                    640:                                   client:(vm_task_t)client
                    641: {
                    642:        sdBuf_t *sdBuf;
                    643:        IOReturn rtn;
                    644:        
                    645:        xpr_sd("sd%d sdCdbWrite: opcode = 0x%x\n", [self unit],
                    646:                scsiReq->cdb.cdb_opcode, 3,4,5);
                    647:                
                    648:        sdBuf = [self allocSdBuf:NULL];
                    649:        sdBuf->command = SDOP_CDB_WRITE;
                    650:        sdBuf->scsiReq = scsiReq;
                    651:        sdBuf->buf = buffer;
                    652:        sdBuf->client = client;
                    653:        sdBuf->pending = NULL;
                    654:        sdBuf->needsDisk = 0;
                    655:        rtn = [self enqueueSdBuf:sdBuf];
                    656:        xpr_sd("sd%d sdCdbWrite: returning %s\n", [self unit],
                    657:                [self stringFromReturn:rtn], 3,4,5);
                    658:        [self freeSdBuf:sdBuf];
                    659:        return(rtn);    
                    660: }
                    661: 
                    662: - (int)target
                    663: {
                    664:        return _target;
                    665: }
                    666: 
                    667: - (int)lun
                    668: {
                    669:        return _lun;
                    670: }
                    671: 
                    672: /*
                    673:  * This is mainly here for the convenience of 486 CDROM boot. It's cheap so
                    674:  * we'll leave it in for other platforms too.
                    675:  */
                    676: - (unsigned char)inquiryDeviceType
                    677: {      
                    678:        return _inquiryDeviceType;
                    679: }
                    680: 
                    681: - controller
                    682: {
                    683:        return _controller;
                    684: }
                    685: 
                    686: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
                    687: {
                    688:     if( [super getDevicePath:path maxLength:maxLen useAlias:doAlias]) {
                    689: 
                    690:        char    unitStr[ 12 ];
                    691:        int     len = maxLen - strlen( path);
                    692: 
                    693:        sprintf( unitStr, "/@%x", [self target]);
                    694:        len -= strlen( unitStr);
                    695:        if( len < 0)
                    696:            return( nil);
                    697:         strcat( path, unitStr);
                    698:        if( [self lun]) {
                    699:             sprintf( unitStr, ",%x", [self lun]);
                    700:             len -= strlen( unitStr);
                    701:             if( len < 0)
                    702:                 return( nil);
                    703:             strcat( path, unitStr);
                    704:        }
                    705:        return( self);
                    706:     }
                    707:     return( nil);
                    708: }
                    709: 
                    710: - (char *) matchDevicePath:(char *)matchPath
                    711: {
                    712:     BOOL       matches = NO;
                    713:     char    *  unitStr;
                    714:     extern long int strtol(const char *nptr, char **endptr, int base);
                    715: 
                    716:     unitStr = [super matchDevicePath:matchPath];
1.1.1.2 ! root      717:     if( unitStr && (*unitStr == '/')) {
1.1       root      718:         unitStr = (char *)strchr( unitStr, '@');
                    719:         if( unitStr) {
                    720:             matches = ([self target] == strtol( unitStr + 1, &unitStr, 16));
                    721:             if( matches && (*unitStr == ','))
                    722:                 matches = ([self lun] == strtol( unitStr + 1, &unitStr, 16));
1.1.1.2 ! root      723:         }
1.1       root      724:     }
                    725:     if( matches)
                    726:         return( unitStr);
                    727:     else
                    728:        return( NULL);
                    729: }
                    730: 
                    731: - property_IOUnit:(char *)result length:(unsigned int *)maxLen
                    732: {
                    733:     if( [self lun])
                    734:         sprintf( result, "%d,%d", [self target], [self lun]);
                    735:     else
                    736:         sprintf( result, "%d", [self target]);
                    737: 
                    738:     return( self);
                    739: }
                    740: 
                    741: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
                    742: {
                    743:     static const char * inquiryDevTypeStrings[ 9 ] = {
                    744:        0, IOTypeTape, IOTypePrinter, 0,
                    745:        IOTypeWORM, IOTypeCDROM, IOTypeScanner, IOTypeOptical,
                    746:        IOTypeChanger
                    747:     };
                    748: 
                    749:     [super property_IODeviceType:types length:maxLen];
                    750: 
                    751:     if( (_inquiryDeviceType <= 8) && inquiryDevTypeStrings[ _inquiryDeviceType ]) {
                    752:        strcat( types, " ");
                    753:        strcat( types, inquiryDevTypeStrings[ _inquiryDeviceType ]);
                    754:     }
                    755:     return( self);
                    756: }
                    757: 
                    758: @end

unix.superglobalmegacorp.com

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