|
|
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 (c) 1992 NeXT Computer, Inc. ! 27: * ! 28: * Driverkit kernel support. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 15 Jan 1998 Martin Minow ! 33: * Added kern_IOCreateMachPort ! 34: * 28 Aug 1992 Joe Pasqua ! 35: * Use new interface to interrupt mechanism. ! 36: * 25 Aug 1992 Joe Pasqua ! 37: * Added minimal implementations of kern{IOAttach|Detach}Interrupt, ! 38: * kern_IOCreateDevicePort. ! 39: * 9 August 1992 ? at NeXT ! 40: * Created. ! 41: */ ! 42: ! 43: #import <mach/mach_types.h> ! 44: ! 45: #import <ipc/ipc_space.h> ! 46: ! 47: #import <kern/kern_port.h> ! 48: #import <kern/task.h> ! 49: ! 50: #import <vm/vm_kern.h> ! 51: ! 52: #import <driverkit/generalFuncs.h> ! 53: #import <driverkit/IODevice.h> ! 54: #import <driverkit/IODeviceParams.h> ! 55: #import <driverkit/i386/driverServer.h> ! 56: #import <driverkit/KernDevice.h> ! 57: #import <driverkit/KernDeviceDescription.h> ! 58: #import <driverkit/KernBus.h> ! 59: #import <driverkit/i386/EISAKernBus.h> ! 60: #import <driverkit/interruptMsg.h> ! 61: #import <driverkit/driverServerXXX.h> ! 62: #import <driverkit/autoconfCommon.h> ! 63: #import <driverkit/Device_ddm.h> ! 64: #import <driverkit/kernelDriver.h> ! 65: #import <driverkit/driverTypesPrivate.h> ! 66: #import <driverkit/configTableKern.h> ! 67: #import <sys/param.h> ! 68: #import <sys/systm.h> ! 69: #import <machkit/NXLock.h> ! 70: #import <objc/List.h> ! 71: ! 72: void ! 73: dev_server_init( ! 74: void ! 75: ) ! 76: { ! 77: #if i386 ! 78: /* ! 79: * Initialize dma controller(s). ! 80: */ ! 81: dma_initialize(); ! 82: ! 83: /* ! 84: * Initialize DMA lock mechanism. ! 85: */ ! 86: initDmaLock(); ! 87: #endif i386 ! 88: } ! 89: ! 90: KernDevice * ! 91: convert_port_to_dev( ! 92: port_t dev_port ! 93: ) ! 94: { ! 95: KernDevice *kernDevice = nil; ! 96: kern_port_t port = (kern_port_t)dev_port; ! 97: ! 98: if (port == IP_NULL) ! 99: return nil; ! 100: ! 101: ip_lock(port); ! 102: ! 103: if(ip_kotype(port) == IKOT_DEVICE) ! 104: kernDevice = (KernDevice *)port->ip_kobject; ! 105: ! 106: ip_unlock(port); ! 107: ! 108: return kernDevice; ! 109: } ! 110: ! 111: port_t ! 112: create_dev_port( ! 113: KernDevice *kernDevice ! 114: ) ! 115: { ! 116: kern_port_t devicePort; ! 117: if ((devicePort = ipc_port_alloc_kernel()) == IP_NULL) ! 118: return (PORT_NULL); ! 119: ! 120: ipc_kobject_set(devicePort, (unsigned int)kernDevice, IKOT_DEVICE); ! 121: ! 122: return (IOConvertPort((port_t)devicePort, ! 123: IO_Kernel, IO_KernelIOTask)); ! 124: } ! 125: ! 126: void ! 127: destroy_dev_port( ! 128: port_t port ! 129: ) ! 130: { ! 131: kern_port_t devicePort; ! 132: ! 133: if (port != PORT_NULL) { ! 134: devicePort = (kern_port_t)IOConvertPort(port, ! 135: IO_KernelIOTask, IO_Kernel); ! 136: ip_lock(devicePort); ! 137: ipc_port_destroy(devicePort); ! 138: } ! 139: } ! 140: ! 141: /* ! 142: * Determine deviceType and deviceName of specified objectNumber. ! 143: */ ! 144: IOReturn kern_IOLookupByObjectNumber( ! 145: host_t device_master, ! 146: IOObjectNumber objectNumber, ! 147: IOString *deviceKind, // returned ! 148: IOString *deviceName) // returned ! 149: { ! 150: if (device_master == HOST_NULL) ! 151: return IO_R_PRIVILEGE; ! 152: ! 153: return [IODevice lookupByObjectNumber:objectNumber ! 154: deviceKind:deviceKind ! 155: deviceName:deviceName]; ! 156: } ! 157: ! 158: /* ! 159: * Determine deviceType and IOObjectNumber of specified IOString. ! 160: */ ! 161: IOReturn kern_IOLookupByDeviceName( ! 162: host_t device_master, ! 163: IOString deviceName, ! 164: IOObjectNumber *objectNumber, // returned ! 165: IOString *deviceKind) // returned ! 166: { ! 167: if (device_master == HOST_NULL) ! 168: return IO_R_PRIVILEGE; ! 169: ! 170: return [IODevice lookupByDeviceName:deviceName ! 171: objectNumber:objectNumber ! 172: deviceKind:deviceKind]; ! 173: } ! 174: ! 175: /* ! 176: * Get/set parameter RPCs. ! 177: */ ! 178: ! 179: IOReturn kern_IOGetIntValues( ! 180: host_t device_master, ! 181: IOObjectNumber objectNumber, ! 182: IOParameterName parameterName, ! 183: unsigned int maxCount, // 0 means "as much as ! 184: // possible" ! 185: unsigned int *parameterArray, // data returned here ! 186: unsigned int *returnedCount) // size returned here ! 187: { ! 188: IOReturn rtn; ! 189: unsigned count = maxCount; ! 190: ! 191: if (device_master == HOST_NULL) ! 192: return IO_R_PRIVILEGE; ! 193: ! 194: rtn = [IODevice getIntValues:parameterArray ! 195: forParameter:parameterName ! 196: objectNumber:objectNumber ! 197: count:&count]; ! 198: *returnedCount = count; ! 199: return rtn; ! 200: } ! 201: ! 202: IOReturn kern_IOGetCharValues( ! 203: host_t device_master, ! 204: IOObjectNumber objectNumber, ! 205: IOParameterName parameterName, ! 206: unsigned int maxCount, // 0 means "as much as ! 207: // possible" ! 208: unsigned char *parameterArray, // data returned here ! 209: unsigned int *returnedCount) // size returned here ! 210: { ! 211: IOReturn rtn; ! 212: unsigned count = maxCount; ! 213: ! 214: if (device_master == HOST_NULL) ! 215: return IO_R_PRIVILEGE; ! 216: ! 217: rtn = [IODevice getCharValues:parameterArray ! 218: forParameter:parameterName ! 219: objectNumber:objectNumber ! 220: count:&count]; ! 221: *returnedCount = count; ! 222: return rtn; ! 223: } ! 224: ! 225: IOReturn kern_IOSetIntValues( ! 226: host_priv_t device_master, ! 227: IOObjectNumber objectNumber, ! 228: IOParameterName parameterName, ! 229: unsigned int *parameterArray, ! 230: unsigned int count) // size of parameterArray ! 231: { ! 232: if (device_master == HOST_NULL) ! 233: return IO_R_PRIVILEGE; ! 234: ! 235: return [IODevice setIntValues:parameterArray ! 236: forParameter:parameterName ! 237: objectNumber:objectNumber ! 238: count:count]; ! 239: } ! 240: ! 241: IOReturn kern_IOSetCharValues( ! 242: host_t device_master, ! 243: IOObjectNumber objectNumber, ! 244: IOParameterName parameterName, ! 245: unsigned char *parameterArray, ! 246: unsigned int count) // size of parameterArray ! 247: { ! 248: if (device_master == HOST_NULL) ! 249: return IO_R_PRIVILEGE; ! 250: ! 251: return [IODevice setCharValues:parameterArray ! 252: forParameter:parameterName ! 253: objectNumber:objectNumber ! 254: count:count]; ! 255: } ! 256: ! 257: IOReturn kern_IOLookUpByStringPropertyList( ! 258: host_priv_t device_master, ! 259: unsigned char * values, ! 260: unsigned int valuesLen, // Mig added ! 261: unsigned char * results, ! 262: unsigned int *returnedCount, // size returned here ! 263: unsigned int length) ! 264: { ! 265: IOReturn rtn; ! 266: ! 267: rtn = [IODevice lookUpByStringPropertyList:(const char *)values ! 268: results : (char *)results ! 269: maxLength : (unsigned int)length]; ! 270: ! 271: if( rtn == IO_R_SUCCESS) ! 272: *returnedCount = strlen( results) + 1; ! 273: ! 274: return( rtn); ! 275: } ! 276: ! 277: IOReturn kern_IOGetStringPropertyList( ! 278: host_priv_t device_master, ! 279: IOObjectNumber objectNumber, ! 280: unsigned char * names, ! 281: unsigned int nameLen, // Mig added ! 282: unsigned char * results, ! 283: unsigned int *returnedCount, // size returned here. Mig added ! 284: unsigned int length) ! 285: { ! 286: IOReturn rtn; ! 287: ! 288: rtn = [IODevice getStringPropertyList:objectNumber ! 289: names : (const char *)names ! 290: results : (char *)results ! 291: maxLength : (unsigned int)length]; ! 292: ! 293: if( rtn == IO_R_SUCCESS) ! 294: *returnedCount = strlen( results) + 1; ! 295: ! 296: return( rtn); ! 297: } ! 298: ! 299: IOReturn kern_IOGetByteProperty( ! 300: host_priv_t device_master, ! 301: IOObjectNumber objectNumber, ! 302: unsigned char * name, ! 303: unsigned int nameLen, // Mig added ! 304: unsigned char * results, ! 305: unsigned int *returnedCount, // size returned here. Mig added ! 306: unsigned int length) ! 307: { ! 308: IOReturn rtn; ! 309: *returnedCount = length; ! 310: ! 311: rtn = [IODevice getByteProperty:objectNumber ! 312: name : (const char *)name ! 313: results : (char *)results ! 314: maxLength : (unsigned int *)returnedCount]; ! 315: ! 316: return( rtn); ! 317: } ! 318: ! 319: IOReturn kern_IOServerConnect( ! 320: host_t device_master, ! 321: IOObjectNumber objectNumber, ! 322: ipc_port_t taskIPCPort, ! 323: ipc_port_t *serverIPCPort) ! 324: { ! 325: extern task_t IOTask_kern; // kernel internal version of IOTask ! 326: IOReturn rtn; ! 327: ! 328: if (device_master == HOST_NULL) ! 329: return IO_R_PRIVILEGE; ! 330: ! 331: rtn = [IODevice serverConnect: (port_t *) serverIPCPort ! 332: objectNumber: objectNumber ! 333: taskPort: (port_t) taskIPCPort]; ! 334: if (MACH_PORT_VALID(*serverIPCPort)) ! 335: (void) ipc_object_copyin_compat(IOTask_kern->itk_space, ! 336: *serverIPCPort, MSG_TYPE_PORT, FALSE, serverIPCPort); ! 337: ! 338: return rtn; ! 339: } ! 340: ! 341: IOReturn kern_IOCallDeviceMethod( ! 342: host_priv_t device_master, ! 343: IOObjectNumber objectNumber, ! 344: char * methodName, ! 345: unsigned char *inputParams, ! 346: unsigned int inputCount, // size of parameterArray ! 347: unsigned int *maxCount, // caller's output buffer size ! 348: // on return the needed size ! 349: unsigned char *outputParams, // data returned here ! 350: unsigned int *returnedCount) // size to be returned here ! 351: { ! 352: IOReturn rtn; ! 353: unsigned count = *maxCount; ! 354: ! 355: rtn = [IODevice callDeviceMethod : methodName ! 356: inputParams : inputParams ! 357: inputCount : inputCount ! 358: outputParams : outputParams ! 359: outputCount : &count ! 360: privileged : device_master ! 361: objectNumber : objectNumber]; ! 362: ! 363: if( count <= *maxCount) ! 364: *returnedCount = count; // how much was returned ! 365: else ! 366: *returnedCount = *maxCount; ! 367: ! 368: *maxCount = count; // how much is available ! 369: ! 370: return rtn; ! 371: } ! 372: ! 373: #ifdef i386 ! 374: ! 375: IOReturn ! 376: kern_IOGetEISADeviceConfig( ! 377: KernDevice *device, ! 378: IOEISAInterruptList interrupts, ! 379: unsigned int *interruptNum, ! 380: IOEISADMAChannelList dmaChannels, ! 381: unsigned int *dmaChannelNum, ! 382: IOEISAPortMap ioRegions, ! 383: unsigned int *ioRegionNum, ! 384: IOEISAMemoryMap memoryRegions, ! 385: unsigned int *memoryRegionNum ! 386: ) ! 387: { ! 388: int i, num; ! 389: Range range; ! 390: id list, deviceDescription; ! 391: ! 392: if (device == nil) ! 393: return IO_R_PRIVILEGE; ! 394: ! 395: deviceDescription = [device deviceDescription]; ! 396: ! 397: list = [deviceDescription resourcesForKey:IRQ_LEVELS_KEY]; ! 398: num = [list count]; ! 399: if (num > IO_NUM_EISA_INTERRUPTS) ! 400: num = IO_NUM_EISA_INTERRUPTS; ! 401: for (i = 0; i < num; i++) ! 402: interrupts[i] = [[list objectAt:i] item]; ! 403: *interruptNum = num; ! 404: ! 405: list = [deviceDescription resourcesForKey:DMA_CHANNELS_KEY]; ! 406: num = [list count]; ! 407: if (num > IO_NUM_EISA_DMA_CHANNELS) ! 408: num = IO_NUM_EISA_DMA_CHANNELS; ! 409: for (i = 0; i < num; i++) ! 410: dmaChannels[i] = [[list objectAt:i] item]; ! 411: *dmaChannelNum = num; ! 412: ! 413: list = [deviceDescription resourcesForKey:IO_PORTS_KEY]; ! 414: num = [list count]; ! 415: if (num > IO_NUM_EISA_PORT_RANGES) ! 416: num = IO_NUM_EISA_PORT_RANGES; ! 417: for (i = 0; i < num; i++) { ! 418: range = [[list objectAt:i] range]; ! 419: ioRegions[i].start = range.base; ! 420: ioRegions[i].size = range.length; ! 421: } ! 422: *ioRegionNum = num; ! 423: ! 424: list = [deviceDescription resourcesForKey:MEM_MAPS_KEY]; ! 425: num = [list count]; ! 426: if (num > IO_NUM_EISA_MEMORY_RANGES) ! 427: num = IO_NUM_EISA_MEMORY_RANGES; ! 428: for (i = 0; i < num; i++) { ! 429: range = [[list objectAt:i] range]; ! 430: memoryRegions[i].start = range.base; ! 431: memoryRegions[i].size = range.length; ! 432: } ! 433: *memoryRegionNum = num; ! 434: ! 435: return IO_R_SUCCESS; ! 436: } ! 437: ! 438: IOReturn ! 439: kern_IOMapEISADevicePorts( ! 440: KernDevice *device, ! 441: thread_t thread ! 442: ) ! 443: { ! 444: IOReturn rtn; ! 445: ! 446: if (device == nil) ! 447: return (IO_R_PRIVILEGE); ! 448: ! 449: if (thread->task->kernel_vm_space) ! 450: return (IO_R_SUCCESS); ! 451: ! 452: rtn = kern_dev_map_port_com(device, thread, FALSE); ! 453: ! 454: return (rtn); ! 455: } ! 456: ! 457: IOReturn ! 458: kern_IOUnMapEISADevicePorts( ! 459: KernDevice *device, ! 460: thread_t thread ! 461: ) ! 462: { ! 463: IOReturn rtn; ! 464: ! 465: if (device == nil) ! 466: return (IO_R_PRIVILEGE); ! 467: ! 468: if (thread->task->kernel_vm_space) ! 469: return (IO_R_SUCCESS); ! 470: ! 471: rtn = kern_dev_map_port_com(device, thread, TRUE); ! 472: ! 473: return (rtn); ! 474: } ! 475: ! 476: IOReturn ! 477: kern_IOMapEISADeviceMemory( ! 478: KernDevice *device, ! 479: task_t task, ! 480: vm_offset_t phys, ! 481: vm_size_t length, ! 482: vm_offset_t *addr, // in/out ! 483: BOOL anywhere, ! 484: IOCache cache ! 485: ) ! 486: { ! 487: IOReturn rtn; ! 488: ! 489: if (device == nil) ! 490: return IO_R_PRIVILEGE; ! 491: ! 492: rtn = kern_dev_map_phys( ! 493: device, ! 494: task->map, ! 495: phys, ! 496: length, ! 497: addr, ! 498: anywhere, ! 499: cache); ! 500: ! 501: return (rtn); ! 502: } ! 503: ! 504: IOReturn ! 505: kern_dev_map_port_com( ! 506: KernDevice *device, ! 507: thread_t thread, ! 508: boolean_t unmap ! 509: ) ! 510: { ! 511: id list, deviceDescription; ! 512: Range range; ! 513: int i, num; ! 514: ! 515: deviceDescription = [device deviceDescription]; ! 516: ! 517: list = [deviceDescription resourcesForKey:IO_PORTS_KEY]; ! 518: num = [list count]; ! 519: ! 520: /* ! 521: * Determine what is the highest port ! 522: * number we need to map. ! 523: */ ! 524: for (i = 0; i < num; i++) { ! 525: range = [[list objectAt:i] range]; ! 526: (void) task_map_io_ports(thread->task, range.base, range.length, unmap); ! 527: } ! 528: ! 529: return (IO_R_SUCCESS); ! 530: } ! 531: ! 532: #endif ! 533: ! 534: IOReturn ! 535: kern_dev_map_phys( ! 536: KernDevice *device, ! 537: vm_map_t map, ! 538: vm_offset_t phys, ! 539: vm_size_t length, ! 540: vm_offset_t *addr, ! 541: boolean_t anywhere, ! 542: IOCache cache ! 543: ) ! 544: { ! 545: id list, deviceDescription; ! 546: kern_return_t result; ! 547: vm_offset_t vaddr; ! 548: Range range; ! 549: int i, num; ! 550: cache_spec_t caching; ! 551: ! 552: switch (cache) { ! 553: ! 554: case IO_CacheOff: ! 555: caching = cache_disable; ! 556: break; ! 557: ! 558: case IO_WriteThrough: ! 559: caching = cache_writethrough; ! 560: break; ! 561: ! 562: default: ! 563: caching = cache_default; ! 564: break; ! 565: } ! 566: ! 567: deviceDescription = [device deviceDescription]; ! 568: ! 569: list = [deviceDescription resourcesForKey:MEM_MAPS_KEY]; ! 570: num = [list count]; ! 571: ! 572: for (i = 0; i < num; i++) { ! 573: range = [[list objectAt:i] range]; ! 574: if (range.base <= phys && ! 575: (range.base + range.length) >= (phys + length)) ! 576: break; ! 577: } ! 578: ! 579: if (i == num) ! 580: return (IO_R_PRIVILEGE); ! 581: ! 582: if (anywhere) ! 583: *addr = vm_map_min(map); ! 584: else ! 585: *addr = trunc_page(*addr); ! 586: ! 587: if (map == kernel_map) { ! 588: if (!anywhere && ! 589: *addr < 1*1024*1024) // In the hole... (between 640K and 1M) ! 590: return (IO_R_SUCCESS); ! 591: } ! 592: ! 593: result = vm_map_find( ! 594: map, ! 595: VM_OBJECT_NULL, (vm_offset_t) 0, ! 596: addr, length, ! 597: anywhere); ! 598: ! 599: if (result != KERN_SUCCESS) ! 600: return (IO_R_NO_SPACE); ! 601: ! 602: vaddr = *addr; ! 603: vaddr = trunc_page(vaddr); ! 604: length = round_page(length); ! 605: ! 606: (void) vm_map_inherit( ! 607: map, ! 608: vaddr, vaddr + length, ! 609: VM_INHERIT_NONE); ! 610: ! 611: phys = trunc_page(phys); ! 612: ! 613: while (length > 0) { ! 614: pmap_enter_cache_spec( ! 615: map->pmap, ! 616: vaddr, ! 617: phys, ! 618: VM_PROT_READ | VM_PROT_WRITE, ! 619: TRUE, ! 620: caching); ! 621: ! 622: vaddr += PAGE_SIZE; length -= PAGE_SIZE; phys += PAGE_SIZE; ! 623: } ! 624: ! 625: return (IO_R_SUCCESS); ! 626: } ! 627: ! 628: IOReturn ! 629: kern_IOProbeDriver(host_priv_t device_master, ! 630: unsigned char *configData, ! 631: unsigned int count) ! 632: { ! 633: struct probeDriverArgs args; ! 634: NXConditionLock *loadDeviceLock; ! 635: char *configString; ! 636: ! 637: if (device_master == HOST_NULL) ! 638: return IO_R_PRIVILEGE; ! 639: ! 640: configString = IOMalloc(count + 1); ! 641: if (configString == NULL) ! 642: return IO_R_NO_SPACE; ! 643: bcopy(configData, configString, count); ! 644: configString[count] = '\0'; ! 645: ! 646: /* ! 647: * We need to configure the driver from the IOTask context, so... ! 648: */ ! 649: ! 650: /* ! 651: * Set up a lock so we know when autoconf is complete. ! 652: */ ! 653: loadDeviceLock = [NXConditionLock alloc]; ! 654: [loadDeviceLock initWith:NO]; ! 655: ! 656: args.waitLock = loadDeviceLock; ! 657: args.configData = configString; ! 658: IOForkThread((IOThreadFunc) configureThread, (void *) &args); ! 659: ! 660: [loadDeviceLock lockWhen:YES]; ! 661: [loadDeviceLock free]; ! 662: IOFree(configString, count + 1); ! 663: ! 664: return (args.rtn ? IO_R_SUCCESS : IO_R_NO_DEVICE); ! 665: } ! 666: ! 667: extern const char *findBootConfigString(int n); ! 668: ! 669: IOReturn kern_IOGetDriverConfig(host_t device_master, ! 670: unsigned driverNum, ! 671: unsigned maxDataSize, ! 672: IOConfigData configData, ! 673: unsigned int *configDataCnt) ! 674: { ! 675: int configLength; ! 676: const char *configString; ! 677: ! 678: if (device_master == HOST_NULL) ! 679: return IO_R_PRIVILEGE; ! 680: ! 681: if(maxDataSize > (IO_CONFIG_TABLE_SIZE - 1)) { ! 682: maxDataSize = IO_CONFIG_TABLE_SIZE - 1; ! 683: } ! 684: configString = findBootConfigString(driverNum); ! 685: if (configString == NULL) { ! 686: return IO_R_NO_DEVICE; ! 687: } ! 688: configLength = strlen(configString); ! 689: if(maxDataSize > configLength) { ! 690: maxDataSize = configLength; ! 691: } ! 692: bcopy(configString, configData, maxDataSize); ! 693: configData[maxDataSize] = '\0'; ! 694: *configDataCnt = maxDataSize + 1; ! 695: return IO_R_SUCCESS; ! 696: } ! 697: ! 698: IOReturn kern_IOGetSystemConfig(host_t device_master, ! 699: unsigned maxDataSize, ! 700: IOConfigData configData, ! 701: unsigned int *configDataCnt) ! 702: { ! 703: return kern_IOGetDriverConfig( ! 704: device_master, ! 705: 0, ! 706: maxDataSize, ! 707: configData, ! 708: configDataCnt); ! 709: } ! 710: ! 711: IOReturn kern_IOUnloadDriver(host_t device_master, ! 712: IOConfigData configData, ! 713: unsigned int configDataSize) ! 714: { ! 715: const char *className; ! 716: IOConfigTable *configTable = nil; ! 717: Class theClass; ! 718: ! 719: if (device_master == HOST_NULL) ! 720: return IO_R_PRIVILEGE; ! 721: ! 722: configTable = [IOConfigTable newForConfigData:configData]; ! 723: className = [configTable valueForStringKey:"Driver Name"]; ! 724: theClass = objc_getClass(className); ! 725: if (theClass == nil) { ! 726: IOLog("IOUnloadDriver: Couldn't find class named %s\n", ! 727: className); ! 728: if(configTable) ! 729: [configTable free]; ! 730: return IO_R_INVALID_ARG; ! 731: } ! 732: ! 733: [theClass unregisterClass: theClass]; ! 734: if (configTable) ! 735: [configTable free]; ! 736: // FIXME: should we do [theClass free] here? ! 737: return IO_R_SUCCESS; ! 738: } ! 739: ! 740: #if defined(hppa) || defined(sparc) /* [*/ ! 741: ! 742: static int mapfun( ! 743: dev_t dev, ! 744: vm_offset_t addr, ! 745: int prot ! 746: ) ! 747: { ! 748: vm_offset_t phys = pmap_extract(kernel_pmap, addr); ! 749: return(atop(phys)); ! 750: } ! 751: ! 752: IOReturn kern_IOMapLockShmem( ! 753: KernDevice *device, ! 754: task_t task, ! 755: vm_size_t size, ! 756: vm_offset_t *shmem) ! 757: { ! 758: vm_object_t vmobject; ! 759: vm_map_t task_map; ! 760: ! 761: task_map = task->map; ! 762: if (task_map == VM_MAP_NULL) ! 763: return(IO_R_VM_FAILURE); ! 764: size = round_page(size); ! 765: ! 766: /* Create a fake object to "hold" these pages for user mapping. */ ! 767: vmobject = (vm_object_t)vm_object_special(0, mapfun, 0, *shmem, size); ! 768: ! 769: /* ! 770: ** Find some memory of the same size in 'task'. We use vm_map_find() ! 771: ** to do this. vm_map_find inserts the found memory object in the ! 772: ** target task's map as a side effect. Ensure that the addresses ! 773: ** are equivalently mapped to avoid aliasing problems. ! 774: */ ! 775: if (vm_map_find(task_map, vmobject, 0, shmem, size, FALSE)) ! 776: { // OK, can't get that, so let it find memory ! 777: if (vm_map_find(task_map, vmobject, 0, shmem, size, TRUE)) ! 778: return(IO_R_NO_MEMORY); ! 779: } ! 780: ! 781: return(IO_R_SUCCESS); ! 782: } ! 783: ! 784: IOReturn kern_IOUnMapLockShmem( ! 785: KernDevice *device, ! 786: task_t task, ! 787: vm_size_t size, ! 788: vm_offset_t *shmem) ! 789: { ! 790: vm_offset_t off; ! 791: kern_return_t krtn; ! 792: vm_map_t task_map; ! 793: ! 794: task_map = task->map; ! 795: if (task_map == VM_MAP_NULL) ! 796: return(IO_R_VM_FAILURE); ! 797: size = round_page(size); ! 798: ! 799: // Pull the shared pages out of the task map ! 800: for ( off = 0; off < size; off += PAGE_SIZE ) ! 801: { ! 802: pmap_remove(task_map->pmap, *shmem + off, *shmem + off + PAGE_SIZE); ! 803: } ! 804: // Free the former shmem area in the task ! 805: krtn = vm_map_remove(task_map, *shmem, *shmem + size ); ! 806: if (krtn) ! 807: { ! 808: IOLog("IOUnMapLockShmem: vm_map_remove() returned %d\n", krtn); ! 809: } ! 810: ! 811: // This deallocate is commented out because it caused some strange ! 812: // kernel hang -- Should be looked into some time. ! 813: // Possibly the ref_cnt is not properly incremented. ! 814: // vm_map_deallocate(task_map); // discard our reference ! 815: return(krtn); ! 816: } ! 817: #endif /*]*/ ! 818: ! 819: IOReturn ! 820: kern_IOMapDeviceMemory( ! 821: KernDevice *device, ! 822: task_t task, ! 823: vm_offset_t phys, ! 824: vm_size_t length, ! 825: vm_offset_t *addr, // in/out ! 826: BOOL anywhere, ! 827: IOCache cache ! 828: ) ! 829: { ! 830: IOReturn rtn; ! 831: ! 832: if (device == nil) ! 833: return IO_R_PRIVILEGE; ! 834: ! 835: rtn = kern_dev_map_phys( ! 836: device, ! 837: task->map, ! 838: phys, ! 839: length, ! 840: addr, ! 841: anywhere, ! 842: cache); ! 843: ! 844: return (rtn); ! 845: } ! 846: ! 847: #if hppa /* [ */ ! 848: IOReturn ! 849: kern_IOGetDeviceConfig( ! 850: KernDevice *device, ! 851: IOHPPAInterruptList interrupts, ! 852: unsigned int *interruptNum, ! 853: IOHPPAMemoryMap memoryRegions, ! 854: unsigned int *memoryRegionNum ! 855: ) ! 856: { ! 857: int i, num; ! 858: Range range; ! 859: id list, deviceDescription; ! 860: ! 861: if (device == nil) ! 862: return IO_R_PRIVILEGE; ! 863: ! 864: deviceDescription = [device deviceDescription]; ! 865: ! 866: list = [deviceDescription resourcesForKey:IRQ_LEVELS_KEY]; ! 867: num = [list count]; ! 868: if (num > IO_NUM_HPPA_INTERRUPTS) ! 869: num = IO_NUM_HPPA_INTERRUPTS; ! 870: for (i = 0; i < num; i++) ! 871: interrupts[i] = [[list objectAt:i] item]; ! 872: *interruptNum = num; ! 873: ! 874: list = [deviceDescription resourcesForKey:MEM_MAPS_KEY]; ! 875: num = [list count]; ! 876: if (num > IO_NUM_HPPA_MEMORY_RANGES) ! 877: num = IO_NUM_HPPA_MEMORY_RANGES; ! 878: for (i = 0; i < num; i++) { ! 879: range = [[list objectAt:i] range]; ! 880: memoryRegions[i].start = range.base; ! 881: memoryRegions[i].size = range.length; ! 882: } ! 883: *memoryRegionNum = num; ! 884: ! 885: return IO_R_SUCCESS; ! 886: } ! 887: #endif /* ] */ ! 888: ! 889: #if sparc /*[*/ ! 890: ! 891: IOReturn ! 892: kern_IOMapSparcDeviceMemory( ! 893: KernDevice *device, ! 894: task_t task, ! 895: vm_offset_t phys, ! 896: vm_size_t length, ! 897: vm_offset_t *addr, // in/out ! 898: BOOL anywhere, ! 899: IOCache cache ! 900: ) ! 901: { ! 902: IOReturn rtn; ! 903: id list, deviceDescription; ! 904: kern_return_t result; ! 905: vm_offset_t vaddr; ! 906: vm_map_t map; ! 907: Range range; ! 908: int i, num; ! 909: cache_spec_t caching; ! 910: unsigned int paddr,spaceid; ! 911: ! 912: if (device == nil) ! 913: return IO_R_PRIVILEGE; ! 914: map = task->map; ! 915: if (anywhere) ! 916: *addr = vm_map_min(map); ! 917: else ! 918: *addr = trunc_page(*addr); ! 919: #if 0 ! 920: // needed only for intel ! 921: if (map == kernel_map) { ! 922: if (!anywhere && ! 923: *addr < 1*1024*1024) // In the hole... (between 640K and 1M) ! 924: return (IO_R_SUCCESS); ! 925: } ! 926: #endif ! 927: result = vm_map_find( ! 928: map, ! 929: VM_OBJECT_NULL, (vm_offset_t) 0, ! 930: addr, length, ! 931: anywhere); ! 932: ! 933: if (result != KERN_SUCCESS) ! 934: return (IO_R_NO_SPACE); ! 935: vaddr = *addr; ! 936: vaddr = trunc_page(vaddr); ! 937: length = round_page(length); ! 938: ! 939: (void) vm_map_inherit( ! 940: map, ! 941: vaddr, vaddr + length, ! 942: VM_INHERIT_NONE); ! 943: // Mapping the frame buffer in user context ! 944: spaceid = (phys ) & 0x0f; // 4bits space id which is packed in bits 24-31; ! 945: paddr = ((unsigned int)(phys & 0xffffff00)); ! 946: pmap_enter_range( map->pmap, ! 947: vaddr, paddr, ! 948: spaceid, length, ! 949: VM_PROT_READ | VM_PROT_WRITE, FALSE, TRUE ); ! 950: return (IO_R_SUCCESS); ! 951: ! 952: ! 953: } ! 954: ! 955: IOReturn ! 956: kern_IOGetDeviceConfig( ! 957: KernDevice *device, ! 958: IOSPARCInterruptList interrupts, ! 959: unsigned int *interruptNum, ! 960: IOSPARCMemoryMap memoryRegions, ! 961: unsigned int *memoryRegionNum ! 962: ) ! 963: { ! 964: int i, num; ! 965: Range range; ! 966: id list, deviceDescription; ! 967: ! 968: if (device == nil) ! 969: return IO_R_PRIVILEGE; ! 970: ! 971: deviceDescription = [device deviceDescription]; ! 972: ! 973: list = [deviceDescription resourcesForKey:IRQ_LEVELS_KEY]; ! 974: num = [list count]; ! 975: if (num > IO_NUM_SPARC_INTERRUPTS) ! 976: num = IO_NUM_SPARC_INTERRUPTS; ! 977: for (i = 0; i < num; i++) ! 978: interrupts[i] = [[list objectAt:i] item]; ! 979: *interruptNum = num; ! 980: ! 981: list = [deviceDescription resourcesForKey:MEM_MAPS_KEY]; ! 982: num = [list count]; ! 983: if (num > IO_NUM_SPARC_MEMORY_RANGES) ! 984: num = IO_NUM_SPARC_MEMORY_RANGES; ! 985: for (i = 0; i < num; i++) { ! 986: range = [[list objectAt:i] range]; ! 987: memoryRegions[i].start = range.base; ! 988: memoryRegions[i].size = range.length; ! 989: } ! 990: *memoryRegionNum = num; ! 991: ! 992: return IO_R_SUCCESS; ! 993: } ! 994: ! 995: ! 996: #endif /*]*/ ! 997: ! 998: #if ppc /* [ */ ! 999: IOReturn ! 1000: kern_IOGetDeviceConfig( ! 1001: KernDevice *device, ! 1002: IOPPCInterruptList interrupts, ! 1003: unsigned int *interruptNum, ! 1004: #ifdef notyet ! 1005: IOPPCDMAChannelList dmaChannels, ! 1006: unsigned int *dmaChannelNum, ! 1007: #endif ! 1008: IOPPCMemoryMap memoryRegions, ! 1009: unsigned int *memoryRegionNum ! 1010: ) ! 1011: { ! 1012: int i, num; ! 1013: Range range; ! 1014: id list, deviceDescription; ! 1015: ! 1016: if (device == nil) ! 1017: return IO_R_PRIVILEGE; ! 1018: ! 1019: deviceDescription = [device deviceDescription]; ! 1020: ! 1021: list = [deviceDescription resourcesForKey:IRQ_LEVELS_KEY]; ! 1022: num = [list count]; ! 1023: if (num > IO_NUM_PPC_INTERRUPTS) ! 1024: num = IO_NUM_PPC_INTERRUPTS; ! 1025: for (i = 0; i < num; i++) ! 1026: interrupts[i] = [[list objectAt:i] item]; ! 1027: *interruptNum = num; ! 1028: ! 1029: #ifdef notyet ! 1030: list = [deviceDescription resourcesForKey:DMA_CHANNELS_KEY]; ! 1031: num = [list count]; ! 1032: if (num > IO_NUM_PPC_DMA_CHANNELS) ! 1033: num = IO_NUM_PPC_DMA_CHANNELS; ! 1034: for (i = 0; i < num; i++) ! 1035: dmaChannels[i] = [[list objectAt:i] item]; ! 1036: *dmaChannelNum = num; ! 1037: #endif ! 1038: list = [deviceDescription resourcesForKey:MEM_MAPS_KEY]; ! 1039: num = [list count]; ! 1040: if (num > IO_NUM_PPC_MEMORY_RANGES) ! 1041: num = IO_NUM_PPC_MEMORY_RANGES; ! 1042: for (i = 0; i < num; i++) { ! 1043: range = [[list objectAt:i] range]; ! 1044: memoryRegions[i].start = range.base; ! 1045: memoryRegions[i].size = range.length; ! 1046: } ! 1047: *memoryRegionNum = num; ! 1048: ! 1049: ! 1050: ! 1051: return IO_R_SUCCESS; ! 1052: } ! 1053: #endif /* ] */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.