Annotation of drvEIDE/EIDE.drvproj/EIDE.lksproj/IdeKernel.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.0 (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 1997-1998 by Apple Computer, Inc., All rights reserved.
                     26:  * Copyright 1994-1997 NeXT Software, Inc., All rights reserved.
                     27:  *
                     28:  * IdeKern.m - UNIX front end for kernel IDE Disk driver.
                     29:  *
                     30:  * HISTORY 
                     31:  * 07-Jul-1994  Rakesh Dubey at NeXT
                     32:  *     Created from original driver written by David Somayajulu.
                     33:  * 19-Jun-97   Dieter Siegmund at Apple
                     34:  *     Updated to use the BSD4.4 ioctl interface that copies user
                     35:  *     buffer in/out of kernel automatically.
                     36:  */
                     37:  
                     38: #if (IO_DRIVERKIT_VERSION == 400)
                     39: #define _POSIX_SOURCE
                     40: #endif
                     41: 
                     42: /*
                     43:  * Note that this file builds with KERNEL_PRIVATE and !MACH_USER_API.
                     44:  */
                     45: #import <sys/types.h>
                     46: #import <sys/ttycom.h>
                     47: #import <sys/ucred.h>
                     48: #import <driverkit/kernelDiskMethods.h> 
                     49: #import <driverkit/generalFuncs.h>
                     50: #import "IdeCnt.h"
                     51: #import "IdeDiskInternal.h"
                     52: #import "IdeDisk.h"
                     53: #import <driverkit/kernelDriver.h>
                     54: #import <driverkit/IODiskPartition.h>
                     55: #import <sys/buf.h>
                     56: #import <sys/uio.h>
                     57: #import <bsd/dev/ldd.h>
                     58: #import <sys/errno.h>
                     59: #import <sys/proc.h>
                     60: #if (IO_DRIVERKIT_VERSION == 330)
                     61: #import <vm/vm_kern.h>
                     62: #endif
                     63: #import <sys/fcntl.h>
                     64: #import <sys/systm.h>
                     65: #import "IdeKernel.h"
                     66: 
                     67: #if (IO_DRIVERKIT_VERSION != 330)
                     68: extern struct vm_map *kernel_map;
                     69: #endif
                     70: 
                     71: IONamedValue iderValues[] = {
                     72: 
                     73:        {IDER_SUCCESS,          "Success"                       },
                     74:        {IDER_TIMEOUT,          "Timeout occured"               },
                     75:        {IDER_MEMALLOC,         "Couldn't allocate memory"      },
                     76:        {IDER_MEMFAIL,          "Memory transfer error"         },
                     77:        {IDER_REJECT,           "Bad field in ide_ioreq"        },
                     78:        {IDER_BADDRV,           "Drive not present"             },
                     79:        {IDER_CMD_ERROR,        "Command Failed"                },
                     80:        {IDER_VOLUNAVAIL,       "Requested Volume not available"},
                     81:        {IDER_SPURIOUS,         "Spurious Interrupt"            },
                     82:        {IDER_CNTRL_REJECT,     "Controller Reject"             },
                     83:        {0,                     NULL                            },
                     84: };
                     85: 
                     86: 
                     87: /*
                     88:  * dev-to-id map array. Instances of DiskObject register their IDs in
                     89:  * this array via registerUnixDisk:.
                     90:  */
                     91: IODevAndIdInfo IdeIdMap[NUM_IDE_DEV];
                     92: 
                     93: /*
                     94:  * Private per-unit data.
                     95:  */
                     96: static Ide_dev_t ide_dev[NUM_IDE_DEV] = {
                     97:        {NULL},
                     98:        {NULL},
                     99:        {NULL},
                    100:        {NULL},
                    101: };
                    102: 
                    103: /*
                    104:  * Indices of our entries in devsw's.
                    105:  */
                    106: static int ide_block_major;
                    107: static int ide_raw_major;
                    108: 
                    109: /*
                    110:  * prototypes for internal functions
                    111:  */
                    112: static unsigned ideminphys(struct buf *bp); 
                    113: static id ide_dev_to_id(dev_t dev);
                    114: 
                    115: /*
                    116:  * Initialize id map and Ide_dev. Currently invoked by Ide probe:.
                    117:  */
                    118: __private_extern__ void ide_init_idmap(id self)
                    119: {
                    120:     IODevAndIdInfo *idMap = IdeIdMap;
                    121:     Ide_dev_t *ide_devp = ide_dev;
                    122:     int unit;
                    123:     
                    124:     /* 
                    125:      * figure out our major device numbers.
                    126:      */
                    127:     ide_block_major = [self blockMajor];
                    128:     ide_raw_major = [self characterMajor];
                    129: 
                    130:     bzero((char *)idMap, sizeof(IODevAndIdInfo) * NUM_IDE_DEV);
                    131:     for (unit = 0; unit < NUM_IDE_DEV; unit++) {
                    132:        idMap->rawDev   = makedev(ide_raw_major, (unit << 3));
                    133:        idMap->blockDev = makedev(ide_block_major, (unit << 3));
                    134:        idMap++;
                    135:        ide_devp->physbuf = (struct buf *)IOMalloc(sizeof(struct buf));
                    136:        ide_devp->physbuf->b_flags = 0;
                    137:        ide_devp++;
                    138:     }
                    139: }
                    140: 
                    141: __private_extern__ IODevAndIdInfo *ide_idmap()
                    142: {
                    143:     return IdeIdMap;
                    144: }
                    145: 
                    146: __private_extern__ int
                    147: ideopen(dev_t dev, int flag, int devtype, struct proc * pp)
                    148: {
                    149:     id diskObj = ide_dev_to_id(dev);
                    150:     
                    151:     if(diskObj == nil)
                    152:        return(ENXIO);
                    153: 
                    154:     if([diskObj isDiskReady:NO])
                    155:        return(ENXIO);
                    156:                
                    157:     /*
                    158:      * Register this 'Unix-level open' event for IODiskPartitions.
                    159:      */
                    160:     if(IO_DISK_PART(dev) != IDE_LIVE_PART) {
                    161:        if(major(dev) == ide_block_major) {
                    162:            [diskObj setBlockDeviceOpen:YES];
                    163:        }
                    164:        else {
                    165:            [diskObj setRawDeviceOpen:YES];
                    166:        }
                    167:     }
                    168:     return(0); 
                    169: } /* ideopen() */
                    170: 
                    171: __private_extern__ int
                    172: ideclose(dev_t dev, int flag, int devtype, struct proc * pp)
                    173: {
                    174:     id diskObj = ide_dev_to_id(dev);
                    175:     
                    176:     if(diskObj == nil)
                    177:        return(ENXIO);
                    178:     if(IO_DISK_PART(dev) == IDE_LIVE_PART) { 
                    179:        return 0;
                    180:     } else     {
                    181:        if(![diskObj isInstanceOpen])
                    182:            return(ENXIO);
                    183:     }
                    184:            
                    185:     /*
                    186:      * Register this 'Unix-level close' event. We won't be called unless
                    187:      * this is the last close.
                    188:      */
                    189:     if(major(dev) == ide_block_major) {
                    190:        [diskObj setBlockDeviceOpen:NO];
                    191:     }
                    192:     else {
                    193:        [diskObj setRawDeviceOpen:NO];
                    194:     }
                    195:     
                    196:     return(0); 
                    197: } /* ideclose() */
                    198: 
                    199: /*
                    200:  * Raw I/O uses standard UNIX physio routine, resulting in async I/O requests
                    201:  * via idestrategy().
                    202:  */
                    203: 
                    204: __private_extern__ int
                    205: ideread(dev_t dev, struct uio *uiop, int ioflag)
                    206: {
                    207:     id                 diskObj = ide_dev_to_id(dev);
                    208:     int        unit = IO_DISK_UNIT(dev);
                    209:     int        rtn;
                    210: 
                    211:     if(diskObj == nil) {
                    212:        return(ENXIO);
                    213:     }
                    214: 
                    215: 
                    216:     rtn = physio(idestrategy, 
                    217:        ide_dev[unit].physbuf, 
                    218:        dev, 
                    219:        B_READ, 
                    220:        ideminphys, 
                    221:        uiop, 
                    222:        [diskObj blockSize]);
                    223:            
                    224:     return rtn;
                    225: } /* ideread() */
                    226: 
                    227: __private_extern__ int
                    228: idewrite(dev_t dev, struct uio *uiop, int ioflag)
                    229: {
                    230:     id                 diskObj = ide_dev_to_id(dev);
                    231:     int        unit = IO_DISK_UNIT(dev);
                    232:     int        rtn;
                    233:            
                    234:     if(diskObj == nil)
                    235:        return(ENXIO);
                    236:     
                    237: 
                    238:     rtn = physio(idestrategy, 
                    239:        ide_dev[unit].physbuf, 
                    240:        dev, 
                    241:        B_WRITE, 
                    242:        ideminphys, 
                    243:        uiop, 
                    244:        [diskObj blockSize]);
                    245:            
                    246:     return rtn;
                    247: } /* idewrite() */
                    248: 
                    249: __private_extern__ void
                    250: idestrategy(struct buf *bp)
                    251: {
                    252:     id diskObj = ide_dev_to_id(bp->b_dev);
                    253:     u_int offset;
                    254:     u_int bytes_req;
                    255:     void *bufp;
                    256:     u_int block_size;
                    257:     IOReturn rtn;
                    258:     vm_task_t client;
                    259:        
                    260:     if(diskObj == nil) {
                    261:        bp->b_error = ENXIO;
                    262:        goto bad;
                    263:     }
                    264:     
                    265:     if((bp->b_flags & (B_PHYS|B_KERNSPACE)) == B_PHYS) {
                    266:        /*
                    267:         * Physical I/O to user space.
                    268:         */
                    269:        client = IOVmTaskForBuf(bp);
                    270:     }
                    271:     else {
                    272:        /*
                    273:         * Either block I/O (always kernel space) or physical I/O
                    274:         * to kernel space (e.g., loadable file system).
                    275:         */
                    276:        client = IOVmTaskSelf();
                    277:     }
                    278:     
                    279:     block_size = [diskObj blockSize];
                    280:     if (block_size == 0) {
                    281:        bp->b_error = ENXIO;
                    282:        goto bad;
                    283:     }
                    284:     offset = bp->b_blkno;
                    285:     bytes_req = bp->b_bcount;
                    286:     bufp = bp->b_un.b_addr;
                    287: 
                    288:     if (bp->b_flags & B_READ) {
                    289:        rtn = [diskObj readAsyncAt:offset
                    290:                length:bytes_req
                    291:                buffer:bufp
                    292:                pending:bp
                    293:                client:client];
                    294:     }
                    295:     else {
                    296:        rtn = [diskObj writeAsyncAt:offset
                    297:                length:bytes_req
                    298:                buffer:bufp
                    299:                pending:bp
                    300:                client:client];
                    301:     }
                    302: 
                    303:     if (rtn) {
                    304:        bp->b_error = [diskObj errnoFromReturn:rtn];
                    305:        goto bad;
                    306:     }
                    307:     return;
                    308: 
                    309: bad:
                    310:     bp->b_flags |= B_ERROR;
                    311:     biodone(bp);
                    312: } /* fdstrategy() */
                    313: 
                    314: /*
                    315:  * Ops which are common to all IODiskPartitions are done on the raw device; 
                    316:  * Ide-specific ioctls are done directly to the live Ide object.
                    317:  */
                    318: __private_extern__ int
                    319: ideioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc * pp)
                    320: {
                    321:     int     unit = IO_DISK_UNIT(dev);
                    322:     id      diskObj;
                    323:     IODevAndIdInfo *idmap;
                    324:     int     rtn = 0;
                    325:     IOReturn irtn = IO_R_SUCCESS;
                    326:     struct ucred cred;
                    327:     u_short acflags;
                    328: 
                    329:     // user src/dest
                    330:     int     i;
                    331:     int     nblk;
                    332:     ideIoReq_t *ideIoReq;
                    333:     int     error;
                    334:     void   *userPtr;
                    335: 
                    336:     // in ideIoReq_t
                    337:     BOOL wrFlag = NO;
                    338:     unsigned bSize = 0;
                    339:     unsigned char *alignedPtr;
                    340: 
                    341:     if (unit > NUM_IDE_DEV)
                    342:        return (ENXIO);
                    343: #if 0
                    344:     if ((major(dev) != ide_raw_major) ||
                    345:        (IO_DISK_PART(dev) >= NUM_IDE_PART)) {
                    346:        return (ENXIO);
                    347:     }
                    348: #endif
                    349: 
                    350:     idmap = &IdeIdMap[unit];
                    351: 
                    352:     /*
                    353:      * First verify valid device. 
                    354:      */
                    355:     switch (cmd) {
                    356:       case DKIOCSFORMAT:
                    357:       case DKIOCGFORMAT:
                    358:       case DKIOCGLABEL:
                    359:       case DKIOCSLABEL:
                    360: 
                    361:        /*
                    362:         * Raw device, whatever the caller asked for. 
                    363:         */
                    364:        diskObj = idmap->partitionId[0];
                    365:        break;
                    366: 
                    367:       case IDEDIOCREQ:
                    368:       case IDEDIOCINFO:
                    369:       case DKIOCINFO:
                    370:       case DKIOCBLKSIZE:
                    371:       case DKIOCNUMBLKS:
                    372: 
                    373:        diskObj = idmap->liveId;
                    374:        break;
                    375: 
                    376:       default:
                    377:        return (EINVAL);
                    378:     }
                    379:     if (diskObj == nil)
                    380:        goto nodev;
                    381: 
                    382:     switch (cmd) {
                    383:       case DKIOCSFORMAT:
                    384: 
                    385:        /*
                    386:         * This can fail if block devices attached to this disk are open. 
                    387:         */
                    388:        irtn = [diskObj setFormatted:(*(u_int *) data)];
                    389:        break;
                    390: 
                    391:       case DKIOCGFORMAT:
                    392:        {
                    393:            *(int *)data = [diskObj isFormatted];
                    394:            break;
                    395:        }
                    396: 
                    397:       case DKIOCGLABEL:
                    398:        {
                    399:            struct disk_label *labelp;
                    400: 
                    401:            labelp = (struct disk_label *)IOMalloc(sizeof(*labelp));
                    402:            irtn = [diskObj readLabel:labelp];
                    403:            if (irtn == IO_R_SUCCESS) {
                    404:                *(struct disk_label *)data = *labelp;
                    405:            }
                    406:            IOFree(labelp, sizeof(*labelp));
                    407:            break;
                    408:        }
                    409: 
                    410:       case DKIOCSLABEL:
                    411:        {
                    412:            struct disk_label *labelp;
                    413: 
                    414:                //IOLog("DKIOCSLABEL called\n");
                    415: 
                    416:            labelp = (struct disk_label *)IOMalloc(sizeof(*labelp));
                    417:            *labelp = *(struct disk_label *)data;
                    418:            irtn = [diskObj writeLabel:labelp];
                    419:            IOFree(labelp, sizeof(*labelp));
                    420:            break;
                    421:        }
                    422: 
                    423:       case DKIOCINFO:
                    424:        {
                    425:            struct drive_info info;
                    426: 
                    427:            bzero(&info, sizeof(info));
                    428:            strcpy(info.di_name,[diskObj driveName]);
                    429:            info.di_devblklen = [diskObj blockSize];
                    430:            info.di_maxbcount = IDE_MAX_PHYS_IO;
                    431:            if (info.di_devblklen) {
                    432:                nblk = howmany(sizeof(struct disk_label),
                    433:                               info.di_devblklen);
                    434:            } else {
                    435:                nblk = 0;
                    436:            }
                    437:            for (i = 0; i < NLABELS; i++)
                    438:                info.di_label_blkno[i] = nblk * i;
                    439:            *(struct drive_info *) data = info;
                    440:            break;
                    441:        }
                    442: 
                    443:       case DKIOCBLKSIZE:
                    444:        *(int *)data = [diskObj blockSize];
                    445:        break;
                    446: 
                    447:       case DKIOCNUMBLKS:
                    448:        *(int *)data = [diskObj diskSize];
                    449:        break;
                    450: 
                    451:       case IDEDIOCREQ:
                    452: 
                    453:        /*
                    454:         * Perform specified I/O.
                    455:         */
                    456:        ideIoReq = (ideIoReq_t *) data;
                    457: //     if (!suser() && (ideIoReq->cmd != IDE_IDENTIFY_DRIVE))
                    458:        if (!suser(&cred, &acflags) && (ideIoReq->cmd != IDE_IDENTIFY_DRIVE))   {
                    459: //         return (u.u_error);
                    460:            return (EINVAL);
                    461:        }
                    462:        
                    463:        if ((ideIoReq->cmd == IDE_WRITE_DMA) ||
                    464:            (ideIoReq->cmd == IDE_READ_DMA)) {
                    465:            if ([[diskObj cntrlr] isDmaSupported:[diskObj driveNum]] != TRUE)
                    466:                return (EINVAL);
                    467:        }
                    468:         if (ideIoReq->cmd == IDE_IDENTIFY_DRIVE)
                    469:            ideIoReq->blkcnt = 1;
                    470: 
                    471:        userPtr = (void *)ideIoReq->addr;
                    472: 
                    473:        alignedPtr = ideIoReq->addr;
                    474:        if ((ideIoReq->cmd == IDE_WRITE) ||
                    475:            (ideIoReq->cmd == IDE_READ) ||
                    476:            (ideIoReq->cmd == IDE_READ_MULTIPLE) ||
                    477:            (ideIoReq->cmd == IDE_WRITE_MULTIPLE) ||
                    478:            (ideIoReq->cmd == IDE_READ_DMA) ||
                    479:            (ideIoReq->cmd == IDE_WRITE_DMA) ||
                    480:            (ideIoReq->cmd == IDE_IDENTIFY_DRIVE)) {
                    481:            if (ideIoReq->blkcnt != 0) {
                    482:                bSize = [diskObj blockSize];
                    483:                wrFlag = ((ideIoReq->cmd == IDE_WRITE) ||
                    484:                          (ideIoReq->cmd == IDE_WRITE_MULTIPLE) ||
                    485:                          (ideIoReq->cmd == IDE_WRITE_DMA));
                    486: 
                    487:                alignedPtr = (unsigned char *)
                    488:                    IOMalloc(ideIoReq->blkcnt * bSize);
                    489:                if (alignedPtr == 0) {
                    490:                    ideIoReq->status = IDER_MEMALLOC;
                    491:                    return (ENOMEM);
                    492:                }
                    493:                if (wrFlag) {
                    494:                    error = copyin(ideIoReq->addr,
                    495:                                   alignedPtr,
                    496:                                   ideIoReq->blkcnt * bSize);
                    497:                    if (error) {
                    498:                        ideIoReq->status = IDER_MEMFAIL;
                    499:                        goto err_exit;
                    500:                    }
                    501:                }
                    502:            }
                    503:            ideIoReq->addr = (caddr_t) alignedPtr;
                    504:            ideIoReq->map = (struct vm_map *)IOVmTaskSelf();
                    505:        }
                    506: 
                    507: 
                    508:        [diskObj ideXfrIoReq:ideIoReq];
                    509: 
                    510:        /*
                    511:         * Note if we got this far, we'll return 0; any errors are in
                    512:         * ideIoReq->status. 
                    513:         */
                    514:        if ((ideIoReq->cmd == IDE_WRITE) ||
                    515:            (ideIoReq->cmd == IDE_READ) ||
                    516:            (ideIoReq->cmd == IDE_READ_MULTIPLE) ||
                    517:            (ideIoReq->cmd == IDE_WRITE_MULTIPLE) ||
                    518:            (ideIoReq->cmd == IDE_READ_DMA) ||
                    519:            (ideIoReq->cmd == IDE_WRITE_DMA) ||
                    520:            (ideIoReq->cmd == IDE_IDENTIFY_DRIVE)) {
                    521: 
                    522:            ideIoReq->addr = userPtr;
                    523:            if (((ideIoReq->cmd == IDE_READ) ||
                    524:                 (ideIoReq->cmd == IDE_READ_MULTIPLE) ||
                    525:                 (ideIoReq->cmd == IDE_IDENTIFY_DRIVE) ||
                    526:                 (ideIoReq->cmd == IDE_READ_DMA)) &&
                    527:                (ideIoReq->blocks_xfered != 0)) {
                    528:                error = copyout(alignedPtr,
                    529:                                userPtr,
                    530:                                ideIoReq->blocks_xfered * bSize);
                    531:                if (error) {
                    532:                    ideIoReq->status = IDER_MEMFAIL;
                    533:                }
                    534:            }
                    535:     err_exit:
                    536: 
                    537:            /*
                    538:             * if we malloc'd any memory, free it. 
                    539:             */
                    540:            if (ideIoReq->blkcnt != 0)
                    541:                IOFree(alignedPtr, ideIoReq->blkcnt * bSize);
                    542:        }
                    543:        break;
                    544: 
                    545:       case IDEDIOCINFO:
                    546:        {
                    547:            ideDriveInfo_t *idep = (ideDriveInfo_t *) data;
                    548: 
                    549:            *idep = (ideDriveInfo_t)[diskObj ideGetDriveInfo];
                    550:            break;
                    551:        }
                    552:       default:
                    553:        return (EINVAL);
                    554:     }
                    555: 
                    556:     if (irtn)
                    557:        rtn = [diskObj errnoFromReturn:irtn];
                    558:     return (rtn);
                    559: 
                    560: nodev:
                    561:     return (ENXIO);
                    562: 
                    563: } /* ideioctl() */
                    564: 
                    565: /*
                    566:  * Obtain physical block size.
                    567:  */
                    568: __private_extern__ int
                    569: idesize(dev_t dev)
                    570: {
                    571:     id diskObj = ide_dev_to_id(dev);
                    572:     
                    573:     if(diskObj == nil) {
                    574:        return -1;
                    575:     }
                    576:     return [diskObj blockSize];
                    577: }
                    578: 
                    579: /*
                    580:  * Returns block and char major nums. This is used so that the PostLoad
                    581:  * program can create block and character nodes for IDE. 
                    582:  */
                    583: __private_extern__ void
                    584: ide_block_char_majors(int *blockmajor, int *charmajor)
                    585: {
                    586:     *blockmajor = ide_block_major;
                    587:     *charmajor = ide_raw_major;
                    588: }
                    589: 
                    590: static unsigned ideminphys(struct buf *bp)
                    591: {
                    592:     if (bp->b_bcount > IDE_MAX_PHYS_IO)
                    593:        bp->b_bcount = IDE_MAX_PHYS_IO;
                    594:     return(bp->b_bcount);
                    595: }
                    596: 
                    597: /*
                    598:  * Map dev_t to id. A nil return indicates ENXIO.
                    599:  */
                    600: static id ide_dev_to_id(dev_t dev)
                    601: {
                    602:     id rtn;
                    603:     int unit = IO_DISK_UNIT(dev);
                    604:     IODevAndIdInfo *idmap;
                    605:     int part = IO_DISK_PART(dev);
                    606:     
                    607:     if((unit >= NUM_IDE_DEV) || (part >= NUM_IDE_PART)) {
                    608:        return nil;
                    609:     }
                    610:     idmap = &IdeIdMap[unit];
                    611:     if(part == IDE_LIVE_PART) {
                    612:        if(major(dev) == ide_block_major) {
                    613:            rtn = nil;  
                    614:        }
                    615:        else {
                    616:            rtn = idmap->liveId;
                    617:        }
                    618:     }
                    619:     else {
                    620:        rtn = idmap->partitionId[part];
                    621:     }
                    622:     return rtn;
                    623: }
                    624: 
                    625: /* end of IdeKern.m */

unix.superglobalmegacorp.com

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