Annotation of kernel/bsd/dev/SCSIDiskKern.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*     Copyright (c) 1991 NeXT Computer, Inc.  All rights reserved. 
        !            26:  *
        !            27:  * SCSIDiskKern.m - UNIX front end for kernel SCSIDisk device. 
        !            28:  *
        !            29:  * HISTORY
        !            30:  * 30-Apr-91    Doug Mitchell at NeXT
        !            31:  *      Created. 
        !            32:  */
        !            33:  
        !            34: /*
        !            35:  * Note that this file builds with KERNEL_PRIVATE and !MACH_USER_API.
        !            36:  */
        !            37: #import        <sys/systm.h>   /* for nblkdev and nchrdev */
        !            38: #import <driverkit/SCSIDisk.h>
        !            39: #import <driverkit/kernelDiskMethods.h>
        !            40: #import <driverkit/SCSIDiskKern.h>
        !            41: #import <driverkit/SCSIDiskPrivate.h>
        !            42: #import <driverkit/SCSIDiskTypes.h>
        !            43: #import <driverkit/scsiTypes.h>
        !            44: #import <driverkit/SCSIStructInlines.h>
        !            45: #import <bsd/dev/scsireg.h>
        !            46: #import <driverkit/IODiskPartition.h>
        !            47: #import <driverkit/xpr_mi.h>
        !            48: #import <sys/buf.h>
        !            49: #import <sys/conf.h>
        !            50: #import <sys/uio.h>
        !            51: #import <bsd/dev/ldd.h>
        !            52: #import <sys/errno.h>
        !            53: #import <sys/proc.h>
        !            54: #import <vm/vm_kern.h>
        !            55: #import <sys/fcntl.h>
        !            56: #import <bsd/dev/disk.h>
        !            57: #import <driverkit/align.h>
        !            58: 
        !            59: #import <kern/assert.h>
        !            60: 
        !            61: 
        !            62: #ifdef ppc //bknight - 12/3/97 - Radar #2004660
        !            63: #define GROK_APPLE 1
        !            64: #endif //bknight - 12/3/97 - Radar #2004660
        !            65: 
        !            66: // wait until 20 seconds after probe non-ready disks
        !            67: #define MAX_DISK_PROBE_TIME    20
        !            68: 
        !            69: 
        !            70: int sdopen(dev_t dev, int flag, int devtype, struct proc * pp);
        !            71: int sdclose(dev_t dev, int flag, int devtype, struct proc * pp);
        !            72: int sdread(dev_t dev, struct uio *uiop, int ioflag);
        !            73: int sdwrite(dev_t dev, struct uio *uiop, int ioflag);
        !            74: int sdstrategy(register struct buf *bp);
        !            75: int sdioctl(dev_t dev, 
        !            76:        u_long cmd, 
        !            77:        caddr_t data, 
        !            78:        int flag, struct proc *pp);
        !            79: int sdsize(dev_t dev);
        !            80: 
        !            81: /*
        !            82:  * dev-to-id map array. Instances of DiskObject register their IDs in
        !            83:  * this array via registerUnixDisk:.
        !            84:  */
        !            85: static IODevAndIdInfo SCSIDiskIdMap[NUM_SD_DEV];
        !            86: 
        !            87: /*
        !            88:  * Private per-unit data.
        !            89:  */
        !            90: typedef struct _SCSIDisk_DataTag {
        !            91:     struct buf         physbuf;
        !            92:     unsigned int maxTransfer;
        !            93: } SCSIDisk_Data_t;
        !            94: 
        !            95: static SCSIDisk_Data_t *SCSIDisk_dev[NUM_SD_DEV];
        !            96: 
        !            97: /*
        !            98:  * Indices of our entries in devsw's.
        !            99:  */
        !           100: static int sd_block_major;
        !           101: static int sd_raw_major;
        !           102: 
        !           103: /*
        !           104:  * prototypes for internal functions
        !           105:  */
        !           106: static unsigned sdminphys(struct buf *bp); 
        !           107: static id sd_dev_to_id(dev_t dev);
        !           108: static id sd_phys_dev_id(dev_t dev);
        !           109: 
        !           110: static void sd_prevent_eject(id physicalDisk, BOOL prevent);
        !           111: 
        !           112: 
        !           113: #ifdef DDM_DEBUG
        !           114: static IONamedValue sdIoctlValues[] = {
        !           115:        {DKIOCSFORMAT,                  "DKIOCSFORMAT"  },
        !           116:        {DKIOCGFORMAT,                  "DKIOCGFORMAT"  },
        !           117:        {DKIOCGLABEL,                   "DKIOCGLABEL"   },
        !           118:        {DKIOCSLABEL,                   "DKIOCSLABEL"   },
        !           119:        {DKIOCEJECT,                    "DKIOCEJECT"    },
        !           120:        {SDIOCSRQ,                      "SDIOCSRQ"      },
        !           121:        {SDIOCGETCAP,                   "SDIOCGETCAP"   },
        !           122:        {DKIOCINFO,                     "DKIOCINFO"     },
        !           123:        {0,                             NULL            }
        !           124: };
        !           125: 
        !           126: #endif DDM_DEBUG
        !           127: 
        !           128: /*
        !           129:  * Initialize id map and SCSIDisk_dev. Currently invoked by SCSIDisk probe:.
        !           130:  */
        !           131: void sd_init_idmap()
        !           132: {
        !           133:        IODevAndIdInfo *idMap = SCSIDiskIdMap;
        !           134:        int unit;
        !           135:        struct bdevsw *bd;
        !           136:        struct cdevsw *cd;
        !           137:        
        !           138:        /* 
        !           139:         * figure out our major device numbers.
        !           140:         */
        !           141:        for (bd = bdevsw; bd < &bdevsw[nblkdev]; bd++) {
        !           142:                if (bd->d_open == (int (*)())sdopen) {
        !           143:                        sd_block_major = bd - bdevsw;
        !           144:                        break;
        !           145:                }
        !           146:        }
        !           147:        for (cd = cdevsw; cd < &cdevsw[nchrdev]; cd++) {
        !           148:                if (cd->d_open == (int (*)())sdopen) {
        !           149:                        sd_raw_major = cd - cdevsw;
        !           150:                        break;
        !           151:                }
        !           152:        }
        !           153: 
        !           154:        bzero(idMap, sizeof(*idMap) * NUM_SD_DEV);
        !           155:        for(unit=0; unit<NUM_SD_DEV; unit++) {
        !           156:                idMap->rawDev = makedev(sd_raw_major, (unit << 3));
        !           157:                idMap->blockDev = makedev(sd_block_major, (unit << 3));
        !           158:                idMap++;
        !           159:                SCSIDisk_dev[unit] = IOMalloc(sizeof(SCSIDisk_Data_t));
        !           160:                SCSIDisk_dev[unit]->physbuf.b_flags = 0;
        !           161:        }
        !           162: }
        !           163: 
        !           164: IODevAndIdInfo *sd_idmap()
        !           165: {
        !           166:        return SCSIDiskIdMap;
        !           167: }
        !           168: 
        !           169: int sdopen(dev_t dev, int flag, int devtype, struct proc *pp)
        !           170: {
        !           171:        id      diskObj;
        !           172:        BOOL    prompt;
        !           173:        int     err;
        !           174:        int     unit;
        !           175: 
        !           176:        // UFS partition a
        !           177:        diskObj = sd_dev_to_id(dev & 0x78);
        !           178:        if( diskObj)
        !           179:             [diskObj waitForProbe:MAX_DISK_PROBE_TIME];
        !           180: 
        !           181:        diskObj = sd_dev_to_id(dev);
        !           182:        if(diskObj == nil) {
        !           183:                return(ENXIO);
        !           184:        }
        !           185:        xpr_sd("%s: sdopen\n", [diskObj name], 2,3,4,5);
        !           186:        if(flag & O_NDELAY) {
        !           187:                prompt = NO;
        !           188:        }
        !           189:        else {
        !           190:                prompt = YES;
        !           191:        }
        !           192:        if([diskObj isDiskReady:prompt]) {
        !           193:                return(ENXIO);
        !           194:        }
        !           195: 
        !           196:        /*
        !           197:         * Register this 'Unix-level open' event for IODiskPartitions.
        !           198:         */
        !           199:        if(IO_DISK_PART(dev) != SD_LIVE_PART) {
        !           200:                // If this is the first open() on a removable disk,
        !           201:                // whether block or raw,  on any of the partitions,
        !           202:                // send a TEST UNIT READY to guarantee the disk is
        !           203:                // still present (isDiskReady doesn't do this). If
        !           204:                // it is, we send a PREVENT MEDIUM REMOVAL to lock
        !           205:                // down the removable disk while it is open.
        !           206:                //
        !           207:                // Note that we don't keep track of live open()'s,
        !           208:                // so we don't send TEST UNIT READY and/or PREVENT
        !           209:                // MEDIUM REMOVAL on live opens.  Should not be an
        !           210:                // issue (for now).
        !           211: 
        !           212:                if ( [diskObj isRemovable]    == YES &&
        !           213:                     [diskObj isInstanceOpen] == NO  &&
        !           214:                     [diskObj isAnyOtherOpen] == NO  )
        !           215:                {
        !           216:                  id physDisk = sd_phys_dev_id(dev);
        !           217:                  ASSERT(physDisk);
        !           218: 
        !           219:                  if ( [physDisk updateReadyState] != IO_Ready )
        !           220:                  {
        !           221:                    [physDisk diskNotReady];  // not ready state
        !           222:                    return ENXIO;
        !           223:                  }
        !           224: 
        !           225:                  sd_prevent_eject(physDisk, YES);
        !           226:                }
        !           227:                if(major(dev) == sd_block_major) {
        !           228:                        [diskObj setBlockDeviceOpen:YES];
        !           229:                }
        !           230:                else {
        !           231:                        [diskObj setRawDeviceOpen:YES];
        !           232:                }
        !           233:        }
        !           234: 
        !           235:        unit = IO_DISK_UNIT(dev);
        !           236: #ifdef GROK_APPLE
        !           237:        if (unit >= NUM_SD_DEV)
        !           238:                unit -= NUM_SD_DEV;
        !           239: #endif /* GROK_APPLE */
        !           240: 
        !           241:        /* We have the physical disk now so grab a maxTransfer if necessary */
        !           242:        if ( !SCSIDisk_dev[unit]->maxTransfer ) {
        !           243:            diskObj = sd_phys_dev_id(dev);      /* Get the physical disk */
        !           244:            SCSIDisk_dev[unit]->maxTransfer = [[diskObj controller] maxTransfer];
        !           245:        }
        !           246: 
        !           247:        return(0);      
        !           248: } /* sdopen() */
        !           249: 
        !           250: int sdclose(dev_t dev, int flag, int devtype, struct proc *pp)
        !           251: {
        !           252:        id diskObj = sd_dev_to_id(dev);
        !           253:        id physDisk = sd_phys_dev_id(dev);
        !           254:        
        !           255:        if(diskObj == nil) {
        !           256:                return(ENXIO);
        !           257:        }
        !           258:        kprintf("%s: sdclose major %d minor %d\n", [diskObj name],
        !           259:                major(dev),minor(dev));
        !           260:        xpr_sd("%s: sdclose\n", [diskObj name], 2,3,4,5);
        !           261: 
        !           262:        /* Issue a Synchronize-cache operation, which will force
        !           263:         * the device to flush its cached blocks.
        !           264:         */
        !           265:        if (physDisk != nil) {
        !           266:            [physDisk synchronizeCache];
        !           267:        }
        !           268: 
        !           269:        /*
        !           270:         * bknight - 12/3/97 - 2004660
        !           271:         * This test is safe, even when IO_DISK_PART denotes an HFS partition.
        !           272:         */
        !           273: 
        !           274:        if(IO_DISK_PART(dev) == SD_LIVE_PART) {
        !           275:                return 0;
        !           276:        } else if(![diskObj isInstanceOpen]) {
        !           277:                return(ENXIO);
        !           278:        }
        !           279:        
        !           280:        /*
        !           281:         * Register this 'Unix-level close' event. We won't be called unless
        !           282:         * this is the last close.
        !           283:         */
        !           284:        if(major(dev) == sd_block_major) {
        !           285:                [diskObj setBlockDeviceOpen:NO];
        !           286:        }
        !           287:        else {
        !           288:                [diskObj setRawDeviceOpen:NO];
        !           289:        }
        !           290: 
        !           291:        // If this is the last close() on a removable disk,
        !           292:        // whether block or raw, for all of the partitions,
        !           293:        // send an ALLOW MEDIUM REMOVAL to the SCSI drive.
        !           294:        //
        !           295:        // Note that we don't keep track of live open()'s,
        !           296:        // so we don't send PREVENT/ALLOW MEDIUM REMOVAL
        !           297:        // on live opens/closes either.
        !           298:        //
        !           299:        // Note that diskObj is an IOLogicalDisk here.
        !           300: 
        !           301:        if ( [diskObj isRemovable]    == YES &&
        !           302:             [diskObj isInstanceOpen] == NO  && // (raw and block)
        !           303:             [diskObj isAnyOtherOpen] == NO)    // (raw and block)
        !           304:        {
        !           305:          sd_prevent_eject(physDisk, NO);
        !           306:        }
        !           307:         
        !           308:        return(0);      
        !           309: } /* sdclose() */
        !           310: 
        !           311: /*
        !           312:  * Raw I/O uses standard UNIX physio routine, resulting in async I/O requests
        !           313:  * via sdstrategy().
        !           314:  *
        !           315:  * For now, we do DMA alignment in both disk driver's phys read and 
        !           316:  * physwrite as well as in the ioctl ops which do DMA. Ugh.
        !           317:  */
        !           318: #define SD_PHYS_ALIGN          1
        !           319: #if    SD_PHYS_ALIGN
        !           320: 
        !           321: #define FORCE_PAGE_ALIGN       1
        !           322: #if    FORCE_PAGE_ALIGN
        !           323: int    forceSdPageAlign = 0;
        !           324: #endif FORCE_PAGE_ALIGN
        !           325: #endif SD_PHYS_ALIGN
        !           326:                        
        !           327: int sdread(dev_t dev, struct uio *uiop, int ioflag)
        !           328: {
        !           329:        id              diskObj = sd_dev_to_id(dev);
        !           330:        int             unit = IO_DISK_UNIT(dev);
        !           331:        int             rtn;
        !           332: #if    SD_PHYS_ALIGN
        !           333:        void            *freePtr = NULL;        // memory to free
        !           334:        void            *alignedPtr = NULL;     // DMA target
        !           335:        int             freeCnt = 0;            // size to free
        !           336:        void            *userPtr = NULL;        // user spec'd pointer 
        !           337:        BOOL            didAlign = NO;
        !           338:        struct iovec    *iov;
        !           339:        int             userCnt = 0;
        !           340:        int             userSegflg = 0;
        !           341:        IODMAAlignment  dmaAlign;
        !           342:        id              liveId = sd_phys_dev_id(dev);
        !           343: #endif SD_PHYS_ALIGN
        !           344: 
        !           345:        if(diskObj == nil) {
        !           346:                return(ENXIO);
        !           347:        }
        !           348:        xpr_sd("sdread %s\n", [diskObj name], 2,3,4,5);
        !           349: 
        !           350:        /*
        !           351:         * Catch unformatted disks right now, since blockSize is zero in
        !           352:         * that case.
        !           353:         */
        !           354:        if(![diskObj isFormatted]) {
        !           355:                return EINVAL;
        !           356:        }
        !           357: 
        !           358: #if    SD_PHYS_ALIGN
        !           359: 
        !           360:        /*
        !           361:         * Note - this is temporary. We assume one vector and a well aligned
        !           362:         * byte count.
        !           363:         */
        !           364:        ASSERT(uiop->uio_iovcnt == 1);  
        !           365:        iov = uiop->uio_iov;
        !           366:        [[liveId controller] getDMAAlignment:&dmaAlign];
        !           367: #if    FORCE_PAGE_ALIGN
        !           368:        if(forceSdPageAlign) {
        !           369:                dmaAlign.readStart = PAGE_SIZE;
        !           370:        }
        !           371: #endif FORCE_PAGE_ALIGN
        !           372:        if( ( (dmaAlign.readStart > 1) && 
        !           373:              !IOIsAligned(iov->iov_base, dmaAlign.readStart)
        !           374:            ) ||
        !           375:            ( (dmaAlign.readLength > 1) && 
        !           376:              !IOIsAligned(iov->iov_len, dmaAlign.readLength)
        !           377:            ) 
        !           378: #if sparc
        !           379:                        || 1
        !           380: #endif
        !           381:          ) {
        !           382:                didAlign = YES;
        !           383:                alignedPtr = [[liveId controller] allocateBufferOfLength:
        !           384:                                iov->iov_len
        !           385:                        actualStart:&freePtr
        !           386:                        actualLength:&freeCnt];
        !           387:                userPtr = (void *)iov->iov_base;
        !           388:                iov->iov_base = (caddr_t)alignedPtr;
        !           389:                userCnt = iov->iov_len;
        !           390:                
        !           391:                /*
        !           392:                 * DMA to kernel space now...
        !           393:                 */
        !           394:                userSegflg = uiop->uio_segflg;
        !           395:                uiop->uio_segflg = UIO_SYSSPACE;
        !           396:        }
        !           397: #endif SD_PHYS_ALIGN
        !           398: 
        !           399: #ifdef GROK_APPLE
        !           400:        if (unit >= NUM_SD_DEV)
        !           401:                unit -= NUM_SD_DEV;
        !           402: #endif /* GROK_APPLE */
        !           403: 
        !           404:        rtn = physio(sdstrategy, 
        !           405:                (struct buf *) SCSIDisk_dev[unit], 
        !           406:                dev, 
        !           407:                B_READ, 
        !           408:                sdminphys, 
        !           409:                uiop, 
        !           410:                [diskObj blockSize]);
        !           411:                
        !           412: #if    SD_PHYS_ALIGN
        !           413:        if(didAlign) {
        !           414:                if(userSegflg == UIO_SYSSPACE) {
        !           415:                        bcopy(alignedPtr, userPtr, userCnt);
        !           416:                } 
        !           417:                else {
        !           418:                        copyout(alignedPtr, userPtr, userCnt);
        !           419:                }
        !           420:                IOFree(freePtr, freeCnt);
        !           421:        }
        !           422: #endif SD_PHYS_ALIGN
        !           423: 
        !           424:        return rtn;
        !           425: 
        !           426: } /* sdread() */
        !           427: 
        !           428: int sdwrite(dev_t dev, struct uio *uiop, int ioflag)
        !           429: {
        !           430:        id              diskObj = sd_dev_to_id(dev);
        !           431:        int             unit = IO_DISK_UNIT(dev);
        !           432:        int             rtn;
        !           433: #if    SD_PHYS_ALIGN
        !           434:        void            *freePtr = NULL;        // memory to free
        !           435:        void            *alignedPtr = NULL;     // DMA target
        !           436:        int             freeCnt = 0;            // size to free
        !           437:        void            *userPtr = NULL;        // user spec'd pointer 
        !           438:        BOOL            didAlign = NO;
        !           439:        struct iovec    *iov;
        !           440:        IODMAAlignment  dmaAlign;
        !           441:        id              liveId = sd_phys_dev_id(dev);
        !           442: #endif SD_PHYS_ALIGN
        !           443:                
        !           444:        if(diskObj == nil)
        !           445:                return(ENXIO);
        !           446:        xpr_sd("sd_write %s\n", [diskObj name], 2,3,4,5);
        !           447:        
        !           448:        /*
        !           449:         * Catch unformatted disks right now, since blockSize is zero in
        !           450:         * that case.
        !           451:         */
        !           452:        if(![diskObj isFormatted]) {
        !           453:                return EINVAL;
        !           454:        }
        !           455: 
        !           456: #if    SD_PHYS_ALIGN
        !           457: 
        !           458:        /*
        !           459:         * Note - this is temporary. We assume one vector and a well aligned
        !           460:         * byte count.
        !           461:         * We force a copyin to kernel space for raw user-level I/O to 
        !           462:         * ensure that rawVerify can work.
        !           463:         */
        !           464:        ASSERT(uiop->uio_iovcnt == 1);  
        !           465:        iov = uiop->uio_iov;
        !           466:        [[liveId controller] getDMAAlignment:&dmaAlign];
        !           467: #if    FORCE_PAGE_ALIGN
        !           468:        if(forceSdPageAlign) {
        !           469:                dmaAlign.writeStart = PAGE_SIZE;
        !           470:        }
        !           471: #endif FORCE_PAGE_ALIGN
        !           472:        if( ( (dmaAlign.writeStart > 1) && 
        !           473:              !IOIsAligned(iov->iov_base, dmaAlign.writeStart)
        !           474:            ) ||
        !           475:            ( (dmaAlign.writeLength > 1) && 
        !           476:              !IOIsAligned(iov->iov_len,  dmaAlign.writeLength)
        !           477:            ) 
        !           478: #if sparc
        !           479:                        || 1
        !           480: #endif
        !           481:                ) {
        !           482:                
        !           483:                didAlign = YES;
        !           484:                alignedPtr = [[liveId controller] allocateBufferOfLength:
        !           485:                                iov->iov_len
        !           486:                        actualStart:&freePtr
        !           487:                        actualLength:&freeCnt];
        !           488:                userPtr = (void *)iov->iov_base;
        !           489:                iov->iov_base = (caddr_t)alignedPtr;
        !           490:                if(uiop->uio_segflg == UIO_SYSSPACE) {
        !           491:                        bcopy(userPtr, alignedPtr, iov->iov_len);
        !           492:                }
        !           493:                else {
        !           494:                        copyin(userPtr, alignedPtr, iov->iov_len);
        !           495:                        uiop->uio_segflg = UIO_SYSSPACE;
        !           496:                }
        !           497:                
        !           498:        }
        !           499: #endif SD_PHYS_ALIGN
        !           500: 
        !           501: #ifdef GROK_APPLE
        !           502:        if (unit >= NUM_SD_DEV)
        !           503:                unit -= NUM_SD_DEV;
        !           504: #endif /* GROK_APPLE */
        !           505: 
        !           506:        rtn = physio(sdstrategy, 
        !           507:                (struct buf *) SCSIDisk_dev[unit], 
        !           508:                dev, 
        !           509:                B_WRITE, 
        !           510:                sdminphys, 
        !           511:                uiop, 
        !           512:                [diskObj blockSize]);
        !           513:                
        !           514: #if    SD_PHYS_ALIGN
        !           515:        if(didAlign) {
        !           516:                IOFree(freePtr, freeCnt);
        !           517:        }
        !           518: #endif SD_PHYS_ALIGN
        !           519: 
        !           520:        return rtn;
        !           521: 
        !           522: } /* sdwrite() */
        !           523: 
        !           524: int sdstrategy(struct buf *bp)
        !           525: {
        !           526:        id diskObj = sd_dev_to_id(bp->b_dev);
        !           527:        u_int offset;
        !           528:        u_int bytes_req;
        !           529:        void *bufp;
        !           530:        u_int block_size;
        !           531:        IOReturn rtn;
        !           532:        vm_task_t client;
        !           533:        
        !           534:        xpr_sd("%s: sdstrategy\n", [diskObj name], 2,3,4,5);
        !           535:        if(diskObj == nil) {
        !           536:                xpr_sd("sdstrategy: bad unit\n", 1,2,3,4,5);
        !           537:                bp->b_error = ENXIO;
        !           538:                goto bad;
        !           539:        }
        !           540:        if((bp->b_flags & (B_PHYS|B_KERNSPACE)) == B_PHYS) {
        !           541:                /*
        !           542:                 * Physical I/O to user space.
        !           543:                 */
        !           544:                client = ((task_t)bp->b_proc->task)->map;
        !           545:        }
        !           546:        else {
        !           547:                /*
        !           548:                 * Either block I/O (always kernel space) or physical I/O
        !           549:                 * to kernel space (e.g., loadable file system).
        !           550:                 */
        !           551:                client = kernel_map;
        !           552:        }
        !           553:        block_size = [diskObj blockSize];
        !           554:        if(block_size == 0) {
        !           555:                xpr_sd("sdstrategy %s: zero block_size\n", 
        !           556:                        [diskObj name], 2,3,4,5);
        !           557:                bp->b_error = ENXIO;
        !           558:                goto bad;
        !           559:        }
        !           560:        offset = bp->b_blkno;
        !           561:        bytes_req = bp->b_bcount;
        !           562:        bufp = bp->b_un.b_addr;
        !           563:        if(bp->b_flags & B_READ) {
        !           564:                rtn = [diskObj readAsyncAt:offset
        !           565:                        length:bytes_req
        !           566:                        buffer:bufp
        !           567:                        pending:bp
        !           568:                        client:client];
        !           569:        }
        !           570:        else {
        !           571:                rtn = [diskObj writeAsyncAt:offset
        !           572:                        length:bytes_req
        !           573:                        buffer:bufp
        !           574:                        pending:bp
        !           575:                        client:client];
        !           576:        }
        !           577:        if(rtn) {
        !           578:                /*
        !           579:                 * Check to see if 'IODisk' object has called completeTransfer.
        !           580:                 * if so then don't try to repair the bp structure just return.
        !           581:                 */
        !           582:                if (bp->b_flags & B_DONE) {
        !           583:                        xpr_sd("sdstrategy: COMMAND REJECT\n", 1,2,3,4,5);
        !           584:                        return -1;
        !           585:                }
        !           586:                bp->b_error = [diskObj errnoFromReturn:rtn];
        !           587:                goto bad;
        !           588:        }
        !           589:        xpr_sd("sdstrategy: SUCCESS\n", 1,2,3,4,5);
        !           590:        return(0);
        !           591:        
        !           592: bad:
        !           593:        bp->b_flags |= B_ERROR;
        !           594:        rtn = -1;
        !           595:        biodone(bp);
        !           596:        xpr_sd("sdstrategy: COMMAND REJECT\n", 1,2,3,4,5);
        !           597:        return(rtn);
        !           598: 
        !           599: } /* sdstrategy() */
        !           600: 
        !           601: /*
        !           602:  * Ops which are common to all IODiskPartitions are done on the raw device; 
        !           603:  * SCSI-specific ioctls are done directly to the live SCSIDisk object.
        !           604:  */
        !           605: int sdioctl(dev_t dev, 
        !           606:        u_long cmd, 
        !           607:        caddr_t data, 
        !           608:        int flag, 
        !           609:        struct proc *pp)
        !           610: {
        !           611:        int             unit = IO_DISK_UNIT(dev);
        !           612:        int             part = IO_DISK_PART(dev);
        !           613:        id              diskObj;
        !           614:        IODevAndIdInfo  *idmap;
        !           615:        int             rtn = 0;
        !           616:        IOReturn        irtn = IO_R_SUCCESS;
        !           617:        char            *userData = *(char **)data;     // user src/dest
        !           618:        void            *alignedPtr = NULL;             // kernel src/des
        !           619:        unsigned        alignedLength;
        !           620:        int             i;
        !           621:        IOSCSIRequest   scsiReq;                // new style - to controller
        !           622:        struct scsi_req *srp;                   // old style - from caller
        !           623:        int             nblk;
        !           624:        void            *freeBuf;
        !           625:        int             freeLength;
        !           626:        
        !           627:        xpr_sd("sdioctl: unit %d cmd %s\n", unit, 
        !           628:                IOFindNameForValue(cmd, sdIoctlValues), 3,4,5);
        !           629: 
        !           630: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           631: 
        !           632:        /* Compensate for an HFS partition. */
        !           633: 
        !           634:        if ( ! ( unit < NUM_SD_DEV ) ) {
        !           635:                unit -= NUM_SD_DEV;
        !           636:                part += NUM_SD_PART;
        !           637:        }
        !           638: 
        !           639: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           640: 
        !           641:        if(!(unit < NUM_SD_DEV))
        !           642:                return (ENXIO);
        !           643: 
        !           644: #if 0
        !           645:        if(major(dev) != sd_raw_major) {
        !           646:                xpr_sd("sdioctl: not raw device\n", 1,2,3,4,5);
        !           647:                return(ENXIO);  
        !           648:        }
        !           649: #endif
        !           650:        idmap = &SCSIDiskIdMap[unit];
        !           651: 
        !           652: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           653: 
        !           654:        /*
        !           655:         * Special cases for HFS partitions.
        !           656:         * DKIOCNUMBLKS - return # blocks on partition, not the whole device
        !           657:         * DKIOCSFORMAT - not permitted
        !           658:         * DKIOCGFORMAT - not permitted
        !           659:         * DKIOCGLABEL - not permitted
        !           660:         * DKIOCSLABEL - not permitted
        !           661:         */
        !           662: 
        !           663:        /* Is it an HFS partition ? */
        !           664: 
        !           665:        if ( ! ( part < NPART ) )
        !           666:        {
        !           667:                /*
        !           668:                 * For an HFS partition, return the # of blocks and block
        !           669:                 * size in the partition, rather than on the whole device.
        !           670:                 */
        !           671:                diskObj = idmap->partitionId[part];
        !           672:                switch ( cmd )
        !           673:                {
        !           674:                        case DKIOCBLKSIZE:
        !           675:                                *(int *)data = [diskObj blockSize];
        !           676:                                return (0);
        !           677:                        break;
        !           678: 
        !           679:                        case DKIOCNUMBLKS:
        !           680:                                *(int *)data = [diskObj diskSize];
        !           681:                                return (0);
        !           682:                        break;
        !           683: 
        !           684:                    case DKIOCSFORMAT:
        !           685:                    case DKIOCGFORMAT:
        !           686:                    case DKIOCGLABEL:
        !           687:                    case DKIOCSLABEL:
        !           688:                        return(EINVAL);
        !           689:                    break;
        !           690:                }
        !           691:        }
        !           692:        
        !           693: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           694: 
        !           695:        /* 
        !           696:         * Get appropriate device. Note we sometimes use the live 
        !           697:         * device partition (partition 7) here even if another partition
        !           698:         * was opened; we're just directing the I/O request to the correct
        !           699:         * object.
        !           700:         *
        !           701:         * Also note that several of these ioctls can fail if not invoked
        !           702:         * upon partition0, or if any block devices are open, or if any
        !           703:         * other partitions are open. That's handled elsewhere.
        !           704:         */
        !           705:        switch (cmd) {
        !           706:            case DKIOCSFORMAT:
        !           707:            case DKIOCGFORMAT:
        !           708:            case DKIOCGLABEL:
        !           709:            case DKIOCSLABEL:
        !           710:            case DKIOCEJECT:
        !           711:                /* 
        !           712:                 * These must be performed on a valid raw device, 
        !           713:                 * but if caller asked for live device (as some disk 
        !           714:                 * diags are liable to do), we'll given them raw
        !           715:                 * partition a.
        !           716:                 */
        !           717:                {
        !           718: 
        !           719: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           720: 
        !           721:                        /* Treat HFS partitions like the live partition, too. */
        !           722: 
        !           723:                        if ( part >= SD_LIVE_PART ) {
        !           724:                                part = 0;
        !           725:                        }
        !           726: 
        !           727: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           728: 
        !           729:                        if(part == SD_LIVE_PART) {
        !           730:                                part = 0;
        !           731:                        }
        !           732: 
        !           733: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !           734: 
        !           735:                        diskObj = idmap->partitionId[part];
        !           736:                }
        !           737:                break;
        !           738: 
        !           739:            case DKIOCGLOCATION:
        !           740:                     diskObj = idmap->partitionId[part];
        !           741:                break;
        !           742: 
        !           743:            case SDIOCSRQ:
        !           744:            case SDIOCGETCAP:
        !           745:            case DKIOCINFO:
        !           746:            case DKIOCBLKSIZE:
        !           747:            case DKIOCNUMBLKS:
        !           748:                diskObj = idmap->liveId;
        !           749:                break;
        !           750:            default:
        !           751:                xpr_sd("sdioctl: BAD cmd (0x%x)\n", cmd,2,3,4,5);
        !           752:                return(EINVAL);
        !           753:        }
        !           754:        if(diskObj == nil)
        !           755:                goto nodev;
        !           756:        
        !           757:        switch (cmd) {
        !           758:            case DKIOCSFORMAT:
        !           759:                /*
        !           760:                 * This can fail if block devices attached to this disk are 
        !           761:                 * open.
        !           762:                 */
        !           763:                irtn = [diskObj setFormatted:(*(u_int *)data)];
        !           764:                break;
        !           765:                
        !           766:            case DKIOCGFORMAT:
        !           767:                {
        !           768:                        *(int *)data = [diskObj isFormatted];
        !           769:                        break;
        !           770:                }
        !           771:                
        !           772:            case DKIOCGLABEL:
        !           773:                {
        !           774:                        struct disk_label *labelp;
        !           775:                        
        !           776:                        labelp = IOMalloc(sizeof(*labelp));
        !           777:                        irtn = [diskObj readLabel:labelp];
        !           778:                        if(irtn == IO_R_SUCCESS) {
        !           779:                        *(struct disk_label *)data = *labelp;
        !           780:                        }
        !           781:                        IOFree(labelp, sizeof(*labelp));
        !           782:                        break;
        !           783:                }
        !           784:                
        !           785:            case DKIOCSLABEL:
        !           786:                {
        !           787:                        struct disk_label *labelp;
        !           788:                        
        !           789:                        labelp = IOMalloc(sizeof(*labelp));
        !           790:                        *labelp = *(struct disk_label *)data;
        !           791:                        irtn = [diskObj writeLabel:labelp];
        !           792:                        IOFree(labelp, sizeof(*labelp));
        !           793:                        break;
        !           794:                }
        !           795:                
        !           796:            case DKIOCINFO:
        !           797:                {
        !           798:                        struct drive_info info;
        !           799:                        
        !           800:                        bzero(&info, sizeof(info));
        !           801:                        strcpy(info.di_name, [diskObj driveName]);
        !           802:                        info.di_devblklen = [diskObj blockSize];
        !           803:                        info.di_maxbcount = SCSIDisk_dev[unit]->maxTransfer;
        !           804:                        if(info.di_devblklen) {
        !           805:                                /*
        !           806:                                 * Careful, blockSize might be 0 for an
        !           807:                                 * unformatted disk.
        !           808:                                 */
        !           809:                                nblk = howmany(sizeof(struct disk_label),
        !           810:                                        info.di_devblklen);
        !           811:                                for (i = 0; i < NLABELS; i++)
        !           812:                                        info.di_label_blkno[i] = nblk * i;
        !           813:                        }
        !           814:                        *(struct drive_info *)data = info;
        !           815:                        break;
        !           816:                }
        !           817:                        
        !           818:            case DKIOCEJECT:
        !           819:                /*
        !           820:                 * This is a (legal) nop for non-removable drives. This 
        !           821:                 * merely accomodates a WSM quirk left over from
        !           822:                 * m68k develolpment; it's handled here instead of
        !           823:                 * in IODiskPartition to avoid propagating further...
        !           824:                 */
        !           825:                if(![diskObj isRemovable]) {
        !           826:                        break;
        !           827:                }
        !           828:                // Send an ALLOW MEDIUM REMOVAL to the SCSI drive
        !           829:                // to permit the ejection of the disk,  unless we
        !           830:                // detect another active open on this disk (aside
        !           831:                // from the one issuing this eject).  The [eject]
        !           832:                // method also does this check, don't worry.   We
        !           833:                // just don't want to send spurious PREVENT/ALLOW
        !           834:                // commands while other folks are doing I/O.
        !           835:                //
        !           836:                // Note that on successful ejection, a 2nd ALLOW
        !           837:                // MEDIUM REMOVAL will be sent after this on the
        !           838:                // close() of this device.  This is not an issue.
        !           839: 
        !           840:                if ( [diskObj isAnyOtherOpen]    == NO  &&
        !           841:                     [diskObj isBlockDeviceOpen] == NO )
        !           842:                {
        !           843:                  // Note that eject ioctls arrive on raw opens,
        !           844:                  // so we only check for outstanding block opens
        !           845:                  // on our device.
        !           846:                  sd_prevent_eject(idmap->liveId, NO);
        !           847: 
        !           848:                  // Eject the disk now.
        !           849:                  irtn = [diskObj eject];
        !           850: 
        !           851:                  // Send a PREVENT MEDIUM REMOVAL to the SCSI drive
        !           852:                  // to re-prevent the ejection of the disk if the
        !           853:                  // eject has failed for any reason.
        !           854:                  if (irtn) sd_prevent_eject(idmap->liveId, YES);
        !           855:                } else {
        !           856:                  irtn = [diskObj eject];
        !           857:                }
        !           858:                break;
        !           859:                
        !           860:            case DKIOCBLKSIZE:
        !           861:                *(int *)data = [diskObj blockSize];
        !           862:                break;
        !           863:                
        !           864:            case DKIOCNUMBLKS:
        !           865:                *(int *)data = [diskObj diskSize];
        !           866:                break;
        !           867: 
        !           868:            case DKIOCGLOCATION:
        !           869:                 if( nil == [diskObj getDevicePath:((struct drive_location *)data)->location
        !           870:                             maxLength:sizeof(((struct drive_location *)data)->location)
        !           871:                            useAlias:YES]       )
        !           872:                    irtn = IO_R_UNSUPPORTED;
        !           873:                break;
        !           874:                
        !           875:            case SDIOCSRQ:
        !           876:               
        !           877:                srp = (struct scsi_req *)data;
        !           878:                
        !           879:                /* if user expects to do some DMA, get some well-aligned
        !           880:                 * memory. Copy in the user's data if a DMA write is 
        !           881:                 * expected. By using allocateBufferOfLength we guarantee 
        !           882:                 * that there is enough space in the buffer we pass to the 
        !           883:                 * controller to handle end-of-buffer alignment, although
        !           884:                 * we won't copy more than sr_dma_max to or from the 
        !           885:                 * caller.
        !           886:                 */
        !           887:                if(srp->sr_dma_max != 0) {
        !           888:                        IODMAAlignment dmaAlign;
        !           889:                        id controller = [idmap->liveId controller];
        !           890:                        unsigned alignment;
        !           891:                        
        !           892:                        [controller getDMAAlignment:&dmaAlign];
        !           893:                        if(srp->sr_dma_dir == SR_DMA_WR) {
        !           894:                                alignment = dmaAlign.writeLength;
        !           895:                        }
        !           896:                        else {
        !           897:                                alignment = dmaAlign.readLength;
        !           898:                        }
        !           899:                        if(alignment > 1) {
        !           900:                                alignedLength = IOAlign(unsigned,
        !           901:                                        srp->sr_dma_max,
        !           902:                                        alignment);
        !           903:                        }
        !           904:                        else {
        !           905:                                alignedLength = srp->sr_dma_max;
        !           906:                        }
        !           907:                        alignedPtr = [controller
        !           908:                                        allocateBufferOfLength:alignedLength
        !           909:                                actualStart:&freeBuf
        !           910:                                actualLength:&freeLength];
        !           911:                        if(srp->sr_dma_dir == SR_DMA_WR) {
        !           912:                                rtn = copyin(srp->sr_addr, alignedPtr,
        !           913:                                        srp->sr_dma_max);
        !           914:                                if(rtn) {
        !           915:                                    xpr_sd(" ...copyin() returned %d\n",
        !           916:                                            rtn, 2,3,4,5);
        !           917:                                    srp->sr_io_status = SR_IOST_MEMF;
        !           918:                                    goto err_exit;
        !           919:                                }
        !           920:                        }
        !           921:                } else {
        !           922:                        alignedLength = 0;
        !           923:                        alignedPtr = 0;
        !           924:                }
        !           925: 
        !           926:                /*
        !           927:                 * Generate a contemporary version of scsi_req.
        !           928:                 */
        !           929:                bzero(&scsiReq, sizeof(scsiReq));
        !           930:                scsiReq.target = [diskObj target];
        !           931:                scsiReq.lun    = [diskObj lun];
        !           932:                /*
        !           933:                 * Careful. this assumes that the old and new cdb structs are
        !           934:                 * equivalent...
        !           935:                 */
        !           936:                scsiReq.cdb = srp->sr_cdb;
        !           937:                scsiReq.read = (srp->sr_dma_dir == SR_DMA_RD) ? 
        !           938:                        YES : NO;
        !           939:                scsiReq.maxTransfer     = alignedLength;
        !           940:                scsiReq.timeoutLength   = srp->sr_ioto;
        !           941:                scsiReq.disconnect      = srp->sr_discon_disable ? 0 : 1;
        !           942:                scsiReq.cmdQueueDisable = srp->sr_cmd_queue_disable;
        !           943:                scsiReq.syncDisable     = srp->sr_sync_disable;
        !           944:                scsiReq.cdbLength       = srp->sr_cdb_length;
        !           945:                
        !           946:                /*
        !           947:                 * Go for it.
        !           948:                 */
        !           949:                if(srp->sr_dma_dir == SR_DMA_WR) {
        !           950:                        irtn = [diskObj sdCdbWrite:&scsiReq
        !           951:                                buffer : alignedPtr
        !           952:                                client : kernel_map];
        !           953:                }
        !           954:                else {
        !           955:                        irtn = [diskObj sdCdbRead:&scsiReq
        !           956:                                buffer : alignedPtr
        !           957:                                client : kernel_map];
        !           958:                }
        !           959: 
        !           960:                /*
        !           961:                 * Copy status back to user. 
        !           962:                 */
        !           963:                srp->sr_io_status = scsiReq.driverStatus;
        !           964:                if(srp->sr_io_status == SR_IOST_BADST) {
        !           965:                        /* 
        !           966:                         * dmitch 9 Jun 94: Warning: this code is 
        !           967:                         * bogus, though benign. Lower levels will give us
        !           968:                         * SR_IOST_CHKSNV or SR_IOST_CHKSV in case of 
        !           969:                         * STAT_CHECK.
        !           970:                         */
        !           971:                        if(scsiReq.scsiStatus == STAT_CHECK)
        !           972:                                srp->sr_io_status = SR_IOST_CHKSNV;
        !           973:                }
        !           974:                srp->sr_scsi_status = scsiReq.scsiStatus;
        !           975:                srp->sr_dma_xfr = scsiReq.bytesTransferred;
        !           976:                if(srp->sr_dma_xfr > srp->sr_dma_max) {
        !           977:                        srp->sr_dma_xfr = srp->sr_dma_max;
        !           978:                }
        !           979:                srp->sr_exec_time.tv_sec = srp->sr_exec_time.tv_usec = 0;
        !           980:                
        !           981:                /*
        !           982:                 * Copy read data back to user if appropriate.
        !           983:                 */
        !           984:                if((srp->sr_dma_dir == SR_DMA_RD) && 
        !           985:                   (scsiReq.bytesTransferred != 0)) {
        !           986:                        rtn = copyout(alignedPtr, 
        !           987:                                srp->sr_addr, 
        !           988:                                srp->sr_dma_xfr);
        !           989:                }
        !           990:                /*
        !           991:                 * Copy sense data back to user if appropriate.
        !           992:                 */
        !           993:                if(srp->sr_io_status == SR_IOST_CHKSV) {
        !           994:                        srp->sr_esense = scsiReq.senseData;
        !           995:                }
        !           996: err_exit:
        !           997:                if (srp->sr_dma_max != 0) {
        !           998:                        IOFree(freeBuf, freeLength);
        !           999:                }
        !          1000:                break;
        !          1001: 
        !          1002:            case SDIOCGETCAP:
        !          1003:            {
        !          1004:                        irtn = [diskObj updatePhysicalParameters];
        !          1005:                        if(irtn)
        !          1006:                                break;
        !          1007:                        scsi_crp_setup((struct capacity_reply *) data,
        !          1008:                                [diskObj blockSize], [diskObj diskSize] - 1);
        !          1009:                }
        !          1010:                break;
        !          1011:                
        !          1012:            default:
        !          1013:                xpr_sd("sdioctl: BAD cmd (0x%x)\n", cmd,2,3,4,5);
        !          1014:                return(EINVAL);
        !          1015:        }
        !          1016: 
        !          1017:        if(irtn)
        !          1018:                rtn = [diskObj errnoFromReturn:irtn];
        !          1019:        xpr_sd("%s sdioctl: returning %s (errno %d)\n", 
        !          1020:                [diskObj name], [diskObj stringFromReturn:irtn],  
        !          1021:                rtn, 4,5);
        !          1022:        return(rtn);
        !          1023:        
        !          1024: nodev:
        !          1025:        xpr_sd("sdioctl: no such device (dev = 0x%x)\n", 
        !          1026:                dev, 2,3,4,5);
        !          1027:        return(ENXIO);
        !          1028:        
        !          1029: } /* sdioctl() */
        !          1030: 
        !          1031: /*
        !          1032:  * Obtain physical block size.
        !          1033:  */
        !          1034: int sdsize(dev_t dev)
        !          1035: {
        !          1036:        id diskObj = sd_dev_to_id(dev);
        !          1037:        
        !          1038:        if(diskObj == nil) {
        !          1039:                xpr_sd("sdsize: bad unit\n", 1,2,3,4,5);
        !          1040:                return -1;
        !          1041:        }
        !          1042:        return [diskObj blockSize];
        !          1043:        
        !          1044: }
        !          1045: 
        !          1046: static unsigned sdminphys(struct buf *bp)
        !          1047: {
        !          1048:        SCSIDisk_Data_t *dataBP = (SCSIDisk_Data_t *) bp;
        !          1049: 
        !          1050:        if (bp->b_bcount > dataBP->maxTransfer)
        !          1051:                bp->b_bcount = dataBP->maxTransfer;
        !          1052:        return bp->b_bcount;
        !          1053: }
        !          1054: 
        !          1055: /*
        !          1056:  * Map dev_t to id. A nil return indicates ENXIO.
        !          1057:  */
        !          1058: 
        !          1059: static id sd_dev_to_id(dev_t dev)
        !          1060: {
        !          1061:        id                                      rtn;
        !          1062:        int                                     unit = IO_DISK_UNIT(dev);
        !          1063:        int                                     part = IO_DISK_PART(dev);
        !          1064:        IODevAndIdInfo  *       idmap;
        !          1065: 
        !          1066: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1067: 
        !          1068:        if ( ! ( unit < NUM_SD_DEV ) ) {
        !          1069:                /* Modify the unit # under the assumption that it is an HFS device. */
        !          1070: 
        !          1071:                unit -= NUM_SD_DEV;
        !          1072:                
        !          1073:                /* Is it an HFS device? */
        !          1074: 
        !          1075:                if ( ! ( unit < NUM_SD_DEV ) ) {
        !          1076:                        rtn = nil;
        !          1077:                        goto Return;
        !          1078:                }
        !          1079: 
        !          1080:                /* Yes, it is an HFS device. */
        !          1081:                
        !          1082:                /* But it doesn't have a raw variant. */
        !          1083:                
        !          1084:                if ( major(dev) == sd_raw_major ) {
        !          1085:                        rtn = nil;
        !          1086:                        goto Return;
        !          1087:                }
        !          1088: 
        !          1089:                /* Modify the partition # to indicate an HFS partition and then proceed. */
        !          1090: 
        !          1091:                part += NUM_SD_PART;
        !          1092: 
        !          1093:        }
        !          1094: 
        !          1095: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1096: 
        !          1097:        if((unit >= NUM_SD_DEV) || (part >= NUM_SD_PART)) {
        !          1098:                return nil;
        !          1099:        }
        !          1100: 
        !          1101: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1102: 
        !          1103:        idmap = &SCSIDiskIdMap[unit];
        !          1104: 
        !          1105:        if(part == SD_LIVE_PART) {
        !          1106:                if(major(dev) == sd_block_major) {
        !          1107:                        /*
        !          1108:                         * Live partition on the block device not permitted.
        !          1109:                         */
        !          1110:                        rtn = nil;  
        !          1111:                }
        !          1112:                else {
        !          1113:                        rtn = idmap->liveId;
        !          1114:                }
        !          1115:        }
        !          1116:        else {
        !          1117:                rtn = idmap->partitionId[part];
        !          1118:        }
        !          1119: 
        !          1120: Return:
        !          1121: 
        !          1122:        return rtn;
        !          1123: }
        !          1124: 
        !          1125: /*
        !          1126:  * Obtain the id of the physical disk assiociated with specified dev.
        !          1127:  */
        !          1128: 
        !          1129: static id sd_phys_dev_id(dev_t dev)
        !          1130: {
        !          1131:        int unit = IO_DISK_UNIT(dev);
        !          1132: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1133:        id rtn;
        !          1134:        
        !          1135:        if ( ! ( unit < NUM_SD_DEV ) ) {
        !          1136:                /* Could it be an HFS partition? */
        !          1137: 
        !          1138:                unit -= NUM_SD_DEV;
        !          1139: 
        !          1140:                if ( ! (unit < NUM_SD_DEV) ) {
        !          1141:                        rtn = nil;
        !          1142:                        goto Return;
        !          1143:                }
        !          1144:                
        !          1145:                /* Yes, it is an HFS partition.  Use adjusted <unit>. */
        !          1146:                
        !          1147:        }
        !          1148: 
        !          1149:        rtn = SCSIDiskIdMap[unit].liveId;
        !          1150: 
        !          1151: Return:
        !          1152: 
        !          1153:        return rtn;
        !          1154: 
        !          1155: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1156:        if(unit > NUM_SD_DEV) {
        !          1157:                return nil;
        !          1158:        }
        !          1159:        return SCSIDiskIdMap[unit].liveId;
        !          1160: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
        !          1161: }
        !          1162: 
        !          1163: void sd_prevent_eject(id physicalDisk, BOOL prevent)
        !          1164: {
        !          1165:   //
        !          1166:   // Sends a SCSI PREVENT/ALLOW MEDIUM REMOVAL command to the given
        !          1167:   // disk (target and lun) in order to prevent or permit the manual
        !          1168:   // ejection of removable disk(s) inside the SCSI drive.
        !          1169:   //
        !          1170: 
        !          1171:   IOSCSIRequest scsiReq;
        !          1172: 
        !          1173:   //
        !          1174:   // Set up the SCSI REQUEST structure.  Note that cdbLength is an
        !          1175:   // optional field and is left as zero.
        !          1176:   //
        !          1177: 
        !          1178:   bzero(&scsiReq, sizeof(scsiReq));
        !          1179: 
        !          1180:   scsiReq.cdb.cdb_c6.c6_opcode = C60P_PREVENTALLOW;
        !          1181:   scsiReq.cdb.cdb_c6.c6_len    = (prevent ? 0x01 : 0x00);
        !          1182:   scsiReq.target               = [physicalDisk target];
        !          1183:   scsiReq.lun                  = [physicalDisk lun];
        !          1184:   scsiReq.read                 = YES;
        !          1185:   scsiReq.timeoutLength        = SD_TIMEOUT_SIMPLE;
        !          1186: 
        !          1187:   //
        !          1188:   // Execute the request.
        !          1189:   //
        !          1190: 
        !          1191:   [physicalDisk sdCdbRead : &scsiReq
        !          1192:                    buffer : NULL
        !          1193:                    client : kernel_map];
        !          1194: }
        !          1195: 
        !          1196: /* end of SCSIDiskKern.m */

unix.superglobalmegacorp.com

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