|
|
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: /* ! 26: * Copyright 1997-1998 by Apple Computer, Inc., All rights reserved. ! 27: * Copyright 1994-1997 NeXT Software, Inc., All rights reserved. ! 28: * ! 29: * ATADiskKernel.m - UNIX front end for kernel IDE/ATA Disk driver. ! 30: * ! 31: * HISTORY ! 32: * 07-Jul-1994 Rakesh Dubey at NeXT ! 33: * Created from original driver written by David Somayajulu. ! 34: * 19-Jun-97 Dieter Siegmund at Apple ! 35: * Updated to use the BSD4.4 ioctl interface that copies user ! 36: * buffer in/out of kernel automatically. ! 37: * 21-Feb-98 Brent Knight at Apple ! 38: * Added support for HFS partitions. Radar 2204950, 2004660 ! 39: */ ! 40: ! 41: #if (IO_DRIVERKIT_VERSION == 400) ! 42: #define _POSIX_SOURCE ! 43: #endif ! 44: ! 45: /* ! 46: * Note that this file builds with KERNEL_PRIVATE and !MACH_USER_API. ! 47: */ ! 48: #import <sys/types.h> ! 49: #import <sys/ttycom.h> ! 50: #import <sys/ucred.h> ! 51: #import <driverkit/kernelDiskMethods.h> ! 52: #import <driverkit/generalFuncs.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 "ATADiskInternal.h" ! 66: #import "ATADisk.h" ! 67: #import "ATADiskKernel.h" ! 68: ! 69: #if (IO_DRIVERKIT_VERSION != 330) ! 70: extern struct vm_map *kernel_map; ! 71: #endif ! 72: ! 73: #ifdef ppc //bknight - 2/21/98 - Radar 2204950, 2004660 ! 74: #define GROK_APPLE 1 ! 75: #endif //bknight - 2/21/98 - Radar 2204950, 2004660 ! 76: ! 77: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 78: /* ! 79: * For consistency with bsd/dev/SCSIDiskKern.m, we use the most ! 80: * significant bit of the 8-bit minor device number to flag HFS ! 81: * partitions. For SCSI devices, this meant that there could be ! 82: * 16 (= 4 bits) SCSI disks, each with 8 (= 3 bits) partitions, ! 83: * either UFS or HFS (= 1 bit). ! 84: * ! 85: * In SCSIDiskKern.h, NUM_SD_DEV is defined to be 16, which is ! 86: * just the right constant for checking that high bit of the ! 87: * Unit number and that's what I used in SCSIDiskKern.m. ! 88: * ! 89: * Unfortunately, we can't just use NUM_IDE_DEV here, because ! 90: * it is defined in IdeDiskInternal.h to be only 4. And since ! 91: * it seems inappropriate to include SCSIDiskKern.h here in ! 92: * IdeKernel.m, I am instead making this definition, which might ! 93: * some day migrate out into IdeDiskInternal.h, or which might ! 94: * be made obsolete by the forthcoming IOKit design. ! 95: */ ! 96: #define MAX_IDE_UNIT 16 ! 97: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 98: ! 99: IONamedValue iderValues[] = { ! 100: ! 101: {IDER_SUCCESS, "Success" }, ! 102: {IDER_TIMEOUT, "Timeout occured" }, ! 103: {IDER_MEMALLOC, "Couldn't allocate memory" }, ! 104: {IDER_MEMFAIL, "Memory transfer error" }, ! 105: {IDER_REJECT, "Bad field in ide_ioreq" }, ! 106: {IDER_BADDRV, "Drive not present" }, ! 107: {IDER_CMD_ERROR, "Command Failed" }, ! 108: {IDER_VOLUNAVAIL, "Requested Volume not available"}, ! 109: {IDER_SPURIOUS, "Spurious Interrupt" }, ! 110: {IDER_CNTRL_REJECT, "Controller Reject" }, ! 111: {0, NULL }, ! 112: }; ! 113: ! 114: static int ideOpenCount = 0; ! 115: ! 116: /* ! 117: * dev-to-id map array. Instances of DiskObject register their IDs in ! 118: * this array via registerUnixDisk:. ! 119: */ ! 120: IODevAndIdInfo IdeIdMap[NUM_IDE_DEV]; ! 121: ! 122: /* ! 123: * Private per-unit data. ! 124: */ ! 125: static Ide_dev_t ide_dev[NUM_IDE_DEV] = { ! 126: {NULL}, ! 127: {NULL}, ! 128: {NULL}, ! 129: {NULL}, ! 130: }; ! 131: ! 132: /* ! 133: * Indices of our entries in devsw's. ! 134: */ ! 135: static int ide_block_major; ! 136: static int ide_raw_major; ! 137: ! 138: /* ! 139: * prototypes for internal functions ! 140: */ ! 141: static unsigned ideminphys(struct buf *bp); ! 142: static id ide_dev_to_id(dev_t dev); ! 143: ! 144: /* ! 145: * Initialize id map and Ide_dev. Currently invoked by Ide probe:. ! 146: */ ! 147: __private_extern__ void ide_init_idmap(id self) ! 148: { ! 149: IODevAndIdInfo *idMap = IdeIdMap; ! 150: Ide_dev_t *ide_devp = ide_dev; ! 151: int unit; ! 152: ! 153: /* ! 154: * figure out our major device numbers. ! 155: */ ! 156: ide_block_major = [self blockMajor]; ! 157: ide_raw_major = [self characterMajor]; ! 158: ! 159: bzero((char *)idMap, sizeof(IODevAndIdInfo) * NUM_IDE_DEV); ! 160: for (unit = 0; unit < NUM_IDE_DEV; unit++) { ! 161: idMap->rawDev = makedev(ide_raw_major, (unit << 3)); ! 162: idMap->blockDev = makedev(ide_block_major, (unit << 3)); ! 163: idMap++; ! 164: ide_devp->physbuf = (struct buf *)IOMalloc(sizeof(struct buf)); ! 165: ide_devp->physbuf->b_flags = 0; ! 166: ide_devp++; ! 167: } ! 168: } ! 169: ! 170: __private_extern__ IODevAndIdInfo *ide_idmap() ! 171: { ! 172: return IdeIdMap; ! 173: } ! 174: ! 175: __private_extern__ int ! 176: ideopen(dev_t dev, int flag, int devtype, struct proc * pp) ! 177: { ! 178: id diskObj = ide_dev_to_id(dev); ! 179: ! 180: if(diskObj == nil) ! 181: return(ENXIO); ! 182: ! 183: if([diskObj isDiskReady:NO]) ! 184: return(ENXIO); ! 185: ! 186: /* ! 187: * Register this 'Unix-level open' event for IODiskPartitions. ! 188: */ ! 189: if(IO_DISK_PART(dev) != IDE_LIVE_PART) { ! 190: if(major(dev) == ide_block_major) { ! 191: [diskObj setBlockDeviceOpen:YES]; ! 192: ideOpenCount++; ! 193: } ! 194: else { ! 195: [diskObj setRawDeviceOpen:YES]; ! 196: } ! 197: } ! 198: return(0); ! 199: } /* ideopen() */ ! 200: ! 201: __private_extern__ int ! 202: ideclose(dev_t dev, int flag, int devtype, struct proc * pp) ! 203: { ! 204: id diskObj = ide_dev_to_id(dev); ! 205: ! 206: if(diskObj == nil) ! 207: return(ENXIO); ! 208: if(IO_DISK_PART(dev) == IDE_LIVE_PART) { ! 209: return 0; ! 210: } else { ! 211: if(![diskObj isInstanceOpen]) ! 212: return(ENXIO); ! 213: } ! 214: ! 215: /* ! 216: * Register this 'Unix-level close' event. We won't be called unless ! 217: * this is the last close. ! 218: */ ! 219: if(major(dev) == ide_block_major) { ! 220: [diskObj setBlockDeviceOpen:NO]; ! 221: if ( ideOpenCount ) ! 222: { ! 223: if ( !--ideOpenCount ) ! 224: { ! 225: IOSleep(1000); ! 226: } ! 227: } ! 228: } ! 229: else { ! 230: [diskObj setRawDeviceOpen:NO]; ! 231: } ! 232: ! 233: return(0); ! 234: } /* ideclose() */ ! 235: ! 236: /* ! 237: * Raw I/O uses standard UNIX physio routine, resulting in async I/O requests ! 238: * via idestrategy(). ! 239: */ ! 240: ! 241: __private_extern__ int ! 242: ideread(dev_t dev, struct uio *uiop, int ioflag) ! 243: { ! 244: id diskObj = ide_dev_to_id(dev); ! 245: int unit = IO_DISK_UNIT(dev); ! 246: int rtn; ! 247: ! 248: if(diskObj == nil) { ! 249: return(ENXIO); ! 250: } ! 251: ! 252: ! 253: rtn = physio(idestrategy, ! 254: ide_dev[unit].physbuf, ! 255: dev, ! 256: B_READ, ! 257: ideminphys, ! 258: uiop, ! 259: [diskObj blockSize]); ! 260: ! 261: return rtn; ! 262: } /* ideread() */ ! 263: ! 264: __private_extern__ int ! 265: idewrite(dev_t dev, struct uio *uiop, int ioflag) ! 266: { ! 267: id diskObj = ide_dev_to_id(dev); ! 268: int unit = IO_DISK_UNIT(dev); ! 269: int rtn; ! 270: ! 271: if(diskObj == nil) ! 272: return(ENXIO); ! 273: ! 274: ! 275: rtn = physio(idestrategy, ! 276: ide_dev[unit].physbuf, ! 277: dev, ! 278: B_WRITE, ! 279: ideminphys, ! 280: uiop, ! 281: [diskObj blockSize]); ! 282: ! 283: return rtn; ! 284: } /* idewrite() */ ! 285: ! 286: __private_extern__ void ! 287: idestrategy(struct buf *bp) ! 288: { ! 289: id diskObj = ide_dev_to_id(bp->b_dev); ! 290: u_int offset; ! 291: u_int bytes_req; ! 292: void *bufp; ! 293: u_int block_size; ! 294: IOReturn rtn; ! 295: vm_task_t client; ! 296: ! 297: if(diskObj == nil) { ! 298: bp->b_error = ENXIO; ! 299: goto bad; ! 300: } ! 301: ! 302: if((bp->b_flags & (B_PHYS|B_KERNSPACE)) == B_PHYS) { ! 303: /* ! 304: * Physical I/O to user space. ! 305: */ ! 306: client = IOVmTaskForBuf(bp); ! 307: } ! 308: else { ! 309: /* ! 310: * Either block I/O (always kernel space) or physical I/O ! 311: * to kernel space (e.g., loadable file system). ! 312: */ ! 313: client = IOVmTaskSelf(); ! 314: } ! 315: ! 316: block_size = [diskObj blockSize]; ! 317: if (block_size == 0) { ! 318: bp->b_error = ENXIO; ! 319: goto bad; ! 320: } ! 321: offset = bp->b_blkno; ! 322: bytes_req = bp->b_bcount; ! 323: bufp = bp->b_un.b_addr; ! 324: ! 325: if (bp->b_flags & B_READ) { ! 326: rtn = [diskObj readAsyncAt:offset ! 327: length:bytes_req ! 328: buffer:bufp ! 329: pending:bp ! 330: client:client]; ! 331: } ! 332: else { ! 333: rtn = [diskObj writeAsyncAt:offset ! 334: length:bytes_req ! 335: buffer:bufp ! 336: pending:bp ! 337: client:client]; ! 338: } ! 339: ! 340: if (rtn) { ! 341: bp->b_error = [diskObj errnoFromReturn:rtn]; ! 342: goto bad; ! 343: } ! 344: return(0); ! 345: ! 346: bad: ! 347: bp->b_flags |= B_ERROR; ! 348: rtn = -1; ! 349: biodone(bp); ! 350: ! 351: return(rtn); ! 352: } /* fdstrategy() */ ! 353: ! 354: /* ! 355: * Ops which are common to all IODiskPartitions are done on the raw device; ! 356: * Ide-specific ioctls are done directly to the live Ide object. ! 357: */ ! 358: __private_extern__ int ! 359: ideioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc * pp) ! 360: { ! 361: int unit = IO_DISK_UNIT(dev); ! 362: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 363: int part = IO_DISK_PART(dev); ! 364: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 365: id diskObj; ! 366: IODevAndIdInfo *idmap; ! 367: int rtn = 0; ! 368: IOReturn irtn = IO_R_SUCCESS; ! 369: struct ucred cred; ! 370: u_short acflags; ! 371: ! 372: // user src/dest ! 373: int i; ! 374: int nblk; ! 375: ideIoReq_t *ideIoReq; ! 376: int error; ! 377: void *userPtr; ! 378: ! 379: // in ideIoReq_t ! 380: BOOL wrFlag = NO; ! 381: unsigned bSize = 0; ! 382: unsigned char *alignedPtr; ! 383: ! 384: ! 385: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 386: ! 387: if ( ! ( unit < MAX_IDE_UNIT ) ) ! 388: { ! 389: unit -= MAX_IDE_UNIT; ! 390: part += NUM_IDE_PART; ! 391: } ! 392: ! 393: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 394: if (unit > NUM_IDE_DEV) ! 395: return (ENXIO); ! 396: #if 0 ! 397: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 398: ! 399: if ((major(dev) != ide_raw_major) || (part >= 2*NUM_IDE_PART)) { ! 400: ! 401: #else GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 402: ! 403: if ((major(dev) != ide_raw_major) || (part >= NUM_IDE_PART)) { ! 404: ! 405: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 406: return (ENXIO); ! 407: } ! 408: #endif ! 409: ! 410: idmap = &IdeIdMap[unit]; ! 411: ! 412: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 413: ! 414: /* ! 415: * Special cases for HFS partitions. ! 416: * DKIOCNUMBLKS - return # blocks on partition, not the whole device ! 417: * DKIOCSFORMAT - not permitted ! 418: * DKIOCGFORMAT - not permitted ! 419: * DKIOCGLABEL - not permitted ! 420: * DKIOCSLABEL - not permitted ! 421: */ ! 422: ! 423: /* Is it an HFS partition ? */ ! 424: ! 425: if ( ! ( part < NPART ) ) ! 426: { ! 427: switch ( cmd ) ! 428: { ! 429: case DKIOCNUMBLKS: ! 430: /* ! 431: * For an HFS partition, return the # of blocks in the ! 432: * partition, rather than # of blocks on the whole device. ! 433: */ ! 434: ! 435: diskObj = idmap->partitionId[part]; ! 436: *(int *)data = [diskObj diskSize]; ! 437: return (0); ! 438: ! 439: break; ! 440: ! 441: case DKIOCSFORMAT: ! 442: case DKIOCGFORMAT: ! 443: case DKIOCGLABEL: ! 444: case DKIOCSLABEL: ! 445: return(EINVAL); ! 446: break; ! 447: } ! 448: } ! 449: ! 450: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 451: ! 452: /* ! 453: * First verify valid device. ! 454: */ ! 455: switch (cmd) { ! 456: case DKIOCSFORMAT: ! 457: case DKIOCGFORMAT: ! 458: case DKIOCGLABEL: ! 459: case DKIOCSLABEL: ! 460: ! 461: /* ! 462: * Raw device, whatever the caller asked for. ! 463: */ ! 464: diskObj = idmap->partitionId[0]; ! 465: break; ! 466: ! 467: case DKIOCGLOCATION: ! 468: diskObj = idmap->partitionId[part]; ! 469: break; ! 470: ! 471: case IDEDIOCREQ: ! 472: case IDEDIOCINFO: ! 473: case DKIOCINFO: ! 474: case DKIOCBLKSIZE: ! 475: case DKIOCNUMBLKS: ! 476: ! 477: diskObj = idmap->liveId; ! 478: break; ! 479: ! 480: default: ! 481: return (EINVAL); ! 482: } ! 483: if (diskObj == nil) ! 484: goto nodev; ! 485: ! 486: switch (cmd) { ! 487: case DKIOCSFORMAT: ! 488: ! 489: /* ! 490: * This can fail if block devices attached to this disk are open. ! 491: */ ! 492: irtn = [diskObj setFormatted:(*(u_int *) data)]; ! 493: break; ! 494: ! 495: case DKIOCGFORMAT: ! 496: { ! 497: *(int *)data = [diskObj isFormatted]; ! 498: break; ! 499: } ! 500: ! 501: case DKIOCGLABEL: ! 502: { ! 503: struct disk_label *labelp; ! 504: ! 505: labelp = (struct disk_label *)IOMalloc(sizeof(*labelp)); ! 506: irtn = [diskObj readLabel:labelp]; ! 507: if (irtn == IO_R_SUCCESS) { ! 508: *(struct disk_label *)data = *labelp; ! 509: } ! 510: IOFree(labelp, sizeof(*labelp)); ! 511: break; ! 512: } ! 513: ! 514: case DKIOCSLABEL: ! 515: { ! 516: struct disk_label *labelp; ! 517: ! 518: labelp = (struct disk_label *)IOMalloc(sizeof(*labelp)); ! 519: *labelp = *(struct disk_label *)data; ! 520: irtn = [diskObj writeLabel:labelp]; ! 521: IOFree(labelp, sizeof(*labelp)); ! 522: break; ! 523: } ! 524: ! 525: case DKIOCINFO: ! 526: { ! 527: struct drive_info info; ! 528: ! 529: bzero(&info, sizeof(info)); ! 530: strcpy(info.di_name,[diskObj driveName]); ! 531: info.di_devblklen = [diskObj blockSize]; ! 532: info.di_maxbcount = IDE_MAX_PHYS_IO; ! 533: if (info.di_devblklen) { ! 534: nblk = howmany(sizeof(struct disk_label), ! 535: info.di_devblklen); ! 536: } else { ! 537: nblk = 0; ! 538: } ! 539: for (i = 0; i < NLABELS; i++) ! 540: info.di_label_blkno[i] = nblk * i; ! 541: *(struct drive_info *) data = info; ! 542: break; ! 543: } ! 544: ! 545: case DKIOCBLKSIZE: ! 546: *(int *)data = [diskObj blockSize]; ! 547: break; ! 548: ! 549: case DKIOCNUMBLKS: ! 550: *(int *)data = [diskObj diskSize]; ! 551: break; ! 552: ! 553: case DKIOCGLOCATION: ! 554: if( nil == [diskObj getDevicePath:((struct drive_location *)data)->location ! 555: maxLength:sizeof(((struct drive_location *)data)->location) ! 556: useAlias:YES] ) ! 557: irtn = IO_R_NO_MEMORY; ! 558: break; ! 559: ! 560: case IDEDIOCREQ: ! 561: ! 562: /* ! 563: * Perform specified I/O. ! 564: */ ! 565: ideIoReq = (ideIoReq_t *) data; ! 566: // if (!suser() && (ideIoReq->cmd != IDE_IDENTIFY_DRIVE)) ! 567: if (suser(pp->p_ucred, &pp->p_acflag) && ! 568: (ideIoReq->cmd != IDE_IDENTIFY_DRIVE)) { ! 569: // return (u.u_error); ! 570: return (EINVAL); ! 571: } ! 572: ! 573: if ((ideIoReq->cmd == IDE_WRITE_DMA) || ! 574: (ideIoReq->cmd == IDE_READ_DMA)) { ! 575: if ([[diskObj cntrlr] isDmaSupported:[diskObj driveNum]] != TRUE) ! 576: return (EINVAL); ! 577: } ! 578: ! 579: if (ideIoReq->cmd == IDE_IDENTIFY_DRIVE) ! 580: ideIoReq->blkcnt = 1; ! 581: ! 582: userPtr = (void *)ideIoReq->addr; ! 583: ! 584: alignedPtr = ideIoReq->addr; ! 585: if ((ideIoReq->cmd == IDE_WRITE) || ! 586: (ideIoReq->cmd == IDE_READ) || ! 587: (ideIoReq->cmd == IDE_READ_MULTIPLE) || ! 588: (ideIoReq->cmd == IDE_WRITE_MULTIPLE) || ! 589: (ideIoReq->cmd == IDE_READ_DMA) || ! 590: (ideIoReq->cmd == IDE_WRITE_DMA) || ! 591: (ideIoReq->cmd == IDE_IDENTIFY_DRIVE)) { ! 592: if (ideIoReq->blkcnt != 0) { ! 593: bSize = [diskObj blockSize]; ! 594: wrFlag = ((ideIoReq->cmd == IDE_WRITE) || ! 595: (ideIoReq->cmd == IDE_WRITE_MULTIPLE) || ! 596: (ideIoReq->cmd == IDE_WRITE_DMA)); ! 597: ! 598: alignedPtr = (unsigned char *) ! 599: IOMalloc(ideIoReq->blkcnt * bSize); ! 600: if (alignedPtr == 0) { ! 601: ideIoReq->status = IDER_MEMALLOC; ! 602: return (ENOMEM); ! 603: } ! 604: if (wrFlag) { ! 605: error = copyin(ideIoReq->addr, ! 606: alignedPtr, ! 607: ideIoReq->blkcnt * bSize); ! 608: if (error) { ! 609: ideIoReq->status = IDER_MEMFAIL; ! 610: goto err_exit; ! 611: } ! 612: } ! 613: } ! 614: ideIoReq->addr = (caddr_t) alignedPtr; ! 615: ideIoReq->map = (struct vm_map *)IOVmTaskSelf(); ! 616: } ! 617: ! 618: ! 619: [diskObj ideXfrIoReq:ideIoReq]; ! 620: ! 621: /* ! 622: * Note if we got this far, we'll return 0; any errors are in ! 623: * ideIoReq->status. ! 624: */ ! 625: if ((ideIoReq->cmd == IDE_WRITE) || ! 626: (ideIoReq->cmd == IDE_READ) || ! 627: (ideIoReq->cmd == IDE_READ_MULTIPLE) || ! 628: (ideIoReq->cmd == IDE_WRITE_MULTIPLE) || ! 629: (ideIoReq->cmd == IDE_READ_DMA) || ! 630: (ideIoReq->cmd == IDE_WRITE_DMA) || ! 631: (ideIoReq->cmd == IDE_IDENTIFY_DRIVE)) { ! 632: ! 633: ideIoReq->addr = userPtr; ! 634: if (((ideIoReq->cmd == IDE_READ) || ! 635: (ideIoReq->cmd == IDE_READ_MULTIPLE) || ! 636: (ideIoReq->cmd == IDE_IDENTIFY_DRIVE) || ! 637: (ideIoReq->cmd == IDE_READ_DMA)) && ! 638: (ideIoReq->blocks_xfered != 0)) { ! 639: error = copyout(alignedPtr, ! 640: userPtr, ! 641: ideIoReq->blocks_xfered * bSize); ! 642: if (error) { ! 643: ideIoReq->status = IDER_MEMFAIL; ! 644: } ! 645: } ! 646: err_exit: ! 647: ! 648: /* ! 649: * if we malloc'd any memory, free it. ! 650: */ ! 651: if (ideIoReq->blkcnt != 0) ! 652: IOFree(alignedPtr, ideIoReq->blkcnt * bSize); ! 653: } ! 654: break; ! 655: ! 656: case IDEDIOCINFO: ! 657: { ! 658: ideDriveInfo_t *idep = (ideDriveInfo_t *) data; ! 659: ! 660: *idep = (ideDriveInfo_t)[diskObj ideGetDriveInfo]; ! 661: break; ! 662: } ! 663: default: ! 664: return (EINVAL); ! 665: } ! 666: ! 667: if (irtn) ! 668: rtn = [diskObj errnoFromReturn:irtn]; ! 669: return (rtn); ! 670: ! 671: nodev: ! 672: return (ENXIO); ! 673: ! 674: } /* ideioctl() */ ! 675: ! 676: /* ! 677: * Obtain physical block size. ! 678: */ ! 679: __private_extern__ int ! 680: idesize(dev_t dev) ! 681: { ! 682: id diskObj = ide_dev_to_id(dev); ! 683: ! 684: if(diskObj == nil) { ! 685: return -1; ! 686: } ! 687: return [diskObj blockSize]; ! 688: } ! 689: ! 690: /* ! 691: * Returns block and char major nums. This is used so that the PostLoad ! 692: * program can create block and character nodes for IDE. ! 693: */ ! 694: __private_extern__ void ! 695: ide_block_char_majors(int *blockmajor, int *charmajor) ! 696: { ! 697: *blockmajor = ide_block_major; ! 698: *charmajor = ide_raw_major; ! 699: } ! 700: ! 701: static unsigned ideminphys(struct buf *bp) ! 702: { ! 703: if (bp->b_bcount > IDE_MAX_PHYS_IO) ! 704: bp->b_bcount = IDE_MAX_PHYS_IO; ! 705: return(bp->b_bcount); ! 706: } ! 707: ! 708: /* ! 709: * Map dev_t to id. A nil return indicates ENXIO. ! 710: */ ! 711: static id ide_dev_to_id(dev_t dev) ! 712: { ! 713: id rtn; ! 714: int unit = IO_DISK_UNIT(dev); ! 715: int part = IO_DISK_PART(dev); ! 716: IODevAndIdInfo *idmap; ! 717: ! 718: #ifdef GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 719: ! 720: if ( ! ( unit < MAX_IDE_UNIT ) ) ! 721: { ! 722: /* Modify the unit # under the assumption that it is an HFS device. */ ! 723: ! 724: unit -= MAX_IDE_UNIT; ! 725: ! 726: /* Is it an HFS device? */ ! 727: ! 728: if ( ! ( unit < MAX_IDE_UNIT ) ) { ! 729: rtn = nil; ! 730: goto Return; ! 731: } ! 732: ! 733: /* Yes, it is an HFS device. */ ! 734: ! 735: /* But it doesn't have a raw variant. */ ! 736: ! 737: if ( major(dev) == ide_raw_major ) { ! 738: rtn = nil; ! 739: goto Return; ! 740: } ! 741: ! 742: /* Modify the partition # to indicate an HFS partition and then proceed. */ ! 743: ! 744: part += NUM_IDE_PART; ! 745: ! 746: } ! 747: ! 748: #else GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 749: ! 750: if((unit >= NUM_IDE_DEV) || (part >= NUM_IDE_PART)) { ! 751: return nil; ! 752: } ! 753: ! 754: #endif GROK_APPLE //bknight - 2/21/98 - Radar 2204950, 2004660 ! 755: ! 756: idmap = &IdeIdMap[unit]; ! 757: ! 758: if(part == IDE_LIVE_PART) { ! 759: if(major(dev) == ide_block_major) { ! 760: rtn = nil; ! 761: } ! 762: else { ! 763: rtn = idmap->liveId; ! 764: } ! 765: } ! 766: else { ! 767: rtn = idmap->partitionId[part]; ! 768: } ! 769: Return: ! 770: return rtn; ! 771: } ! 772: ! 773: /* end of IdeKern.m */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.