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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     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.